Google Play Billing Library - consumeAsync not working properly

Viewed 1408

I am trying to integrate the Google Play Billing Library in our app to sell a consumable in-app product. According to the official integration guide by developer.android.com, using the consumeAsync method on a purchase will allow the user to buy the product again. However, for me, the method does not always work correctly and the user cannot buy the product again.

Also, in the case of a 'slow test card, payment gets declined' scenario, the payment is never completed and the consumeAsync method does not work at all.

I have gone through all similar stack overflow question but no solution is working. Also, the official example app by Google mostly focuses on the subscription model so that is also not helping.

You can take a look at my implementation below:

public class PremiumMembershipActivity extends AppCompatActivity implements AcknowledgePurchaseResponseListener {

// Billing Client
private BillingClient billingClient;
private List<String> skuList = new ArrayList<String>();

private String sku = "buy_1000_credits";

private PurchasesUpdatedListener purchaseUpdateListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> list) {

        methodForPurchaseUpdated(billingResult, list);
    }
};

private ConsumeResponseListener consumeResponseListener = new ConsumeResponseListener() {
    @Override
    public void onConsumeResponse(BillingResult billingResult, @NotNull String s) {
        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK){
        }
    }
};


private AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = new AcknowledgePurchaseResponseListener() {
    @Override
    public void onAcknowledgePurchaseResponse(@NotNull BillingResult billingResult) {
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_premium);

    mBuyCredits = findViewById(R.id.premium_membership_buy_credits_card);
    skuList.add(sku);
    setupBillingClient();
}

    
private void setupBillingClient() {

    billingClient = BillingClient
            .newBuilder(PremiumMembershipActivity.this)
            .enablePendingPurchases()
            .setListener(purchaseUpdateListener)
            .build();

    billingClient.startConnection(new BillingClientStateListener() {
        @Override
        public void onBillingSetupFinished(@NotNull BillingResult billingResult) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                // The BillingClient is ready. You can query purchases here.
                loadAllSkus();

            }else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ERROR) {
                Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_added_error, Toast.LENGTH_SHORT).show();

            }else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.BILLING_UNAVAILABLE) {
                Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_client_unavailable, Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onBillingServiceDisconnected() {
            // Try to restart the connection on the next request to
            // Google Play by calling the startConnection() method.
            Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_client_disconnected, Toast.LENGTH_SHORT).show();
        }
    });
}

private void loadAllSkus() {

    if (billingClient.isReady()){

        SkuDetailsParams params = SkuDetailsParams.newBuilder()
                .setSkusList(skuList)
                .setType(BillingClient.SkuType.INAPP)
                .build();

        billingClient.querySkuDetailsAsync(params, new SkuDetailsResponseListener() {
            @Override
            public void onSkuDetailsResponse(@NotNull BillingResult billingResult, List<SkuDetails> list) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK){
                    for (Object skuDetailsObject : list){
                        final SkuDetails skuDetails = (SkuDetails) skuDetailsObject;

                        if (skuDetails.getSku().equals(sku)){
                            //Only enable the Buy credits button when the required SKU (from Google Play Console Managed Products) is found
                            mBuyCredits.setEnabled(true);
                            mBuyCredits.setOnClickListener(buyCreditsOnClickListener(skuDetails));
                        }
                    }
                }
            }
        });
    }
    else{
        Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_client_notready, Toast.LENGTH_SHORT).show();
    }
}

private View.OnClickListener buyCreditsOnClickListener(final SkuDetails skuDetails) {
    return new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            BillingFlowParams params = BillingFlowParams
                    .newBuilder()
                    .setSkuDetails(skuDetails)
                    .build();

            billingClient.launchBillingFlow(PremiumMembershipActivity.this, params);
        }
    };
}



public void methodForPurchaseUpdated(BillingResult billingResult, @Nullable List<Purchase> list) {

    int responseCode = billingResult.getResponseCode();

    if (responseCode == BillingClient.BillingResponseCode.OK  && list != null){

        for (Purchase purchase : list) {
            handlePurchase(purchase);
        }

    }else if (responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
        Toast.makeText(PremiumMembershipActivity.this, R.string.buy_item_owned, Toast.LENGTH_SHORT).show();

    }else if (responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
        Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_added_cancel, Toast.LENGTH_SHORT).show();
    }else if (responseCode == BillingClient.BillingResponseCode.SERVICE_TIMEOUT){
        Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_added_error, Toast.LENGTH_SHORT).show();
    }else{
        Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_card_declined, Toast.LENGTH_SHORT).show();
        
    }
}

public void handlePurchase(Purchase purchase) {

    if (purchase.getSku().equals(sku) && purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED){

        // Add Credits in user account in backend
        addCreditsinBackend(1000);

        // Add the purchase token to backend so transaction can be tracked
        String token = purchase.getPurchaseToken();
        addPurchaseToken(token);

        // Consume the credits so they can be bought again
        ConsumeParams consumeParams = ConsumeParams.newBuilder()
                .setPurchaseToken(purchase.getPurchaseToken())
                .build();

        billingClient.consumeAsync(consumeParams, consumeResponseListener);

        // Acknowledge the purchase if it hasn't already been acknowledged.
        if (!purchase.isAcknowledged()) {
            AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();

            billingClient.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
        }
  }
    else if (purchase.getSku().equals(sku) && purchase.getPurchaseState() == Purchase.PurchaseState.PENDING){
        Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_card_slow, Toast.LENGTH_SHORT).show();

    } else if (purchase.getSku().equals(sku) && purchase.getPurchaseState() == Purchase.PurchaseState.UNSPECIFIED_STATE){

        Toast.makeText(PremiumMembershipActivity.this, R.string.buy_credits_card_unspecified, Toast.LENGTH_SHORT).show();

    }
}

@Override
public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {

}


private void addCreditsinBackend(int credits) {

//Code for adding credits to the users' account in the backend

}

    private void addPurchaseToken (String token) {

//Code for adding PurchaseToken of the purchase to our backend

}

}
0 Answers
Related