Billing Client Not Ready for In App Billing

473 Views Asked by At

I knew i have added similar question before regrding the issue for not able to launch the paymentflow dialog , but here i have changed the code accrding to the IAB/IAP v6.01 , previous one was v4.0.0

so when im clicking the btn to show the paymentflow dialog , the toast regading the billin client is not ready is being aprerd accrding to this

if(billingclient.isReady())

means its going to else

idk what is wrong here, i have added the product details properly the product id and the licece base64 key but dont know what is cuasing this

    private final String premiumProductId = <Product ID>;
 private final String baseKey64 = <Licence Base 64>;
    

OnCreateView {

    // Initialize BillingClient
        billingClient = BillingClient.newBuilder(requireContext()).setListener(purchasesUpdatedListener).enablePendingPurchases().build();

    // Buy Premium Btn Click
        Premium_ImgPostTab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (billingClient.isReady()){
                    Toast.makeText(requireContext(),"Billing Client Ready",Toast.LENGTH_SHORT).show();
                    PurchaseDialog();
                }else {
                    Toast.makeText(reqverifyuireContext(),"Billing Client Not Ready",Toast.LENGTH_SHORT).show();
                }
            }
        });

        return view;
    }


   private void PurchaseDialog() {
        billingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().setProductList(ImmutableList.of(QueryProductDetailsParams.Product.newBuilder().setProductId(premiumProductId).setProductType(BillingClient.ProductType.INAPP).build())).build();

                    billingClient.queryProductDetailsAsync(queryProductDetailsParams, new ProductDetailsResponseListener() {
                        public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
                            for (ProductDetails productDetails : productDetailsList) {
                                String offerToken = productDetails.getSubscriptionOfferDetails().get(0).getOfferToken();
                                ImmutableList productDetailsParamsList = ImmutableList.of(BillingFlowParams.ProductDetailsParams.newBuilder()
                                        // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
                                        .setProductDetails(productDetails)
                                        // to get an offer token, call ProductDetails.getSubscriptionOfferDetails()
                                        // for a list of offers that are available to the user
                                        .setOfferToken(offerToken).build());
                                BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder().setProductDetailsParamsList(productDetailsParamsList).build();

                                // Launch the billing flow
                                billingResult = billingClient.launchBillingFlow(requireActivity(), billingFlowParams);
                            }
                        }
                    });

                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
            }
        });
    }

    void handlePurchase(Purchase purchase) {
        if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
            if (!verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
                Toast.makeText(requireContext(), "Error: Invaild Purchase", Toast.LENGTH_SHORT).show();
                return;
            }
            if (!purchase.isAcknowledged()) {
                AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();
                billingClient.acknowledgePurchase(acknowledgePurchaseParams, ackPurchase);
            }
        } else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING) {
            Toast.makeText(requireContext(), "Purchase is Pending", Toast.LENGTH_SHORT).show();
        } else if (purchase.getPurchaseState() == Purchase.PurchaseState.UNSPECIFIED_STATE) {
            Toast.makeText(requireContext(), "Purchase Handing: Unexpected Error", Toast.LENGTH_SHORT).show();
        }
    }

private final PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
        @Override
        public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
            // To be implemented in a later section.
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
                for (Purchase purchase : purchases) {
                    handlePurchase(purchase);
                }
            } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
                // Handle an error caused by a user cancelling the purchase flow.
            } else {
                // Handle any other error codes.
            }
        }
    };

    private boolean verifyValidSignature(String signedData, String signature) {
        try {
            // To get key go to Developer Console > Select your app > Development Tools > Services & APIs.
            String base64Key = baseKey64;
            return Security.verifyPurchase(base64Key, signedData, signature);
        } catch (IOException e) {
            return false;
        }
    }

    AcknowledgePurchaseResponseListener ackPurchase = new AcknowledgePurchaseResponseListener() {
        @Override
        public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                // Acknowledgment successful
                Toast.makeText(requireContext(), "Acknowledgment successful", Toast.LENGTH_SHORT).show();

            } else {
                // Handle acknowledgment error
                Toast.makeText(requireContext(), "Acknowledgment unsuccessful", Toast.LENGTH_SHORT).show();
            }
        }
    };

 public void onDestroy() {
        super.onDestroy();
        if (billingClient != null) {
            billingClient.endConnection();
        }
    }

after sometime i thought maybe loading the connection before the onclick can be helpfull , like this

// Buy Premium Btn Click
        
        getConnection();
        Premium_ImgPostTab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (billingClient.isReady()){
                    Toast.makeText(requireContext(),"Billing Client Ready",Toast.LENGTH_SHORT).show();
                    PurchaseDialog();
                }else {
                    Toast.makeText(requireContext(),"Billing Client Not Ready",Toast.LENGTH_SHORT).show();
                }
            }
        });


private void getConnection() {
        billingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().setProductList(ImmutableList.of(QueryProductDetailsParams.Product.newBuilder().setProductId(premiumProductId).setProductType(BillingClient.ProductType.INAPP).build())).build();

                    billingClient.queryProductDetailsAsync(queryProductDetailsParams, new ProductDetailsResponseListener() {
                        public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
                            for (ProductDetails productDetails : productDetailsList) {
                                String offerToken = productDetails.getSubscriptionOfferDetails().get(0).getOfferToken();
                                ImmutableList productDetailsParamsList = ImmutableList.of(BillingFlowParams.ProductDetailsParams.newBuilder()
                                        // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
                                        .setProductDetails(productDetails)
                                        // to get an offer token, call ProductDetails.getSubscriptionOfferDetails()
                                        // for a list of offers that are available to the user
                                        .setOfferToken(offerToken).build());
                            }
                        }
                    });

                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
            }
        });
    }

here i didnt add the launchBillingFlow , in this case the codintion billingclient.isReady() gets true and show the toast inside it , but didnt able to luanch the billingflow in the end

Edit:- I thought maybe adding the .csv export from play console product details here is the file

> Blockquote

the only concern here is the price section its shows 400000000 value , which is no corrrect its INR 400 not 400000000 , but its showing correct in the console

enter image description here

0

There are 0 best solutions below