It seems that subscription status gives different results with XCode testing and Sandbox testing.
I am using StoreKit2 to implement an IAP of an autorenewable subscription. I want to determine whether the subscription has been cancelled, so that the UI reflects that the subscription will stop after the expiry date and not be renewed.
the 'willAutoRenew' property of the subscription status renewalInfo seems to do exactly what is required, and works fine in XCode testing. My setup is very similar to the StoreKit demo associated with the WWDC21 session available here:
https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api/
To demonstrate its use, add:
print(renewalInfo.willAutoRenew)
after line 79 of the SubscriptionsView in the demo project. When you run the app, and purchase a Standard Navigation assistance subscription, the console shows 'true'. If you then cancel the subscription in XCode (Debug:StoreKit:Manage Transactions), the console will show 'false' as expected
So far so good. My problem is that when I move to Sandbox testing, and cancel the subscription in another way (eg using the .manageSubscriptionsSheet view modifier, or in Settings:App Store:Sandbox Account), the willAutoRenew property remains true, even though the subscription is in fact cancelled (ie it disappears after the expiry date)
Does anyone know a workaround to determine cancellation status?
StoreKit
RSS for tagSupport in-app purchases and interactions with the App Store using StoreKit.
Post
Replies
Boosts
Views
Activity
When testing In-App Purchases in Xcode with a .storekit file, I can delete past purchase transactions, so I can re-test the purchase experience.
I've switched to using a Sandbox tester and made purchases. However, I cannot find how to delete previous purchase transactions made in the sandbox so I can re-run the tests.
Is this possible?
I'm using TestFlight to test an app with payment/subscription functionality. I created sandbox accounts in AppStore Connect accordingly to be able to test the subscriptions. I'm logged in with the sandbox account.
When I try to subscribe in the App the wrong account (this is my actual real AppleID) is used for the subscription although it is recognized that this is just a sandbox subscription.
I tried:
logging off/on into the sandbox account
creating a totally new sandbox account
trying to trigger the payment with no logged in sandbox account
The result is always: in the payment popup it is stated that the purchase account will be my original AppleID and not a sandbox account.
How can I switch the accounts? Is this a bug at Apple's side somehow?
StoreKit2 provide great API AppStore.showManageSubscription(in:) to downgrade, upgrade or cancel the user's subscription, however, can the App detect the cancellation in App? (without server to server notification)
I understand the upgrade and downgrade can be detected in Transaction.updates, but I'm not sure about the cancellation.
I want to update my label's text from Next billing date: \(date) to Expires \(date) if the user cancels the subscription in showManageSubscription(in:) sheet.
Can I implement that?
We have implementend Storekit 2 in our app, for one time purchases and subscriptions, so it is iOS15 and higher only.
Everything works fine, but now we want to add App Store promotions for our IAP's. That doesn't work because the App requires the app to implement SKPaymentTransactionObserver
How to Promote Your In-App Purchases
Make sure your app supports a delegate method in SKPaymentTransactionObserver. You can choose to customize which promoted in-app purchases a user sees on a specific device by implementing SKProductStorePromotionController.
The problem is that this observer is part of the original Storekit API and not of the new one.
What can we do to make this work with the new Storekit 2 API?
Hello,
we are facing an issue, that the Code Redemption Sheet is not continuing correctly.
Sometimes its just disabling the "Redeem" button and nothing happens for a while.
After a while the button gets enabled again and you can press the button again. Sometimes its working then, sometimes not.
Furthermore after the button action works and the payment method was chosen, the same issue can happen again. Its doing nothing for a while and you have to start again.
The app has the target SDK iOS 14 and uses SwiftUI.
We just display the Code Redemption Sheet by using this snippet:
SKPaymentQueue.default().presentCodeRedemptionSheet()
The screenshot show the "stuck" behavior. The button is disabled and nothing is happening for a while.
The code itself is fine and it is working.
Best regards,
Sebastian
I would like to programmatically keep track of offer codes that have been used.
I just configured a Test Offer Code (Reference name), which contains 500 codes (Offer Codes) to buy a 1-month subscription for 0,49€.
I was able to redeem the code and everything works, but I was expecting to receive the used code. Instead I received the Reference name in the payload from the App Store Server Notification in the field offer_code_ref_name="Test Offer Code". (expected was sth like offer_code_ref_name="JFFDS61SBJDBJ5BXJS4BX")
I would be able to identify the Reference name by the code, if it was provided, because I have the following table in my app's backend:
reference_name | code | url | expires_at | used | reserved
Test Offer Code | xadz | zzz | 31-07-2022 | t | f
Test Offer Code | asdf | *** | 31-07-2022 | f | f
The used code doesn't seem to be included in the latest receipt. How can I obtain it?
Can I somehow call App Store Connect API?
Thanks
We uploaded to App Store Connect a new app version with new subscription groups & items. Everything was approved, and we received the emails from App Store connect, but if we visit our App Store Connect account App, some of these subscription items are still "Waiting for review" for more than 4 days. It has no sense as the email informed us that the new app version and all the items had been approved. The app is online, but some subscription items are not available.
We even uploaded a new app version, it was updated, but the subscription items are still "Waiting for review".
Has anyone faced this problem? How do you solved it? We have contacted App Store Connect but it is pretty difficult to get real assistance, most of the time they reply with template email answers.
Hi, I can't get into "manage" sandbox account. I either get to a screen to put my password in. Here there is no way to click "next" or "login". (I have tried pressing "enter" on my keyboard to no effect). Or I get directly into "Cannot Connect" page. I have tried this two days in a row. I have tried turning it off and on again. I have tried logging out and in.
Device: iPhone 13 pro max, iOS: 16.0.3 (also tried the version before this)
Hello, thank you for your time. I'm using several physical devices to test IAPs in builds from xCode. Some of my test devices are logged into child accounts from my family account.
Child accounts "Ask Permission" from devices logged into adult accounts in the family. when you attempt to make a purchase. I'm hoping to be able to use these devices to test my IAPs but I get the following error after supplying the password for the sandbox account:
Unable to Ask Permission
You can't ask permission because you have signed in with iCloud and iTunes accounts that are not associated with each other.
[Environment: Sandbox]
Is there any way to make this work?
My app calls Product.SubscriptionInfo.status(for:) to get the subscription status when the app starts.
Users with multiple Apple IDs have reported that every few days they get an unpurchased status, and when I checked that, the Product.SubscriptionInfo.status(for:) result array was empty.
(When the app is restarted, Product.SubscriptionInfo.status(for:) gives the correct result.)
StoreKit.Transaction.currentEntitlements, which is executed immediately after Product.SubscriptionInfo.status(for:), seems to be getting the correct result, so I am trying to check the subscription status with this result.
Is it a bug that Product.SubscriptionInfo.status(for:) returns an empty result for the purchaser?
There is a mismatch between Product.SubscriptionInfo.status(for:) and StoreKit.Transaction.currentEntitlements.
Is it possible for a mismatch to occur?
And In such a case, which result should be adopted?
We are facing a issue of transaction mismatch between App Store server notification and subscription status api because of this we are not able to activate the expected subscription for user.
User has successfully purchased a subscription from application. On our server we got the notification with below transaction :
{
** "transactionId": "170001503839428",
"originalTransactionId": "170001503839428",**
"webOrderLineItemId": "170000681682289",
"bundleId": "com.*****",
"productId": "com.**.*",
"subscriptionGroupIdentifier": "21020104",
"purchaseDate": 1668398097000,
"originalPurchaseDate": 1668398098000,
"expiresDate": 1699934097000,
"quantity": 1,
"type": "Auto-Renewable Subscription",
"appAccountToken": "2d98c4f1-3af9-4965-89ca-0495940d1a58",
"inAppOwnershipType": "PURCHASED",
"signedDate": 1669031276395,
"environment": "Production"
}
We tried to validate the transaction using originalTransactionId (170001503839428) through subscription status api. We got below latest transaction from api having different originalTransactionId:
{
** "transactionId": "170001466326163",
"originalTransactionId": "170001466326163",**
"webOrderLineItemId": "170000661796452",
"bundleId": "com.*****",
"productId": "com.**.",
"subscriptionGroupIdentifier": "21020104",
"purchaseDate": 1665113844000,
"originalPurchaseDate": 1665113845000,
"expiresDate": 1665718644000,
"quantity": 1,
"type": "Auto-Renewable Subscription",
"inAppOwnershipType": "PURCHASED",
"signedDate": 1669036686044,
"offerType": 1,
"environment": "Production"
}
Because of this mismatch our validation is getting failed at our server.
How is it possible to get different transaction when we are providing different originalTransactionId as api parameter?
Dear team, please look into this.
I'm using the iOS simulator with a StoreKit configuration file. I can see that there have been transactions while the app has been closed, but my StoreKit 2 listener is never called with those updates to be able to finish them When I open my app from a cold start.
I've added a listener on application(_:didFinishLaunching:launchOptions:) like this:
func startObservingTransactions() {
task = Task(priority: .background) {
for await result in Transaction.updates {
if case .verified(let transaction) = result {
await transaction.finish()
}
}
}
}
But the Transaction.updates loop never gets called (have added breakpoints to check). It's only ever called when a purchase is made, or subsequent transaction renewals when the app is open. Only then it will get the previously unfinished transactions.
Steps to reproduce:
Create an app with a StoreKit config file (with sped up transactions) to purchase an item
Make a purchase then quit the app
Wait for a bit for more transactions to be made while the app is closed.
Open the app from a cold start and none of the transactions will be finished by the listener in your app. Cancel the subscription via the transaction manager.
Close and open the app from a cold start. The first transaction will be finished by the listener but none of the others will be.
In Apple's docs it says
If your app has unfinished transactions, the listener receives them immediately after the app launches
Why is this not the case?
Hi.
A couple of days ago I've released my new iOS app version update including subscription(in-app-purchase).
App is successfully updated and deployed on store but App Store Connect says subscription is still waiting-for-review, and users cannot subscribe our paid features.
(API says it's an error; invalid product id)
On App Store Connect, it says
"A subscription has been returned and is highlighted in the table below."
in subscription section.
But there's no clue what am I supposed to do next to fix this.
I even have received the E-Mail says app update and subscription is successfully reviewed.
I am so confused can anyone help me with this?
Hi there,
This may be a dumb question but I'm trying to confirm this before we go down this road. Essentially, we are looking to have one premium subscription available to users within our app. A yearly subscription and that's it.
Since our app is brand new, we are looking to offer some "early adopter pricing" where early users can sign up for premium and lock in their yearly subscription at a fraction of what we will eventually charge. Will we be able to preserve pricing for select users while also making sure that new users aren't able to access that price?
I was reading some articles and saw mention of "unpreserving users subscription pricing" so I figured there must be the functionality to preserve then?
Thanks for the help!
We started getting error code 21002 from the verifyReceipt endpoint today for any receipt passed to it:
{
"status": 21002
}
I have created a new sandbox tester, and cleared and reinstalled the application before attempting the purchase. I'm seeing this response through RevenueCat's receipt validation tool (https://www.revenuecat.com/app-store-receipt-validation/) and from a direct cURL command:
curl --location --request POST 'https://sandbox.itunes.apple.com/verifyReceipt' \
--header 'content-type: application/json' \
--data-raw '{
"receipt-data":"{RECEIPT_DATA}",
"password":"{SECRET}",
"exclude-old-transactions":"false"
}'
This was working as of yesterday, but seems to be failing for anyone who has tried today. Has anyone else run into issues with this?
The sample code provided in https://developer.apple.com/wwdc21/10114 doesn't appear to call finish() on unverified transactions, and I haven't been able to find any documentation regarding what to do with unfinished transactions. However, Apple has always emphasized the importance of finishing transactions, and since a transaction object is provided even with the unverified state, I'd love some guidance!
Problem was observed on the published App because the IAP offer code processing is only done on the published App.
I implemented the ".presentCodeRedemptionSheet()" command by tapping Offer Code button.
Then the typed in offer code was processed by this page and the offer was successfully purchased from AppStore.
After detecting the purchased status, executed "SKPaymentQueue.default().finishTransaction(transaction)".
I thought that finishTransaction() would close the offer code processing page that is not written in document. However the page for offer code processing page was still displayed and was never closed.
The only way to close the input page for offer code is to manually tapping "Cancel" button.
Since there is no way to close the offer code processing page, I added ".popToRootViewController(animated: true)" in order to close all pages and views after detection of purchased status but failed to close the offer code processing page managed by Apple.
I need to know how to programmatically close the offer code processing page invoked by ".presentCodeRedemptionSheet()".
I got no response from FeedBackAssistant and Apple Developer Technical Support.
Thank you.
Suddenly in-app purchases of already productive IAPs are failing in the production with the error code:
NSUnderlyingError=0x283b42e20 {Error Domain=ASDServerErrorDomain Code=3504 "找不到此项目。" UserInfo={NSLocalizedDescription=找不到此项目。}}}
Environment: Production
OS Version:iOS 15.6.1
I confirm that there have been no prohibited sales areas for the product
I want to know
What does Code 3504 represent?
Where can I find documentation related to error codes?
I've tried to use AppTransaction.shared / AppTransaction.refresh() to verify that my app has been purchased from the Mac App Store.
It works when testing a release build on my Mac, using a Sandbox Apple ID.
But when I submit the app for review, the reviewer says it doesn't work. The error message returned by AppTransaction is "Unable to Complete Request", which is pretty vague.
I get the same error when I try to use a real Apple ID for testing on my machine, so I have been wondering if maybe the problem is that App Review is testing a build that doesn't accept Sandbox Apple IDs?
My app doesn't have a provisioning profile, could it be that this is the problem? As a Mac app developer, I'm not sure what provisioning profiles are good for, I thought they were only useful for iOS.
Has anybody successfully submitted a Mac app that uses AppTransaction?