StoreKit

RSS for tag

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

Posts under StoreKit tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Family Sharing IAP Transaction IDs
Are the original_transaction_id fields in family sharing in-app purchase receipts populated with the ID of the original transaction (from the original purchaser), or does each family member get a new independent one? We're interested in supporting Family Sharing for our non-consumable in-app purchases, but since we also allow purchases to be activated on the web / other platforms, we're concerned that Family Sharing might enable somebody to create multiple accounts from a single purchase and use them independently on many more devices.
2
0
1k
Dec ’23
Can I bypass apple in-app purchase to unlock premium content in my app.
As far as I know, an app should use an In-app purchase to unlock premium content, features, or levels, etc. Apple won't allow making payments via third-party payment gateways or even providing a link to do payment other than in-app purchase is against the guidelines. Today I found an app in AppStore where they use a third-party payment gateway to unlock their premium content. Attaching the screenshot Here they are asking for credit card details and entering the card details completes their payments process (Worth mentioning they have cool UX for this!). I am wondering how did they manage to get into the store? or did apple update the policies? or is it a new feature? I am clueless. Any help is greatly appreciated.
2
0
3.2k
Jul ’23
Price Locale not available in Product
In the latest Product object we are unable to get the price locale of the current product. Even though the display price string available with currency symbol, we need to display discount price of current product by comparing with other products. Earlier in SKProduct we had price locale property to achieve this.But in latest Product object we are missing this. Is there a way to get the price locale of the current storefront?. There is a countryCode property in Storefront enum. But there is no option to create locale using country code.
3
0
3.5k
Sep ’23
Is subscription autoRenewStatus in StoreKit2 working correctly with Sandbox testing?
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?
5
0
3.7k
Aug ’23
TestFlight App uses wrong sandbox account for payment
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?
17
11
16k
Jan ’24
In-App Purchase consumable can be purchased just once
I am making an app in SwiftUI using an In-app purchase. In this app, the user should be able to buy points as many times as he wants, so I have used consumable products (in the app store connect). But when I've tried to buy them once again I got the information "This In-App purchase has already been bought. It will be restored for free". I've already searched for a way how to do it but none of the ideas worked for me. Here is my StoreManager class: import Foundation import StoreKit import SwiftUI class StoreManager : NSObject, ObservableObject, SKProductsRequestDelegate { @EnvironmentObject var authViewModel: AuthViewModel @Published var transactionState: SKPaymentTransactionState? @Published var myProducts = [SKProduct]() var request: SKProductsRequest! func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { print("Did receive response") if !response.products.isEmpty { for fetchedProduct in response.products { DispatchQueue.main.async { self.myProducts.append(fetchedProduct) } } for invalidIdentifier in response.invalidProductIdentifiers { print("Invalid identifiers found: \(invalidIdentifier)") } }else{ print("it's empty") } } func getProducts(productIDs: [String]) { let request = SKProductsRequest(productIdentifiers: Set(productIDs)) request.delegate = self request.start() } func request(_ request: SKRequest, didFailWithError error: Error) { print("Request did fail: \(error)") } func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .purchasing: transactionState = .purchasing break case .purchased: print("purchased") queue.finishTransaction(transaction) transactionState = .purchased break case .restored: print("restored") transactionState = .restored queue.finishTransaction(transaction) break case .failed, .deferred: queue.finishTransaction(transaction) transactionState = .failed break default: queue.finishTransaction(transaction) break } } } func purchaseProduct(product: SKProduct) { if SKPaymentQueue.canMakePayments() { let payment = SKPayment(product: product) SKPaymentQueue.default().add(payment) } else { print("User can't make payment.") } } func restoreProducts() { SKPaymentQueue.default().restoreCompletedTransactions() } } And I am simply using getProducts with onAppear, and purchase product on button's action. Please help me or if an answer to a similar question already exists send me a link to that thread.
3
0
1.9k
Oct ’23
StoreKit2 verification fail after app update
Hello, I have a production issue with StoreKit2. My app has a renewal subscription, people can subscribe and get their benefits. The issue occurs when I release a new version of the app, as soon as subscribed people install the update they loose their benefits because the transaction is detected as unverified by storeKit2. If they delete the app and reinstall everything works properly again until the next app update. It hard to debug because it happens only in production. It is very frustrating and I have no idea how to solve this issue. The only solution I have though of is to remove the transaction verification. Thanks for your help, Cédric
2
0
1k
Sep ’23
SKAdNetwork: Error while updating conversion value
Hello! I make use of the new iOS 15.4 SKAdNetwork.updatePostbackConversionValue feature: SKAdNetwork.updatePostbackConversionValue(0) { error in                 if let error = error {                     print(error.localizedDescription)                 }             } I am not sure why, but I always see this error message in the console: SKAdNetwork: Error while updating conversion value: Error Domain=SKANErrorDomain Code=10 "(null)" The operation couldn’t be completed. (SKANErrorDomain error 10.) Any idea what’s going on there? What does Error Code 10 mean? Couldn't find anything in the documentation about that so far. I have the NSAdvertisingAttributionReportEndpoint key with domain (https://api2.branch.io/v1/skadnetwork/advertiser_app) in my .plist.
5
0
4.9k
Oct ’23
Can an App detect a subscription's cancellation in itself?
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?
3
0
1.1k
2w
Redeeming code stucks very often after pressing "Redeem offer code"
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
31
17
7.9k
1w
Where can I get used Offer Codes from?
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
5
0
2.1k
Apr ’24
Is there a limit to how many Subscription Groups we can create in total?
We have identified Subscription Groups for our use-case based on the below note from Apple, but there is no mention of any limitations in the doc. Can we create unlimited number of Subscription Groups or is there a limit? If your app needs to offer users the ability to buy multiple subscriptions — for example, to subscribe to more than one channel in a streaming app — you can add these subscriptions to different groups. Users who buy subscriptions in multiple groups will be billed separately for each subscription. Thanks in advance!
1
2
936
May ’24
Not receiving Refund notification from app store server api
Hi, I am creating an app which provides in-app purchases to users, currently I am in testing phase of the purchase functionality and facing an issue regarding refunds. On upgrading a product that I am subscribed to (all products are auto-renewable subscriptions), I am receiving the UPGRADE notification type but I haven't yet received a REFUND notification type as the documentation suggests. I am using app store server-to-server Notifications 2.0+ with node.js as backend, I am receiving all the types of notifications just not the REFUND notification type.
4
0
880
Oct ’23
App store connect API returns 401 with production url but works with sandbox url
Hi, My app is currently in review (wasn't approved yet). I'm using the Get Transaction History API with a sandbox user transaction ID. I successfully get results when using the sandbox url (https://api.storekit-sandbox.itunes.apple.com/inApps/v1/history/{originalTransactionId}) However, when using the production url (https://api.storekit.itunes.apple.com/inApps/v1/history/{originalTransactionId}) - I'm consistently getting 401 - unauthorized, which according to the doc means something is wrong with my JWT. Should I generate my JWT differently for sandbox vs production? If not, what else could cause this issue? Thanks,
7
1
6.8k
Sep ’23
Subscriptions Status Stuck "Developer Action Needed" "Submit for Review" button grayed out in App Store Connect. Cannot submit revised app.
I have an iOS app that was rejected and I submitted a revised binary. In my case auto-renewable subscriptions were returned with the initial rejections and I didn't realize I had to add them for review again with my revised submission....so I submitted a revised binary which got rejected because the subscriptions were returned on the initial rejection. So I go to "Subscriptions" area for my app and the status is "Developer Action Needed." If I click a subscription the "Submit for Review" button is disabled. I tried making an edit to the Subscription to see if that would cause the button to become enabled but it does not. Can't figure out how I can resubmit these subscriptions for review....so my submission is stuck... Perhaps when an app with attached iAP/Subscriptions is rejected they shouldn't detach iAP/subscriptions from the app? Developers can easily not notice and submit a new build and not realize that their iAP/subscriptions are no longer attached to the build...and if App Review doesn't notice you could have an app get on the Store which potentially shows UI for non-working iAP/subscriptions. If anyone has ran into this and could help I'd appreciate it. Thanks a lot.
2
0
1k
Jul ’23
verifyReceipt in storekit v2
Hi, Currently we are using store kit api and we get the receipt which then backend validate from apple using /verifyReceipt. Now we are planning to move to store kit v2 api. But in this case, we are getting signedPayload instead of receipt. Now this signedPayload cannot be used in the /verifyReceipt. So what is the other way to validate the signedToken from apple and get the data that we get from the /verifyReceipt response. Thanks for the help!
2
2
3.9k
Oct ’23
Testing failed IAP purchase
Does anyone know how to test failed IAP flows? There is documentation here: https://developer.apple.com/documentation/storekit/in-app_purchase/testing_in-app_purchases_with_sandbox/testing_failed_in-app_purchases_and_subscription_renewals which starts with the instructions Sign in to the App Store using a Sandbox Apple ID. Go to Settings > App Store > Sandbox Account > Manage > Account Settings. Disable the Allow Purchases & Renewals setting. This setting is enabled by default. But there is no "Allow Purchases & Renewals" option (or any other option) in the Accounts settings
6
1
1.1k
Jul ’23
Cannot handle unfinished consumable in Transaction.currentEntitlements when testing Ask to Buy in Xcode
I am trying to test Ask to Buy for consumable product. When the transaction was approved, I can get verified transaction in Transaction.updates, meaning the process stops at a breakpoint in Transaction.updates. However, when I call Transaction.currentEntitlements after that, I cannot handle transaction as consumable. Am I missing anything? Here is my code. func newTransactionListenerTask() -> Task<Void, Never> { Task(priority: .background) { for await verificationResult in Transaction.updates { guard case .verified(let transaction) = verificationResult,             transaction.revocationDate == nil         else { return }         // Breakpoint stops here await refreshPurchasedProducts()         await transaction.finish()         }    } } func refreshPurchasedProducts() async { for await verificationResult in Transaction.currentEntitlements { guard case .verified(let transaction) = verificationResult else { return } switch transaction.productType { case .consumable: // This code is not called             updateConsumablePurchaseCount(productID: transaction.productID)         default:             break }     } }
3
0
1.5k
Oct ’23