Post not yet marked as solved
Hi,
We signed up to register for skAdNetwork id as an ad network (SDK) almost two months ago but never got a reply from Apple. Is there a way to check what's going on?
Thanks
Omri (Taboola)
Post not yet marked as solved
My app us running in debug mode and I want to display rating popup after user finishes payment and then proceeds further.
However If user chooses apple pay then prompt is showing up every time. but if he selects credit/debit card then it doesn't. We are using Braintree service for payments.
There is a common screen after payment on which SKStoreReviewController.requestReview api is called.
This issue sounds strange but still unresolved.
Post not yet marked as solved
Can't create a sandbox test use, by warning that has a simple password. no matter how strong the password I used. Including 1 punctuation , 1 Upper, 1 Lower, 1 Special and at least 1 number, more than 8 characters. It still gave an error of a simple password and i can be easily guessed.
Post not yet marked as solved
My app only offers consumable in-app purchase products.
I can successfully purchase a product once but when I try to purchase it again, a popup "This In-App purchase has already been bought. It will be restored for free." appears and the first transaction is restored: the payment queue delegate is notified that a new transaction (with the same identifier as the successful transaction) is updated to the purchased state. I never get a purchased transaction with a new identifier and hence I consider that the purchase failed.
Also, each time the app is put in foreground again or at startup, the payment queue delegate is notified that a transaction has been updated (as if it had never been finished). Even though the app properly finishes the transaction each time.
Side notes: I guarantee that all purchased or failed transactions are finished (confirmed by the removedTransactions SKPaymentQueueDelegate method being called each time). I even tried to call finishTransaction from the main thread with no success.
Right before the subsequent purchase attempts, the transactions queue is empty.
I'm also pretty sure I was able to purchase several times the same product last week, with no change in code (same app version from Testflight).
I observe this behaviour when building the app with Xcode or when distributed via Testflight. It has not been published yet so I cannot check how it behaves in the Production environment.
Do you have any clue on what's going on? Could it be a side effect of using the Sandbox environment?
Thanks for your help,
Aurélien.
In the session on StoreKit 2 (which looks amazing!), the presenter says:
In fact, if your app is running when a purchase is made on another device, you'll be notified about the new transaction.
This seems to mean that when an app uses the listener API to be notified of transactions, it will get transactions that happened on other devices.
My app offers purchases across other platforms in addition to iOS, and when a purchase happens we register it with our own account system. If a user has the app running on both their iPad and iPhone and makes a purchase on the phone, if the iPad gets notified of it the same way it would of a purchase made on the iPad, both devices will try to report it to our system. This seems undesirable.
What's the recommended approach here? Should we just make sure our system will disregard duplicate transaction reports? Or is there a way to know whether a transaction originated on this device? I don't see a property on the transaction type that looks like it could accomplish this. Maybe the deviceVerification properties? But that's seems more like the new edition of transaction receipt verification - failing that check would presumably mean that the purchase is invalid, not that it didn't happen on this device...?
Post marked as Apple Recommended
Following the sample code from the session, I received errors when verifying the renewal info:
[Default] [StoreKit] Failed to verify certificate chain due to client recoverable failure:
Error Domain=NSOSStatusErrorDomain Code=-67843 "“Test Apple Root CA - G3” certificate is not trusted" UserInfo={NSLocalizedDescription=“Test Apple Root CA - G3” certificate is not trusted, NSUnderlyingError=0x2800835d0 {Error Domain=NSOSStatusErrorDomain Code=-67843 "Certificate 2 “Test Apple Root CA - G3” has errors: Root is not trusted;" UserInfo={NSLocalizedDescription=Certificate 2 “Test Apple Root CA - G3” has errors: Root is not trusted;}}}
[Default] [StoreKit] Failed to verify signature for subscription status, will assume invalid:
failedToVerifyCertificateChain
Here's the code I'm using for getting subscription status
@MainActor
func subscriptionStatus() async -> (Product, Product.SubscriptionInfo.Status)? {
do {
// This app has only one subscription group so products in the subscriptions
// array all belong to the same group. The statuses returned by
// `product.subscription.status` apply to the entire subscription group.
guard let product = subscriptions.first,
let statuses = try await product.subscription?.status else {
return nil
}
var highestSubscriptionStatus: (product: Product, status: Product.SubscriptionInfo.Status)?
for status in statuses {
switch status.state {
case .expired, .revoked:
continue
default:
let renewalInfo = try checkVerified(status.renewalInfo)
guard let newSubscription = subscriptions.first(where: { $0.id == renewalInfo.currentProductID }) else {
continue
}
guard let currentProduct = highestSubscriptionStatus?.product else {
highestSubscriptionStatus = (newSubscription, status)
continue
}
let highestTier = tier(for: currentProduct.id)
let newTier = tier(for: renewalInfo.currentProductID)
if newTier > highestTier {
highestSubscriptionStatus = (newSubscription, status)
}
}
}
return highestSubscriptionStatus
} catch {
print("Could not update subscription status \(error)")
return nil
}
}
I'm running this on a real device without the storekit configuration file. Is this a known issue or am I missing something to get this working?
Thanks
Post not yet marked as solved
Hi,
I have been testing StoreKit 2. I'm trying to query for available subscription products by using the following query code as per the document. I have configured the in-app purchases with subscriptions in appstoreconnect. The request query keeps throwing an error.
Would appreciate some help.
Query Code
let productIdentifiers: Set = ["monthly_subscription", "yearly_subscription", "family_monthly_subscription", "family_yearly_subscription"]
async {
do {
let _subscribableProducts = try await Product.request(with: productIdentifiers)
self.subscribableProducts = _subscribableProducts
}
catch {
print("Something went wronge \(error)")
}
}
Error thrown
systemError(Error Domain=ASDErrorDomain Code=507 "Error decoding response" UserInfo={NSLocalizedDescription=Error decoding response, NSLocalizedFailureReason=Could not decode media products response})
Post not yet marked as solved
While reviewing our app to prepare for macOS Monterey, I noticed an error when restoring purchased subscriptions. The error is issued via the following log method:
- (void)paymentQueue:(SKPaymentQueue*)queue restoreCompletedTransactionsFailedWithError:(NSError*)error
The error is the following:
Error Domain=SKErrorDomain Code=0 "UNKNOWN_ERROR" UserInfo={NSLocalizedDescription=UNKNOWN_ERROR, NSUnderlyingError=0x600003c9b690 {Error Domain=ASDErrorDomain Code=950 "Unhandled exception" UserInfo={NSLocalizedDescription=Unhandled exception, NSLocalizedFailureReason=An unknown error occurred}}}
Is this error known? Has the API for macOS Monterey changed? How can we solve that issue?
Post not yet marked as solved
Bundle.main.appStoreReceiptURL always returns nil with below error message:
[db] _LSSchemaConfigureForStore failed with error Error Domain=NSOSStatusErrorDomain Code=-10817 "(null)" UserInfo={_LSFunction=_LSSchemaConfigureForStore, ExpectedSimulatorHash={length = 32, bytes = 0x8ef2fca0 cb757e35 1fb11cc9 d1e458ff ... d9788ba4 1dfbfe07 }, _LSLine=405, WrongSimulatorHash={length = 32, bytes = 0xd75c7f04 33d0d527 a961c083 c51869b1 ... 5e4b01fe 8ff2f37f }}
Both in Xcode 12.5 and Xcode 13.0 beta (13A5154h).
Any help would be appreciated.
We have enabled family sharing for our in-app purchases in AppStore connect.
From several customers we received feedback that their purchases are not available on their family members devices.
If the family members want to purchase the product, an AppStore pop-up will tell them that a family member has made the purchase and they will get it for free. Then the purchase cannot proceed. This makes sense.
I have investigated the appstore receipts of the customers reporting issues, and it turns out that these receipts do not contain the purchases of the other family members. Refreshing the receipt via SKReceiptRefreshRequest does not solve the issue.
Because the purchases of the other family members do not show up in the receipt, the app does not unlock the content and the user is displayed the not-functioning purchase button.
Sometimes customers also report that one in-app purchase is family shared but others (for which we enabled family sharing) not.
Any people familiar with this issues with family sharing of in-app purchases? Is there a solution?
Post not yet marked as solved
I'm trying to test a declined "Ask to buy" transaction and it runs but I'm getting a result I didn't expect: after the decline, the transaction's status shows as .pending, not .failed, which is what my mental model of the transaction cycle expects.
Here's the test code:
func testAskToBuyThenDecline() throws {
let session = try SKTestSession(configurationFileNamed: "Configuration")
// We clear out all the old transactions before doing this transaction
session.clearTransactions()
// Make the test run without human intervention
session.disableDialogs = true
// Set AskToBuy
session.askToBuyEnabled = true
// Make the purchase
XCTAssertNoThrow(try session.buyProduct(productIdentifier: "com.borderstamp.IAP0002"), "Couldn't buy product IAP0002")
// A new transaction should be created with the purchase status == .deferred. The transaction will remain in the deferred state until it gets approved or rejected.
XCTAssertTrue(session.allTransactions().count == 1, "Expected transaction count of 1, got \(session.allTransactions().count)")
XCTAssertTrue(session.allTransactions()[0].state == .deferred, "Deferred purchase should be .deferred. Instead, we got a status of \(session.allTransactions()[0].state)")
// Now we decline that transaction
XCTAssertNoThrow(try session.declineAskToBuyTransaction(identifier: session.allTransactions()[0].identifier), "Failed to approve AskToBuy transaction")
XCTAssertTrue(session.allTransactions()[0].state == .failed, "Declined purchase should fail. Instead, we got a status of \(session.allTransactions()[0].state.rawValue)")
// Why is transaction.state set to .pending instead of .failed?
My mental model looks like PurchaseFlow1, where there are two separate transactions that occur. The result of my unit test, though, seems to imply PurchaseFlow2. Are either of these models correct?
PurchaseFlow1
PurchaseFlow2
In the SKDemo app (sample code project associated with WWDC21 session 10114: Meet StoreKit 2, the code to handle deferred transactions is
func listenForTransactions() -> Task.Handle<Void, Error> {
return detach {
//Iterate through any transactions which didn't come from a direct call to `purchase()`.
for await result in Transaction.updates {
do {
let transaction = try self.checkVerified(result)
//Deliver content to the user.
await self.updatePurchasedIdentifiers(transaction)
//Always finish a transaction.
await transaction.finish()
} catch {
//StoreKit has a receipt it can read but it failed verification. Don't deliver content to the user.
print("Transaction failed verification")
}
}
}
}
It seems to me the catch section should try to handle declined transactions but we don't get a transaction to handle unless we pass checkVerified. But we failed to pass checkVerified, which is how we ended up in the catch section.
I'm obviously thinking about this wrongly. Can anyone help me understand how it all actually does work?
Thanks
We try to get transaction history per this doc https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history
However, we got 404, and response details are
< HTTP/2 404
< server: daiquiri/3.0.0
< date: Mon, 19 Jul 2021 09:04:48 GMT
< content-length: 0
< x-apple-jingle-correlation-key: TROLAF3A72KS6FCSQRCVCFFJKY
< x-apple-request-uuid: 9c5cb017-60fe-952f-1452-84455114a956
< b3: 9c5cb01760fe952f145284455114a956-cdbaee3838492961
< x-b3-traceid: 9c5cb01760fe952f145284455114a956
< x-b3-spanid: cdbaee3838492961
< apple-seq: 0.0
< apple-tk: false
< apple-originating-system: CommerceGateway
< x-responding-instance: CommerceGateway:010196:::
< apple-timing-app: 3 ms
< strict-transport-security: max-age=31536000; includeSubDomains
< x-daiquiri-instance: daiquiri:45824002:st44p00it-hyhk15104701:7987:21HOTFIX14
<
Does it mean there is no related transaction history or something wrong with API usage?
Thanks
Post not yet marked as solved
We are testing in-app purchases in a sandbox environment. In doing so, we encountered a problem with the "Interrupted Purchase" section.
In the documentation, it says that "Interrupted Purchase" can be tested with steps 1-12. In fact, we can pass from 1 to 9, but at 10, we could not receive a new transaction of "SKPaymentTransactionState.purchased" in updatedTransactions. Is there something wrong with our app or sandbox environment?
Best regards and thanks in advance.
Post not yet marked as solved
We have a case to show users a message that their subscription was in Billing Retry.
Current Entitlements documentation says only active subscription transactions will be returned. Our doubt is whether the current entitlements will also provide billing retry subscriptions.
If not what is the best way to get the billing retry subscriptions?
Post not yet marked as solved
We have a case to show users a message that their subscription was in Billing Retry.
But we were unable to test it in Sandbox Environment. In the Sandbox environment, we were enabled interrupted purchase after initial purchase but that's not working as expected.
In Xcode environment tried interrupted purchase and fail transactions with error. But Nothing works for renewal transactions. These all are working as expected only for the Initial purchase.
Please provide a proper way to test the Billing Retry case.
We're validating app receipts and use the original_purchase_date and original_application_version to determine if the user is a legacy user and thus entitled to certain privileges. (We moved from paid to freemium and give legacy users free access to features now requiring a subscription.)
Now we're wondering what values the above fields have if the user purchased an app bundle (consisting of two apps).
Is the receipt for both apps the same?
If yes, which bundle_id and which original_application_version is sent in the receipt?
If not, how is original_application_version set? (According to the version of each app at purchase time?)
How is original_purchase_date set? (According to the bundle purchase date? Or the first installation date of each app? – one of the apps could be installed much later!)
Post not yet marked as solved
I've added IAP to an iOS App that includes consumables and non-consumables. I'm going though each criteria for Testing at All Stages of Development with Xcode and Sandbox and Step 10 of Testing an Interrupted Purchase is not happening.
For the transaction...
I've set everything up
I get the transactionState .failed and
I call finishTransaction for the queue (as outlined in the docs)
After accepting the agreement, the payment queue does not receive a new transaction.
Is anyone experiencing the same thing? If yes, how to do get around updating the purchase?
If I call restoreCompletedTransactions on the queue, it will pull the transaction (FYI - I am doing a single purchase on a consumable item to start).
So does this mean I need to call up the queue on my own each time an interruption appears? (as there is no way to determine if and when the user completed the interrupted transaction).
I would appreciate input and how to handle this gracefully so that I can update the UI.
Thanks!
Post not yet marked as solved
Hello!
The docs for paymentQueue(_:didRevokeEntitlementsForProductIdentifiers:) state:
Tells an observer that the user is no longer entitled to one or more family-shared purchases.
documentation link
My app does not use family sharing. But when I test StoreKit Refund, paymentQueue(_:didRevokeEntitlementsForProductIdentifiers:) called. why Is it called?
Post not yet marked as solved
We had several users whose subscription suddenly disappeared from the last week. They all got a system dialog showing the purchase was from another Apple ID when restoring purchase, and they were logged-in with exactly the same ID they used to purchase.
Is there anything wrong with StoreKit?
Post not yet marked as solved
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.