Can't re-buy in-app billing item on Google Play after it was refunded

后端 未结 4 1820
一生所求
一生所求 2021-02-09 13:46

I implemented in-app billing into my app and am now testing its handling of refunds.

I bought my app\'s managed in-app billing item with a test account and refunded it.

相关标签:
4条回答
  • 2021-02-09 14:23

    I was seeing the same issue. GP crash and everything.

    In addition to waiting a few hours, you may want to open up 'Google Play' app info and clear cache and clear data. This solved it for me. It appears GP caches purchase information on the device and only checks Google's servers rarely, if ever, for refund information.

    Update: You may also want to kill the Google Play process since it appears to keep purchase info in memory too.

    0 讨论(0)
  • 2021-02-09 14:26

    I asked Google about this issue and they told me that it's not possible to re-buy an in-app billing item on Google Play if it was previously refunded. But when I tried to buy it again about 24 hours later, the purchase went through ...

    So it looks like it's possible to re-buy, but only after some delay.

    0 讨论(0)
  • 2021-02-09 14:32

    In case somebody needs android and not kotlin code. All the explanation that smitty wrote:

    When starting up the application , You have to check queryPurchases and look for the refunded items. like that:

    if (purchase.getPurchaseState() != Purchase.PurchaseState.UNSPECIFIED_STATE)
    {
         handleConsumablePurchasesAsync(purchasesList);
         return false;
    }
    

    Than you CONSUME this item. smitty1 is a Genius

    private void handleConsumablePurchasesAsync(List<Purchase> consumables) {
        Log.d(TAG, "handleConsumablePurchasesAsync");
        for (Purchase purchase : consumables) {
            ConsumeParams params = ConsumeParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
    
            billingClient.consumeAsync(params, (billingResult, purchaseToken) -> {
                if (billingResult.getResponseCode() == OK) {
                    Log.d(TAG, "Consumed the old purchase that hasn't already been acknowledged");
                } else {
                    Log.d(TAG, "Error consume the old purchase that hasn't already been acknowledged -> %s" + String.valueOf(billingResult.getResponseCode()));
                }
            });
        }
    }
    
    0 讨论(0)
  • 2021-02-09 14:33

    I know this is an old question, but i have been looking for an answer to this same question and eventually came to my own conclusion. Google doesn't spell it out, but I believe they want you to decide on your own logic as to how to handle cancelled and refunded purchases. Another point to keep in mind is that there there is essentially no difference between a consumable and non consumable managed product. All managed products are consumable.

    For me, when a user cancels a purchase, or if I decide to give the user a refund, what I want to happen is that 1) the user receives their money back and 2) the user loses access to the paid feature and 3) the user has the option to purchase the feature again if they choose.

    What I did was to check the purchaseState of the purchase on my back end server using the in-app billing API. If the returned purchaseState is a 1 (canceled) or 2 (refunded), I consume the purchase in my app. Google handles item 1, giving the user their money back. The logic in my app handles 2, locking access to the paid features. Consuming the purchase handles 3, giving the user the option to purchase the feature again.

    The basic gist of it is, when a purchase is sent to my back end server for verification, I check the purchase state. If the purchase state is a 1 or a 2, I return an appropriate code to my app. When my app receives the code indicating the purchase is cancelled or refunded, my app consumes the purchase.

    I use the PHP version of the API, so my simplified code to get the purchase state is :

    $purchases = $service->purchases_products->get($packageName, $productId, $purchaseToken);
    
    $purchaseState = $purchases->getPurchaseState();
    
    if($purchaseState === 1){
            $serverResponseCode = 3;
        }
    
        if($purchaseState === 2){
            $serverResponseCode = 4;
        }
    

    ...and then in my app, I check the server response codes.

    if(serverResponseCode == 3 || serverResponseCode ==4 ){
         lockFeatures();
         ConsumeParams params = ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();
         billingClient.consumeAsync(params, listener);
    }
    

    I hope this helps someone else looking for an answer to this problem.

    0 讨论(0)
提交回复
热议问题