Shopping/Restoration inside the app on Android

Asked

Viewed 469 times

2

I am running an app that will have in-app purchases (hide advertising and new features), however I have some questions. The whole purchase process is already working, well hide the advertising and the new features are available to the user however I have two doubts.

  1. We imagine that the user formats the mobile phone (or changes Tlm), re-downloads my app, but this will still have advertising, the user to get the full app without paying again, just perform the purchase process again (and Google knows that he has already bought and does not charge anything) or you need to implement a button in the app to allow you to restore?
  2. The user makes the purchase in app, but then wants to recover his money (e.g. regret or disliked, etc.). In this case, how does the user get his money? I ask this because I have read somewhere that in in-app purchases the user cannot recover his money, this is true?
  • Is using the Google Play In-app Billing?

  • 1

    Yes @Wakim, I’m using that Google library

  • All purchases made are associated with the user, not the device. You just need to check the purchases made in your app to see if the user has previously purchased. Regarding the refund, it can be done and has to be done manually by you.

  • How do I "check purchases made in your app to see if the user has previously purchased"? refund, found that in Urchase in app refund are manual between user and trader

  • In item 2 of Purchasing Items (http://developer.android.com/google/play/billing/api.html#Purchase) it says that you can query it (it even has local cache, which allows you to query it more often).

  • I don’t know who suspended this thread, but this has to do with programming. Thanks for the answers so far

  • Okay, I’ll reopen the question based on penultimate item of this metaquestion. CC @Wakim

Show 2 more comments

2 answers

1


The purchases made by Google Play in-app Billing v3 are always attached to the user’s account on Google Play, no matter if it removed your app, formatted the device, bought another one. As long as everything happens with the same account1.

  1. Whenever you launch the app, you can query using the getPurchases (The Google Play Services still caches purchases, which does not cost so much in this case) if the user has already paid for the removal of ads or release of resources, code example2:

    Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
    
    int response = ownedItems.getInt("RESPONSE_CODE");
    
    if (response == 0) {
        ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
        ArrayList<String>  purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
        ArrayList<String>  signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
    
        String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
    
        for (int i = 0; i < purchaseDataList.size(); ++i) {
            String purchaseData = purchaseDataList.get(i);
            String signature = signatureList.get(i);
            String sku = ownedSkus.get(i);
    
            JSONObject purchaseJSON = new JSONObject(purchaseData);
    
            // Você também pode verificar o purchaseState
            // (0 para purchased, 1 para canceled e 2 para refunded)
            int purchaseState = purchaseJSON.getInt("purchaseState");
    
            if(purchaseState == 0) {
                // Faça algo com a informação dessa compra
                // Desabilitar ADS, liberar funcionalidades ou
                // atualizar um SharedPreferences para não
                // precisar consultar denovo.
            }
        }
    
        // se continuationToken != null, chame getPurchases denovo 
        // e passe o token para obter mais items
        // O limite que o Google Play retorna é de 700 itens
    }
    
  2. To refund a purchase, the user must contact you by email or other means of communication and request the cancellation. Cancellation should be done manually by you at Google Wallet Merchant.

    It is possible to detect refunds using the purchase status code in the method getPurchases, when making a refund for an item that was purchased, the field purchaseState will come with value 23 (save some delay of communication), being made a treatment for the removal of Ads or release of functionalities back to the previous state.

References:

  1. http://developer.android.com/google/play/billing/api.html#Purchase and http://developer.android.com/google/play/billing/api.html#consume (Paragraph about "Non-consumable Items")
  2. Sample code of getPurchases was taken from http://developer.android.com/google/play/billing/billing_integrate.html.
  3. Tables 4 and 5 with the fields available in the methods used: http://developer.android.com/google/play/billing/billing_reference.html
  • Thank you for the reply. I had to read this and to test this before publishing, I need to send the apk to the store (alpha) and user tests so that no value is charged. What I don’t understand is whether these test users have an associated credit card or not, you can answer this?

  • @Kiotto, there are two ways: The Test Purchase's where it does not generate any charge, but you need to create them on the console to not be charged. And the "Real" test, with a real product that will generate a charge even for a test account. With regard to the card, it should not be necessary as the Google Play has other payment methods ( https://support.google.com/googleplay/answer/2651410?hl=en) and ( https://developer.android.com/google/play/billing_testing.html#testing-Purchases).

  • Now regarding the Testing Purchases, i believe that you do not need any payment method, I’m not sure, it is necessary to test first.

  • To make the payment, I had to put in a valid CC number, but then the money is not withdrawn. But after the purchase made and used the code, it is returned that I have not yet made purchases

  • @Kiotto, the purchase appears on Google Wallet Merchant how completed? The getPackageName returns the same registered in Google Play?

  • In Google Wallet Merchant appears with the yellow ball, getPackgageName returns the name of the package I declared in the manifest. In this Bundle method ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null); getPackName() is the package name or the sku name declared in google play?

  • @Kiotto, this has to be the packageName even.

  • Then it’s all right :(

  • @Kiotto, from what I’ve seen, the yellow circle says the transaction is pending. I saw this information here: http://stackoverflow.com/questions/23549953/google-transaction-canceled.

  • I’m going to wait until it turns green, but if this starts to work after it turns green, it doesn’t make sense because this process takes on average seven hours. And the user when buying is soon available, the getPurchases method should return this.

  • The state does not pass green, as it is a test the state should not change...

  • Solved, finally.. The problem is that at the time of purchase, I was using the mHelper.consumeAsync method, and I shouldn’t use it. I’ve removed and already shopping and I can tell if the user bought it or not. Question, where you saw that the result code for the refund is 2?

  • Table 4: http://developer.android.com/google/play/billing/billing_reference.html, I will clarify this in the reply.

Show 9 more comments

0

I made a test, which means I made an in-app purchase, but with the top code, it returns that there are no purchased products. I have this code:

     mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IInAppBillingService.Stub.asInterface(service);

            try {
                Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);

                int response = ownedItems.getInt("RESPONSE_CODE");

                if (response == 0) {

                    ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
                    ArrayList<String> purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
                    ArrayList<String> signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
                    String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");

                    if (purchaseDataList.size() > 0) {
                        for (int i = 0; i < purchaseDataList.size(); ++i) {
                            String purchaseData = purchaseDataList.get(i);
                            String signature = signatureList.get(i);
                            String sku = ownedSkus.get(i);

                            Utils.showPopUp(PreferencesActivity.this, "Info", "purchaseData: " + purchaseData + "\nsignature: " + signature + "\nsku: " + sku, false);

                            //TODO REVER
                            shared.setPurchaseInApp(true);
                        }
                    } else {
                        //TODO REVER
                        Utils.showPopUp(PreferencesActivity.this, "Info", "Não efectou compras", false);
                        shared.setPurchaseInApp(false);
                        initPurchaseInApp();
                    }
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }
    };

    Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
    serviceIntent.setPackage("com.android.vending");
    bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);

Browser other questions tagged

You are not signed in. Login or sign up in order to post.