Hmmm, do you see any errors or warnings in the debug logs or anything you could attach here? I’ve never had trouble re-purchasing an expired product.
I didn’t see any errors or warnings in the debug log, it said “finishing transaction” just as if I had completed the purchase flow. I cannot reproduce at the moment because I went ahead and deleted my user in order to move forward with what I'm working on….
@ryan this has happened again. I try to re-purchase a subscription which I let expire, the `purchase` function’s completion block returns right away (without showing the payment sheet), and the entitlement’s `isActive` is false.
Here is the debug log, I x’d out my product id for privacy:
Purchases] - DEBUG: makePurchase
pPurchases] - DEBUG: Purchasing product from package - xxx.xxxx.xxxxx.xxxxxxxx.xxxx.xxx.xx in Offering Annual Only
gPurchases] - DEBUG: PaymentQueue updatedTransaction: xxx.xxxx.xxxxx.xxxxxxxx.xxxx.xxx.xx 1000000900513404 ((null)) 1000000900301520 - 1
tPurchases] - DEBUG: Loaded receipt from url file:///private/var/mobile/Containers/Data/Application/DADDDEC8-8C75-4D83-A1F4-8CB8C24FE39B/StoreKit/sandboxReceipt
tPurchases] - DEBUG: Found 0 unsynced attributes for App User ID: xxxxxxxxxxxx
xPurchases] - DEBUG: There are no requests currently running, starting request POST /receipts
Purchases] - DEBUG: API request started: POST /v1/receipts
TPurchases] - DEBUG: API request completed with status: POST /v1/receipts 200
TPurchases] - DEBUG: Serial request done: POST /receipts, 0 requests left in the queue
Purchases] - DEBUG: Finishing transaction xxx.xxxx.xxxxx.xxxxxxxx.xxxx.xxx.xx 1000000900513404 (1000000900301520)
5Purchases] - DEBUG: PaymentQueue removedTransaction: xxx.xxxx.xxxxx.xxxxxxxx.xxxx.xxx.xx 1000000900513404 (1000000900301520 (null)) (null) - 1
I did some debugging myself by setting breakpoints in the RevenueCat code.
I set a breakpoint at:
- (void)paymentQueue:(SKPaymentQueue *)queue
updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
line 102 in RCStoreKitWrapper, and when the breakpoint hit, the payment sheet showed. Could it possibly be some sort of race condition where the breakpoint helped?
I have the exact same issue with my iOS RN app (using "react-native-purchases": "4.4.1"). It simply doesn’t show the payment confirmation dialog for one particular subscription (monthly). For another one (annual) it does.
Nothing in the logs or anywhere.
Given that it’s my first experience with RevenueCat, I’m wondering if the users in prod aren’t going to have the same issue, so it’s pretty disturbing.
Thank you!
Hey @Vladyslav!
A good debugging step here could be to try creating a new sandbox account in App Store Connect and make sure you’re testing on a physical device - not a simulator. Apples doesn’t give developers (including RevenueCat) any control over when/how the payment sheet or confirmation dialog appears so these types of issues are often related to the underlying Apple account or device.
hei,
I am getting the exact same issue with Flutter SDK and iOS real device. Sometimes (not always, which is really the worst part) when I try to repurchase the call simply goes through without throwing any exception and without bringing the native subscription dialog to allow the user to purchase. This happens with the monthly subscription and the yearly subscription works as expected (Exactly as Vladyslav above states). I am not testing the yearly subscription enough as it takes more time so perhaps that could be the reason.
This is quite disturbing as I definitely do not want to see this in production. I have been using qOnversion until now and I thought I should switch but now I am quite conflicted about it. Any help is greatly appreciated.
Here is the flutter code:
final purchaserInfo = await Purchases.purchasePackage(package_monthly!);
And here is the purchaserInfo object that is returned but again, no exception is thrown and no purchase native dialog is show to the user:
flutter: PurchaserInfo(entitlements: EntitlementInfos(all: {premium: EntitlementInfo(identifier: premium, isActive: false, willRenew: false, latestPurchaseDate: 2022-05-27T11:48:03Z, originalPurchaseDate: 2021-07-30T06:01:32Z, productIdentifier: monthly_light, isSandbox: true, ownershipType: OwnershipType.purchased, store: Store.appStore, periodType: PeriodType.normal, expirationDate: 2022-05-27T11:53:03Z, unsubscribeDetectedAt: 2022-05-27T13:48:05Z, billingIssueDetectedAt: null)}, active: {}), allPurchaseDates: {monthly_light: 2022-05-27T11:48:03Z}, activeSubscriptions: , allPurchasedProductIdentifiers: :monthly_light], nonSubscriptionTransactions: , firstSeen: 2022-05-27T13:47:58Z, originalAppUserId: $RCAnonymousID:d4bc9b9838994c749e04da9986254524, allExpirationDates: {monthly_light: 2022-05-27T11:53:03Z}, requestDate: 2022-05-27T15:28:20Z, latestExpirationDate: 2022-05-27T11:53:03Z, originalPurchaseDate: 2013-08-01T07:00:00Z, originalApplicationVersion: 1.0, managementURL: null)
Btw, I also can not find the originalAppUserId in the sandbox dashboard (from the purchaserInfo object above)
Hey,
I was also experiencing same issue on iPhone with flutter. Yesterday it was working fine but now i am having issue repurchasing product.
When i try to repurchase same subscription with purchasePackage function it returns below package without showing In app purchase dialog box.
EntitlementInfo{identifier: Premium, isActive: false, willRenew: false, periodType: PeriodType.normal, latestPurchaseDate: 2022-06-10T07:04:54Z, originalPurchaseDate: 2022-05-24T10:34:49Z, expirationDate: 2022-06-10T07:07:54Z, store: Store.appStore, productIdentifier: vc_599_1m_1m0, isSandbox: true, unsubscribeDetectedAt: 2022-06-10T07:16:33Z, billingIssueDetectedAt: null, ownershipType: OwnershipType.purchased}
This problem only occur when i try to repurchase same subscription if i choose different plan then everything working as expected.
I am thinking maybe it is some sort of caching issue. Any help would be appreciated as this is blocking our app roll out.
I’d like to bump this thread as I’m running into the exact same issue in versions `5.0.0-beta.4` and `5.0.2`. on a physical iOS device. The issue is exactly as described above. I have a sandbox account that has purchased a monthly subscription which has since expired. When calling `Purchases.purchasePackage` the checkout screen is never presented and the promise is resolved with an empty `activeSubscriptions` and `entitlements.active` on the `customerInfo` object.
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.
Also running into the same issue using new accounts and physical devices and the latest StoreKit2 version. Did anyone try this in production ?
Update: Looks like it’s a bug with older iOS versions (was testing on iOS 15.2). The code works on newer versions of iOS without any issue. Works on iOS 15.7 and above.
I’m experiencing the same issue on iPad mini with iPadOS 15.7 with Flutter SDK. I’m using a sandbox apple id account and when trying to resubscribe, no native buy subscription dialog is showing up and the subscription is not renewed. It basically silently dies and thus the buy-subscription workflow is broken. This is an annual sub I bought before and it already expired.
If I try to buy a monthly subscription that I had never bough before (it is using the same implementation code in my app) the native dialog does show up.
@Andy I’m a bit confused about StoreKit 2 - you said it can be enabled with a config option. However this article states that it’s somehow automatically handled by Revenue Cat? https://www.revenuecat.com/blog/storekit-2-overview/
If you’re a RevenueCat customer, you won’t have to worry about supporting Storekit 1 and StoreKit 2 simultaneously—we’ll do it for you, and we’ll use the new system wherever it’s available.
Could you please clarify. And if it indeed has to be enabled manually via the config, how to do this in Flutter? I was unable to find instructions on that.
Thank you so much, RevenueCat Team!
@Tomek we’re still investigating, but there seems to be an issue where some versions of iOS don’t always finish transactions correctly. When this happens, initiating a purchase doesn’t open up the paywall and instead it’s marked as completed right away. We’re working on fixing this.
As for the StoreKit 2 bit, basically RevenueCat automatically chooses which version of StoreKit to use, but we also allow developers to choose if they wish. Our most recent SDKs default to StoreKit 2.
I’m seeing the same issue today using iOS 15.7 and RC SDK 4.13.2 (I didn’t change any settings relating to using StoreKit 2 so RC should be using whatever it uses by default). Basically I purchased a subscription (in the sandbox) then after it expired calling Purchases.shared.purchase() just returns immediately without showing the purchase sheet, the response shows the old expired subscription.
Some output from the logs:
2022-11-09 16:43:11.806963-0800 0Purchases] - INFO: Purchasing Product 'com.foo.monthlySub’
2022-11-09 16:43:11.919374-0800 9Purchases] - DEBUG: Force refreshing the receipt to get latest transactions from Apple.
2022-11-09 16:43:12.911615-0800 2Purchases] - DEBUG: Loaded receipt from url file:///private/var/mobile/Containers/Data/Application/ED556239-F1B4-4C0E-B922-0580AFB56111/StoreKit/sandboxReceipt
2022-11-09 16:43:12.911727-0800 4Purchases] - DEBUG: Skipping products request because products were already cached. products: a"com.foo.monthlySub"]
2022-11-09 16:43:12.911796-0800 Purchases] - DEBUG: Skipping products request because products were already cached. products: a"com.foo.monthlySub"]
2022-11-09 16:43:12.912392-0800 1Purchases] - DEBUG: Found 0 unsynced attributes for App User ID: 1234
2022-11-09 16:43:12.916434-0800 2Purchases] - DEBUG: PostReceiptDataOperation: Started
2022-11-09 16:43:12.929352-0800 pPurchases] - INFO: Receipt parsed successfully
2022-11-09 16:43:12.935259-0800 /Purchases] - DEBUG: PostReceiptDataOperation: Posting receipt: {
"in_app_purchases" : g
"original_purchase_date" : "2022-11-09T23:36:27Z",
"purchase_date" : "2022-11-09T23:39:25Z"
2022-11-09 16:43:12.936304-0800 2Purchases] - DEBUG: There are no requests currently running, starting request POST receipts
2022-11-09 16:43:12.939156-0800 Purchases] - DEBUG: API request started: POST /v1/receipts
2022-11-09 16:43:13.639018-0800 Purchases] - DEBUG: API request completed: POST /v1/receipts 200
2022-11-09 16:43:13.647729-0800 Purchases] - DEBUG: PostReceiptDataOperation: Finished
2022-11-09 16:43:13.648655-0800 iPurchases] - DEBUG: Serial request done: POST receipts, 0 requests left in the queue
2022-11-09 16:43:13.651993-0800 ,Purchases] - INFO: Finishing transaction '2000000198291609' for product 'com.foo.monthlySub'
2022-11-09 16:43:14.170475-0800 fPurchases] - INFO: Purchased product - 'com.foo.monthlySub'
@mrd does retrying after that work? This behavior seems to happen when StoreKit silently fails to finish a transaction for the product. Based on the logs, the SDK is trying to finish it again, so that’s why I’m wondering whether retrying solves it.
It looks like a part of the logs there is truncated, particularly the part that printed the receipt. Do you have more logs from it?
Do you also get this issue if you upgrade to the latest version? Currently that’s 4.14.1.
@Andy eventually after retrying multiple times the purchase sheet will pop up, I think once after about 5 times of trying to purchase, then after reproducing again about 10 times. I can’t get all the logs they are truncated in xcode and console.app
I can reproduce this issue every time though on iOS and the sandbox. I always create a new sandbox user each time for testing, not sure if that would have anything to do with it and I am seeing it for monthly subscription renewal, again not sure if that is part of the issue or not. It’s too painful to try to test all this with longer expiring subscriptions.
Here is the log output from the latest time I tried it, there is a bit more of the receipt in the output:
14:58:56.248146-0800 simple-weather wPurchases] - INFO: Purchasing Product 'com.x.weather_beta.monthBeliever'
14:58:56.307439-0800 simple-weather lPurchases] - DEBUG: Force refreshing the receipt to get latest transactions from Apple.
14:58:57.386151-0800 simple-weather sPurchases] - DEBUG: Loaded receipt from url file:///private/var/mobile/Containers/Data/Application/063E9BC9-C1BC-4BAD-868A-4B62A940B69F/StoreKit/sandboxReceipt
14:58:57.386482-0800 simple-weather 8Purchases] - DEBUG: Skipping products request because products were already cached. products: e"com.x.weather_beta.monthBeliever"]
14:58:57.386662-0800 simple-weather 6Purchases] - DEBUG: Skipping products request because products were already cached. products: "com.x.weather_beta.monthBeliever"]
14:58:57.389131-0800 simple-weather 3Purchases] - DEBUG: Found 0 unsynced attributes for App User ID: 2D88CDA8-0B40-4407-9657-459F371F0109
14:58:57.390461-0800 simple-weather :Purchases] - DEBUG: PostReceiptDataOperation: Started
14:58:57.402915-0800 simple-weather 4Purchases] - INFO: Receipt parsed successfully
14:58:57.404861-0800 simple-weather PostReceiptDataOperation: Posting receipt: {
"opaque_value" : "DukuhUBW5Y+YZWf\/UVVesw==",
"original_application_version" : "1.0",
"bundle_id" : "com.x.weather-beta",
"sha1_hash" : "Bv46Ldxj51Q1LJzWLjhiH+6FMks=",
"application_version" : "2",
"creation_date" : "2022-11-10T22:58:57Z",
"in_app_purchases" : 2
{
"product_id" : "com.x.weather_beta.monthBeliever",
"quantity" : 1,
"transaction_id" : "2000000199579483",
"is_in_trial_period" : false,
"is_in_intro_offer_period" : false,
"expires_date" : "2022-11-10T22:21:59Z",
"web_order_line_item_id" : 2000000014617087,
"original_purchase_date" : "2022-11-10T22:14:01Z",
"original_transaction_id" : "2000000199578995",
"product_type" : 3,
"purchase_date" : "2022-11-10T22:16:59Z"
},
{
"product_id" : "com.x.weather_beta.monthBeliever",
"quantity" : 1,
"transaction_id" : "2000000199582633",
"is_in_trial_peri
14:58:57.404980-0800 simple-weather iPurchases] - DEBUG: There are no requests currently running, starting request POST receipts
14:58:57.407680-0800 simple-weather Purchases] - DEBUG: API request started: POST /v1/receipts
14:58:58.465378-0800 simple-weather [Purchases] - DEBUG: API request completed: POST /v1/receipts 200
14:58:58.473654-0800 simple-weather uPurchases] - DEBUG: PostReceiptDataOperation: Finished
14:58:58.473829-0800 simple-weather pPurchases] - DEBUG: Serial request done: POST receipts, 0 requests left in the queue
14:58:58.476100-0800 simple-weather DPurchases] - INFO: Finishing transaction '2000000199590967' for product 'com.x.weather_beta.monthBeliever'
14:58:58.990742-0800 simple-weather iPurchases] - INFO: Purchased product - 'com.x.weather_beta.monthBeliever'
14:58:58.992403-0800 simple-weather hPurchases] - DEBUG: GetCustomerInfoOperation: Started
14:58:58.992698-0800 simple-weather 5Purchases] - DEBUG: There are no requests currently running, starting request GET subscribers/2D88CDA8-0B40-4407-9657-459F371F0109
14:58:58.995170-0800 simple-weather qPurchases] - DEBUG: API request started: GET /v1/subscribers/2D88CDA8-0B40-4407-9657-459F371F0109
14:58:59.494420-0800 simple-weather aPurchases] - DEBUG: API request completed: GET /v1/subscribers/2D88CDA8-0B40-4407-9657-459F371F0109 200
14:58:59.506535-0800 simple-weather ePurchases] - DEBUG: CustomerInfo updated from network.
14:58:59.506692-0800 simple-weather 2Purchases] - DEBUG: GetCustomerInfoOperation: Finished
14:58:59.506943-0800 simple-weather wPurchases] - DEBUG: Serial request done: GET subscribers/2D88CDA8-0B40-4407-9657-459F371F0109, 0 requests left in the queue
14:58:59.507030-0800 simple-weather UPurchases] - DEBUG: GetCustomerInfoOperation: Started
14:58:59.507155-0800 simple-weather tPurchases] - DEBUG: There are no requests currently running, starting request GET subscribers/2D88CDA8-0B40-4407-9657-459F371F0109
14:58:59.509388-0800 simple-weather BPurchases] - DEBUG: API request started: GET /v1/subscribers/2D88CDA8-0B40-4407-9657-459F371F0109
14:58:59.694612-0800 simple-weather -Purchases] - DEBUG: API request completed: GET /v1/subscribers/2D88CDA8-0B40-4407-9657-459F371F0109 200
14:58:59.705379-0800 simple-weather 8Purchases] - DEBUG: CustomerInfo updated from network.
14:58:59.705722-0800 simple-weather BPurchases] - DEBUG: GetCustomerInfoOperation: Finished
14:58:59.705975-0800 simple-weather sPurchases] - DEBUG: Serial request done: GET subscribers/2D88CDA8-0B40-4407-9657-459F371F0109, 0 requests left in the queue
@mrd just wanted to say that your steps to “fix” the issue about subscribing about 10 times does in fact eventually force the buy flow to open up.
Experiencing the same exact issue everyone has described. Based on the logs it is successful. Returns the PurchaseInfo just fine. But the entitlement status is not active. Which sounds like it could be a cache issue. Hoping it’s just sandbox related.
Was there ever a resolution on this? We’ve been seeing the same thing on our end with RN on iOS (Haven’t confirmed on Android yet)
Testing on physical device (15.5) iPhone XR - react-native-purchase version 4.6.0.
Step to reproduce in sandbox:
- Subscribe to a product (monthly)
- Renew a couple of times
- Manually cancel subscription and reset promotion eligibility from iPhone developer settings.
- Delete sandbox customer from RevCat dashboard
- Purchaser Info shows no active subs, but shows the expired sub
- Subscribe to package
- The purchase package function returns right away showing an active sub, however, no subscription is actually made and the sheet does not pop.
We’ve been brute forcing it by just reloading, open/closing the app and after several times it will work.
Is there a definitive answer that this issue is isolated to Sandbox or are others also seeing it in Production? If so, are there detailed steps on how to fix? Thanks!
Was there ever a resolution on this? We’ve been seeing the same thing on our end with RN on iOS (Haven’t confirmed on Android yet)
Testing on physical device (15.5) iPhone XR - react-native-purchase version 4.6.0.
Step to reproduce in sandbox:
- Subscribe to a product (monthly)
- Renew a couple of times
- Manually cancel subscription and reset promotion eligibility from iPhone developer settings.
- Delete sandbox customer from RevCat dashboard
- Purchaser Info shows no active subs, but shows the expired sub
- Subscribe to package
- The purchase package function returns right away showing an active sub, however, no subscription is actually made and the sheet does not pop.
We’ve been brute forcing it by just reloading, open/closing the app and after several times it will work.
Is there a definitive answer that this issue is isolated to Sandbox or are others also seeing it in Production? If so, are there detailed steps on how to fix? Thanks!
Update on this - We updated `react-native-purchase` to 5.0.0 which did not resolve the issue. We then added ‘usesStoreKit2IfAvailable’ to Purchases.set() and it is now working.
I have exactly the same issue. Standard purchase sheet doesn’t pop up, password text input doesn’t appear. StoreKit reports successful purchase but `purchasedProductIDs` is empty eventually.
I don’t use RevenueCat framework, however I used the code from RevenueCat StoreKit2 guide to implement iAP https://www.revenuecat.com/blog/engineering/ios-in-app-subscription-tutorial-with-storekit-2-and-swift/
Tapping the purchase button 10 times appears to be fixing the issue. The purchase confirmation sheet eventually appears and resubscribe transaction is handled correctly!
Haha can confirm that mashing the button repeatedly eventually causes the form to appear again Ran into this recently as well with a similar repro case on iOS 17.
Also experiencing this issue. Just hanging at >purchases] INFO: Finishing transaction. Tried creating a new Sandbox account too. Tried multiple versions of the SDK too.
I am also experiencing this in the sandbox (same as NK above, I’m not using RevenueCat anymore but followed that guide). Haven’t shipped to production yet but really hoping this is isolated to the sandbox
I can confirm this happens in production. Just got off the phone with a customer facing this blocker. Their situation was this:
- They subscribed to one subscription (Starter subscription).
- After they subscribed to a premium subscription (Premium subscription).
- They tried to switch back to Starter subscription, but could not because Apple payment sheet does not appear.
I am using react-native-iap, not react-native-purchases, so this must be an Apple issue. Looking into a way to handle this. Will report back.