Apple Pay

RSS for tag

Provide a fast, easy, and secure way for users to buy goods and services in your app or on your website using Apple Pay.

Posts under Apple Pay tag

200 Posts

Post

Replies

Boosts

Views

Activity

Apple Pay In-App Provisioning
Hello, I am following up on my previous feedback (Feedback ID: FB17175593) regarding the in-app provisioning failure for Apple Pay. In that report, I detailed errors encountered during the card addition process (notably issues related to a missing teamID and cryptographic material errors). Could you please provide an update on the investigation progress? I appreciate your assistance and look forward to your response.
1
0
168
Oct ’25
Automation on apple pay certificates
Hi! I am working on automating the Apple Pay integration process in our CI/CD pipeline and would like to confirm whether a fully automated setup is currently possible for our preproduction environment. Right now, our process is as follows: A certificate is generated for the root domain and for each individual merchant subdomain. Both certificates are manually uploaded to our preproduction servers to test and verified via HTTP. We’d like to automate this flow in GitLab CI, mainly the generation of the necessary certificates programmatically or via API. However, from my research, it seems that Apple does not currently provide an API or any support to automate this task, but I’d like to confirm this directly with you. Is there any official support or workaround for this kind of automation? If not, do you have any plans to provide it in the future? Thanks in advance for your help.
1
0
222
Oct ’25
Apple Pay integration and Merchant IDs.
Hi, We’re a franchise business with over 100 franchisees, and each franchisee has their own unique Merchant ID. We're building a single app that allows customers to place orders, and based on the selected franchisee, the payment needs to be processed through that specific franchisee’s merchant account. However, when we integrate Apple Pay and publish the app, it asks us to provide a payment gateways' Merchant ID, but we don’t use just one – we have many. How can we handle this situation? Is there a way to dynamically use multiple Merchant IDs in one app, depending on which franchisee the customer is ordering from?
1
0
140
Oct ’25
Payment not completed in Apple Pay
We have an Apple Pay account and have successfully created and verified the payment processing certificate in our Apple Developer account. When initiating an Apple Pay payment, the Apple session is created successfully with the correct data return from api , but it is not accepted with the error: “Payment not completed.” The issue occurs even though the merchant validation step works without errors. Our websites where this is happening are: https://magicdeliver.com/ https://www.pulsarmodular.com/ Could you please help us identify the cause of the issue and guide us on resolving it?
1
0
211
Oct ’25
App ID Configuration - Capabilities state inconsistency
Hello, I am experiencing an issue with the Apple Pay capability on my App ID. I have created a Merchant ID. I enabled Apple Pay in the App ID configuration and linked it to the merchant. However, sometimes when I revisit the App ID in the Apple Developer portal, the Apple Pay capability appears disabled, even though I saved it. This happens intermittently; at some times the capability is correctly shown as enabled, and other times it disappears. Context: I am using Expo Managed Workflow with EAS Build for iOS. The issue prevents the provisioning profile from including Apple Pay, which causes Stripe isPlatformPaySupported function to return false on ios devices. Attached: Screenshots of the App ID page showing Apple Pay enabled and disabled. Could you please advise why the capability is not being consistently saved, and how to ensure it stays enabled? Thank you,
2
0
306
Oct ’25
Apple Pay fractional amounts for RSD
Hello all, I’m helping a customer integrate Apple Pay, and I’m seeing a behavior I can’t fully explain. I hope someone here can help clarify whether this is expected or whether it’s a bug / misconfiguration on my side. Currency: RSD (Serbian Dinar) Amount: 3.45 RSD (two decimals) Result: Apple Pay cancels the payment automatically when the amount includes decimals, without even displaying the paymentsheet. Things I have checked: ISO 4217 defines RSD with 2 minor units, so fractional amounts like 3.45 should be valid. Processors treat RSD as a two-decimal currency. Apple’s documentation does not provide a per-currency decimal rule table. In testing, whole-number RSD amounts succeed, while fractional amounts (e.g. 3.45 RSD) fail. I did not encounter this problem with other currencies like EUR, USD. Has anyone encountered this issue before?
3
0
301
Oct ’25
ApplePaySession.applePayCapabilities() started returning applePayUnsupported in third-party browsers
We rely on ApplePaySession.applePayCapabilities() to decide whether to show the Apple Pay button. We use two different merchant IDs for non-prod/prod environments, and encountered a change in behavior where this API now returns different results. These merchant IDs are generated from a third-party provider Adyen. However, Adyen has informed us that they are unable to identify the root cause of the issue and advised us to seek assistance directly from Apple Pay support. Timeline Last known working date: 13/08/2025 Issue first noticed: 18/08/2025 Environment Details Apple Pay JS API version 1.latest Browsers Tested: Third party browsers including Chrome/139.0.0.0, Firefox/141.0 Browsers with ApplePaySession built-in (like iOS Chrome, iOS Safari, and macOS Safari) are working fine Framework Stack: Angular v18.1.3 (important) no configuration setup in Apple dev account, merchantId is generated from a third-party provider Adyen. Current Execution Flow: Apple Pay JS API script element is injected <script type="text/javascript" async="" src="https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js"></script> Triggers below to check apple pay readiness, different ${merchantId_credential} is used: await window.ApplePaySession.applePayCapabilities(`${merchantId_credential}`); (**ApplePaySession is a valid object at this point) Observed that different paymentCredentialStatus is returned // nonprod env { "paymentCredentialStatus": "applePayUnsupported" // unexpected } // prod env { "paymentCredentialStatus": "paymentCredentialStatusUnknown" } The same code is executed in each environment and the behaviour was also the same, but has changed since then. Side notes By checking the SDK’s internal code, we saw that in third-party browsers it makes an extra call to the following endpoint. Responses from this call also come back differently depending on the merchantId. When invoking below: curl -X POST \ https://smp-paymentservices.apple.com/paymentservices/v3/checkStatus/merchant/{merchantId} \ -H 'Content-Type: application/json' \ -d '{ "initiative": "web", "initiativeContext": "env_specific_domain" }' Our non-prod environment returns {"registered":false} while using prod's merchantId and domain it returns {"registered":true}. We thought the issue might be domain-related since the environments are on different domains, but so far, no luck. The main questions we're looking to resolve are: Why did the behavior change at a certain point despite no code changes? How should we approach this investigation, and what specific requests should we be making to the Adyen team? Why does the response from the call to https://smp-paymentservices.apple.com/paymentservices/v3/checkStatus/merchant/{merchantId} return different results? Perhaps this could provide a clue regarding the question above? We noticed that canMakePayments() is returning true, so we could consider using that as a workaround. Would it be safe to change the source of truth relying on canMakePayments() for displaying Apple Pay? There is a concern that this issue may also occur in our production environment, so we would appreciate assistance in understanding what is happening and finding a resolution.
4
0
529
Oct ’25
我在使用java验证apple pay支付提示401
我在对接apple pay内购,调用https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/{transactionId},一直提示401,我不知道是我对接代码的错误,还是在开发者配置有问题或者是对应的参数提供错误,排查很久,依旧提示: Server returned HTTP response code: 401 for URL: https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/xxx 请问我该如何去查找我的问题呢
0
0
171
Oct ’25
Apple Pay integration in our app
Hi, We have app in which we take donations from people and send to non-profit organisations. I have read that Apple Pay can be integrated on non profit platforms to take donations, but we are middle man, we are not non profit .. we take donations, cut our platform fees and then sent to donations to non profit orgs. My question is can we integrate Apple Pay in our iOS app to take donations from apple? as we have integrated Apple Pay on the web.
1
0
227
Oct ’25
Apple Pay pre-auth: how to not show hold amount (gas-station style) for usage-based rentals?
We’re building a usage-based rental flow. The final charge is only known after the session ends (like gas pumps). We want the same Apple Pay UX that gas stations like at a gas station has: the user does not see a pre-authorization amount up front; they only see “approved” and later the final posted amount on the statement. What we observe (gas stations / desired UX) When paying at gas station with Apple Pay (card-present), the user confirms their card (double-tap) but no pre-auth amount is shown in Wallet/notification UI. The small notification is from the bank (not the merchant) and shows only bank + merchant name, no total. After fueling ends, the final amount appears on the statement from the merchant. What happens in our flow (current behavior) Platform: Apple Pay via Stripe (Apple Pay on the Web with QR → mobile Safari Wallet sheet). When a user confirms payment, the pre-authorization amount is shown immediately to the user (appears like a charge from the user’s perspective). We want to avoid showing that amount, matching the pay-at-pump experience.
3
0
661
Oct ’25
Apple Pay JS API - applePayCapabilities no longer working
We’ve noticed that the ApplePaySession.applePayCapabilities() check has stopped working correctly in Safari over the past couple of days. Behavior observed: 1.) In Safari Private Window, paymentCredentialStatus behaves as expected and case 1 is triggered. 2.) In a normal Safari window, it always triggers case 3 (paymentCredentialsUnavailable), even when the user has active cards provisioned in Wallet. We tested across multiple devices, and the behavior is consistent. if (window.ApplePaySession) { var merchantIdentifier = 'YOUR MERCHANT IDENTIFIER'; var promise = ApplePaySession.applePayCapabilities(merchantIdentifier); promise.then(function(capabilities) { switch (capabilities.paymentCredentialStatus) { case "paymentCredentialsAvailable": // Show Apple Pay button as primary option case "paymentCredentialStatusUnknown": // Offer Apple Pay case "paymentCredentialsUnavailable": // Consider showing Apple Pay button case "applePayUnsupported": // Don’t show Apple Pay button } }) } This used to work fine until a few days ago, but now the capability check in non-private Safari windows always indicates unavailable, even with valid active cards. Has anyone else faced this issue recently? Could this be a Safari regression or a change on Apple’s side? Thanks in advance!
1
0
380
Oct ’25
ApplePay mTLS long response time
I'm calling the endpoint https://apple-pay-gateway-cert.apple.com/paymentservices with mTLS and it's taking over 15 seconds to complete the request. This is happening only when deployed through AWS. I have tried a dummy dotnet and node lambda with the same result. Wondering if anyone had the same issue. Also stack overflow post explaining the code in more depth - https://stackoverflow.com/questions/79755891/mtls-http-call-taking-over-15-seconds
1
1
229
Sep ’25
iOS 16 recurring payment configuration not reflecting in UI
We are integrating iOS 16 recurring payments in our app, everything works fine but we have a few questions Question 1 let recurringPaymentRequest = PKRecurringPaymentRequest(         paymentDescription: "Pro Membership",         regularBilling: regularBilling,         managementURL: url       ) we assume managementURL is supposed to come in the user's wallet where he/she can tap to change the recurring payment option to our backend, but in the wallet, the transaction appears without this URL and have no indication that it is a recurring payment, Can someone guide what we missed Question 2 For apps that only have apple pay on mobile, managementURL can open the app as a deep link from the Wallet app and the user can update or delete the payment method for the automatic reload payment from the app directly, Question 3 For cancellation, the recurring payment app should have some UI where the user can tap which hit our backend and remove the apple pay merchant token from our system and apply cancellation business logic, no apple API involves in the cancellation of recurring payment
2
0
1.6k
Sep ’25
Apple Pay on Google Chrome
Hi - I have a question. I am trying to understand when Apple Pay will be available on non-IOS desktop devices (specifically Google Chrome). I was hoping to understand better the process, specifically the following: How can I get the Apple Pay QR code installed on my desktop checkout page on Google Chrome? How long does this process usually take? If I work with Stripe, do I need to get approval from them to install the Apple QR code onto my Google Chrome checkout page? Is this readily available to all merchants (i.e., installing Apple Pay on Google Chrome)/ I have not seen this on any other checkout pages yet. Are there any examples you could point me to of merchants that have installed Apple Pay onto non-IOS desktop so I could trial the process (i.e., a list of existing merchants that have put the QR code onto their Google Chrome checkout pages)?
2
0
2.6k
Sep ’25
WCSessionDelegate not being called in the Apple Wallet Extension With UI
Hi, we are implementing the push provisioning via the Apple Wallet Extension starting from the example at https://developer.apple.com/documentation/passkit/implementing-wallet-extensions. To correctly manage the push provisioning on Apple Watch, specifically for a card tokenised in the iPhone but not in the Watch, we need to know if there is a connected Apple Watch to the iPhone. We are using the following code from the Apple Wallet Extension example to detect whether there is a connected watch: WCSession* session = [WCSession defaultSession]; session.delegate = delegate; [session activateSession]; In the main target of the app, at the end of the activation the system correctly calls the delegate method: session:activationDidCompleteWithState:error: but we noticed it is not being called in the UI extension context (the one having NSExtensionPointIdentifier: com.apple.PassKit.issuer-provisioning.authorization). We don't understand why the delegate is not being called in the UI extension, can you please help? Thanks! Steps to Reproduce: Start with a card not added in the Apple Wallet app Open the Apple Wallet app Click on add card Select the app to launch the Wallet Extension flow The Apple Wallet Extension with UI is on screen and invokes the activateSession method, the delegate method is not invoked and session.isPaired returns "no". Xcode Version 16.2 macOS Version 15.6.1 (24G90) Feedback ID FB20082564
1
0
401
Sep ’25
Apple Pay button not showing up in apple pay demo site.
MacOS: 12 ( Monterrey ) Safari: 17.6 Demo Site: https://applepaydemo.apple.com/ At the bottom where the Apple Pay button should appear, I see a warning something like "This browser doesn't support Apple Pay, please use safari" along with a link to requirements for apple pay. All the requirements are fulfilled, OS and Safari's version are above the minimum required. Link was opened in Safari. And the other thing is if I open the same site in Chrome, I can see the apple pay button and when I click on it a QR appears which is the expected behaviour. How to resolve this?
0
0
306
Sep ’25
Clarification on Apple Pay Domain Verification File Behavior
I'm implementing Apple Pay in my Flutter web app and I'm following the guidelines for domain verification using the apple-developer-merchantid-domain-association file. When I access the file at https://mydomain.com/.well-known/apple-developer-merchantid-domain-association through my web app, the browser silently downloads the file instead of displaying its content on the webpage. My question is: Is this the expected behavior for the apple-developer-merchantid-domain-association file? Should the browser download the file silently, or is there another step required, such as displaying the content on the webpage for verification purposes? I've consulted some resources and they indicate that the file download is the correct behavior. However, I'd appreciate confirmation from the community to ensure I'm implementing the verification process correctly. Summary is how do we know if apple has verified it?
1
0
440
Aug ’25
Apple Pay Not Complete On Web
{ "epochTimestamp": 1755169981033, "expiresAt": 1755173581033, "merchantSessionIdentifier": "SSH4ADF1D97A60B47FC8537037BE9892237_FF777A9CB5E9EDAB38A01E4EDF71CB5572F19153853DAC70ADC5AA3E75877CB4", "nonce": "b6f1e016", "merchantIdentifier": "7C52E6BFA112124092008236BE1EE49791E4E82E9082AD9AC98D55B03A088120", "domainName": "1960-ikffk.checkout.trypeppr.com", "displayName": "peppr", "signature": "308006092a864886f70d010702a0803080020101310d300b0609608648016503040201308006092a864886f70d0107010000a080308203ee30820394a00302010202080e7210e510586e34300a06082a8648ce3d040302307a312e302c06035504030c254170706c65204170706c69636174696f6e20496e746567726174696f6e204341202d20473331263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b3009060355040613025553301e170d3231303131303032313632395a170d3236303130393032313632395a306b3131302f06035504030c286563632d736d702d62726f6b65722d7369676e5f5543342d50524f445f4b727970746f6e5f45434331143012060355040b0c0b694f532053797374656d7331133011060355040a0c0a4170706c6520496e632e310b30090603550406130255533059301306072a8648ce3d020106082a8648ce3d0301070342000466e0ea0e787dcb3f66bc533189da2bda08ed9574e421117aa1af2cc310f6a8b19ca3e77ed00fa84e8df2ac8688e529866e76ebad89eda5b7c336e0f0d8a7d05da38202113082020d300c0603551d130101ff04023000301f0603551d2304183016801423f249c44f93e4ef27e6c4f6286c3fa2bbfd2e4b304506082b0601050507010104393037303506082b060105050730018629687474703a2f2f6f6373702e6170706c652e636f6d2f6f63737030342d6170706c65616963613330323082011d0603551d2004820114308201103082010c06092a864886f7636405013081fe3081c306082b060105050702023081b60c81b352656c69616e6365206f6e207468697320636572746966696361746520627920616e7920706172747920617373756d657320616363657074616e6365206f6620746865207468656e206170706c696361626c65207374616e64617264207465726d7320616e6420636f6e646974696f6e73206f66207573652c20636572746966696361746520706f6c69637920616e642063657274696669636174696f6e2070726163746963652073746174656d656e74732e303606082b06010505070201162a687474703a2f2f7777772e6170706c652e636f6d2f6365727469666963617465617574686f726974792f30340603551d1f042d302b3029a027a0258623687474703a2f2f63726c2e6170706c652e636f6d2f6170706c6561696361332e63726c301d0603551d0e0416041457c735942abd9ea2feccd3cbe7ede0a37c8cc5fa300e0603551d0f0101ff040403020780300f06092a864886f76364061d04020500300a06082a8648ce3d0403020348003045022100f2fa622622128cd1e1642084bc4117ccdede7289690e864cfb88abb43e04338e022065f85a90b82711d1fd762e0b59c45496e9e683c265c8279998e37872feae46ec308202ee30820275a0030201020208496d2fbf3a98da97300a06082a8648ce3d0403023067311b301906035504030c124170706c6520526f6f74204341202d20473331263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b3009060355040613025553301e170d3134303530363233343633305a170d3239303530363233343633305a307a312e302c06035504030c254170706c65204170706c69636174696f6e20496e746567726174696f6e204341202d20473331263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b30090603550406130255533059301306072a8648ce3d020106082a8648ce3d03010703420004f017118419d76485d51a5e25810776e880a2efde7bae4de08dfc4b93e13356d5665b35ae22d097760d224e7bba08fd7617ce88cb76bb6670bec8e82984ff5445a381f73081f4304606082b06010505070101043a3038303606082b06010505073001862a687474703a2f2f6f6373702e6170706c652e636f6d2f6f63737030342d6170706c65726f6f7463616733301d0603551d0e0416041423f249c44f93e4ef27e6c4f6286c3fa2bbfd2e4b300f0603551d130101ff040530030101ff301f0603551d23041830168014bbb0dea15833889aa48a99debebdebafdacb24ab30370603551d1f0430302e302ca02aa0288626687474703a2f2f63726c2e6170706c652e636f6d2f6170706c65726f6f74636167332e63726c300e0603551d0f0101ff0404030201063010060a2a864886f7636406020e04020500300a06082a8648ce3d040302036700306402303acf7283511699b186fb35c356ca62bff417edd90f754da28ebef19c815e42b789f898f79b599f98d5410d8f9de9c2fe0230322dd54421b0a305776c5df3383b9067fd177c2c216d964fc6726982126f54f87a7d1b99cb9b0989216106990f09921d00003182018930820185020101308186307a312e302c06035504030c254170706c65204170706c69636174696f6e20496e746567726174696f6e204341202d20473331263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b300906035504061302555302080e7210e510586e34300b0609608648016503040201a08193301806092a864886f70d010903310b06092a864886f70d010701301c06092a864886f70d010905310f170d3235303831343131313330315a302806092a864886f70d010934311b3019300b0609608648016503040201a10a06082a8648ce3d040302302f06092a864886f70d010904312204209378ff57580c3205e9ea38d985a2e9ca2db7f06db29b7560f585561a23894402300a06082a8648ce3d04030204483046022100fad47e840779070d097ef91cd4bfa5381d77426071cb38c1cdc77ff9460ba1470221009215c246893bff0983052caaae610a16117237e73ab36d859008e7b234670eaa000000000000", "operationalAnalyticsIdentifier": "peppr:7C52E6BFA112124092008236BE1EE49791E4E82E9082AD9AC98D55B03A088120", "retries": 0, "pspId": "7C52E6BFA112124092008236BE1EE49791E4E82E9082AD9AC98D55B03A088120" } This is generated in the onvalidatemerchant event handler, and passed into session.completeMerchantValidation. Using a sandbox account with linked cards, the next thing that happens is a "payment not completed" message in the ApplePay popup on the page, and the oncancel event is hit Inspecting the event, I don't see anything that hints at the issue. There is a sessionError object, but its code is "unknown" and the info object is empty.
0
0
234
Aug ’25
Problem Generating Signature for Subscription Offers – Error Code 18
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?
1
0
237
Jul ’25
Provisioning profile doesn't support the Tap to Pay on iPhone capability.
Tap to Pay capabilities are enable and I can use in development profile but I cannot make build that I can upload on TestFlight using the distribution profile because during create build I am getting "Provisioning profile doesn't support the Tap to Pay on iPhone capability." this should be working because I checked twice that distribution profile and certificate have this capability and added in Xcode. how can I resolve this mismatched profile issue I am using Xcode - 15.0.1
3
0
3.5k
Jul ’25
Apple Pay In-App Provisioning
Hello, I am following up on my previous feedback (Feedback ID: FB17175593) regarding the in-app provisioning failure for Apple Pay. In that report, I detailed errors encountered during the card addition process (notably issues related to a missing teamID and cryptographic material errors). Could you please provide an update on the investigation progress? I appreciate your assistance and look forward to your response.
Replies
1
Boosts
0
Views
168
Activity
Oct ’25
Automation on apple pay certificates
Hi! I am working on automating the Apple Pay integration process in our CI/CD pipeline and would like to confirm whether a fully automated setup is currently possible for our preproduction environment. Right now, our process is as follows: A certificate is generated for the root domain and for each individual merchant subdomain. Both certificates are manually uploaded to our preproduction servers to test and verified via HTTP. We’d like to automate this flow in GitLab CI, mainly the generation of the necessary certificates programmatically or via API. However, from my research, it seems that Apple does not currently provide an API or any support to automate this task, but I’d like to confirm this directly with you. Is there any official support or workaround for this kind of automation? If not, do you have any plans to provide it in the future? Thanks in advance for your help.
Replies
1
Boosts
0
Views
222
Activity
Oct ’25
Apple Pay integration and Merchant IDs.
Hi, We’re a franchise business with over 100 franchisees, and each franchisee has their own unique Merchant ID. We're building a single app that allows customers to place orders, and based on the selected franchisee, the payment needs to be processed through that specific franchisee’s merchant account. However, when we integrate Apple Pay and publish the app, it asks us to provide a payment gateways' Merchant ID, but we don’t use just one – we have many. How can we handle this situation? Is there a way to dynamically use multiple Merchant IDs in one app, depending on which franchisee the customer is ordering from?
Replies
1
Boosts
0
Views
140
Activity
Oct ’25
Payment not completed in Apple Pay
We have an Apple Pay account and have successfully created and verified the payment processing certificate in our Apple Developer account. When initiating an Apple Pay payment, the Apple session is created successfully with the correct data return from api , but it is not accepted with the error: “Payment not completed.” The issue occurs even though the merchant validation step works without errors. Our websites where this is happening are: https://magicdeliver.com/ https://www.pulsarmodular.com/ Could you please help us identify the cause of the issue and guide us on resolving it?
Replies
1
Boosts
0
Views
211
Activity
Oct ’25
App ID Configuration - Capabilities state inconsistency
Hello, I am experiencing an issue with the Apple Pay capability on my App ID. I have created a Merchant ID. I enabled Apple Pay in the App ID configuration and linked it to the merchant. However, sometimes when I revisit the App ID in the Apple Developer portal, the Apple Pay capability appears disabled, even though I saved it. This happens intermittently; at some times the capability is correctly shown as enabled, and other times it disappears. Context: I am using Expo Managed Workflow with EAS Build for iOS. The issue prevents the provisioning profile from including Apple Pay, which causes Stripe isPlatformPaySupported function to return false on ios devices. Attached: Screenshots of the App ID page showing Apple Pay enabled and disabled. Could you please advise why the capability is not being consistently saved, and how to ensure it stays enabled? Thank you,
Replies
2
Boosts
0
Views
306
Activity
Oct ’25
Apple Pay fractional amounts for RSD
Hello all, I’m helping a customer integrate Apple Pay, and I’m seeing a behavior I can’t fully explain. I hope someone here can help clarify whether this is expected or whether it’s a bug / misconfiguration on my side. Currency: RSD (Serbian Dinar) Amount: 3.45 RSD (two decimals) Result: Apple Pay cancels the payment automatically when the amount includes decimals, without even displaying the paymentsheet. Things I have checked: ISO 4217 defines RSD with 2 minor units, so fractional amounts like 3.45 should be valid. Processors treat RSD as a two-decimal currency. Apple’s documentation does not provide a per-currency decimal rule table. In testing, whole-number RSD amounts succeed, while fractional amounts (e.g. 3.45 RSD) fail. I did not encounter this problem with other currencies like EUR, USD. Has anyone encountered this issue before?
Replies
3
Boosts
0
Views
301
Activity
Oct ’25
ApplePaySession.applePayCapabilities() started returning applePayUnsupported in third-party browsers
We rely on ApplePaySession.applePayCapabilities() to decide whether to show the Apple Pay button. We use two different merchant IDs for non-prod/prod environments, and encountered a change in behavior where this API now returns different results. These merchant IDs are generated from a third-party provider Adyen. However, Adyen has informed us that they are unable to identify the root cause of the issue and advised us to seek assistance directly from Apple Pay support. Timeline Last known working date: 13/08/2025 Issue first noticed: 18/08/2025 Environment Details Apple Pay JS API version 1.latest Browsers Tested: Third party browsers including Chrome/139.0.0.0, Firefox/141.0 Browsers with ApplePaySession built-in (like iOS Chrome, iOS Safari, and macOS Safari) are working fine Framework Stack: Angular v18.1.3 (important) no configuration setup in Apple dev account, merchantId is generated from a third-party provider Adyen. Current Execution Flow: Apple Pay JS API script element is injected <script type="text/javascript" async="" src="https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js"></script> Triggers below to check apple pay readiness, different ${merchantId_credential} is used: await window.ApplePaySession.applePayCapabilities(`${merchantId_credential}`); (**ApplePaySession is a valid object at this point) Observed that different paymentCredentialStatus is returned // nonprod env { "paymentCredentialStatus": "applePayUnsupported" // unexpected } // prod env { "paymentCredentialStatus": "paymentCredentialStatusUnknown" } The same code is executed in each environment and the behaviour was also the same, but has changed since then. Side notes By checking the SDK’s internal code, we saw that in third-party browsers it makes an extra call to the following endpoint. Responses from this call also come back differently depending on the merchantId. When invoking below: curl -X POST \ https://smp-paymentservices.apple.com/paymentservices/v3/checkStatus/merchant/{merchantId} \ -H 'Content-Type: application/json' \ -d '{ "initiative": "web", "initiativeContext": "env_specific_domain" }' Our non-prod environment returns {"registered":false} while using prod's merchantId and domain it returns {"registered":true}. We thought the issue might be domain-related since the environments are on different domains, but so far, no luck. The main questions we're looking to resolve are: Why did the behavior change at a certain point despite no code changes? How should we approach this investigation, and what specific requests should we be making to the Adyen team? Why does the response from the call to https://smp-paymentservices.apple.com/paymentservices/v3/checkStatus/merchant/{merchantId} return different results? Perhaps this could provide a clue regarding the question above? We noticed that canMakePayments() is returning true, so we could consider using that as a workaround. Would it be safe to change the source of truth relying on canMakePayments() for displaying Apple Pay? There is a concern that this issue may also occur in our production environment, so we would appreciate assistance in understanding what is happening and finding a resolution.
Replies
4
Boosts
0
Views
529
Activity
Oct ’25
我在使用java验证apple pay支付提示401
我在对接apple pay内购,调用https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/{transactionId},一直提示401,我不知道是我对接代码的错误,还是在开发者配置有问题或者是对应的参数提供错误,排查很久,依旧提示: Server returned HTTP response code: 401 for URL: https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/xxx 请问我该如何去查找我的问题呢
Replies
0
Boosts
0
Views
171
Activity
Oct ’25
Apple Pay integration in our app
Hi, We have app in which we take donations from people and send to non-profit organisations. I have read that Apple Pay can be integrated on non profit platforms to take donations, but we are middle man, we are not non profit .. we take donations, cut our platform fees and then sent to donations to non profit orgs. My question is can we integrate Apple Pay in our iOS app to take donations from apple? as we have integrated Apple Pay on the web.
Replies
1
Boosts
0
Views
227
Activity
Oct ’25
Apple Pay pre-auth: how to not show hold amount (gas-station style) for usage-based rentals?
We’re building a usage-based rental flow. The final charge is only known after the session ends (like gas pumps). We want the same Apple Pay UX that gas stations like at a gas station has: the user does not see a pre-authorization amount up front; they only see “approved” and later the final posted amount on the statement. What we observe (gas stations / desired UX) When paying at gas station with Apple Pay (card-present), the user confirms their card (double-tap) but no pre-auth amount is shown in Wallet/notification UI. The small notification is from the bank (not the merchant) and shows only bank + merchant name, no total. After fueling ends, the final amount appears on the statement from the merchant. What happens in our flow (current behavior) Platform: Apple Pay via Stripe (Apple Pay on the Web with QR → mobile Safari Wallet sheet). When a user confirms payment, the pre-authorization amount is shown immediately to the user (appears like a charge from the user’s perspective). We want to avoid showing that amount, matching the pay-at-pump experience.
Replies
3
Boosts
0
Views
661
Activity
Oct ’25
Apple Pay JS API - applePayCapabilities no longer working
We’ve noticed that the ApplePaySession.applePayCapabilities() check has stopped working correctly in Safari over the past couple of days. Behavior observed: 1.) In Safari Private Window, paymentCredentialStatus behaves as expected and case 1 is triggered. 2.) In a normal Safari window, it always triggers case 3 (paymentCredentialsUnavailable), even when the user has active cards provisioned in Wallet. We tested across multiple devices, and the behavior is consistent. if (window.ApplePaySession) { var merchantIdentifier = 'YOUR MERCHANT IDENTIFIER'; var promise = ApplePaySession.applePayCapabilities(merchantIdentifier); promise.then(function(capabilities) { switch (capabilities.paymentCredentialStatus) { case "paymentCredentialsAvailable": // Show Apple Pay button as primary option case "paymentCredentialStatusUnknown": // Offer Apple Pay case "paymentCredentialsUnavailable": // Consider showing Apple Pay button case "applePayUnsupported": // Don’t show Apple Pay button } }) } This used to work fine until a few days ago, but now the capability check in non-private Safari windows always indicates unavailable, even with valid active cards. Has anyone else faced this issue recently? Could this be a Safari regression or a change on Apple’s side? Thanks in advance!
Replies
1
Boosts
0
Views
380
Activity
Oct ’25
ApplePay mTLS long response time
I'm calling the endpoint https://apple-pay-gateway-cert.apple.com/paymentservices with mTLS and it's taking over 15 seconds to complete the request. This is happening only when deployed through AWS. I have tried a dummy dotnet and node lambda with the same result. Wondering if anyone had the same issue. Also stack overflow post explaining the code in more depth - https://stackoverflow.com/questions/79755891/mtls-http-call-taking-over-15-seconds
Replies
1
Boosts
1
Views
229
Activity
Sep ’25
iOS 16 recurring payment configuration not reflecting in UI
We are integrating iOS 16 recurring payments in our app, everything works fine but we have a few questions Question 1 let recurringPaymentRequest = PKRecurringPaymentRequest(         paymentDescription: "Pro Membership",         regularBilling: regularBilling,         managementURL: url       ) we assume managementURL is supposed to come in the user's wallet where he/she can tap to change the recurring payment option to our backend, but in the wallet, the transaction appears without this URL and have no indication that it is a recurring payment, Can someone guide what we missed Question 2 For apps that only have apple pay on mobile, managementURL can open the app as a deep link from the Wallet app and the user can update or delete the payment method for the automatic reload payment from the app directly, Question 3 For cancellation, the recurring payment app should have some UI where the user can tap which hit our backend and remove the apple pay merchant token from our system and apply cancellation business logic, no apple API involves in the cancellation of recurring payment
Replies
2
Boosts
0
Views
1.6k
Activity
Sep ’25
Apple Pay on Google Chrome
Hi - I have a question. I am trying to understand when Apple Pay will be available on non-IOS desktop devices (specifically Google Chrome). I was hoping to understand better the process, specifically the following: How can I get the Apple Pay QR code installed on my desktop checkout page on Google Chrome? How long does this process usually take? If I work with Stripe, do I need to get approval from them to install the Apple QR code onto my Google Chrome checkout page? Is this readily available to all merchants (i.e., installing Apple Pay on Google Chrome)/ I have not seen this on any other checkout pages yet. Are there any examples you could point me to of merchants that have installed Apple Pay onto non-IOS desktop so I could trial the process (i.e., a list of existing merchants that have put the QR code onto their Google Chrome checkout pages)?
Replies
2
Boosts
0
Views
2.6k
Activity
Sep ’25
WCSessionDelegate not being called in the Apple Wallet Extension With UI
Hi, we are implementing the push provisioning via the Apple Wallet Extension starting from the example at https://developer.apple.com/documentation/passkit/implementing-wallet-extensions. To correctly manage the push provisioning on Apple Watch, specifically for a card tokenised in the iPhone but not in the Watch, we need to know if there is a connected Apple Watch to the iPhone. We are using the following code from the Apple Wallet Extension example to detect whether there is a connected watch: WCSession* session = [WCSession defaultSession]; session.delegate = delegate; [session activateSession]; In the main target of the app, at the end of the activation the system correctly calls the delegate method: session:activationDidCompleteWithState:error: but we noticed it is not being called in the UI extension context (the one having NSExtensionPointIdentifier: com.apple.PassKit.issuer-provisioning.authorization). We don't understand why the delegate is not being called in the UI extension, can you please help? Thanks! Steps to Reproduce: Start with a card not added in the Apple Wallet app Open the Apple Wallet app Click on add card Select the app to launch the Wallet Extension flow The Apple Wallet Extension with UI is on screen and invokes the activateSession method, the delegate method is not invoked and session.isPaired returns "no". Xcode Version 16.2 macOS Version 15.6.1 (24G90) Feedback ID FB20082564
Replies
1
Boosts
0
Views
401
Activity
Sep ’25
Apple Pay button not showing up in apple pay demo site.
MacOS: 12 ( Monterrey ) Safari: 17.6 Demo Site: https://applepaydemo.apple.com/ At the bottom where the Apple Pay button should appear, I see a warning something like "This browser doesn't support Apple Pay, please use safari" along with a link to requirements for apple pay. All the requirements are fulfilled, OS and Safari's version are above the minimum required. Link was opened in Safari. And the other thing is if I open the same site in Chrome, I can see the apple pay button and when I click on it a QR appears which is the expected behaviour. How to resolve this?
Replies
0
Boosts
0
Views
306
Activity
Sep ’25
Clarification on Apple Pay Domain Verification File Behavior
I'm implementing Apple Pay in my Flutter web app and I'm following the guidelines for domain verification using the apple-developer-merchantid-domain-association file. When I access the file at https://mydomain.com/.well-known/apple-developer-merchantid-domain-association through my web app, the browser silently downloads the file instead of displaying its content on the webpage. My question is: Is this the expected behavior for the apple-developer-merchantid-domain-association file? Should the browser download the file silently, or is there another step required, such as displaying the content on the webpage for verification purposes? I've consulted some resources and they indicate that the file download is the correct behavior. However, I'd appreciate confirmation from the community to ensure I'm implementing the verification process correctly. Summary is how do we know if apple has verified it?
Replies
1
Boosts
0
Views
440
Activity
Aug ’25
Apple Pay Not Complete On Web
{ "epochTimestamp": 1755169981033, "expiresAt": 1755173581033, "merchantSessionIdentifier": "SSH4ADF1D97A60B47FC8537037BE9892237_FF777A9CB5E9EDAB38A01E4EDF71CB5572F19153853DAC70ADC5AA3E75877CB4", "nonce": "b6f1e016", "merchantIdentifier": "7C52E6BFA112124092008236BE1EE49791E4E82E9082AD9AC98D55B03A088120", "domainName": "1960-ikffk.checkout.trypeppr.com", "displayName": "peppr", "signature": "308006092a864886f70d010702a0803080020101310d300b0609608648016503040201308006092a864886f70d0107010000a080308203ee30820394a00302010202080e7210e510586e34300a06082a8648ce3d040302307a312e302c06035504030c254170706c65204170706c69636174696f6e20496e746567726174696f6e204341202d20473331263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b3009060355040613025553301e170d3231303131303032313632395a170d3236303130393032313632395a306b3131302f06035504030c286563632d736d702d62726f6b65722d7369676e5f5543342d50524f445f4b727970746f6e5f45434331143012060355040b0c0b694f532053797374656d7331133011060355040a0c0a4170706c6520496e632e310b30090603550406130255533059301306072a8648ce3d020106082a8648ce3d0301070342000466e0ea0e787dcb3f66bc533189da2bda08ed9574e421117aa1af2cc310f6a8b19ca3e77ed00fa84e8df2ac8688e529866e76ebad89eda5b7c336e0f0d8a7d05da38202113082020d300c0603551d130101ff04023000301f0603551d2304183016801423f249c44f93e4ef27e6c4f6286c3fa2bbfd2e4b304506082b0601050507010104393037303506082b060105050730018629687474703a2f2f6f6373702e6170706c652e636f6d2f6f63737030342d6170706c65616963613330323082011d0603551d2004820114308201103082010c06092a864886f7636405013081fe3081c306082b060105050702023081b60c81b352656c69616e6365206f6e207468697320636572746966696361746520627920616e7920706172747920617373756d657320616363657074616e6365206f6620746865207468656e206170706c696361626c65207374616e64617264207465726d7320616e6420636f6e646974696f6e73206f66207573652c20636572746966696361746520706f6c69637920616e642063657274696669636174696f6e2070726163746963652073746174656d656e74732e303606082b06010505070201162a687474703a2f2f7777772e6170706c652e636f6d2f6365727469666963617465617574686f726974792f30340603551d1f042d302b3029a027a0258623687474703a2f2f63726c2e6170706c652e636f6d2f6170706c6561696361332e63726c301d0603551d0e0416041457c735942abd9ea2feccd3cbe7ede0a37c8cc5fa300e0603551d0f0101ff040403020780300f06092a864886f76364061d04020500300a06082a8648ce3d0403020348003045022100f2fa622622128cd1e1642084bc4117ccdede7289690e864cfb88abb43e04338e022065f85a90b82711d1fd762e0b59c45496e9e683c265c8279998e37872feae46ec308202ee30820275a0030201020208496d2fbf3a98da97300a06082a8648ce3d0403023067311b301906035504030c124170706c6520526f6f74204341202d20473331263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b3009060355040613025553301e170d3134303530363233343633305a170d3239303530363233343633305a307a312e302c06035504030c254170706c65204170706c69636174696f6e20496e746567726174696f6e204341202d20473331263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b30090603550406130255533059301306072a8648ce3d020106082a8648ce3d03010703420004f017118419d76485d51a5e25810776e880a2efde7bae4de08dfc4b93e13356d5665b35ae22d097760d224e7bba08fd7617ce88cb76bb6670bec8e82984ff5445a381f73081f4304606082b06010505070101043a3038303606082b06010505073001862a687474703a2f2f6f6373702e6170706c652e636f6d2f6f63737030342d6170706c65726f6f7463616733301d0603551d0e0416041423f249c44f93e4ef27e6c4f6286c3fa2bbfd2e4b300f0603551d130101ff040530030101ff301f0603551d23041830168014bbb0dea15833889aa48a99debebdebafdacb24ab30370603551d1f0430302e302ca02aa0288626687474703a2f2f63726c2e6170706c652e636f6d2f6170706c65726f6f74636167332e63726c300e0603551d0f0101ff0404030201063010060a2a864886f7636406020e04020500300a06082a8648ce3d040302036700306402303acf7283511699b186fb35c356ca62bff417edd90f754da28ebef19c815e42b789f898f79b599f98d5410d8f9de9c2fe0230322dd54421b0a305776c5df3383b9067fd177c2c216d964fc6726982126f54f87a7d1b99cb9b0989216106990f09921d00003182018930820185020101308186307a312e302c06035504030c254170706c65204170706c69636174696f6e20496e746567726174696f6e204341202d20473331263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b300906035504061302555302080e7210e510586e34300b0609608648016503040201a08193301806092a864886f70d010903310b06092a864886f70d010701301c06092a864886f70d010905310f170d3235303831343131313330315a302806092a864886f70d010934311b3019300b0609608648016503040201a10a06082a8648ce3d040302302f06092a864886f70d010904312204209378ff57580c3205e9ea38d985a2e9ca2db7f06db29b7560f585561a23894402300a06082a8648ce3d04030204483046022100fad47e840779070d097ef91cd4bfa5381d77426071cb38c1cdc77ff9460ba1470221009215c246893bff0983052caaae610a16117237e73ab36d859008e7b234670eaa000000000000", "operationalAnalyticsIdentifier": "peppr:7C52E6BFA112124092008236BE1EE49791E4E82E9082AD9AC98D55B03A088120", "retries": 0, "pspId": "7C52E6BFA112124092008236BE1EE49791E4E82E9082AD9AC98D55B03A088120" } This is generated in the onvalidatemerchant event handler, and passed into session.completeMerchantValidation. Using a sandbox account with linked cards, the next thing that happens is a "payment not completed" message in the ApplePay popup on the page, and the oncancel event is hit Inspecting the event, I don't see anything that hints at the issue. There is a sessionError object, but its code is "unknown" and the info object is empty.
Replies
0
Boosts
0
Views
234
Activity
Aug ’25
Problem Generating Signature for Subscription Offers – Error Code 18
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?
Replies
1
Boosts
0
Views
237
Activity
Jul ’25
Provisioning profile doesn't support the Tap to Pay on iPhone capability.
Tap to Pay capabilities are enable and I can use in development profile but I cannot make build that I can upload on TestFlight using the distribution profile because during create build I am getting "Provisioning profile doesn't support the Tap to Pay on iPhone capability." this should be working because I checked twice that distribution profile and certificate have this capability and added in Xcode. how can I resolve this mismatched profile issue I am using Xcode - 15.0.1
Replies
3
Boosts
0
Views
3.5k
Activity
Jul ’25