cordova-plugin-inapppurchase
cordova-plugin-inapppurchase copied to clipboard
Check subscription is active
Does someone have some code to do this that works with both iOS and Android?
Would that show up in inAppPurchase.getProducts(productIds)?
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?
I've been working with this plugin for a while and here are my experiences on subscriptions:
- 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.
-
Do receipt validation on your backend. Just do it.
-
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.
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: 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 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 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).
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 did you find a way of checking to see if a subscription was canceled?
@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 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()
@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 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?
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()?
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?
Hi @komalW21 , Did you solve this problem.I too facing the same problem with auto-renewable subscription. Thanks.
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/