If I have a subscription based app that's available on iOS, Android, and the web.I use the appropriate billing systems for each platform (Apple IAP for iOS, Google Play Billing for Android, and my own system for web) What happens when a user subscribes on Android or the web, then logs into the same account on the iOS app? Am I allowed to honor that existing subscription on iOS, or am I required to have them purchase a separate subscription through Apple’s in app purchase system in order to access premium features on the iOS app?
In-App Purchase
RSS for tagOffer extra content, digital goods, and features directly within your app using in-app purchases.
Posts under In-App Purchase tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
If I have an app available on IOS/Android/Web and offer subscriptions in each (Obviously using apple IAP / Google Play Billing when in those contexts) and a user creates an account on Android / Web and pays for that subscription and then logs in with the same account on the App Store, do I need to charge them again for a new subscription, or can I use their account subscription?
问题描述:
创建苹果商品的促销优惠功能异常,查询官方接口文档,发现接口协议没有变更(协议文档:https://api.appstoreconnect.apple.com/v1/subscriptionPromotionalOffers) ,有人了解id字段的格式是什么?应该如何传值?
请求参数:
{"data":{"attributes":{"duration":"ONE_WEEK","name":"20250817_test_2055","numberOfPeriods":1,"offerCode":"20250817_test_2055","offerMode":"FREE_TRIAL"},"relationships":{"prices":{"data":[{"id":"e467f67b-3d75-4319-aa6a-adebfc9f80da","type":"subscriptionPromotionalOfferPrices"}]},"subscription":{"data":{"id":"6673898723","type":"subscriptions"}}},"type":"subscriptionPromotionalOffers"},"included":[{"id":"e467f67b-3d75-4319-aa6a-adebfc9f80da","type":"subscriptionPromotionalOfferPrices","relationships":{"territory":{"data":{"id":"AUS","type":"territories"}}}}]}
响应参数:
{
"errors" : [ {
"id" : "49d94648-0a8a-4aba-8856-72e69ac56aca",
"status" : "409",
"code" : "ENTITY_ERROR.INCLUDED.INVALID_ID",
"title" : "The provided entity id is invalid",
"detail" : "The provided included entity id 'e467f67b-3d75-4319-aa6a-adebfc9f80da' has invalid format",
"source" : {
"pointer" : "/included/0/id"
}
} ]
}
Hi, I have a .NET MAUI app which I've added subscriptions to using the Plugin.InAppBilling nuget package. When I tested on TestFlight I got an almost immediate crash. After doing some research I followed advice to add an Entitlements.plist file to Platforms > iOS with the following entry:
com.apple.developer.in-app-purchase
The distribution provisioning profile I'm using to sign my app has the App ID set to an Identifier which has "In-App Purchase" ticked, but greyed out in it's "Capabilities" section on https://developer.apple.com/. I'm not sure why it's ticked and greyed out, but I assume that means that "In-App Purchase" is enabled.
The app runs file locally but when I create an IPA file and add it to Transporter for upload to App Store Connect I get the following error:
"Validation failed (409)
Invalid Code Signing Entitlements. Your application bundle's signature contains code signing entitlements that are not supported on iOS. Specifically, key 'com.apple.developer.in-app-purchase' in 'Payload/[Removed].app/[Removed]' is not supported. (ID: [Removed])".
Here is the structure of my csproj code for creating a IPA file for iOS:
The command I use:
dotnet publish [Removed]/app.csproj -f:net9.0-ios -c:Release ^
/p:PlatformTarget=Arm64 ^
/p:RuntimeIdentifier=ios-arm64 ^
/p:ServerAddress=[Removed] ^
/p:ServerUser=[Removed] ^
/p:ServerPassword=[Removed] ^
/p:ArchiveOnBuild=true ^
/p:BuildIpa=true
I'm stuck trying to figure this out. If you could please point out any issues with what I'm doing or if you have any suggestions to resolve the problem I would very much appreciate it.
Thanks,
Ben
When redeeming a custom offer code, I'm not able to see the actual offer code ID in the Subscriber report - only the subscription offer name is present.
I'm going off of the documentation for the Promotional Offer ID column:
A code that you create for customers to enter and redeem the subscription offer.
https://developer.apple.com/help/app-store-connect/reference/subscriber-report
Is the documentation wrong? How are we supposed to measure the performance of our offer codes beyond the initial redemption?
For example, with the offer name I can see how my "Holiday Promos" offer is doing but can't see the actual performance of "BLACKFRIDAY30" vs "MOTHERSDAY30".
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect API
Tags:
In-App Purchase
Analytics & Reporting
I have implemented IAP. The purchases are successful. The refresh receipt is working fine, which then calls the requestDidFinish(_ request: SKRequest) delegate. I'm fetching the receipt url through 'Bundle.main.appStoreReceiptURL'. When I convert the receipt data in base64 string and send it to app store's sandbox api and try to validate the receipt, it fails giving status code : 21002.
I just created my first in-app purchase. I got this message:
Your first in-app purchase must be submitted with a new app version. Create your in-app purchase, then select it from the app’s In-App Purchases and Subscriptions section on the version page before submitting the version to App Review.
Once your binary has been uploaded and your first-in app purchase has been submitted for review, additional in-app purchases can be submitted from the In-App Purchases section. Learn More
However when I go to the new version of the app I am preparing to send for review. There is NO section to attach the in app purchase to that version. Its supposed to be underneath the screenshots and such but its not there no matter what
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
StoreKit
App Store Connect
In-App Purchase
I have three questions about verify receipt
I use this api (https://buy.itunes.apple.com/verifyReceipt)to verify receipt is success or not. But since last month, this interface has started to return an error(21002).
I see this document (https://developer.apple.com/documentation/appstorereceipts/verifyreceipt) say its Deprecated.
My question is, is the error suddenly returned recently because the interface has been deprecated or for some other reason? (I haven't modified my code about this recently)
2. I can not understand this document: (https://developer.apple.com/documentation/appstorereceipts/validating_receipts_on_the_device)
Does this mean that in the new version, as long as the app returns a payment success (purchaseDetails.status == PurchaseStatus.purchased), the payment is guaranteed to be successful, and my server does not need to request payment result verification from Apple's server?
3. I try to use this (https://github.com/apple/app-store-server-library-java) to get TransactionInfo, but I dont konw to get Transaction status to know is success or not.
my java server code :
AppStoreServerAPIClient client = new AppStoreServerAPIClient(encodedKey, keyId, issuerId, bundleId, environment);
TransactionInfoResponse response = client.getTransactionInfo(transactionId);
(bug i can note get transaction status, how do i konw this Transaction is success or not)
Hi,
I've been unable to successfully test in the sandbox environment for a StoreKit 2 subscription group and can't seem to find the missing piece.
I am calling the following line of code:
let products = try await Product.products(for: [subscriptionID])
Expected behavior: The product is returned in the products array.
Actual result: The array is empty
I have done the following:
Successfully tested our logic using a storekit configuration file locally in Xcode.
Created the Subscription group in App Store Connect. The subscription product is currently "Waiting for Review", but it is our first so will not be approved without being attached to a distribution build review.
Created a Sandbox user account in App Store Connect -> Users -> Sandbox
Signed into the sandbox user account in Settings -> Developer -> Sandbox Apple Account
Signed the Paid Apps Agreement for our organization
A few debugging notes:
I deleted all apps before installing from Xcode
I've tried both locally and in TestFlight builds
Restarted my device
Verified productID matches the productID in App Store Connect
I'm not sure if I'm missing something, but any help would be appreciated.
Thanks
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
App Store Connect
In-App Purchase
Hello Apple Developer Team,
We're experiencing consistent IAP approval rejections under Guideline 2.1, despite successful TestFlight verification. Here's our detailed situation:
Environment
StoreKit 1 implementation
Tested on iOS 18.5 or 18.6 devices
Sandbox environment works perfectly
Verification Steps Taken
✅ Confirmed all Product IDs match App Store Connect exactly
✅ Validated 10+ successful TestFlight transactions (attached screenshot samples)
✅ Verified banking/tax agreements are active
Objective-C Code (StoreKit1 Implementation)
- (void)buyProductId:(NSString *)pid AndSetGameOrderID:(NSString *)orderID{
if([SKPaymentQueue canMakePayments]){
if (!hasAddObserver) {
[[SKPaymentQueue defaultQueue] addTransactionObserver:_neo];
hasAddObserver = YES;
}
self.neoOrderID = orderID;
[[NSUserDefaults standardUserDefaults] setValue:orderID forKey:Pay_OrderId_Key];
self.productID = pid;
NSArray * product = [[NSArray alloc]initWithObjects:self.productID, nil];
NSSet * nsset = [NSSet setWithArray:product];
SKProductsRequest * request = [[SKProductsRequest alloc]initWithProductIdentifiers:nsset];
request.delegate = self;
[request start];
}else{
NSString * Err = @"Pembelian tidak diizinkan. Silakan aktifkan perizinan di pengaturan";
// UnitySendMessage("GameManager", "IAPPurchaseFailed", [Err UTF8String]);
return;
}
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray * product = response.products;
if ([product count] == 0)
{
[[SKPaymentQueue defaultQueue]removeTransactionObserver:_neo];
hasAddObserver = NO;
NSString * Err = [NSString stringWithFormat:@"Err = 01, Item tidak ditemukan %@",self.productID];
// UnitySendMessage("GameManager", "IAPPurchaseFailed", [Err UTF8String]);
return;
}
SKProduct * p = nil;
for (SKProduct * pro in product)
{
if ([pro.productIdentifier isEqualToString:self.productID]){
p = pro;
}else{
[request cancel];
[[SKPaymentQueue defaultQueue]removeTransactionObserver:_neo];
hasAddObserver = NO;
NSString * Err = [NSString stringWithFormat:@"Err = 02, %@",self.productID];
// UnitySendMessage("GameManager", "IAPPurchaseFailed", [Err UTF8String]);
return;
}
}
SKMutablePayment * mPayment = [SKMutablePayment paymentWithProduct:p];
mPayment.applicationUsername = [NSString stringWithFormat:@"%@",self.neoOrderID];
if(!hasAddObserver){
[[SKPaymentQueue defaultQueue] addTransactionObserver:_neo];
hasAddObserver = YES;
}
[[SKPaymentQueue defaultQueue] addPayment:mPayment];
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
[[SKPaymentQueue defaultQueue]removeTransactionObserver:_neo];
hasAddObserver = NO;
NSString * Err = [NSString stringWithFormat:@"Err = 0%ld %@", (long)error.code, self.productID];
// UnitySendMessage("GameManager", "IAPPurchaseFailed", [Err UTF8String]);
}
- (void)requestDidFinish:(SKRequest *)request{
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{
for(SKPaymentTransaction *tran in transaction){
if (SKPaymentTransactionStatePurchased == tran.transactionState){
[self completeTransaction:tran];
}else if(SKPaymentTransactionStateFailed == tran.transactionState){
[self failedTransaction:tran];
}
}
}
- (void)failedTransaction: (SKPaymentTransaction *)transaction
{
NSString * detail = [NSString stringWithFormat:@"%ld",(long)transaction.error.code];
// UnitySendMessage("GameManager", "IAPPurchaseFailed", [detail UTF8String]);
[[SKPaymentQueue defaultQueue]removeTransactionObserver:_neo];
hasAddObserver = NO;
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
NSMutableDictionary * mdic = [NSMutableDictionary dictionary];
NSString * productIdentifier = transaction.payment.productIdentifier;
NSData * _recep = nil;
NSString * _receipt = @"";
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
_recep = transaction.transactionReceipt;
_receipt = [[NSString alloc]initWithData:_recep encoding:NSUTF8StringEncoding];
} else {
_recep = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
_receipt = [_recep base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
}
NSString * gameOrderid = [transaction payment].applicationUsername;
if (gameOrderid == nil) {
gameOrderid = [[NSUserDefaults standardUserDefaults] objectForKey:Pay_OrderId_Key];
}
if(_receipt != nil && gameOrderid != nil){
mdic[@"orderid"] = gameOrderid;
mdic[@"productid"] = productIdentifier;
mdic[@"receipt"] = _receipt;
}else{
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
return;
}
NSData * data = [NSJSONSerialization dataWithJSONObject:mdic options:kNilOptions error:nil];
NSString * jsonString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
if (hasAddObserver) {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:_neo];
hasAddObserver = NO;
}
// UnitySendMessage("GameManager", "IAPPurchaseSuecess", [jsonString UTF8String]);
[self verifyReceipt:_recep completion:^(BOOL success, NSDictionary *response) {
if (success) {
NSLog(@"verify success");
// [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
[self verifySuecessDelTransactions];
}
}];
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
for(SKPaymentTransaction *tran in queue.transactions){
if (SKPaymentTransactionStatePurchased == tran.transactionState){
[self completeTransaction:tran];
}
}
}
- (void)verifySuecessDelTransactions{
SKPaymentQueue *paymentQueue = [SKPaymentQueue defaultQueue];
NSArray<SKPaymentTransaction *> *transactions = paymentQueue.transactions;
if (transactions.count == 0) {
return;
}
for (SKPaymentTransaction *transaction in transactions) {
if (transaction.transactionState == SKPaymentTransactionStatePurchased ||
transaction.transactionState == SKPaymentTransactionStateRestored) {
[paymentQueue finishTransaction:transaction];
}
}
}
Hey everyone,
I'm currently preparing an older iOS app for App Store release that includes a non-consumable In‑App Purchase using StoreKit 2. Everything works perfectly in the StoreKitTest environment inside Xcode – the product loads, the purchase flow runs, the transaction verifies.
However, when I run the same app through TestFlight, I always get the error:
❌ Product not available - mapped to
Here’s what I’ve already checked:
✅ The product ID is correct and matches what’s in App Store Connect (case-sensitive).
✅ The IAP is created in App Store Connect and includes:
Title
Product ID
Price Tier
Screenshot for review
✅ The App Store "Paid Applications" agreement is active.
✅ The app is using the correct bundle ID.
✅ I'm using Product.products(for: [productID]) from StoreKit 2.
✅ I’ve implemented fallback and retry logic (e.g. reload after delay).
✅ All IAP logic is wrapped in @MainActor and async-safe.
As the App got Rejected on Review, the IAP is also now in the Rejected Status.
Now the IAP shows status:
🟠 "Developer Action Required"
And App Review rejected the IAP with the message:
"Your first In‑App Purchase must be submitted together with a new app version."
But if I add the App to the Test again and therefore the IAP, then the app will get Rejected again for App Completeness, IAP does not work...
What am I doing wrong here? :)
Thanks a lot in advance
Cheers,
Niklas
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
StoreKit Test
App Review
StoreKit
In-App Purchase
Hi,
My app has an IAP and the view that let user to purchase is simply a ProductView. The purchase flow should be handled by the ProductView itself. I have tested the app with xcode storekit configuration, xcode run with sandbox account and also TestFlight environment as well. The purchase is triggered and the app feature is unlocked after purchase. However, I keep getting app review team feedback with the following problem:
Bug description: the purchase button is greyed out after we tapped on it, however, there's no purchase flow popped up
I have tried multiple things. Building with xcode cloud, removing the storekit configuration from the build scheme. But none can get the app review team to get through the problem.
The IAP is not available in certain region. In that case, the app will show a message. However, the app review attached an screenshot which shows the product view.
The view that allow users to purchase
if let product = store.products.first(where: { $0.id == "com.xxx.xxxxxxx" }) {
// If the product is available, show the ProductView
ProductView(id: product.id)
.productViewStyle(.compact)
} else {
// If the product is not available, show a message
Text("In-app purchase is not available in your region.")
}
The store class
@Published private(set) var products: [Product] = []
...
init() {
//To handle the parental approval flow
getUpdateTransaction()
}
func getUpdateTransaction() {
updates = Task {
for await update in StoreKit.Transaction.updates {
if let transaction = try? update.payloadValue {
await fetchActiveTransactions()
await transaction.finish()
}
}
}
}
Does anyone what can go wrong with ProductView? As this is part of the StoreKit API, I don't know what can go wrong. At least the purchase flow should be covered by it.
Also, is sandbox and TestFlight a good way to test IAP?
Thanks!
<SKPaymentQueue: 0x10629d1b0>: Payment completed with error: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={client-environment-type=Sandbox, storefront-country-code=USA, NSUnderlyingError=0x108f15c80 {Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008030-001E19361A12202E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={
"cancel-purchase-batch" = 1;
customerMessage = "Unable to process your request.";
dialog = {
defaultButton = ok;
explanation = "Please try again later.\n\n[Environment: Sandbox]";
initialCheckboxValue = 1;
isFree = 1;
"m-allowed" = 0;
message = "Unable to process your request.";
okButtonString = OK;
};
failureType = "";
"m-allowed" = 0;
metrics = {
actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy";
asnState = 0;
dialogId = "MZCommerce.SystemError";
eventType = dialog;
message = "Unable to process your re";
mtEventTime = "2025-07-30 07:08:24 Etc/GMT";
mtTopic = "xp_its_main";
options = (
OK
);
};
pings = (
);
}, NSDebugDescription=Purchase Failed Server canceled the purchase}}}
Hi!
My product SKU has been approved for Advanced Commerce API. I successfully receive a purchase pop-up with the correct information.
However, I am still having issues with completing the purchase. I always receive Unauthorize error when I confirm the purchase (subscription in my case; see the screenshot). I am using the node.js server library to sign the request. I made sure that the account is a valid account enabled for Sandbox.
Logs unfortunately don't indicate any further detail.
Thanks for your advice! We've been stuck on this for a while now and would appreciate your help.
Marek
I'm successfully using Apple subscriptions in my app, but I'm encountering SKErrorCodeDomain error 18 when trying to apply a subscription offer.
I want apply offer code first time only for subscription. Below are details of what i set in appstore and what i have tested.
Subscription Offer Details
Offer Type: For the first month
Customer Eligibility: New, Existing, and Expired Subscribers
Code Status: Active
Offer Code Creation Steps:
App Store Connect → App → Subscription → Select Subscription Product → Offer Codes → Add → Add Custom Codes
Signature Generation for Promotional Offers
I'm following Apple's documentation to generate a signature:
https://developer.apple.com/documentation/storekit/generating-a-signature-for-promotional-offers
I’ve constructed the payload as instructed:
appBundleId + '\u2063' + keyIdentifier + '\u2063' + productIdentifier + '\u2063' + offerIdentifier + '\u2063' + appAccountToken + '\u2063' + nonce + '\u2063' + timestamp
Keys and Identifiers
keyIdentifier, issuerId, and .p8 file are obtained from:
App Store Connect → Users and Access → Integrations → In-App Purchase
Test user created under:
App Store Connect → Users and Access → Sandbox → Test Accounts
Logged in with this account on the iPhone
What I’ve Tried
Verified all values used in the payload are correct
Tried both seconds and milliseconds for the timestamp (as per documentation, it should be in milliseconds)
Tried setting appAccountToken to:
a valid UUID
an empty string
not setting it at all
Used Apple’s sample code to generate a signature: https://developer.apple.com/documentation/storekit/generating-a-promotional-offer-signature-on-the-server
Verified the generated signature locally, and it validated successfully: https://developer.apple.com/documentation/storekit/generating-a-signature-for-promotional-offers#Validate-locally-and-encode-the-signature
Apple’s sample code to generate a signature
Downloaded from
const express = require('express');
const router = express.Router();
const crypto = require('crypto');
const ECKey = require('ec-key');
const secp256k1 = require('secp256k1');
const uuidv4 = require('uuid/v4');
const KeyEncoder = require('key-encoder');
const keyEncoder = new KeyEncoder('secp256k1');
const fs = require('fs');
function getKeyID() {
return "KEYIDXXXXX";
}
router.post('/offer', function(req, res) {
const appBundleID = req.body.appBundleID;
const productIdentifier = req.body.productIdentifier;
const subscriptionOfferID = req.body.offerID;
const applicationUsername = req.body.applicationUsername;
const nonce = uuidv4();
const currentDate = new Date();
const timestamp = currentDate.getTime();
const keyID = getKeyID();
const payload = appBundleID + '\u2063' +
keyID + '\u2063' +
productIdentifier + '\u2063' +
subscriptionOfferID + '\u2063' +
applicationUsername + '\u2063'+
nonce + '\u2063' +
timestamp;
// Get the PEM-formatted private key string associated with the Key ID.
// const keyString = getKeyStringForID(keyID);
// Read the .p8 file
const keyString = fs.readFileSync('./SubscriptionKey_47J5826J8W.p8', 'utf8');
// Create an Elliptic Curve Digital Signature Algorithm (ECDSA) object using the private key.
const key = new ECKey(keyString, 'pem');
// Set up the cryptographic format used to sign the key with the SHA-256 hashing algorithm.
const cryptoSign = key.createSign('SHA256');
// Add the payload string to sign.
cryptoSign.update(payload);
/*
The Node.js crypto library creates a DER-formatted binary value signature,
and then base-64 encodes it to create the string that you will use in StoreKit.
*/
const signature = cryptoSign.sign('base64');
/*
Check that the signature passes verification by using the ec-key library.
The verification process is similar to creating the signature, except it uses 'createVerify'
instead of 'createSign', and after updating it with the payload, it uses `verify` to pass in
the signature and encoding, instead of `sign` to get the signature.
This step is not required, but it's useful to check when implementing your signature code.
This helps debug issues with signing before sending transactions to Apple.
If verification succeeds, the next recommended testing step is attempting a purchase
in the Sandbox environment.
*/
const verificationResult = key.createVerify('SHA256').update(payload).verify(signature, 'base64');
console.log("Verification result: " + verificationResult)
// Send the response.
res.setHeader('Content-Type', 'application/json');
res.json({ 'keyID': keyID, 'nonce': nonce, 'timestamp': timestamp, 'signature': signature });
});
module.exports = router;
Postman request and response
Request URL: http://192.168.1.141:3004/offer
Request JSON: {
"appBundleID":"com.app.bundleid",
"productIdentifier":"subscription.product.id",
"offerID":"OFFERCODE1",
"applicationUsername":"01234b43791ea309a1c3003412bcdaaa09d39a615c379cc246f5f479760629a1"
}
Response JSON: {
"keyID": "KEYIDXXXXX",
"nonce": "f98f2cda-c7a6-492f-9f92-e24a6122c0c9",
"timestamp": 1753510571664,
"signature": "MEYCIQCnA8UGWhTiCF+F6S55Zl6hpjnm7SC3aAgvmTBmQDnsAgIhAP6xIeRuREyxxx69Ve/qjnONq7pF1cK8TDn82fyePcqz"
}
Xcode Code
func buy(_ product: SKProduct) {
let discountOffer = SKPaymentDiscount(
identifier: "OFFERCODE1",
keyIdentifier: "KEYIDXXXXX",
nonce: UUID(uuidString: "f98f2cda-c7a6-492f-9f92-e24a6122c0c9")!,
signature: "MEYCIQCnA8UGWhTiCF+F6S55Zl6hpjnm7SC3aAgvmTBmQDnsAgIhAP6xIeRuREyxxx69Ve/qjnONq7pF1cK8TDn82fyePcqz",
timestamp: 1753510571664)
let payment = SKMutablePayment(product: product)
payment.applicationUsername = "01234b43791ea309a1c3003412bcdaaa09d39a615c379cc246f5f479760629a1"
payment.paymentDiscount = discountOffer
SKPaymentQueue.default().add(payment)
}
Issue
Even following instructions to the documentation and attempting various combinations, the offer keeps failing with SKErrorCodeDomain error 18.
Has anyone else experienced this? Any suggestions as to what may be amiss or how it can be corrected?
Topic:
App & System Services
SubTopic:
Apple Pay
Tags:
Subscriptions
In-App Purchase
Apple Pay
App Store Server Library
I would like to inquire about an error that has started occurring while debugging AppStore billing. (In sandbox environment)
This error occurs after entering a password and completing the purchase process, and in this case, no completion alert appears. The error doesn't seem to depend on the purchase item, sandbox account, or device, and shows unstable behavior - sometimes succeeding and sometimes failing.
Additionally, this error started occurring after special debugging where the network was disconnected during the purchase process. Moreover, the same error occurs in the TestFlight version of our already released normal (supposedly) version.
I think this might be a sandbox-specific error where the system has temporarily become unstable, but what do you think? If so, how can I resolve this issue?
I would appreciate your insights on the cause and appropriate response.
Error details below:
<SKPaymentQueue: 0x283b3d070>: Payment completed with error: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={NSUnderlyingError=0x28364d770 {Error Domain=AMSErrorDomain Code=305 "Purchase Failed" UserInfo={NSLocalizedDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={
"cancel-purchase-batch" = 1;
customerMessage = "Unauthorized_message";
failureType = "";
"m-allowed" = 0;
pings = (
);
}, NSLocalizedFailureReason=Server canceled the purchase}}, storefront-country-code=JPN, client-environment-type=Sandbox}
Received error that does not have a corresponding StoreKit Error: Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase
More details:
Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={
"cancel-purchase-batch" = 1;
customerMessage = "Unable to process your request.";
dialog = {
defaultButton = ok;
explanation = "Please try again later.\n\n[Environment: Sandbox]";
initialCheckboxValue = 1;
isFree = 1;
"m-allowed" = 0;
message = "Unable to process your request.";
okButtonString = OK;
};
failureType = "";
"m-allowed" = 0;
metrics = {
actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy";
asnState = 0;
dialogId = "MZCommerce.SystemError";
eventType = dialog;
message = "Unable to process your re";
mtEventTime = "2025-07-28 12:34:22 Etc/GMT";
mtTopic = "xp_its_main";
options = (
OK
);
};
pings = (
);
}, NSDebugDescription=Purchase Failed Server canceled the purchase}
Received error that does not have a corresponding StoreKit Error: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={client-environment-type=Sandbox, storefront-country-code=IND, NSUnderlyingError=0x1276116e0 {Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={
"cancel-purchase-batch" = 1;
customerMessage = "Unable to process your request.";
dialog = {
defaultButton = ok;
explanation = "Please try again later.\n\n[Environment: Sandbox]";
initialCheckboxValue = 1;
isFree = 1;
"m-allowed" = 0;
message = "Unable to process your request.";
okButtonString = OK;
};
failureType = "";
"m-allowed" = 0;
metrics = {
actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy";
asnState = 0;
dialogId = "MZCommerce.SystemError";
eventType = dialog;
message = "Unable to process your re";
mtEventTime = "2025-07-28 12:34:22 Etc/GMT";
mtTopic = "xp_its_main";
options = (
OK
);
};
pings = (
);
}, NSDebugDescription=Purchase Failed Server canceled the purchase}}}
Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={client-environment-type=Sandbox, storefront-country-code=IND, NSUnderlyingError=0x1276116e0 {Error Domain=AMSErrorDomain Code=305 "Purchase Failed Server canceled the purchase" UserInfo={AMSFailureReason=Server canceled the purchase, AMSURL=https://sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy?guid=00008110-000A4DC10E51401E, AMSDescription=Purchase Failed, AMSStatusCode=200, AMSServerPayload={
"cancel-purchase-batch" = 1;
customerMessage = "Unable to process your request.";
dialog = {
defaultButton = ok;
explanation = "Please try again later.\n\n[Environment: Sandbox]";
initialCheckboxValue = 1;
isFree = 1;
"m-allowed" = 0;
message = "Unable to process your request.";
okButtonString = OK;
};
failureType = "";
"m-allowed" = 0;
metrics = {
actionUrl = "sandbox.itunes.apple.com/WebObjects/MZBuy.woa/wa/inAppBuy";
asnState = 0;
dialogId = "MZCommerce.SystemError";
eventType = dialog;
message = "Unable to process your re";
mtEventTime = "2025-07-28 12:34:22 Etc/GMT";
mtTopic = "xp_its_main";
options = (
OK
);
};
pings = (
);
}, NSDebugDescription=Purchase Failed Server canceled the purchase}}}
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit Test
StoreKit
In-App Purchase
i want to make purchase for app subscription (recurring payment)
but it showing debit card "not accepted by app"
why is that
I implemented consumable in-app purchases in an iPhone app using StoreKit's ProductView().
When I tap the payment button in ProductView(), I am taken to the payment screen and once the payment is completed, the desired code appears to be executed, so there doesn't seem to be a problem, but when I tap the payment button in ProductView() again, the desired code is executed without being taken to the payment screen.
So one payment can be used any number of times.
I thought I wrote it exactly according to the reference, but
will it be okay in a production environment?
Is there any code that is necessary?
We have some users who have upgraded to iOS 26 beta3. Currently, we observe that when these users make in-app purchases, our code calls [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; method, and we clearly receive the successful removal callback in the delegate method - (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray<SKPaymentTransaction *> *)transactions. However, when users click on products with the same productId again, the method - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions still returns information about previously removed transactions, preventing users from making further in-app purchases.