#android #google-play-services #google-play-console #android-billing #in-app-subscription
#Android #google-play-сервисы #google-play-консоль #android-выставление счетов #подписка в приложении
Вопрос:
Я внедряю выставление счетов в Google Play в своем приложении для Android. Я продаю подписки на Google Play.
- Когда я использую тестовую карту, Google успешно взимает плату за подписку.
- Проблема в том, что когда реальный пользователь пытается приобрести план подписки, он успешно подписывается на план, но Google взимает 0 долларов.
- Я несколько раз перепроверял свой код
Пожалуйста, помогите мне решить эту проблему.
Скриншот консоли Google Play.
Вот мой код для BillingClient:
public class BillingHandler implements ASubscriptionClickListener,
PurchasesUpdatedListener,
AcknowledgePurchaseResponseListener
{
private static String TAG = BillingHandler.class.getSimpleName();
private Activity activity;
private List<SkuDetails> skuDetailsList;
private BillingClient billingClient;
private RecyclerView rvSKUs;
public BillingHandler(@NonNull Activity activity, @Nullable RecyclerView recyclerView) {
this.activity = activity;
this.rvSKUs = recyclerView;
initBillingClient();
}
private void initBillingClient() {
billingClient = BillingClient.newBuilder(activity).enablePendingPurchases().setListener(this).build();
Log.e(TAG, "billing client built.");
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
Log.e(TAG, "billing client setup successful.");
queryAvailablePlans();
}else {
Log.e(TAG, "billing client setup failed.");
handleAllBillingErrors(billingResult);
}
}
@Override
public void onBillingServiceDisconnected() { }
});
}
private void handleAllBillingErrors(BillingResult billingResult){
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK){
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
showAFailureMsg("User cancelled the purchase after showing plans to the user", false);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED) {
showAFailureMsg("Feature not supported on this phone.", true);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.DEVELOPER_ERROR) {
showAFailureMsg("DEVELOPER_ERROR", false);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.BILLING_UNAVAILABLE) {
showAFailureMsg("BILLING_UNAVAILABLE", false);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
showAFailureMsg("ITEM_ALREADY_OWNED", false);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_NOT_OWNED) {
showAFailureMsg("ITEM_NOT_OWNED", false);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_UNAVAILABLE) {
showAFailureMsg("ITEM_UNAVAILABLE", false);
}else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.SERVICE_DISCONNECTED) {
showAFailureMsg("SERVICE_DISCONNECTED", false);
}else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE) {
showAFailureMsg("SERVICE_UNAVAILABLE", false);
}else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.SERVICE_TIMEOUT) {
showAFailureMsg("SERVICE_TIMEOUT", false);
} else {
showAFailureMsg("Something went wrong while setting up purchase after showing plans to the user", false);
}
}
/**
* get all plans from play console!
*/
private void queryAvailablePlans() {
List<String> skuList = new ArrayList<>();
skuList.add("1_months_plan");
skuList.add("3_months_plan");
skuList.add("6_months_plan");
skuList.add("12_months_plan");
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS);
billingClient.querySkuDetailsAsync(params.build(),
(billingResult, skuDetailsList) -> {
//loaded all available the subscription plans.
// Process the result.
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK amp;amp; skuDetailsList != null) {
String msg = "SKU details response received: OK (Number of Plans:" skuDetailsList.size() ")";
Log.e(TAG, msg);
this.skuDetailsList = skuDetailsList;
//Show all plans
if (rvSKUs != null) {
rvSKUs.setLayoutManager(new LinearLayoutManager(activity, RecyclerView.VERTICAL, false));
rvSKUs.setAdapter(new RVAdapt_SKUs(this.skuDetailsList, activity, this));
}
} else {
Log.e(TAG, "SKU details response received: null");
}
});
}
/**
* On update of a purchase plan
* @param purchase details of subscription/ purchase of user
*/
private void handlePurchase(BillingClient client, Purchase purchase) {
Log.e(TAG, "handling a pending purchase");
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
Log.e(TAG, "Successfully purchased a plan(" purchase.getSku() "). t Order ID: "
purchase.getOrderId() ". Token: " purchase.getPurchaseToken());
// Acknowledge the purchase if it hasn't already been acknowledged.
if (!purchase.isAcknowledged()) {
Log.e(TAG, "not acknowledged yet!!");
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
purchaseToAcknowledge = purchase;
client.acknowledgePurchase(acknowledgePurchaseParams, this);
} else {
Log.e(TAG, "Already Acknowledged");
}
} else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING
|| purchase.getPurchaseState() == Purchase.PurchaseState.UNSPECIFIED_STATE) {
MyShrdPref.instantiate(activity).writePlanType(MyGlobalAppData.PLANS_TYPES.FREE);
MyFirebaseServices.saveOrRemovePlan(activity, null, null);
Toast.makeText(activity, "A pending payment found!", Toast.LENGTH_SHORT).show();
Log.e(TAG, "A pending payment found!");
}
}
private void showAFailureMsg(String msg, boolean exit){
Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
Log.e(TAG, msg);
if (exit)activity.finish();
}
/**
* Listener for SKUs RecyclerView to get the the clicked sku
* @param skuDetails clicked sku details
*/
@Override
public void onClick(SkuDetails skuDetails) {
//Callback which returns the selected sku by the user
if (billingClient.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS)
.getResponseCode() == BillingClient.BillingResponseCode.OK) {
//Show purchase process/ flow
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
BillingResult responseCode = billingClient.launchBillingFlow(activity, flowParams);
if (responseCode.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.e("BillingHandler", "billing flow completed successfully!");
}
handleAllBillingErrors(responseCode);
}
}
private Purchase purchaseToAcknowledge;
@Override
public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
if (purchaseToAcknowledge==null) return;
if (billingResult.getResponseCode()==BillingClient.BillingResponseCode.OK) {
Log.e(TAG, "purchaseToAcknowledge: " purchaseToAcknowledge.getPackageName()
"n Purchase Acknowledgment Time: "
purchaseToAcknowledge.getPurchaseTime()
);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
String message = "Congrats! You have successfully subscribed for premium features.nn";
for (SkuDetails d : skuDetailsList) {
if (d.getSku().equals(purchaseToAcknowledge.getSku())) {
MyFirebaseServices.saveOrRemovePlan(activity, d, null);
message = "Plan: " d.getTitle() "nn";
message = "" d.getDescription() "nn";
break;
}
}
message = "OrderID: " purchaseToAcknowledge.getOrderId();
builder.setTitle("Subscription successful")
.setMessage(message)
.setPositiveButton("Okay", (dialogInterface, i) -> {
})
.show();
}else handleAllBillingErrors(billingResult);
}
@Override
public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> purchaseList) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
amp;amp; purchaseList != null) {
for (Purchase purchase : purchaseList) {
handlePurchase(billingClient, purchase);
}
} else{
handleAllBillingErrors(billingResult);
}
}
}
Комментарии:
1. Google взимает 0 долларов или взимает желаемую сумму, но клиенты запрашивают возврат и, следовательно, зарегистрированы, но не взимаются?
2. @AliHas google взимает 0 долларов и показывает успешную подписку как в ответе, так и в Play console.
3. @AliHas google взимает комиссию в размере 0 долларов США даже при подтверждении покупки.