cordova-plugin-inapppurchase icon indicating copy to clipboard operation
cordova-plugin-inapppurchase copied to clipboard

Check subscription is active

Open etiennea opened this issue 8 years ago • 16 comments

Does someone have some code to do this that works with both iOS and Android?

Would that show up in inAppPurchase.getProducts(productIds)?

etiennea avatar May 27 '16 14:05 etiennea

I have the same problem. When trying to call this method. products array is empty. I have tried with a productId with and without app package. I have latest android 6 sdk. Do we need to install gogle play billing library from extras?

rsallar avatar May 27 '16 20:05 rsallar

I've been working with this plugin for a while and here are my experiences on subscriptions:

  1. Keep a copy of the subscription state (store the entire receipt) on your own server and use logic based on your own server to disable / enable features. The reason for this is that android subs (in particular) can be forged.

iOS receipts will include an expiry date. Android receipts will not, so you should name your productIds something like product_a_1m, product_a_6m and parse the duration of that subscription based on the product Id.

  1. Do receipt validation on your backend. Just do it.

  2. In order to know if a subscription have been renewed (billed successfully by Google Play / AppStore), you'll need to call inAppPurchase.getReceipt(). It might sound like a good idea to call this on every app startup, but it is not. Requesting a refreshed receipt on iOS will trigger a AppStore email / password popup. Only if the user enters her/his password will you get the new receipt. If you keep asking for that on every startup, they'll most likely stop entering it and you'll stop receiving receipts. On Android, no email / password prompt is required.

Best practice is therefore to detect if a subscription has expired with your own client side / server side logic, then notify iOS users that they will be required to enter their username / password to validate their current subscription. For Android users, just get the new receipt, post it to your API and re-unlock the subscribed features.

Do we need to install gogle play billing library from extras?

Yes, afaik.

kristfal avatar Jun 03 '16 16:06 kristfal

Hi, how do we validate restored subscriptions? When we call inAppPurchase.restorePurchases() there's no receipt on iOS but only transactionId.

If I call inAppPurchase.getReceipt() it doesn't contain the transactionId returned from inAppPurchase.restorePurchases() neither in in_app nor in latesr_receipt_info arrays.

heaven avatar Jun 08 '16 10:06 heaven

@heaven: You'll need to call restorePurchases and then getReceipt. This is an excerpt from our implementation.

_getReceipt: function() {
        window.inAppPurchase.restorePurchases().then((data) => {
            // iOS provides the receipt isolated from the restore data
            if (this.deviceType === 'ios') {
                return window.inAppPurchase.getReceipt().then((receipt) => {
                    // Handle receipt

                }).catch((error) => {
                    // Handle error
                });

            // Android provides the receipts with the restore data
            } else {
                    // Handle Receipt
            }

        }).catch((error) => {
            // Handle error
        });
    }

kristfal avatar Jun 08 '16 11:06 kristfal

@kristfal thanks for the help, that's what I did but found that this receipt doesn't include the transaction id I received during the restore.

Not sure how to validate this, it seems I have to go through all transactions from this receipt and restore all products, instead of restoring just one. But why then does apple call restore for every user's purchase if I anyway can't identify which exactly purchase to restore using the returned transaction id?

So for example a user purchased 3 things, then clicked restore – our restore callback gets called 3 times with the same receipt and useless transaction ids that I can't use to determine which product to restore. As a result we have to go through the complete restore process 3 times (do the same thing 3 times in a row).

heaven avatar Jun 08 '16 12:06 heaven

@heaven That is how the iOS receipt works. It is one receipt for all products instead of an individual receipt per product (as it is on Android).

kristfal avatar Jun 08 '16 12:06 kristfal

Old issue I know but hopefully I can get some advice on it. I'm implementing the subscription expiries in my API. It seems quite straight forward, the only issue I'm having is handling canceled subscriptions?

@kristfal is this something that you had implemented in your API? Would love to know your views on it. For reasons you outlined I'd prefer not to use the client getReciept to periodically check if the subscription was cancelled.

Does restorePurchases prompt for username/password on iOS? (only working with Android for the moment)

stoconnor avatar Nov 03 '16 16:11 stoconnor

@stoconnor did you find a way of checking to see if a subscription was canceled?

santekotturi avatar Feb 15 '17 07:02 santekotturi

@skotturi not ideal but I have a cronjob running to check for canceled subscriptions. I save subscription purchases on my server and have another cronjob running to remove expired subscriptions.

When time allows, I think the right approach is to fully implement the store API and process purchases and receipts through the app

stoconnor avatar Feb 15 '17 07:02 stoconnor

@stoconnor so you store the initial receipt on the backend and then use voltrue2's validation module, in particular, iap.isExpired(), every night to check the status? ios and android?

Do you have to re-request the ios receipt using inAppPurchase.getReceipt()

santekotturi avatar Feb 15 '17 17:02 santekotturi

@stoconnor and @skotturi , I have a similar solution where I store receipt on the server and daily job checks them with appstore to validate the receipt. What I can't get my head round to is how to renew subscription on my server when subscription get renewed on app store (automatically e.g. every month/year). I did look at the way @skotturi explained where triggering getReceipt when my server indicate it is expired. But getReceipt returns all the subscription users bought rather than the latest one.

Appreciate your time and help.

mustaqt avatar Mar 14 '17 11:03 mustaqt

@mustaqt I think your approach is correct though, have you tried iterating over the list of subscriptions and if you find one active one, then you assume the user has not cancelled their renewing subscription?

santekotturi avatar Apr 01 '17 04:04 santekotturi

Hi @skotturi

I am trying implement auto renew subscription on iOS. inAppPurchase.getReceipt() return a base64 string, when I decode this string this appears to be a binary object. Is that right?

How should be used inAppPurchase.getReceipt()?

jbgomez21 avatar Oct 14 '17 20:10 jbgomez21

As I tried with this code. Subscription creation is done. But please help me out how to check its status.

this.iap
        .getProducts([CUSTOMER_SUBSCRIPTION])
          .then((products) => {
              console.log('products',products);
              this.products = products;
            this.iap
              .subscribe(CUSTOMER_SUBSCRIPTION)
              .then((response) => {
                console.log("response after payment",response);
              
                    this.iap
                    .getReceipt()
                      .then((res) =>{
                        console.log('reciepts',res);
                      })
                   
              })
              .catch((err) => {console.log("buy",err);})
            
          }, Error => {})
        .catch((err) => {
          console.log(err);
        });

As In response of iap.subscribe() function ,i gor receipt and transationID. But how should I check that subscription is active or expired for that particular user?

komalW21 avatar Nov 30 '17 14:11 komalW21

Hi @komalW21 , Did you solve this problem.I too facing the same problem with auto-renewable subscription. Thanks.

akhilsanker avatar Dec 21 '17 11:12 akhilsanker

Hey guys, @kristfal had a great summary of how to approach this problem. It still took me a while to figure this all out, so I wrote a post to help explain how I check for an active subscription. Hope it helps! http://scottbolinger.com/cordova-app-purchases-validating-subscriptions/

scottopolis avatar Mar 26 '18 19:03 scottopolis