← Payment Reference GuidesSecurity Reference

Payment Tokenization

How real card numbers (FPAN) are replaced by tokens (DPAN) for digital wallets, card-on-file, and IoT payments. Covers the full lifecycle, cryptogram generation, and the Visa VTS vs. Mastercard MDES service comparison.

Adding a card to Apple Pay and Google Wallet

There are two ways a card gets into a phone wallet. With manual provisioning the cardholder types or photographs the card in Apple Wallet or Google Wallet, and the issuer usually asks for an extra check (a code by SMS or email, or a confirmation in the bank app). With push provisioning the cardholder taps "Add to Apple Wallet" / "Add to Google Wallet" inside the bank's own app, the card data never passes through the user's hands, and the issuer can approve instantly because the user is already logged in.

Who does what

PartyRole in push provisioning
Issuer appShows the add button, checks whether the card is already in the wallet, and relays inputs between the wallet SDK and its backend. It never encrypts card data on the phone.
Issuer backendEncrypts the card for the network token service and adds an authentication value that proves the request came from the issuer. Often done by the issuer processor, or by the network's own API.
Wallet (Apple, Google, Samsung)The token requestor. It carries the encrypted card to the network without being able to read it, and stores the resulting token on the device.
Network TSP (Visa VTS, Mastercard MDES…)Decrypts the card, checks the authentication value, asks the issuer to approve, creates the token and its keys, and manages its lifecycle.

Animated flows — Apple In-App, Google push, Wallet Extensions, yellow path

The cardholder taps "Add to Apple Wallet" in the bank app. The bank never encrypts on the phone: its backend encrypts the card for the payment network using Apple’s certificate chain and a one-time nonce, and the network’s token service issues a Device Account Number into the Secure Element.

1 / 11
📱Issuer appPassKit
🍎AppleWallet + servers
🏦Issuer backendEncrypts card
🔗Network TSPVTS / MDES
1
Eligibility check
2
Present PKAddPaymentPassViewController
3
certificateChain + nonce + nonceSignature
4
Forward to issuer backend
5
Build the encrypted payload
6
PKAddPaymentPassRequest
7
Completion handler
8
Tokenize request
9
Issuer decision
10
Token issued
11
didFinishAdding
Initiation

Eligibility check

canAddSecureElementPass(primaryAccountIdentifier:) — hide the button if every device already has the card.

Requires the com.apple.developer.payment-pass-provisioning entitlement, which Apple grants on request. primaryAccountIdentifier is an opaque issuer value, not the PAN; compare it with the passes on the iPhone (passes(of: .secureElement)) and a paired Apple Watch (remoteSecureElementPasses).

Initiation
Issuer Risk Check
Response
Provisioning
ID&V
Completion

Apple Pay: In-App Provisioning

The app needs Apple's com.apple.developer.payment-pass-provisioning entitlement, which Apple grants to issuers on request. Before showing the button it calls PKPassLibrary.canAddSecureElementPass(primaryAccountIdentifier:) and compares the opaque primaryAccountIdentifier with the passes already on the iPhone and a paired Apple Watch, so the button disappears once every device has the card.

Tapping it presents PKAddPaymentPassViewController with a PKAddPaymentPassRequestConfiguration: the encryption scheme (ECC_V2 or RSA_V2), cardholder name, last digits, description and optionally the payment network. It is for display only and must hold nothing sensitive. PassKit then calls the delegate with three inputs:

  • certificateChain: DER X.509 certificates, leaf first. The backend validates the chain to the root; the leaf key is what the card is encrypted to.
  • nonce: a one-time value from Apple's servers.
  • nonceSignature: a device-specific signature over the nonce.

The backend returns, within 20 seconds, a PKAddPaymentPassRequest: encryptedPassData (the encrypted JSON {primaryAccountNumber, expiration, name, nonce, nonceSignature}), activationData (a network-defined one-time value that Apple passes on without reading), and ephemeralPublicKey for ECC_V2 or wrappedKey for RSA_V2. Including the nonce and its signature binds the payload to this session and this device.

Wallet Extensions (iOS 14+) let the user start from Apple Wallet itself. A non-UI extension (PKIssuerProvisioningExtensionHandler) reports status() and lists cards via passEntries() and remotePassEntries() (Apple Watch); a UI extension signs the user in with the bank app's credentials when requiresAuthentication is set. The encryption step is identical to the in-app flow.

