j3k0 / cordova-plugin-purchase

In-App Purchase for Cordova on iOS, Android and Windows
https://purchase.cordova.fovea.cc
1.3k stars 537 forks source link

[IOS] Expiration of paid subscription and owned attribute of IAPProduct #1000

Closed ebeling closed 4 years ago

ebeling commented 4 years ago

I develop InApp - purchase in an ionic app. For testing under ios I use sandbox and sandbox user as you described. My product is a paid subscription. For server side receipt validation I use your server (https://billing.fovea.cc). I can see at your web interface under Customer that a subscription is expired - the Expiry Date is red. In my application an expired-event is triggered. While the attribute 'isExpired' is 'true' (I can see this in Safari Developer Console) the value of the attribute 'owned' is 'true'. On your [API documentation] (https://github.com/j3k0/cordova-plugin-purchase/blob/master/doc/api.md) you say under the title Subscription: "If the validator returns a store.PURCHASE_EXPIRED error code, the subscription will automatically loose its owned status." Why is the owned attribute not false, if subscription is expired? Is this a sandbox problem?

system info

Ionic CLI: 5.4.15 Cordova CLI: 9.0.0 cordova-ios: 5.1.1 @ionic-native/in-app-purchase-2: 5.21.5 cordova-plugin-purchase: 10.0.1

Device: iPhone 11, iOS 13.3.1

Expected behavior

product.owned = false (after expiration)

Observed behavior

product.owned = true

Dexus commented 4 years ago

You know https://developer.apple.com/documentation/storekit/in-app_purchase/subscriptions_and_offers/handling_subscriptions_billing?changes=_8 ?

That maybe explain the problem that you see.

ebeling commented 4 years ago

Thank you for your reply! I've read the article. I realized, that isBillingRetryPeriod = true in my example. But how can I ask for it with Ionic api, the IAPProduct - type does not have this attribute ? And when you set the owned-attribute to 'true'? Other question: can you tell me please, what does this icons on the "Receipt"-page means: image

jfpwork commented 4 years ago

Good question, get the same. but playing with google and ionic.

The only way is to make a change in code with --livereload, and after app reload, product state become valid.

This is my first (french) days with IAP and it's heavy...

@ebeling : How do you setup to cordova-plugin-purchase: 10.0.1 ? when i follow in-app-purchase-2 i get "cc.fovea.cordova.purchase": "^8.1.1", So to add applicationUsername i have to follow application-username with version < 9

Ionic CLI: 5.4.5 Cordova CLI: 9.0.0 Cordova Platforms : android 8.1.0 "@ionic-native/in-app-purchase-2": "^5.22.0" "cc.fovea.cordova.purchase": "^8.1.1"

Best regards

ebeling commented 4 years ago

@jfpwork You can get the new version of cordova-plugin-purchase with ionic cordova plugin add cordova-plugin-purchase@10.0.1

I found out, that 'owned' - attribute will be written only once: if 'owened' - event triggered it is set to "true". It will never be set back to "false". A reload is the same like a new app start: then the store is new initialized and therefore the 'owned' - attribute is false, if subscription is expired. I don't use the 'owned' - attribute now to decide if the payed function is available, I use the 'state' - attribute:

if (product.state === this.store.OWNED) { //TODO payed function available } else if (product.state === this.store.VALID) { // TODO payed function not available }

And I call 'this.store.refresh()' every time, the user wants to use the payed function. I don't know if this is the correct way for auto renewable subscriptions.

jfpwork commented 4 years ago

@ebeling thanks, i strike out by following a similar way. Now the question is how to check and when to check the product state throw ngrx... I will test this point of view; this is outside the topic but welcome if you want to discuss about it. Take care

ebeling commented 4 years ago

@jfpwork Thanks for your link. it's very interesting. I detected another problem in praxis test: what to do, if there are no internet connection while testing subscription state and products can't be loaded from store. Is it necessary to store product information local?

jfpwork commented 4 years ago

My response is maintain a info about your customer/purchase and keep your app up to date with your server which is up to date with google

j3k0 commented 4 years ago

Hey, what's the status of your issue?

ebeling commented 4 years ago

The question is open: Why is the owned attribute not false, if subscription is expired?

steveetm commented 4 years ago

Having the very same issue. I made a sandbox purchase, it is now expired is but owned is true. What is worse that the plugin tries to verify it every minute with the server.

expiryDate: Mon Mar 30 2020 12:16:56 GMT+0200 (CEST)
isBillingRetryPeriod: false
isExpired: true
isIntroPeriod: false
isTrialPeriod: false
lastRenewalDate: Mon Mar 30 2020 12:11:56 GMT+0200 (CEST)
loaded: true
owned: true
purchaseDate: Mon Mar 30 2020 12:11:02 GMT+0200 (CEST)
renewalIntent: "Lapse"
state: "valid"
j3k0 commented 4 years ago

The server does give a few minutes of grace period to the user (sometime renewal events take some time to arrive). If you don't want to apply a grace period, you can use the condition owned && !expired.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.