Digital Wallet Integration
Executive Summary
Apple Pay and Google Pay integration through the gateway requires fundamentally different work for card-present (NFC) vs. card-not-present (web/in-app) flows.
Card-present (NFC): Traditional certified terminals handle EMV contactless before the gateway receives the transaction. Do not use EMV_CONTACTLESS as a confirmed TransIT value; the local TransIT source list contains EMV and CONTACTLESS, and the EMVContactless samples submit cardDataSource = EMV.
Card-not-present: Gateway exposes wallet endpoints through online-txn, delegates wallet sale/authorization to processing, and publishes matching Kotlin/TypeScript SDK methods. Current architecture uses processor decryption (Apple Pay) and PAYMENT_GATEWAY tokenization (Google Pay) so encrypted wallet tokens remain opaque to gateway services.
Remaining production work: keep merchant/account configuration, certificate rotation, processor routing, and TSYS certification evidence aligned before production cutovers.
Architecture Overview
┌─────────────────────────────────────────────────────────────────┐
│ CARD-PRESENT (NFC) │
│ │
│ iPhone/Android ──NFC──► Terminal ──EMV Contactless──► Gateway │
│ │
│ Gateway action: submit terminal EMV/contactless result to TransIT│
│ Decryption: NONE (terminal + card network handle it) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ CARD-NOT-PRESENT: APPLE PAY │
│ │
│ 1. Browser → Gateway: POST /apple-pay/session │
│ Gateway → Apple (mTLS): validate merchant │
│ Gateway → Browser: merchantSession │
│ │
│ 2. Browser → Gateway: POST /apple-pay/charge │
│ { applePayToken: "<encrypted PKPaymentToken>" } │
│ Gateway → TransIT: digital wallet charge │
│ { walletType: APPLE_PAY, encryptedToken: "..." } │
│ TransIT decrypts (holds Payment Processing Cert) │
│ │
│ Decryption: TransIT (processor decryption model) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ CARD-NOT-PRESENT: GOOGLE PAY │
│ │
│ 1. Browser → Gateway: GET /google-pay/config │
│ Returns: { gateway: "tsys", gatewayMerchantId: "..." } │
│ (No session validation needed) │
│ │
│ 2. Browser → Gateway: POST /google-pay/charge │
│ { googlePayToken: "<ECv2 encrypted token>" } │
│ Gateway → TransIT: digital wallet charge │
│ { walletType: GOOGLE_PAY, encryptedToken: "..." } │
│ TransIT decrypts (PAYMENT_GATEWAY mode, holds private key) │
│ │
│ Decryption: TransIT (PAYMENT_GATEWAY tokenization) │
└─────────────────────────────────────────────────────────────────┘
Section 1: Apple Pay
Card-Present (NFC Tap)
No gateway-specific logic required. When a customer taps an iPhone/Apple Watch on an NFC terminal:
- Device Secure Element communicates via NFC using EMVCo contactless spec (ISO/IEC 14443).
- Secure Element passes DPAN (Device PAN), dynamic cryptogram (TAVV), and transaction details to the terminal.
- Terminal processes as standard EMV contactless, sends to gateway normally.
- Gateway forwards the terminal-originated EMV/contactless result to TransIT using the certified terminal integration mapping.
- Card network detokenizes DPAN to FPAN and authorizes with issuer.
Card-Not-Present (Web / In-App)
Two server-side steps required:
Step A: Merchant Session Validation (Web only)
Before the Apple Pay sheet appears, Apple requires server-side merchant validation:
- Browser calls
new ApplePaySession(version, paymentRequest)andonvalidatemerchantfires. - Event provides a
validationURL(Apple server URL). - Gateway makes mTLS POST to
validationURLusing the Merchant Identity Certificate (.p12 from Apple Developer portal). - Apple returns a
merchantSessionopaque object. - Gateway returns it to browser and
session.completeMerchantValidation(). - Payment sheet appears.
Gateway endpoint: POST /v1/wallet/apple-pay/session
Step B: Payment Token Handling
After Face ID / Touch ID auth, Apple generates a PKPaymentToken containing:
paymentData: encrypted blob (DPAN + TAVV cryptogram + transaction details)paymentMethod: card network, display name, typetransactionIdentifier: unique transaction ID
Two decryption paths:
| Path | Who Decrypts | PCI Impact |
|---|---|---|
| Processor Decryption (recommended) | TransIT/TSYS holds cert | Gateway stays out of scope |
| Merchant Decryption | Gateway decrypts | SAQ-D scope, avoid |
Recommendation: Use processor decryption. Register Payment Processing Certificate with TSYS/TransIT. Gateway passes raw paymentData blob through opaquely.
Apple Pay Registration Requirements
| Asset | Description | Rotation |
|---|---|---|
| Apple Developer Account (Organization, $99/yr) | Required for all certs | Annual |
Merchant ID (merchant.com.myriad.gateway) | Registered in Apple portal | Never expires |
| Payment Processing Certificate | Public key encrypts tokens; private key held by TSYS | Annually |
| Merchant Identity Certificate (.p12) | mTLS cert for session validation | Every 25 months |
| Domain Verification File | .well-known/apple-developer-merchantid-domain-association | Per domain, one-time |
For multi-tenant: Apply for Apple's Payment Platform status to use the Web Merchant Registration API for programmatic domain registration.
For operational setup and rotation, keep certificate and key material out of
Terraform state. Terraform creates the Secret Manager containers and Cloud Run
bindings; operators upload Apple-issued certificate/key versions out-of-band.
Use the secrets rotation runbook
for the current CSR, upload, redeploy, and verification procedure. For local
synthetic-token development only, use scripts/generate-apple-pay-keys.sh.
Apple Pay / TSYS Material
Apple Pay / TSYS credential material includes Apple Pay payment-processing certificate material, Apple WWDR G2 certificate files, and password/private-key files for processor upload workflows. Do not copy these files or passwords into documentation. Move live secrets into the approved secret-management path before implementation, and track only non-secret inventory metadata under the source root.
This material is evidence for the Apple Pay card-not-present processor-decryption workstream. Apple Tap to Pay on iPhone is a separate Apple-native path: ABR / Partner Hub setup, PSP KEK and terminal-profile artifacts, Proximity Payment Service configuration, and card-present network certification evidence must be verified from the Apple partner/onboarding records without copying secret material into repo docs.
Section 2: Google Pay
Card-Present (NFC Tap)
Identical to Apple Pay card-present. Standard certified-terminal EMV contactless, with no Google Pay-specific gateway logic for the tap itself. The exact cardDataSource value belongs to the terminal/TransIT certification profile; local EMVContactless samples use EMV.
Card-Not-Present (Web / Android)
Simpler than Apple Pay, no merchant session validation required.
- Client initializes
PaymentsClientwith gateway config. - User taps Google Pay button, selects card, authenticates.
- Google returns encrypted
PaymentMethodToken(ECv2 protocol). - Client sends token to gateway.
- Gateway passes through to TransIT.
Tokenization Modes
PAYMENT_GATEWAY (recommended):
const tokenizationSpecification = {
type: 'PAYMENT_GATEWAY',
parameters: {
'gateway': 'tsys', // Must confirm with TSYS
'gatewayMerchantId': 'YOUR_MERCHANT_ID'
}
};
- Google encrypts with TransIT's public key (registered by TSYS with Google).
- Gateway passes encrypted blob straight through.
- No key management. No PCI scope increase.
DIRECT (not recommended):
- Google encrypts with your gateway's ECDSA public key.
- Gateway must decrypt using Google's Tink library.
- Requires annual key rotation and PCI DSS compliance for card data.
Auth Methods in Google Pay Tokens
| Method | Description | Security |
|---|---|---|
CRYPTOGRAM_3DS | Device-bound DPAN + TAVV cryptogram | Higher, equivalent to Apple Pay |
PAN_ONLY | Card stored in Google account, no device binding | Lower, returns real PAN, no cryptogram |
Google Pay Registration
- Create profile at https://pay.google.com/business/console
- Accept Terms of Service.
- Merchant ID appears in console.
- Submit integration for production review.
- No domain verification file needed. No mTLS certificates needed.
Google Pay API vs Google Wallet
| Google Pay API | Google Wallet | |
|---|---|---|
| Purpose | Accept payments | Store passes/loyalty/transit |
| Our use case | Yes | Not relevant |
| Token type | PaymentMethodToken (ECv2) | N/A |
Section 3: TransIT API Integration
Card-Present Fields
| Field | Current local evidence | Notes |
|---|---|---|
cardDataSource | EMV in local EMVContactless samples; CONTACTLESS listed in the support-doc source table | EMV_CONTACTLESS is not confirmed in the local TransIT materials reviewed so far |
| EMV tag data | Standard EMV/contactless tags in emvTags.tag[] | Terminal handles card read and emits the tag set |
Card-Not-Present Fields
Based on TSYS-family processor documentation (Heartland Portico WalletData):
| Field | Values | Description |
|---|---|---|
PaymentSource | ApplePayWeb, ApplePayApp, GooglePayWeb, GooglePayApp | Wallet type |
Cryptogram | Base64/Hex encoded | TAVV (Apple) or TAVV/DSRP (Google) |
ECI | 05, 06, 07 | Electronic Commerce Indicator |
WalletType | APPLE_PAY, GOOGLE_PAY | Processor-level wallet identifier |
Certification
TSYS was among the first processors certified for Apple Pay (2015). Digital wallet certification involves:
- Running test transactions through TSYS sandbox (
stagegw.transnox.com) - Wallet-specific test data scenarios
- Passthrough mode, simpler certification than decryption mode
Section 4: PCI Scope Impact
Token Types
| Token Type | What It Is | PCI Scope |
|---|---|---|
| FPAN (Funding PAN) | Real card number | Full scope, never touch |
| DPAN (Device PAN) | Network token (DPAN != FPAN) | In scope if decrypted |
| Encrypted PKPaymentToken | Apple's encrypted blob | Out of scope if passthrough |
| Encrypted ECv2 token | Google's encrypted blob | Out of scope if passthrough |
| Cryptogram (TAVV) | One-time auth value | In scope only if decrypted |
By Integration Path
| Path | PCI Impact |
|---|---|
| Full passthrough (recommended) | Minimal, encrypted tokens are not cardholder data |
| Gateway decrypts | SAQ-D scope, HSM required, annual QSA audit |
| Card-present NFC | Same as existing EMV scope |
Recommendation: Use PAYMENT_GATEWAY (Google) + processor decryption (Apple). Gateway never sees plaintext DPAN or cryptogram. No PCI scope expansion.
Section 5: Current Gateway Surface
Public Wallet Endpoints
Apple Pay
| Endpoint | Method | Runtime role | Source of truth |
|---|---|---|---|
/v1/wallet/apple-pay/session | POST | Merchant session validation (mTLS to Apple) | Public OpenAPI, online-txn WalletController, SDK WalletApi |
/v1/wallet/apple-pay/charge | POST | Process Apple Pay token (CNP) | Public OpenAPI, online-txn WalletController, SDK WalletApi |
/v1/wallet/apple-pay/authorize | POST | Authorize Apple Pay token (CNP) | Public OpenAPI, online-txn WalletController, SDK WalletApi |
Google Pay
| Endpoint | Method | Runtime role | Source of truth |
|---|---|---|---|
/v1/wallet/google-pay/charge | POST | Process Google Pay token (CNP) | Public OpenAPI, online-txn WalletController, SDK WalletApi |
/v1/wallet/google-pay/authorize | POST | Authorize Google Pay token (CNP) | Public OpenAPI, online-txn WalletController, SDK WalletApi |
/v1/wallet/google-pay/config | GET | Return gateway/merchantId config | Public OpenAPI, online-txn WalletController, SDK WalletApi |
Card-Present
No new endpoints are required for traditional certified-terminal NFC. SoftPOS / Tap to Pay on iPhone remains card-present certification work; host-submission mapping stays governed by the TransIT SoftPOS mapping boundary and disabled capability flag until TSYS evidence confirms the request fields.
SDK Surface
class WalletApi(private val client: HttpClient) {
suspend fun validateApplePaySession(request: ApplePaySessionRequest): ApplePaySession
suspend fun chargeApplePay(request: ApplePayChargeRequest): WalletChargeResult
suspend fun authorizeApplePay(request: ApplePayAuthorizeRequest): WalletChargeResult
suspend fun getGooglePayConfig(): GooglePayConfig
suspend fun chargeGooglePay(request: GooglePayChargeRequest): WalletChargeResult
suspend fun authorizeGooglePay(request: GooglePayAuthorizeRequest): WalletChargeResult
}
The TypeScript SDK exposes the same wallet surface through GatewayPayClient.wallet and WalletApi.
Certificates & Keys
| Asset | Who Holds It | Storage | Rotation |
|---|---|---|---|
| Apple Merchant Identity Certificate (.p12) | Gateway | Secret Manager | Every 25 months |
| Apple Payment Processing Cert private key | TSYS (processor decryption) | N/A | Annually |
| Apple domain verification file | Gateway domain | Cloud Run / CDN | One-time per domain |
| Google Pay ECDSA key pair | N/A (PAYMENT_GATEWAY mode) | N/A | N/A |
| Google Pay Merchant ID | Configuration | Spanner / config | N/A |
Third-Party Registrations
| Registration | Where | Operational owner |
|---|---|---|
| Apple Developer Account (Organization) | developer.apple.com | Gateway platform / business owner |
| Apple Merchant ID + certs | Apple Developer portal | Gateway platform |
| Apple Pay Web Merchant Registration API | Apple (application) | Gateway platform |
| Google Pay & Wallet Console | pay.google.com/business/console | Gateway platform |
| Google Pay production approval | Google review | Gateway platform / merchant onboarding |
| TSYS digital wallet certification | TSYS account team | Gateway platform / certification owner |
| SoftPOS / Tap to Pay processor mapping | TSYS account team | Card-present certification owner |
Remaining Production Controls
| Control | Current boundary |
|---|---|
| Merchant wallet registration | Keep per-merchant Apple/Google IDs aligned with management and online-txn configuration before enablement. |
| Certificate rotation | Store Apple Merchant Identity certificates in Secret Manager and rotate before the 25-month expiration. |
| Processor routing | Do not change TransIT wallet-token serialization or processor routing without certification evidence. |
| SoftPOS / Tap to Pay | Keep production host submission disabled until the TransIT mapping questions in the TransIT integration doc are answered. |
Section 6: Vendor Verification Boundaries
The gateway owns the card-not-present wallet flow: Apple Pay merchant-session validation, Google Pay configuration, wallet charge/authorize endpoints, Apple merchant registration, and processing handoff are implemented in the online-txn, management, processing services, and SDKs. Vendor and account-team confirmation is still required before changing processor routing or certification scope:
- Google Pay gateway identifier: keep the configured
PAYMENT_GATEWAYtokenization identifier aligned with the TSYS/TransIT account profile. - Apple Pay processor-decryption registration: confirm Payment Processing Certificate registration, certificate rollover, and merchant registration with Apple/TSYS before production cutovers.
- TransIT wallet-token fields: validate encrypted-token and decrypted-field mappings against authenticated TransIT docs and certification evidence before changing request serialization.
- Certification scope and timing: schedule separate wallet transaction certification for Apple Pay and Google Pay when enabling new merchant or processor profiles.
- Multi-merchant wallet configuration: confirm whether each merchant/location needs separate Apple, Google, and TSYS registration or can share the gateway profile.
- Card-present Tap to Pay/SoftPOS: treat Tap to Pay on iPhone and terminal contactless output as separate card-present certification work; local
EMVContactlesssamples are not sufficient network evidence by themselves.
Reference Links
| Resource | URL |
|---|---|
| Apple Pay Platform Integration Guide | https://developer.apple.com/download/files/Apple-Pay-Platform-Integration-Guide.pdf |
| Apple Pay Token Format Reference | https://developer.apple.com/documentation/passkit/payment-token-format-reference |
| Apple Pay Environment Setup | https://developer.apple.com/documentation/applepayontheweb/configuring-your-environment |
| Google Pay Web API | https://developers.google.com/pay/api/web/overview |
| Google Pay Payment Data Cryptography | https://developers.google.com/pay/api/web/guides/resources/payment-data-cryptography |
| Google Pay Console | https://pay.google.com/business/console |
| GOV.UK Pay Connector (reference impl) | https://github.com/alphagov/pay-connector |
| Adyen Apple Pay Decryption | https://docs.adyen.com/payment-methods/apple-pay/api-only/apple-pay-token-decryption |
| TransIT Developer Portal | https://developers.tsys.com |