where to get TestFlight invitation redeem code ?
StoreKit
RSS for tagSupport in-app purchases and interactions with the App Store using StoreKit.
Post
Replies
Boosts
Views
Activity
Greetings for App Store Server Notifications especially sandbox (I have not tried production) it seems that that is no way to associate two transactions to their orignal subscription instance
the docs indicate webLineItemOrderId id but they are different from each subscription
the originalTransactionId is the same among all subscription instances and customers, theres originalPurchaseDate but that is not reliable becuase 2 transactions can occur on the same date what can be done here. I even tried to use it but its like the sandbox is broken with the originalPurchaseDate of one instance being the same as another. is it a bug or will things get in line once I go to production?
I am currently using the verifyReceipt method to implement subscriptions, but it has been deprecated. Do you know when this verifyReceipt method is scheduled to be closed?
https://developer.apple.com/documentation/appstorereceipts/verifyreceipt
We are programming a marketplace for digital artwork, which shall use in-app purchases. Are we allowed/supposed to create only one storekit product, which we can call "item-x" and assign a fix price of i. e. 5,00$, assuming all items are sold for 5,00$, and use this product for all items? Or shall we create one product for each item which is selled on or platform, which could be 1.000?
There are several auto-renewable subscriptions with the same 'webOrderLineItemId' value. (The 'originalTransactionId' value is the same and 'transactionId' is different.) If you look up the History API based on 'originalTransactionId', you can see that only one auto-renewable subscription with the same 'webOrderLineItemId' value is viewed. What is the criteria for looking up?
I searched History API based on 'originalTransactionId' value. However, auto-renewable subscriptions that do not match 'originalTransactionId' are also being viewed in response. What is the reason?
https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history
platform: Please let me know which platform 'Non-Apple platform' is referring to. For example, Google or Amazon? And is it correct to mean the platform that consumed the products received due to in-app purchases?
playTime: Does 'playTime' mean the time when the customer purchased the app and actually accessed the app? Or do you mean the time you accessed after the in-app purchase?
lifetimeDollarsPurchased/lifetimeDollarsRefunded: If the app has multiple accounts for that customer, is the purchased/refunded amount for all accounts?
We have a React Native application and are implementing Promotional Offers for our subscriptions. Our backend service decides what users are eligible for the offer and will send the offer and signature in the request.
The SKU, offer, and signature values are sent over the bridge to Objective-C where we then attach the discount to the payment if one exists.
When we hardcode the signature values on objective-C we get a successful purchase. When we try to use the signature parameters that were passed down we get a purchase error (SKErrorDomain: 12)
Some code snippets here:
if (offerSignature[@"offerId"] != nil) {
// convert timestamp to NSNumber
NSString *numberString = offerSignature[@"timestamp"];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
NSNumber *number = [formatter numberFromString:numberString];
productIAP.paymentDiscount = [
[SKPaymentDiscount alloc] initWithIdentifier: offerSignature[@"offerId"]
keyIdentifier: offerSignature[@"keyIdentifier"]
nonce: [[NSUUID alloc] initWithUUIDString:offerSignature[@"nonce"]]
signature: offerSignature[@"signature"]
timestamp: number];
}
Here we are adding the SKPaymentDiscount to our custom product. and later on add it to the SKMutablePayment in the following snippet
SKMutablePayment *productIAPPayment = [SKMutablePayment paymentWithProduct:productIAP.skProduct];
productIAPPayment.applicationUsername = [self hashedValueForAccountName];
if (productIAP.paymentDiscount != nil) {
productIAPPayment.paymentDiscount = productIAP.paymentDiscount;
}
When we hardcode the values using the same values our backend service sends the payment goes through. Here is a snippet of how it looks like when we hardcode the values
productIAP.paymentDiscount = [
[SKPaymentDiscount alloc] initWithIdentifier: @"offer-here"
keyIdentifier: @"keyIdentifier-here"
nonce: [[NSUUID alloc] initWithUUIDString:@"nonce-here"]
signature: @"signature-here"
timestamp: @1715303421691];
We have attached the debugger and have verified the values are correct and at this moment do not know what else we can do to get this unblocked.
购买订阅型商品,为什么回调给苹果客户端的 SKPaymentTransaction.transactionIdentifier 不在从票据验证返回的receiptDataText(票据字符串)数据集合里
苹果客户端获取到的:
SKPaymentTransaction.transactionIdentifier 苹果支付回调返回的id
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL]; // 票据URL
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL]; //票据二进制
NSString *receiptDataText = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; //票据字符串
Hi there!
I have been trying to overrideUserInterfaceStyle for SKOverlay but no luck. I tried to directly override the view controller style that presents it but it only changed the view controller and not the overlay theme.
Any help is appreciated!
I was trying to write unit test of ask to buy for SKDemo app.
Even if I set SKTestSession.askToBuyEnabled = true, I got transaction state as .purchased after I call SKTestSession.buyProduct(identifier:).
import StoreKitTest
import XCTest
final class SKDemoTests: XCTestCase {
private var session: SKTestSession!
override func setUp() async throws {
session = try .init(SKTestSession(configurationFileNamed: "Products"))
session.disableDialogs = true
session.resetToDefaultState()
session.clearTransactions()
}
func test() async throws {
session.askToBuyEnabled = true
try await session.buyProduct(identifier: "consumable.fuel.octane89")
XCTAssertEqual(session.allTransactions().first!.state, .deferred) // Gets error here. The actual state I get is .purchased
}
}
I was using Xcode 15.0.1 (15A507), Simulator iPhone 15 Pro iOS 17.0.1 (21A342)
I couldn't find the problem so I'm happy to hear any solutions.
We are currently implementing in-app purchases with auto-renewing subscriptions.
If an AccountNotFoundError is returned from the App Store Server API, is it correct for the app to stop the service offered with that subscription?
The documentation does not go into detail, so I am just checking to be sure.
https://developer.apple.com/documentation/appstoreserverapi/accountnotfounderror
Plenty of info on test IAPs in xCode. I need to test whether the user has previously purchased the product in order to adjust my business model from a paid app to an in-app-purchased subscription.
I have implemented the code from "What's New in StoreKit" found at https://developer.apple.com/wwdc22/10007?time=527 and this works. but I don't know how to create a mock purchase that I can use to validate a previous purchase. This means I have no way of testing if the code actually works with a previous purchase in place.
My question is specifically: How do I create a mock/test "purchased product" that I can use in testing this functionality?
For clarity, I have successfully test IAP IAW: https://developer.apple.com/documentation/xcode/setting-up-storekit-testing-in-xcode/
Thanks
Is there an App store server notification (V2) when the free trial period ends?
Unfortunately, I can't find any information about whether and what information I receive as an app store notification when a free trail period expires. I assumed that there would be an expired or initial buy notification, but apparently this is not the case.
Can anyone help me? Thank you!
Hello
I called the 'Get Transaction Info' API with Auto-Renewable Subscription product type transactionId.
I received a success response and called the 'Get Transaction History' API with the value 'originalTransactionId'.
The response 'transaction' of the 'Get Transaction History' API that matches the 'webOrderLineItemId' value received through the 'Get Transaction Info' API was found, but the 'transactionId' value was different.
Why is this happening?
Which of the two transactions is normal?
https://developer.apple.com/documentation/appstoreserverapi/get_transaction_info
https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history
This is a copy of a reply to this post.
https://developer.apple.com/forums/thread/722222?page=1
I'm posting as new in the hope someone might have more up-to-date information, as I'm pulling out what little hair I have left.
I'm using Storekit 2, testing in Xcode with a local Storekit config file. I have created a very minimal system to investigate this issue. I have a SwiftUI-based window using SubscriptionStoreView, and my app set up with the usual listener. I have four types of auto renewing subscription, configured in the local Storekit config file.
With my app running, I subscribe to the lowest-level subscription I offer, via the SubscriptionStoreView. Notification of the inital purchase arrives, but subsequent auto-renewals do not trigger any action in my listener for Transaction.updates. They arrive as expected in the Transaction Manager. Radio silence in my listener.
If I upgrade one subscription (via my SubscriptionStoreView) I see this reflected in the UI immediately, and also in the Transaction Manager, but the update that arrives in Transaction.updates refers to the old subscription, and has the isUpgraded flag set to false.
Also, can anyone remind me what the grey warning triangle next to entries in the Transaction Manager means. I'm assuming it means unfinished, as that's what the sidebar indicates.
Can the testing system really be this broken, or am I wildly off the mark? Unless I'm doing something fundamentally wrong this all seems extremely flakey, but happy to be proved wrong.
I find this all rather unsettling if I can't test reliably, and am concerned that I my app may end up in this situation if I use storekit 2:
https://stackoverflow.com/questions/73530849/storekit-renewal-transactions-missing-in-transaction-all-or-transaction-updates
StoreKit2 is being tested in a Sandbox environment for the purchase of consumable items.
The code being implemented is below.
let result = try? await product.purchase()
switch result {
case let .success(verification):
switch verification {
case let .verified(transaction):
let jws = verification.jwsRepresentation
let success = await purchaseItem(of: itemId, with: jws)
if success {
await transaction.finish()
return (success: true, error: nil)
} else {
return (success: false, error: .serverError)
}
case .unverified:
return (success: false, error: .unverified)
}
Assume that the verification was successful, but a server error occurred. in let success = await purchaseItem(of: itemId, with: jws), success = false
When tested in Sandbox and local environment, the first alert of purchase completion is displayed. After that, a purchase failure alert is displayed. (The purchase failure alert is displayed by the result of return (success: false, error: .serverError))
Is it proper behavior to display purchase completion once?
Is it appropriate behavior for the purchase completion to be displayed once in the production environment?
Is the billing actually occurring at this time?
Thank you in advance for your answers!
We want to have subscription that exist within user account. With Apple IAP if you buy a subscription once, it cannot be bought again for the same iCloud account. But if our user within our app logged out and created another account (app account not iCloud account) he should have ability to buy subscription for this new account.
Does Apple allow to use third-party service to implement subscriptions now (e.g. Stripe)? Because Apple IAP renewable subscription model wont work for our case.
I am reaching out regarding an issue I have encountered with the notification data I received. Here are the relevant details:
Notification Details:
Notification Type: DID_CHANGE_RENEWAL_STATUS
Subtype: AUTO_RENEW_DISABLED
Concern: I noticed an inconsistency within the provided data:
The data.signedrenewalinfo.autorenewstatus is indicated as "1," suggesting that auto-renewal is enabled.
Contrarily, the subtype field asserts that AUTO_RENEW is disabled.
I am puzzled by this contradiction. How is it possible that the autorenewstatus field indicates that auto-renew is enabled when the type specifically states the opposite?
Any insights or guidance on resolving this discrepancy would be greatly appreciated.
P.S
base on following api -> https://developer.apple.com/documentation/appstoreservernotifications
Hello, Apple Developer Team,
Recently, we have encountered some rather tricky issues regarding different transactionIds but the same appAccountToken appearing in the JSON data returned when calling the Apple API /inApps/v1/transactions/.
The situation is as follows:
We obtained the order numbers from the payment receipts provided by the customer. The customer gave us two different order numbers. The payment date is July 9, 2024.
By checking our server, we can see two different transactionIds.
However, when calling /inApps/v1/transactions/, the JSON data we receive contains the same appAccountToken.
The purchase dates for these two orders are very close to each other:
transactionId1: July 9, 2024, 21:37:06
transactionId2: July 9, 2024, 21:37:00
Additional Information:
1)The server is using App Store Server API V2.
2)The client is using StoreKit V1.
3)Environment: Production.
4)type: Consumable
This issue is not an isolated case. It occurs almost every month.
We kindly request assistance from the Apple Developer Team to help us identify and resolve this issue.
Thank you.
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?