Google Wallet: push provisioning

Access is allowlisted by Google: the issuer registers its package name and signing certificates. The app uses TapAndPay.getClient(activity), checks isTokenized or listTokens(), then asks its backend for an Opaque Payment Card (OPC): the card encrypted for the network TSP. It calls pushTokenize with a PushTokenizeRequest (setOpaquePaymentCard, setNetwork, setTokenServiceProvider, setDisplayName, setLastDigits, setUserAddress). On success the activity result carries EXTRA_ISSUER_TOKEN_ID.

Token states are UNTOKENIZED, PENDING, NEEDS_IDENTITY_VERIFICATION, SUSPENDED and ACTIVE; a token stuck in identity verification is resumed with tokenize(…). Since July 2025 new issuers default to Unified Android Push Provisioning (UAPP), which returns a second, PGP-encrypted Google OPC so the card is also saved to the user's Google account. Google also offers push provisioning from the issuer's website (googlepay.openAppWindow plus a PGP-encrypted server notification).

Google Wallet tokens are cloud (HCE) tokens: the phone gets short-lived keys that are replenished, unlike Apple Pay's Secure Element.

What the network needs: encrypted card + authentication value

Both wallets carry the same two things, in their own wrapping. With Mastercard, the issuer or its processor gets them from MDES APIs:

  • Google / Samsung: POST /cards/{id}/android-iidds returns Issuer-Initiated Digitization Data: base64 JSON with cardInfo (Mastercard field-level encryption: encryptedData, encryptedKey, publicKeyFingerprint, oaepHashingAlgorithm, iv) and a signed tokenizationAuthenticationValue. That is the OPC.
  • Apple: POST /cards/{id}/apple-iidds takes Apple's nonce, nonce signature and certificates and returns encryptedPassData, ephemeralPublicKey and the same authentication value as activationData.
  • Token Connect (any token requestor, incl. merchants): pushAccount returns a push account receipt valid for up to 15 minutes, which the requestor redeems instead of receiving card data.

Visa's equivalent is VTS in-app provisioning, where card fields prefixed enc are JWE (RSA-OAEP-256 or A256GCMKW, with A256GCM). Paste any of these into the Wallet Provisioning Inspector to identify and check the structure.

Apple Pay vs Google Wallet vs Samsung Wallet

AttributeApple PayGoogle WalletSamsung Wallet
Issuer accessEntitlement granted by AppleAllowlist (package + signing certs)Samsung Pay partner onboarding
App APIPKAddPaymentPassViewController, Wallet ExtensionsTapAndPay.pushTokenizeCardManager.addCard with a provision payload
Encrypted cardencryptedPassData + ephemeralPublicKey / wrappedKeyOpaque Payment Card (+ Google OPC under UAPP)Provision payload (for Mastercard the same IIDD as Google)
Session bindingApple nonce + device nonce signature inside the payloadWallet ID and stable hardware ID used when building the OPC
Token storageSecure Element (Device Account Number)Cloud / HCE with replenished keysOn the Samsung device (varies by model)
Start from walletWallet Extensions (iOS 14+)
Step-up via bank appPKPassLibrary.activate(_:activationData:)App-to-app ID&V intent, BANKING_APP_ACTIVATION_RESPONSEApp-to-app ID&V

Green, yellow and red paths

For every add, the issuer (through the TSP) decides: green, approve now; yellow, approve after extra verification; red, decline. Push provisioning with a valid authentication value usually lands on green. On yellow, the wallet offers the issuer's verification methods; the best one is app-to-app: Google Wallet opens the bank app with an issuer-defined intent (base64 JSON in EXTRA_TEXT) and the app answers approved or declined; on iOS the bank app completes activation with PKPassLibrary.activate(_:activationData:) while the pass is requiresActivation.

After activation the token is managed by the issuer through the TSP: suspend, resume and delete, card replacement (the token survives a new card number or expiry), and card-art updates. Mastercard notifies token requestors with notifyTokenUpdated; issuers act through MDES and VTS customer-service and lifecycle APIs.

Keep reading

Related articles