StoreKit

RSS for tag

Support in-app purchases and interactions with the App Store using StoreKit.

StoreKit Documentation

Posts under StoreKit subtopic

Post

Replies

Boosts

Views

Activity

Multiple subscriptions of the same product
Hello, I have an app where the users can connect their vehicles to an API and record trips and so on. Currently I have one subscription, where the user can add as many vehicles as he wants. But now I want (need) to change this to one vehicle per subscription. So if the user want to add two vehicles, he need to subscribe two times to the same product. How can I handle this? Thanks, Arangoool
0
0
266
Sep ’24
How to use In-app purchase for Auto Reload?
I have an app that allows users to complete a video call and then bills them a per-minute charge for the length of the call. How can I automatically bill my app user using in-app purchase without prompting for approval? I'm using Stripe on the web to complete an automatic purchase with the user's stored credit card. How do I accomplish the same thing on the web while on Apple device (or within my app) without prompting them for approval? They've already given approval by completing the call. I am aware that I can create an in-app purchase product for the necessary "credits" but this will prompt them to complete the purchase which should instead be automatic. Thanks!
1
0
388
Sep ’24
Unable to make a sandbox purchasing with SubscriptionStoreView
Hi I'm writing my first in-app purchase app, and I'm trying to do some testing with sandbox accounts. I wrote my subscription page use SwiftUI SubscriptionStoreView. And I read the documentation it says : The sandbox account appears in Settings > App Store after the first time you use the device to attempt a purchase in a development-signed app. But I have no idea how to make a sandbox purchasing. Every time I click the subscription button it just making a purchase in xcode environment. Did I missed anything? What can I do to make a sandbox pruchasing?
2
0
476
Sep ’24
Purchase receipts are empty since today
Since today, we are receiving reports from several customers on iPadOS17.x and iPadOS18 that their app runs in 'demo' mode. This can only happen if the purchase receipt is not found and this also shows in the log file they sent us. We can also reproduce it on an officially installed version of our app, but not when run from Xcode. Is anyone else experiencing this?
1
0
411
Oct ’24
question about App Store Server Notifications
I have 2 subscriptions, monthly and year first:DID_CHANGE_RENEWAL_PREF + DOWNGRADE: Customer downgrades a subscription within the same subscription group; The current subscribe is year;if i change to month;when the subscribe year was expire,Automatic renewal will change to month second:DID_CHANGE_RENEWAL_PREF+UPGRADE: Customer upgrades a subscription within the same subscription group. The current subscribe is month;if i change to year;I need to pay for the annual subscription immediately;and The subscription immediately switches to the annual third:DID_CHANGE_RENEWAL_PREF subtype is None Customer reverts to the previous subscription, effectively canceling their downgrade. what this mean? This is Test Env,month is five minutes;year is one hour ①My current subscription is an annual, startTime:2024-10-02 15:04:58 ,expireTime:2024-10-02 16:04:58 ②first DOWNGRADE to month,at 2024-10-02 15:14:16 ②after 38 minutes,I change to the annual subscribe;at 2024-10-02 15:52:00 in the end,the Notification purchaseDate 2024-10-02 15:52:00;expiresDate 2024-10-02 16:52:00; So When I get NotificationType=DID_CHANGE_RENEWAL_PREF,NotificationSubType=None,Do I need to create a new subscription for the users? Is it the latest notice of purchaseDate and expiresDate, for a year? The appleNotification Payload as follows: JWSTransactionDecodedPayload( originalTransactionId='2000000731045285', transactionId='2000000731088945', webOrderLineItemId='2000000076096676', bundleId='app.xxxx', productId='com.xxxx.365', subscriptionGroupIdentifier='21514251', purchaseDate=1727855520000, 2024-10-02 15:52:00 originalPurchaseDate=1727852699000, 2024-10-02 15:04:59 expiresDate=1727859120000, 2024-10-02 16:52:00 quantity=1, type=<Type.AUTO_RENEWABLE_SUBSCRIPTION: 'Auto-Renewable Subscription'>, rawType='Auto-Renewable Subscription', appAccountToken='fa37b7a2-2b0b-43cb-8fda-a1fb21168efe', inAppOwnershipType=<InAppOwnershipType.PURCHASED: 'PURCHASED'>, rawInAppOwnershipType='PURCHASED', signedDate=1727855526632, 2024-10-02 15:52:06 revocationReason=None, rawRevocationReason=None, revocationDate=None, isUpgraded=None, offerType=None, rawOfferType=None, offerIdentifier=None, environment=<Environment.SANDBOX: 'Sandbox'>, rawEnvironment='Sandbox', storefront='CAN', storefrontId='143455', transactionReason=<TransactionReason.PURCHASE: 'PURCHASE'>, rawTransactionReason='PURCHASE', currency='CAD', price=14990, offerDiscountType=None, rawOfferDiscountType=None) JWSRenewalInfoDecodedPayload( expirationIntent=None, rawExpirationIntent=None, originalTransactionId='2000000731045285', autoRenewProductId='com.xxxx.365', productId='com.xxxx.365', autoRenewStatus=<AutoRenewStatus.ON: 1>, rawAutoRenewStatus=1, isInBillingRetryPeriod=None, priceIncreaseStatus=None, rawPriceIncreaseStatus=None, gracePeriodExpiresDate=None, offerType=None, rawOfferType=None, offerIdentifier=None, signedDate=1727855526632, 2024-10-02 15:52:06 environment=<Environment.SANDBOX: 'Sandbox'>, rawEnvironment='Sandbox', recentSubscriptionStartDate=1727852698000, 2024-10-02 15:04:58 renewalDate=1727859120000, 2024-10-02 16:52:00 currency='CAD', renewalPrice=14990, offerDiscountType=None, rawOfferDiscountType=None, eligibleWinBackOfferIds=None)
0
0
415
Oct ’24
IAP not working in production but in TestFlight
Over 50 hours ago, we created an app update with 4 IAP:s. We use revenue cat for the payment features. All IAP:s are approved, and they were bundled into this version. Still, none of the IAP:s are working. They work as intended on TestFlight. All of them are approved. I have reached out with a case to apple developer support but have received no assistance. This is a really frustrating situation and there are no logs or any ability to understand what is going on.
1
0
298
Oct ’24
[macOS] AppTransaction questions (internet connection requirement)
Hello, I hope to find out more about how AppTransaction works on macOS, specifically about its internet connection requirements: if I use this to validate that the app is a legit purchase from the Mac App Store, I would not want it to have an always-on requirement just to validate. Does AppTransaction require the user to always be online for AppTransaction.shared ? When an app is downloaded from the Mac App Store, is the data needed for AppTransaction automatically embedded during that download, or is that data downloaded upon first launch of the app, therefore requiring an internet connection at launch time? Once the data/receipt has been downloaded by AppTransaction, is it cached until the app's next update, or is it cleared at some time during the version's life and needs to be re-downloaded, therefore requiring an internet connection at launch? Where is that receipt/data stored? Also, if you don't mind me sneaking in this non-related but sort of related question, in terms of receipt validation: Does macOS Sequoia's MAC address rotation feature affect receipt validation in any way when using IOKit? Thank you kindly, – Matthias
2
4
563
Oct ’24
[macOS] Failed to perform in-line receipt renewal for application at path <path>
Hello, I have a customer who keeps getting an "app is damaged" error for a freshly downloaded app from the Mac App Store. The logs show the following lines: standard 12:58:40.390872+0200 storeuid Receipt Validation (at.EternalStorms.Yoink) Signature Check: PASS Bundle ID Check: PASS Bundle Version Check: PASS GUID Check: PASS Expiration Check: PASS standard 12:58:40.391649+0200 storelegacy StoreLegacy: Failed to perform in-line receipt renewal for application at path /Applications/Yoink.app : '(null)' The Mac in question is running macOS 12 Monterey - curiously, the customer has another Mac with that same system version and there it works just fine. What can be done to make this work again? Thank you, – Matthias
0
0
563
Oct ’24
Subscription renewal problem
Hello! Since October 2, we have observed a problem with the renewal of subscriptions. We have not changed anything, but the receipts no longer have the information whether a valid subscription exists after the subscription was actually automatically extended. The subscription status can then be queried correctly via verify Receipt. Has anything been changed to the receipts from Apple? PS: we know that StoreKit1 is deprecated and we should switch to StoreKit2 asap.
5
0
571
Oct ’24
Apple tax for products inside game
I work as QA and we develop mobile farm game. Inside our game we have shop where user can buy coins or special prem.coins. And interface shows price with Apple Tax. Also we have battle pass, and when user want to buy battle pass the price shows without Apple tax. Anybody knows what is wrong? Pass price inside game > 9.99$ Price when user want to buy it > 11.99
0
0
284
Oct ’24
Submitting in-app purchases
I have got from App Review Team this same feedback during several months: Guideline 2.1 - Performance - App Completeness We are unable to complete the review of your app because one or more of your in-app purchase products have not been submitted for review. Next Steps To resolve this issue, please be sure to take action and submit your in-app purchases and upload a new binary in App Store Connect so we can proceed with our review. I am unable to understand and implement what is meant by the feedback: … take action … What "action" to take? … submit your in-app purchases … How to "submit in-app purchases"? I know how to submit my app but how "submitting in-app purchases”? My app contains no separate in-app purchases but several pathways through the app. The app's code contains three flags that act as signposts on user’s way through the app (Basic, Standard, Premium). The signposts are not extra content and features distributed on the App Store. They are existing parts in the app from the very beginning. They are activated according to the model user chooses (Basic, Standard, Premium) and loads down from the App Store. I try to solve the problem since several months - without success. Links offer no solution. Links say what one can do but not how to do it. What is missing are a couple of lines of code I can adapt and integrate into my app's Objective-C code. Best regards gefa
1
0
648
Oct ’24
Apple In App Purchase Validation through Server Notification
We are currently experiencing an issue where our server is not receiving Apple’s server notification (webhook) for in-app purchase confirmations. This notification is critical as it helps us confirm the purchase status and fulfill the corresponding services to the users. Despite the successful completion of purchases within the app, the lack of webhook notifications prevents us from tracking and processing these payments on our backend. In addition to resolving this issue, we are also concerned about the security aspect of receiving server notifications. Specifically, we want to ensure that any requests or notifications we receive are indeed coming from Apple, and not subject to potential man-in-the-middle (MIM) attacks. We are looking for information or best practices on how to validate that the request originates from a legitimate Apple source, ensuring the integrity of the communication and safeguarding our system from spoofed or malicious requests. Key questions: Server Notification Issue: Why might we not be receiving Apple's payment confirmation notifications, and what steps can we take to troubleshoot this issue? Request Validation: What security mechanisms or validation techniques can we implement to confirm that the server notifications are genuinely from Apple, ensuring no interference from MIM attacks? Does Apple provide any headers, tokens, or signatures in the server notification that we can use to verify the origin? Are there any known methods or configurations to ensure secure receipt of in-app purchase confirmations? We are looking for guidance and possible solutions to ensure a secure and reliable payment validation process for our in-app purchases. Any support in this regard would be highly appreciated.
0
0
465
Oct ’24
OSX Subscriptions not working in Sandbox
I am working on the integration of subscriptions in my OSX application. The subscription flow works perfectly but after the purchase it is not creating _MASReceipt folder in Contents folder of application so I cannot send the receipt to apple to verify this purchase. when I checked the logs it showing below error. Anyone who is familiar to this issue please help. Error writing receipt (13401 bytes) using privileged service to /private/var/folders/xw/yd038cts3b94qmtvlxzb1sy80000gp/T/AppTranslocation/9B8BB321-1C16-4F41-93EA-E27675791E79/d/test.app Error Domain=NSCocoaErrorDomain Code=642 "You can’t save the file “_MASReceipt” because the volume “9B8BB321-1C16-4F41-93EA-E27675791E79” is read only." UserInfo={NSFileOriginalItemLocationKey=file:///private/var/folders/xw/yd038cts3b94qmtvlxzb1sy80000gp/T/AppTranslocation/9B8BB321-1C16-4F41-93EA-E27675791E79/d/Advanced%20Uninstall%20Manager.app/Contents/_MASReceipt, NSURL=file:///private/var/folders/xw/yd038cts3b94qmtvlxzb1sy80000gp/T/AppTranslocation/9B8BB321-1C16-4F41-93EA-E27675791E79/d/abc.app/Contents/_MASReceipt, NSFileNewItemLocationKey=file:///System/Library/Caches/com.apple.appstored/abc.app/_MASReceipt/, NSUnderlyingError=0x7fdc618ded90 {Error Domain=NSCocoaErrorDomain Code=642 "You can’t save the file “_MASReceipt
0
0
353
Oct ’24
Selling the same subscription in multiple apps
I want to sell the same subscription in multiple apps so that if someone subscribes in one they show up as having a subscription in the other. Apple's documentation states "To get started, use App Store Connect to create a separate and equivalent auto-renewable subscription for each app that offers the multi-app subscription so that users can subscribe from any app." (https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/offering_a_subscription_across_multiple_apps) But I'm unable to create two subscriptions with the same Product ID. I could create two subscriptions that are equivalent but with different Product IDs that are treated as the same by our server, which would accomplish the main goal, but I believe this risks someone subscribing to both subscriptions if they do so directly through the App Store, for example using a promo code link, because they're still two different subscriptions to Apple. Thanks!
0
0
381
Oct ’24
促销优惠一直拉起不成功
<SKPaymentQueue: 0x30217e480>: Payment completed with error: Error Domain=ASDServerErrorDomain Code=3904 "优惠已不再提供" UserInfo={storefront-country-code=CHN, AMSServerErrorCode=3904, client-environment-type=Sandbox, NSLocalizedFailureReason=优惠已不再提供}
1
0
288
Oct ’24
How to use 'appStoreReceiptURL' to obtain players' paid purchase information and the purchased version
The application has changed from paid purchase to free use. We need to obtain the previous player's purchase records to unlock the paid content. //Here is the code for the client to obtain the player's payment information: NSURL * receiptURL = [[NSBundle mainBundle] appStoreReceiptURL]; if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptURL path]]){ NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL]; NSString *receiptUrlString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; NSLog(@"requestAppStoreReceipt receiptUrlString = %@", receiptUrlString); } else { // 如果凭证为空,则再发一次凭证请求 SKReceiptRefreshRequest *refreshReceiptRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:@{}]; refreshReceiptRequest.delegate = self; [refreshReceiptRequest start]; NSLog(@"requestAppStoreReceipt 如果凭证为空,则再发一次凭证请求!"); } //The following is the server-side parsing code: Path filePath = Path.of("SubscriptionKey_ABCDEFGHIJ.p8"); String encodedKey = Files.readString(filePath); Environment environment = Environment.SANDBOX; AppStoreServerAPIClient client = new AppStoreServerAPIClient(encodedKey, keyId, issuerId, bundleId, environment); String appReceipt = "MIIcs..."; ReceiptUtility receiptUtil = new ReceiptUtility(); String transactionId = receiptUtil.extractTransactionIdFromTransactionReceipt(transactionReceipt); System.out.println(transactionId); if (transactionId != null) { long now = System.currentTimeMillis(); TransactionHistoryRequest request = new TransactionHistoryRequest() .sort(TransactionHistoryRequest.Order.DESCENDING) .revoked(false) .productTypes(List.of(TransactionHistoryRequest.ProductType.CONSUMABLE)); HistoryResponse response = null; List<String> transactions = new LinkedList<>(); do { String revision = response != null ? response.getRevision() : null; response = client.getTransactionHistory(transactionId, revision, request, GetTransactionHistoryVersion.V2); transactions.addAll(response.getSignedTransactions()); } while (response.getHasMore()); Set<InputStream> rootCAs = Set.of( new FileInputStream("AppleComputerRootCertificate.cer"), new FileInputStream("AppleIncRootCertificate.cer"), new FileInputStream("AppleRootCA-G2.cer"), new FileInputStream("AppleRootCA-G3.cer") ); Long appAppleId = 1234567899L; // appAppleId must be provided for the Production environment System.out.println(transactions.size()); SignedDataVerifier signedPayloadVerifier = new SignedDataVerifier(rootCAs, bundleId, appAppleId, environment, true); for (String notificationPayload : transactions) { try { AppTransaction payload = signedPayloadVerifier.verifyAndDecodeAppTransaction(notificationPayload); System.out.println(payload); } catch (VerificationException e) { e.printStackTrace(); } } } //Return result analysis: JWSTransactionDecodedPayload{originalTransactionId='2000000641683476', transactionId='2000000641683476', webOrderLineItemId='null', bundleId='', productId='', subscriptionGroupIdentifier='null', purchaseDate=1719566962000, originalPurchaseDate=1719566962000, expiresDate=null, quantity=1, type='Consumable', appAccountToken=null, inAppOwnershipType='PURCHASED', signedDate=1728885967093, revocationReason=null, revocationDate=null, isUpgraded=null, offerType=null, offerIdentifier='null', environment='Sandbox', storefront='CHN', storefrontId='143465', transactionReason='PURCHASE', price=6000, currency='CNY', offerDiscountType='null', unknownFields=null} We have develop according to the following document on our end: https://developer.apple.com/documentation/foundation/nsbundle/1407276-appstorereceipturl#4098404 https://developer.apple.com/documentation/appstoreserverapi/get_transaction_info/ https://developer.apple.com/documentation/appstoreserverapi/data_types We would like to know if the solutions in the document can be used to solve the problems we encountered? Is there a problem with our method of parsing bills that prevents us from obtaining the necessary information?
0
0
591
Oct ’24
Issues with Subscription Validation using Apple APIs and Server Notifications
Hello, We’re implementing subscription validation on our server using Apple’s latest APIs and have run into a few issues and uncertainties. We are transitioning away from the deprecated /verifyReceipt endpoint and are now using the /inApps/v1/subscriptions/{transactionId} API. However, we have questions about how to handle transaction validation, particularly around older transactions and notification behavior in the sandbox environment. Additionally, we are facing challenges with Apple Server Notifications, especially regarding when we should expect to be notified of subscription cancellations or expirations. Below are the specific questions we hope the community can help us with: Question 1: We are using the inApps/v1/subscriptions/{transactionId} API to retrieve the subscription status and validate subscriptions on our server side, since the /verifyReceipt endpoint has been deprecated. This API always returns the last transaction for a subscription. Should we only validate the latest transaction, and is it guaranteed that even if we provide an older transaction ID, the API will always return the most up-to-date transaction information? https://developer.apple.com/documentation/appstoreserverapi/get_all_subscription_statuses/ https://developer.apple.com/documentation/appstorereceipts/verifyreceipt Question 2: In the sandbox environment, we encountered an empty response when trying to validate a transaction ID. We are attempting to validate older transactions made by the user to keep our system and store subscriptions in sync. Could you provide guidance on why this might be happening and how we can validate older transactions? Question 3: We are using Apple Server Notifications to track subscription renewals and changes. However, when a user disables auto-renewal, we do not receive a webhook notification when the subscription actually expires or is canceled. We only get notified when the user changes their renewal preferences. Should we expect a separate notification when the subscription fully expires or is canceled, or is this behavior expected? https://developer.apple.com/documentation/appstoreservernotifications/notificationtype
0
0
351
Oct ’24
Unable to add subscription
We have subscriptions for our app that are in the "waiting for review" state. The subscriptions page has the message "Your first subscription must be submitted with a new app version. Create your subscription, then select it from the app’s In-App Purchases and Subscriptions section on the version page before submitting the version to App Review." However I don't see any section in the app to enter this. It seems to be a similar issue to what is being described at https://stackoverflow.com/questions/73098652/app-store-connect-in-app-purchase-and-subscriptions-section-missing?rq=2, but I have all requirements fulfilled; all compliance and tax forms have been completed, and I have made changes to my subscriptions in response to app review. I did add these subscriptions to my app in a previous round in the approval process, and I thought that was why it wasn't appearing now. However, my app is now live and users are not seeing the subscriptions options when they try to enter the app (which had previously worked in sandbox mode)
2
0
1.1k
Oct ’24