Skip to main content

I noticed when testing that my subscription expires pretty quickly. Subscription acceleration is vaguely explained in the docs (more details would be super helpful). The odd thing is that if I go through with the purchase again, it appears to succeed (it does not throw a PlatformException) but then when I print the entitlements right after the purchase code (await Purchases.purchasePackage(package)) I see this:

{premium: EntitlementInfo{identifier: premium, isActive: false, willRenew: false, periodType: PeriodType.normal, latestPurchaseDate: 2021-09-22T01:58:04Z, originalPurchaseDate: 2021-09-21T20:58:05Z, expirationDate: 2021-09-22T02:58:04Z, store: Store.appStore, productIdentifier: jsdev_59_1y_1w0, isSandbox: true, unsubscribeDetectedAt: 2021-09-22T02:59:55Z, billingIssueDetectedAt: null}}

If going through with a purchase does not renew an expired subscription, what does?

(sorry for the mediocre formatting, your code formatter for this forum doesn’t support markdown and doesn’t support dart/flutter)

Hey @Tony,

Sandbox subscriptions renew very quickly so that you can test all the states of a subscription. This is expected behavior from Apple and Google. The renewal period of App Store sandbox subscriptions can be found in this subscription testing guide. We don’t have a similar guide for Android yet but the Play Store behaves the same way when it comes to sandbox subscription renewals.

Can you enable debug logs and try testing again? The logs should tell you the complete story of the purchase process, including any errors or warnings you may have missed without them. Feel free to paste them here if you’d like me to take a look at them.


@sharif I’m aware of that and read the docs. But why I can’t I purchase again after the expiration? So let’s say a subscription expires for a user. They open the app later to buy again. How do I make it possible to buy again? The issue I am experiencing is that the purchase after the subscription operation does not work.


You should be able to subscribe again without any extra code on your part since that’s managed by the app stores. If not then that’s unexpected behavior. Have you managed to reproduce it with debug logs enabled? I think we’ll be able to figure out what’s going on if you share them here.


@sharif Yes I can reproduce it with debug logs. I’ll do that again today. Should I filter the logs with “hPurchases]” and copy and paste everything? Maybe there’s sensitive stuff so I should send to you over email?


[Purchases] - DEBUG: ℹ️ Vending Offerings from cache
rPurchases] - DEBUG: ℹ️ Vending Offerings from cache
hPurchases] - DEBUG: ℹ️ makePurchase
rPurchases] - DEBUG: 💰 Purchasing product from package - jsdev_59_1y_1w0 in Offering default
gPurchases] - DEBUG: ℹ️ PaymentQueue updatedTransaction: jsdev_59_1y_1w0 1000000886954876 ((null)) 1000000885126343 - 1
8Purchases] - DEBUG: ℹ️ Loaded receipt from url file:///private/var/mobile/Containers/Data/Application/BC9BBD95-4B73-4F39-AB24-1DAE89A15C8E/StoreKit/sandboxReceipt
iPurchases] - DEBUG: ℹ️ Found 0 unsynced attributes for App User ID: ab5839a4-231c-11ec-8d24-aa665a180610
1Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request POST /receipts
nPurchases] - DEBUG: ℹ️ API request started: POST /v1/receipts
sPurchases] - DEBUG: ℹ️ API request completed with status: POST /v1/receipts 200
iPurchases] - DEBUG: ℹ️ Serial request done: POST /receipts, 0 requests left in the queue
ePurchases] - DEBUG: 💰 Finishing transaction jsdev_59_1y_1w0 1000000886954876 (1000000885126343)
_Purchases] - DEBUG: ℹ️ PaymentQueue removedTransaction: jsdev_59_1y_1w0 1000000886954876 (1000000885126343 (null)) (null) - 1

Above it is reproduced. I had a subscription that worked, one day later it expired which I think is expected because it’s sandbox, but then I go to do the purchase again and it looks successful because there is no exception thrown which is the way your Flutter SDK communicates a failed purchase (I think?).
 

Below is my log of the entitlements:

 

{premium: EntitlementInfo{identifier: premium, isActive: false, willRenew: false, periodType: PeriodType.normal, latestPurchaseDate: 2021-10-02T06:07:14Z, originalPurchaseDate: 2021-09-29T05:29:18Z, expirationDate: 2021-10-02T07:07:14Z, store: Store.appStore, productIdentifier: jsdev_59_1y_1w0, isSandbox: true, unsubscribeDetectedAt: 2021-10-02T07:10:17Z, billingIssueDetectedAt: null}}

 

