Think of Apple Pay as two moments that matter. First, you add a card to Apple Wallet. Second, you pay in a store or inside an app or on the web. If you can follow what actually happens in those two moments, you understand how the system works, why it is safer than typing card numbers, and what minimal code you need to write.
I will introduce each term only when we reach the point where you need it. Then I will keep moving so the story stays connected.
The two security parts inside your iPhone
There are two specialized components that make Apple Pay work safely.
The first is the Secure Element. It is a tiny, tamper-resistant chip whose job is to store very sensitive payment material and to run the small payment programs that respond to terminals. When you pay at a terminal, those programs prepare the response inside this chip. The response is then routed out over the near field communication path, not through normal application memory. Apple’s security material says this is deliberate so contactless payment details stay in the radio field and do not touch the main processor. (Apple Support)
The second is the Secure Enclave. It is a security coprocessor that checks your Face ID or Touch ID and enforces that a real person on the real device approved the payment. The Secure Enclave and the Secure Element do not plug into each other directly, so they establish a shared secret at runtime and use it to send an authorization signal that the Secure Element trusts. Apple’s platform notes also describe an Authorization Random value that helps the device invalidate old cards if the device state is rolled back. (Apple Support)
For the rest of this walkthrough, remember this mapping. Secure Element equals vault that stores tokens and creates the payment response. Secure Enclave equals bouncer that approves user intent and signals the vault to proceed.
What you add to Wallet is not your card number
When you add a card in Wallet, the system does not store your real card number on the phone. Instead, the card network or your bank creates a substitute number that behaves like your card for payments but is safe to keep on a device. This process is called tokenization in the EMV specifications. The substitute is a payment token that Apple calls a Device Account Number. It is specific to this device and to this card. The mapping from token back to the real card number lives in a token service at the network or issuer, not on your phone. EMVCo publishes the technical framework for this model, including roles and requirements. (EMVCo)
Here is the provisioning flow as one connected thread.
- You enter or scan your card. The device packages the card details with some device context and encrypts that package.
- Apple’s server forwards the encrypted package to the issuer or the network’s token service. The issuer may ask for a one time code or a bank app confirmation before approving.
- The token service generates a device-specific token with the keys it needs. The payload is wrapped so only this phone’s Secure Element can open it.
- The wrapped payload arrives at the device and the Secure Element installs it. The Wallet app shows a card face, but the sensitive token and keys live inside the Secure Element.
Apple’s security pages make two points that are easy to remember. For contactless payments, the payment response is prepared in the Secure Element and routed out to the terminal field, which keeps sensitive data out of app memory. For in-app and web payments, the payment data is encrypted by the Secure Element before it ever reaches Apple’s servers for relay. (Apple Support)
Two consequences matter to developers and users. Each device receives its own token for the same card, which means a lost phone can have its token suspended without reissuing the card. Merchants do not receive your real card number when you use Apple Pay. Apple summarizes this in the Apple Pay security and privacy overview. (Apple Support)
What really happens at the terminal
Double click, Face ID passes, phone meets reader. The conversation is short but precise.
The terminal begins by sending a small piece of unpredictable data, sometimes called a challenge. The phone’s NFC controller hands that to the Secure Element. The Secure Element selects the correct token, combines that challenge with counters and a secret that only it holds, and creates a one-time proof for this transaction. In payments this proof is called a cryptogram. You can think of it as a signed statement that says this exact device token approved this exact purchase once. The Secure Element returns the token plus that one-time proof. The NFC controller then routes the response directly into the radio field for the terminal to read. Apple’s platform security guide calls the NFC controller the gateway to the Secure Element for contactless transactions. (Apple Help)
From here the message follows the normal card rails. The merchant’s acquirer forwards the message to the card network. The network checks the cryptogram using keys associated with the token. If the check passes, the network maps the token back to the real card number and asks the bank to approve. If the bank approves, you see the green check and a receipt. Apple’s privacy page also restates that neither Apple nor the device sends the actual payment card number to the merchant. (Apple Support)
Why there is usually no terminal PIN prompt after you used Face ID. The transaction carries a flag that says cardholder verification was performed on the consumer device. The industry calls this Consumer Device Cardholder Verification Method, or CDCVM. EMVCo’s public notes explain how CDCVM works and why biometric or passcode on device is accepted as the verification method when implemented correctly. (EMVCo)
Two simple takeaways. The cryptogram is fresh every time, so replaying old data does not work. The token can be revoked or replaced without touching your real card number.
What really happens in an app or on the web
There is no terminal in this case, but the same two ideas still hold. You approve the payment on the device. You do not share the real card number with the merchant.
When you authorize Apple Pay in an app or in Safari, the device returns a payment token object to your code. It is a small, versioned JSON envelope. It contains an encrypted data blob, a signature, and a header that includes an ephemeral public key, a hash that ties the payload to your merchant key, and a transaction identifier. Apple’s Payment Token Format Reference shows the exact field names and structure. In your code you forward this object to your backend without unpacking it. Your backend hands it to your payment processor, who either decrypts with your merchant keys or routes it to the network for decryption and authorization. (Apple Developer)
A minimal example helps you see the shape without getting lost in options.
{
"version": "EC_v1",
"data": "BASE64_ENCRYPTED_DATA",
"signature": "BASE64_SIGNATURE",
"header": {
"ephemeralPublicKey": "BASE64_P256",
"publicKeyHash": "BASE64_SHA256",
"transactionId": "GUID"
}
}On the web there is one prerequisite that many teams miss once. Before the browser can show the Apple Pay sheet on your domain, you must complete two steps that are easy but exact. First, verify the domain by hosting an association file at the well-known path Apple provides for the merchant ID. Second, perform merchant validation for each checkout session by having your server call Apple’s validation endpoint with mutual TLS, then return the session JSON to the browser. Apple’s web docs have short pages for both tasks. If either step is skipped or misconfigured, the sheet will not appear. (Apple Developer)
Privacy and data boundaries in plain language
Apple describes three simple boundaries that help you reason about risk. In contactless transactions, the Secure Element prepares the payment response and the NFC controller routes it to the field, which keeps the sensitive parts out of app memory. In in-app and web transactions, the Secure Element encrypts the payment data before it reaches Apple servers, and the merchant does not receive your real card number. Those boundaries are why Apple Pay transactions tend to see lower fraud than typed card details. (Apple Support)
Code you actually need to write
On iOS your job is to present the Apple Pay sheet, then forward the opaque token object to your backend. Keep the snippet small and readable.
import PassKit
final class CheckoutVC: UIViewController, PKPaymentAuthorizationViewControllerDelegate {
func startApplePay() {
// Show the button only if Apple Pay is available with at least one supported network
guard PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: [.visa, .masterCard, .amex]) else {
// Show a setup path or another payment method
return
}
let req = PKPaymentRequest()
req.merchantIdentifier = "merchant.com.example"
req.countryCode = "US"
req.currencyCode = "USD"
req.supportedNetworks = [.visa, .masterCard, .amex]
req.merchantCapabilities = [.capability3DS]
req.paymentSummaryItems = [PKPaymentSummaryItem(label: "Order", amount: 9.99)]
guard let vc = PKPaymentAuthorizationViewController(paymentRequest: req) else { return }
vc.delegate = self
present(vc, animated: true)
}
func paymentAuthorizationViewController(
_ controller: PKPaymentAuthorizationViewController,
didAuthorizePayment payment: PKPayment,
handler completion: @escaping (PKPaymentAuthorizationResult) -> Void
) {
// Send payment.token to your backend, do not parse it on device
completion(PKPaymentAuthorizationResult(status: .success, errors: nil))
}
}That is the core pattern. Capability check, present sheet, forward token. The token structure is documented in the Payment Token Format Reference so your backend can treat it as an opaque payload and hand it to your processor. (Apple Developer)
On the web your job is to validate the merchant session on your server, then forward the token to your backend for authorization. Keep it short.
<button id="apple-pay" style="display:none">Buy with Apple Pay</button>
<script>
(async function () {
if (!window.ApplePaySession || !ApplePaySession.canMakePayments()) return;
document.getElementById('apple-pay').style.display = 'inline-block';
document.getElementById('apple-pay').onclick = async () => {
const request = {
countryCode: 'US',
currencyCode: 'USD',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa','masterCard','amex'],
total: { label: 'Order', amount: '49.00' }
};
const session = new ApplePaySession(6, request);
session.onvalidatemerchant = async (e) => {
// Your server calls Apple's validation endpoint using mTLS, then returns JSON
const res = await fetch('/apple-pay/validate', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ validationURL: e.validationURL })
});
session.completeMerchantValidation(await res.json());
};
session.onpaymentauthorized = async (e) => {
// Forward e.payment.token to your backend and complete based on the result
const ok = await fetch('/apple-pay/charge', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(e.payment.token)
}).then(r => r.ok);
session.completePayment(ok ? ApplePaySession.STATUS_SUCCESS : ApplePaySession.STATUS_FAILURE);
};
session.begin();
};
})();
</script>Two non-negotiables. Verify your domain by hosting the association file for each origin, including staging. Perform merchant validation from your server using mutual TLS and return the session to the browser. Apple’s docs cover both steps. (Apple Developer)
What changes if you are building for physical shops
If the point of sale terminals already accept EMV contactless, they can accept Apple Pay. There is nothing Apple specific to install on the terminal beyond keeping the contactless kernel current and honoring device verification for high values. CDCVM is the reason the terminal can skip a PIN after Face ID. EMVCo’s notes explain that model clearly so your acquirer configuration lines up with user expectations. (EMVCo)
If you are building software for sellers, Tap to Pay on iPhone lets an iPhone accept contactless payments without external hardware. The entitlement, security guarantees, and UX guidance are documented. The security foundation is the same set of platform protections that power Apple Pay. This is useful for micromerchants and pop-ups who want to reduce hardware friction. (Apple Developer)
A short glossary that matches the story
Secure Element. The vault chip that stores device tokens and produces payment responses. It talks to the terminal through the NFC controller. Apple’s security guides are explicit about this path. (Apple Help)
Secure Enclave. The bouncer that checks biometrics or passcode and signals authorization to the Secure Element using a secure channel created at runtime. Apple’s platform security pages describe the pairing keys and the Authorization Random value. (Apple Support)
Tokenization. The industry mechanism that replaces the real card number with a device-scoped token. EMVCo publishes the framework that explains token services, detokenization, and responsibilities. (EMVCo)
Cryptogram. A one-time proof generated per transaction that binds the token, device state, and transaction context. The card network validates it before asking the bank to approve. Apple’s security pages and EMVCo material together make this clear. (Apple Support, EMVCo)
CDCVM. Consumer Device Cardholder Verification Method. The industry term for using device biometrics or passcode as the cardholder verification. This is why a terminal can skip a PIN after a successful device check. EMVCo explains the concept and its security properties. (EMVCo)
Payment token object. The versioned JSON envelope your app or site receives for in-app and web payments. Apple’s Payment Token Format Reference lists the fields, the signature, and the encryption approach. (Apple Developer)
Merchant validation and domain verification. The two steps that enable Apple Pay on the Web on a given origin. Verification is a one time origin proof. Validation is the short server round trip that unlocks a session. Apple’s web docs separate them. (Apple Developer)
A final vertical view, from start to finish
- You add a card. The issuer or network creates a device-specific token and installs it securely inside the Secure Element. The mapping from token to real card number lives off device. (EMVCo)
- You pay in a store. The terminal sends a challenge. The Secure Element returns the token plus a one-time cryptogram. The network validates the cryptogram, then asks the bank to approve. The card number is not shared with the merchant. (Apple Help, Apple Support)
- You pay in an app or on the web. The device returns a versioned JSON payment token. Your backend forwards it to your processor. You do not process card numbers. (Apple Developer)
- You keep the web setup clean. Verify your domain and perform merchant validation on your server. If either step is missing, the sheet will not appear. (Apple Developer)
- You keep privacy in mind. Contactless details stay in the NFC path, and in-app or web payloads are encrypted before they leave the device. Merchants do not receive the real card number from Apple Pay. (Apple Support)
I found this pretty interesting.