Apple Pay™ Integration
Overview
Apple Pay™ provides an easy and secure way to make payments in your iOS, iPadOS, and watchOS apps, and on websites in Safari. By using Face ID, Touch ID, or double-clicking Apple Watch, users can quickly and securely provide their payment, shipping, and contact information to check out. Customers love the simplicity of Apple Pay, and you'll love the increased conversion rates and new user adoption that come with it.
This guide focuses on the integration mechanics. For the operating model behind Apple Pay at NetValve — and why you no longer need to manage Apple Pay certificates yourself — read the Digital Wallets overview.
Integration paths
NetValve supports two paths for Apple Pay. They use the same API endpoints, the same front-end SDK, and the same Sale request shape — the only difference is who owns the cryptographic identity registered with Apple.
| Path A — NetValve processor certificate | Path B — Bring your own certificate | |
|---|---|---|
| Apple Developer Account | Not required. | Owned by the merchant. NetValve does not have access to it. |
| Merchant Identity & Payment Processing certificates | Managed by NetValve. | Generated by the merchant in the Apple Developer portal, then handed to NetValve to load against your MID. |
| Domain registration | NetValve registers domains for you via POST /registerApplePayDomain. | Merchant registers domains directly in the Apple Developer portal under their own Merchant ID. The NetValve POST /registerApplePayDomain endpoint is not used. |
| Well-known association file | NetValve provides the file contents (matches NetValve's processor identity). | Merchant downloads the file from the Apple Developer portal when adding the domain to their Merchant ID. |
| Session validation (per transaction) | POST /initializeApplePaySession — NetValve handles the mTLS call to Apple with its processor certificate. | Two options: call POST /initializeApplePaySession (requires sharing the Merchant Identity Certificate with NetValve), or have your own backend POST to Apple's validationURL directly with your Merchant Identity Certificate (keep the cert on your side). |
| What customers see in the Apple Pay sheet | Your display name; the underlying merchant identity is NetValve's. | Your display name and your own Apple Merchant ID. |
| Renewals | Handled transparently by NetValve. | Merchant rotates certs in the Apple Developer portal; resends to NetValve only the ones NetValve holds. |
| Who it's for | Most merchants. Fastest to launch. | Merchants with an existing Apple Pay setup, brand-direct requirements with Apple, or regulatory reasons to hold the certificate themselves. |
The rest of this guide describes Path A. If you want to use your own certificates, skip ahead to Bring your own certificate — that section walks through the Apple-side setup and the differences in the runtime flow.
Prerequisites
NetValve operates as an Apple Pay Payment Service Provider, so the certificate-heavy setup that Apple's own documentation describes is handled on our side. To accept Apple Pay through NetValve you only need:
- A NetValve MID with Apple Pay enabled. Speak to your NetValve representative if you're not sure whether your MID is enabled.
- HTTPS on every domain that will display the Apple Pay button. Self-signed certificates are not accepted by Apple.
- The well-known domain-association file hosted at
/.well-known/apple-developer-merchantid-domain-associationon every domain you register. NetValve provides the exact file contents.
You do not need an Apple Developer Account, a Merchant ID, a Merchant Identity Certificate, or a Payment Processing Certificate. NetValve's processor certificate covers all of those.
Integration Steps
Follow these steps to integrate Apple Pay into your platform:
-
Host the domain-association file — Request the file contents from your NetValve representative and serve them at
https://<your-domain>/.well-known/apple-developer-merchantid-domain-associationwithContent-Type: text/plain. The same file content is used on every domain. -
Register each domain with Apple via NetValve — Call
POST /registerApplePayDomainfrom your backend with the domains you want to register and a display name to show in the Apple Pay sheet. NetValve performs the mTLS handshake with Apple using its processor certificate and stores the registration against your client.POST /registerApplePayDomain — request{"domainNames": ["shop.example.com","www.shop.example.com"],"displayName": "Example Store"}200 OK — response{"traceID": "b126345b-6199-4635-9bf2-f9aadbdd4d58","responseTimestamp": "2026-05-13T09:21:04.512+00:00","responseCode": "GTW_1000","responseMessage": "Registration successful","merchantRegistrationId": "289e253d-f955-4e29-a2c7-bb1805883ee0"}If you'd rather not call the API yourself, contact your NetValve representative with the same details and we will register the domains on your behalf. A Backoffice UI for managing this is on the roadmap.
See Register Apple Pay™ Domain for the full reference.
-
Validate the merchant session per transaction — When the customer taps the Apple Pay button, your backend must validate a session with Apple before the payment sheet can complete. Call
POST /initializeApplePaySessionand pass the resulting session object straight into the browser'sApplePaySession.completeMerchantValidation()call. NetValve performs the mTLS call to Apple on your behalf — your backend never touches any certificate.POST /initializeApplePaySession — request{"domainName": "shop.example.com"}See Initialize Apple Pay™ session for the full reference.
-
Submit the payment — Once the customer authorises the payment on their device (Face ID, Touch ID, or passcode), Apple Pay returns an encrypted payment payload to your front-end. Forward that payload to your backend and include it in a NetValve Sale request as the
applePaySSLfield. NetValve decrypts the payload server-side using its processor key and routes the authorisation to the acquirer.Already decrypting the token yourself?If you decrypt the Apple Pay token on your own backend — for example because you hold your own Payment Processing Certificate (Path B) — you can skip
applePaySSLand send the decrypted network-token fields directly in atokenizedDTOobject instead. See Submitting a decrypted payload.
{
"data": "j2DEV4+KvjvAVJgAYW/T2Tj0XfWHwlCH2t2swU0HX+benHAd6J+Qc63Y2CO+JsG+my8rnL6DNqNXslrplLw3ZeeBVRF1eVw93onpc5ZbfKUBRl0FQAesBmPIEYfRWiaAgq/7FWyio3a12r5IlfYBDImHDZJGmP92STH5Nl4ZhRWlIlW7N+G9ZgeqY+0V0GKiQWQyEjOrAUILUqfPctOmmXGabQuG1nFyaQJ25JEemU3KkcYMTxVs4kunnwt8TZUl/NOutV6ghis3xZfWMBF4WkjzpTll7rm3pC/7p63i9Ne7ORZBByOfOHzpHNEPq03p4ytMJzweVvdjmRgwQkJOaT4A5VUQYE7Zuv6/99+HfSbGlBPrSYFkRu8zjc1VAE/P8kxyi4uMyhlBhBDH4tjxk9rF2eTT0A5DOe81BGvmsu8=",
"signature": "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",
"header": {
"publicKeyHash": "IhhPGBcPOucUmM3XS6gAYDaBSVrY+afwSf1Y+sCG9pY=",
"ephemeralPublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEozFHMd8s3HUYSexnYBDi7Bsu2LCnrUII/T2f7Dq4zNnrUvy73h8OC/rZwpML4HyDepBQWcAWMYxoINBEVRo2wQ==",
"transactionId": "ad6432495110a7ebeaf8ed048efa81cec5912233ef7fbe6ceaff03ceca0cd6ab"
},
"version": "EC_v1"
}
This Apple Pay payload should be included as part of the NetValve payment request body (i.e. Sale operation).
All requests must include your API credentials. See API Authentication for details.
Content-Type: application/json
netvalve-api-key: YOUR_API_KEY
netvalve-client-id: YOUR_CLIENT_ID
{
"amount": 100.00,
"clientOrderId": {{clientOrderId}},
"currency": "USD",
"customerAddress": "123 Main St",
"customerCity": "New York",
"customerCountryCode": "US",
"customerEmail": "docs@netvalve.com",
"customerIp": "203.0.113.1",
"customerName": "John",
"customerLastName": "Doe",
"customerPhone": "+12025551234",
"customerState": "NY",
"customerZipCode": "10001",
"netvalveMidId": "{{netvalveMidId}}",
"paymentType": "WALLET",
"walletType": "APPLE_PAY",
"applePaySSL": {
"paymentData": {
// Insert Apple Pay payload here.
},
"paymentMethod": {
"displayName": "Visa 0326",
"network": "Visa",
"type": "debit"
},
"transactionIdentifier": "ad6432495110a7ebeaf8ed048efa81cec5912233ef7fbe6ceaff03ceca0cd6ab"
}
}
The full request body example should look like this:
{
"amount": 100.00,
"clientOrderId": {{clientOrderId}},
"currency": "USD",
"customerAddress": "123 Main St",
"customerCity": "New York",
"customerCountryCode": "US",
"customerEmail": "docs@netvalve.com",
"customerIp": "203.0.113.1",
"customerName": "John",
"customerLastName": "Doe",
"customerPhone": "+12025551234",
"customerState": "NY",
"customerZipCode": "10001",
"netvalveMidId": "{{netvalveMidId}}",
"paymentType": "WALLET",
"walletType": "APPLE_PAY",
"applePaySSL": {
"paymentData": {
"data": "j2DEV4+KvjvAVJgAYW/T2Tj0XfWHwlCH2t2swU0HX+benHAd6J+Qc63Y2CO+JsG+my8rnL6DNqNXslrplLw3ZeeBVRF1eVw93onpc5ZbfKUBRl0FQAesBmPIEYfRWiaAgq/7FWyio3a12r5IlfYBDImHDZJGmP92STH5Nl4ZhRWlIlW7N+G9ZgeqY+0V0GKiQWQyEjOrAUILUqfPctOmmXGabQuG1nFyaQJ25JEemU3KkcYMTxVs4kunnwt8TZUl/NOutV6ghis3xZfWMBF4WkjzpTll7rm3pC/7p63i9Ne7ORZBByOfOHzpHNEPq03p4ytMJzweVvdjmRgwQkJOaT4A5VUQYE7Zuv6/99+HfSbGlBPrSYFkRu8zjc1VAE/P8kxyi4uMyhlBhBDH4tjxk9rF2eTT0A5DOe81BGvmsu8=",
"signature": "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",
"header": {
"publicKeyHash": "IhhPGBcPOucUmM3XS6gAYDaBSVrY+afwSf1Y+sCG9pY=",
"ephemeralPublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEozFHMd8s3HUYSexnYBDi7Bsu2LCnrUII/T2f7Dq4zNnrUvy73h8OC/rZwpML4HyDepBQWcAWMYxoINBEVRo2wQ==",
"transactionId": "ad6432495110a7ebeaf8ed048efa81cec5912233ef7fbe6ceaff03ceca0cd6ab"
},
"version": "EC_v1"
},
"paymentMethod": {
"displayName": "Visa 0326",
"network": "Visa",
"type": "debit"
},
"transactionIdentifier": "ad6432495110a7ebeaf8ed048efa81cec5912233ef7fbe6ceaff03ceca0cd6ab"
}
}
-
Test Integration — Test the Apple Pay integration thoroughly in the Sandbox environment. Ensure that payments are processed correctly and that the merchant session validates on every domain you've registered.
-
Go Live — Register your production domains in the production environment and deploy. Monitor transactions and performance to ensure everything functions as expected.
Submitting a decrypted payload (tokenizedDTO)
The applePaySSL flow above hands NetValve the encrypted Apple Pay token and lets NetValve decrypt it server-side. If you'd rather decrypt the token yourself and pass NetValve the resulting card-network data, send a tokenizedDTO object in place of applePaySSL. Everything else about the Sale request is identical — same endpoint, same paymentType: WALLET, same walletType: APPLE_PAY.
This is useful when:
- You hold your own Payment Processing Certificate (Path B) and already decrypt the token on your backend, so there is nothing left for NetValve to decrypt.
- You run your own Apple Pay decryption for other processors and want to keep a single integration path.
Send either applePaySSL or tokenizedDTO — not both. If tokenizedDTO is present, NetValve treats the wallet payload as already decrypted and does not attempt to decrypt anything.
Where the fields come from
After you decrypt the Apple Pay payment token, you get a JSON object like this (Apple's fields shown for reference):
{
"applicationPrimaryAccountNumber": "4012000098765439",
"applicationExpirationDate": "281231",
"currencyCode": "840",
"transactionAmount": 1100,
"cardholderName": "John Doe",
"paymentDataType": "3DSecure",
"paymentData": {
"onlinePaymentCryptogram": "Az2Uq7EABOvUpHEqLyFuMAACAAA=",
"eciIndicator": "5"
}
}
Map those into tokenizedDTO as follows:
tokenizedDTO field | Source in the decrypted token | Notes |
|---|---|---|
cardNumber | applicationPrimaryAccountNumber | The device/network token (DPAN), not the funding PAN. |
cardExpiryMonth | applicationExpirationDate (YYMMDD) → MM | e.g. 281231 → 12. |
cardExpiryYear | applicationExpirationDate (YYMMDD) → YYYY | e.g. 281231 → 2028. |
cryptogram | paymentData.onlinePaymentCryptogram | Passed to the acquirer as the online cryptogram (AAV/TAVV) for Visa and Mastercard. |
eciIndicator | paymentData.eciIndicator | Authentication ECI. May be absent for some card networks. |
Example request
{
"amount": 11.00,
"clientOrderId": {{clientOrderId}},
"currency": "USD",
"customerAddress": "123 Main St",
"customerCity": "New York",
"customerCountryCode": "US",
"customerEmail": "docs@netvalve.com",
"customerIp": "203.0.113.1",
"customerName": "John",
"customerLastName": "Doe",
"customerPhone": "+12025551234",
"customerState": "NY",
"customerZipCode": "10001",
"netvalveMidId": "{{netvalveMidId}}",
"paymentType": "WALLET",
"walletType": "APPLE_PAY",
"tokenizedDTO": {
"cardExpiryMonth": "12",
"cardExpiryYear": "2028",
"cardNumber": "4012000098765439",
"cryptogram": "Az2Uq7EABOvUpHEqLyFuMAACAAA=",
"eciIndicator": "5"
}
}
The same tokenizedDTO shape is used for Google Pay and Samsung Pay — only walletType changes. See the Digital Wallets overview.
Bring your own certificate
If you'd prefer to hold the Apple Pay relationship yourself — for example, because you already have a working Apple Pay setup with another processor, or because your compliance posture requires you to control the certificates — NetValve also supports loading per-merchant certificates against your MID.
In this path you own the Apple Developer Account, you create the Merchant ID, and you register your domains directly with Apple through the Developer portal. NetValve does not have access to your Apple Developer account. What NetValve needs from you are the two certificates Apple issues against your Merchant ID — they're loaded against your NetValve MID and used at runtime to validate Apple Pay sessions and to decrypt payment payloads.
Step 1 — Set up your Apple Merchant ID
In the Apple Developer portal, under Certificates, Identifiers & Profiles → Identifiers, create a new Merchant ID (Apple's identifier format is merchant.<reverse-dns>). See Apple's guide: Configure Apple Pay — Create a merchant identifier.
An Organization-level Apple Developer Account is required (Individual accounts are not eligible for Apple Pay on the web).
Step 2 — Register your domains in the Apple Developer portal
Domain registration in this path is done directly with Apple, not through NetValve. The POST /registerApplePayDomain endpoint described earlier in this guide is for Path A only and should not be used here.
In the Apple Developer portal:
- Open your Merchant ID → Merchant Domains → Add Domain.
- Enter the domain you want to register (every customer-facing variant — apex,
www, subdomains). - Apple presents the
apple-developer-merchantid-domain-associationfile. Download it. - Host the file at
https://<your-domain>/.well-known/apple-developer-merchantid-domain-associationon the domain you're registering, served over HTTPS withContent-Type: text/plain. - Click Verify in the portal. Apple fetches the file and, on success, marks the domain as verified.
Repeat for every domain. Unlike Path A, the file contents are unique to your Merchant ID — you get them from Apple, not from NetValve.
Step 3 — Generate the two certificates
In the same Apple Developer portal, navigate to Certificates, Identifiers & Profiles → Identifiers → Merchant IDs → your Merchant ID. From there, generate:
- Apple Pay Merchant Identity Certificate — used to authenticate to Apple over mTLS when validating a payment session.
- Apple Pay Payment Processing Certificate — used to decrypt the encrypted payment payload returned by Apple Pay on the device.
Follow Apple's instructions to generate a CSR, upload it to the portal, download the issued certificate, and export it together with its private key. Export both certificates in PEM format.
Treat the private keys like any other production secret in your organisation.
Step 4 — Choose how session validation runs, then send the certs you need NetValve to hold
Before you send anything, decide who performs the per-transaction merchant session validation. The two options are functionally equivalent — pick whichever fits your backend better.
Option 1 — NetValve handles session validation
Your frontend calls POST /initializeApplePaySession, NetValve performs the mTLS handshake with Apple using your Merchant Identity Certificate, and returns the session blob. You need to share the Merchant Identity Certificate with NetValve.
Option 2 — You call Apple directly
Your own backend POSTs to the validationURL that Apple's JS supplies in the onvalidatemerchant event, presenting the Merchant Identity Certificate from your own keystore. NetValve is not involved in this step at all. The Merchant Identity Certificate stays on your side.
In both cases, NetValve still needs the Payment Processing Certificate so it can decrypt the wallet payload submitted with the Sale request.
Send the following to your NetValve representative through a secure channel (PGP-encrypted email, or whatever your account manager has set up with you):
- The NetValve MID(s) the certificates apply to.
- Your Apple Pay Merchant ID (the
merchant.<reverse-dns>string from the Developer portal). - A display name to show in the Apple Pay sheet.
- The Payment Processing Certificate and its private key, in PEM format. Always required.
- The Merchant Identity Certificate and its private key, in PEM format. Required only for Option 1.
- The list of domains you've already verified with Apple.
A Backoffice UI for self-service uploads is on the roadmap. NetValve loads what you send into the gateway, KMS-encrypts the private keys at rest, and tags the entry against your MID.
Runtime behaviour
Once your certificates are loaded against the MID, the runtime API is the same as Path A apart from domain registration and (optionally) session validation:
- Session validation — either:
POST /initializeApplePaySession— NetValve uses your Merchant Identity Certificate for the mTLS call to Apple. Resolution is MID-aware: if the request carriesnetvalveMidIdand that MID has its own certificate on file, NetValve uses it; otherwise the processor certificate is used as a fallback.- Or your backend POSTs to Apple's
validationURLdirectly, presenting your Merchant Identity Certificate. NetValve is not called in this step. You then pass the session blob to the browser as usual.
- Sale request (
applePaySSL) — NetValve decrypts the payload with your Payment Processing Certificate's private key before routing the authorisation to the acquirer. POST /registerApplePayDomain— not used in this path. All domain registration happens in the Apple Developer portal.
If you have multiple MIDs, you can mix-and-match: some MIDs on Path A (processor cert), others on Path B (your own cert). Each Sale request is routed by netvalveMidId.
Calling Apple's validationURL directly
If you choose Option 2, your backend handler for the onvalidatemerchant event POSTs to the validationURL Apple supplies (a different URL each time) with a JSON body and mTLS authentication.
{
"merchantIdentifier": "merchant.com.example.store",
"displayName": "Example Store",
"initiative": "web",
"initiativeContext": "shop.example.com"
}
merchantIdentifier— your Apple Merchant ID (themerchant.<reverse-dns>string).displayName— what the customer sees in the Apple Pay sheet.initiative—"web"for Apple Pay on the Web.initiativeContext— the hostname the customer is browsing.
The HTTPS client must present your Merchant Identity Certificate during the TLS handshake. Apple returns an opaque session object on success; pass it through to the browser and call session.completeMerchantValidation(...). See Apple's reference: Requesting an Apple Pay payment session.
The validation URL is single-use and short-lived (it expires within minutes). Do not cache responses across customers or transactions.
Renewals
Apple Pay certificates expire (typically two years for the Merchant Identity Certificate, around 25 months for the Payment Processing Certificate — check the exact expiry date in the Apple Developer portal). You're responsible for renewing them in your Apple Developer account and sending the new PEMs to NetValve before the old ones expire. NetValve will hot-swap the credentials without downtime, but if a certificate expires before replacement, session validation will fail and the Apple Pay button will silently stop working in customer browsers.
We recommend setting calendar reminders 30 and 7 days before each expiry.
Enable Apple Pay on Hosted Payment Page
If you use NetValve's Hosted Payment Page, Apple Pay can be enabled per MID from the Backoffice — no private key or certificate to upload. The HPP uses the same processor-certificate flow described above, so once your MID is enabled and the HPP domain is registered (hpp.netvalve.com is registered for you), the Apple Pay button will appear automatically on supported devices.
Testing
Apple Pay™ is available for testing in a Sandbox environment. Register your sandbox domains via POST /registerApplePayDomain against the UAT base URL (see Environments). Sandbox and production are separate Apple environments — you'll need to register each domain in both before going live. Contact the NetValve support department if you need help with sandbox setup.
Create a Sandbox Tester Account
To test Apple Pay end-to-end, you'll need an Apple sandbox tester account and a supported test device (iPhone 6 or later, iPad mini 3 or later, iPad Air 2, iPad Pro, or Apple Watch).
- Sign in to App Store Connect.
- On the homepage, click Users and Access.
- Under Sandbox, click Testers.
- Click + to set up a new tester account.
- Complete the tester information form and click Invite.
- On your test device, sign out of your Apple Account and sign back in using the new sandbox tester account.
For more details, see Apple's guide: Create a sandbox tester account.
Add a Test Card
Once signed into your test device with the sandbox tester account:
- Make sure you're signed out of iCloud on the device.
- Open Wallet and tap Add Credit or Debit Card.
- Enter one of Apple's published sandbox test card numbers manually.
- Once the card is added, you can begin testing.
Make sure your device's region is set to a country supported by the Apple Pay sandbox.