So again, the question is, with this expired subscription, a user comes in and wants to buy again. How do we handle that?  Right now that purchase code looks like `await Purchases.purchasePackage(package);`


Hey @Tony!

So again, the question is, with this expired subscription, a user comes in and wants to buy again. How do we handle that?  

There isn’t anything you need to do to handle this scenario besides re-purchasing the product. 

From the logs you shared, the purchase is succeeding and the POST /receipt call to RevenueCat is successful. Do you see any other logs that indicate you may be switching the App User ID before or after a purchase? 

Another thing to try could be to create a new sandbox account in App Store Connect. Occasionally the sandbox accounts get into a funky state so it can be a good debugging step. 


I am having the exact same issue! I have not created any sandbox account on AppStoreConnect to begin with and my first trial purchase just worked in the revenue cat’s sandbox. My app is still in TestFlight state and not published. Now the subscription is expired I am unable to repurchase it. 

 

After the purchase is done, my purchaseInfo.activeSubscription length is still 0.


I have the same here but I only tried sandbox users on iOS. Does someone know if the issue is also for real users/purchases?

I also have notice that if the user purchase the subscription again from the subscriptions screen (in the system) the restore transactions will work


Having the same problem. Would be great to know if this issue is only when testing with Sandbox or if this is a concern for production


Hello!

We have the same issue.

There is no error during re-purchase:

[Purchases] - DEBUG: ℹ️ makePurchase
rPurchases] - DEBUG: 💰 Purchasing product - subscription.free3d.7.99.week
kPurchases] - DEBUG: ℹ️ PaymentQueue updatedTransaction: subscription.free3d.7.99.week 2000000067430055 ((null)) 2000000067428849 - 1
9Purchases] - DEBUG: ℹ️ Loaded receipt from url file:///private/var/mobile/Containers/Data/Application/6B1B52C0-504A-45ED-923D-752CC7D998D2/StoreKit/sandboxReceipt
oPurchases] - DEBUG: ℹ️ Found 0 unsynced attributes for App User ID: BDAF7BC3-7243-43F5-B7E0-EAB43BF9F540
-Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request POST /receipts
sPurchases] - DEBUG: ℹ️ API request started: POST /v1/receipts
ePurchases] - DEBUG: ℹ️ API request completed with status: POST /v1/receipts 200
uPurchases] - DEBUG: ℹ️ Serial request done: POST /receipts, 0 requests left in the queue
Purchases] - DEBUG: 💰 Finishing transaction subscription.free3d.7.99.week 2000000067430055 (2000000067428849)
0Purchases] - DEBUG: ℹ️ Vending PurchaserInfo from cache.

dPurchases] - DEBUG: ℹ️ PaymentQueue removedTransaction: subscription.free3d.7.99.week 2000000067430055 (2000000067428849 (null)) (null) - 1

But `EntitlementInfo` still has `isActive=false`

billingIssueDetectedAt = null
expirationDate = "2022-05-31T05:01:49Z"
identifier = "subscription.free3d.7.99.week"
isActive = false
isSandbox = true
latestPurchaseDate = "2022-05-31T04:58:49Z"
originalPurchaseDate = "2022-05-31T04:26:51Z"
ownershipType = {OwnershipType} OwnershipType.purchased
periodType = {PeriodType} PeriodType.normal
productIdentifier = "subscription.free3d.7.99.week"
store = {Store} Store.appStore
unsubscribeDetectedAt = "2022-05-31T05:01:01Z"
willRenew = false

Is this the case only with sandbox user?


For folks who’ve been seeing this lately:

We’ve had a few reports of this and it seems to be an issue with StoreKit 1. Upgrading to using an SDK version that allows you to use StoreKit 2 under the hood should help. 

The latest version of our iOS, Flutter, React-Native and Unity SDKs support StoreKit 2, by passing an extra parameter when configuring. 

 

Could you give it a shot? Let me know if you need instructions for any particular SDK. 


I just started using RevenueCat and while testing saw this issue and subsequently found this post. Once I added the parameter usesStoreKit2IfAvailable to the config (using React Native/Expo), I was able to successfully complete another subscription purchase after the first one expired.


@duggster thanks for letting us know! 


Reply