> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Direct Apple Pay integration

> Decrypt Apple Pay tokens on your server and pass the decrypted result to Waffo in the required format.

For a direct integration, use Apple Pay JS or PassKit to obtain the Apple Pay token and send it to Waffo from your server.

You manage:

* an Apple Developer account and Merchant ID;
* a Payment Processing Certificate and its private key;
* domain verification for Apple Pay on the Web;
* the Apple Pay JS or PassKit frontend integration;
* token signature verification, decryption, replay protection, and sensitive-data compliance.

Before you begin, contact Waffo technical support to confirm the Merchant and payment method configuration.

## Currently supported: Send a decrypted token

You must currently decrypt the Apple Pay token on your server and send the decrypted result to Waffo in the format below.

<Info>
  The request must contain `token.decryptedPaymentData`. You may also keep `token.paymentData`, but you cannot submit it as the only pass-through result.
</Info>

## Original encrypted token structure

Apple Pay JS or PassKit returns the following original payment token envelope. This object is currently the input for signature verification and decryption on the Merchant server. It is not a [`paymentTokenData`](/docs/api-reference/order-create/create-new-order#body-payment-token-data) value that you can submit directly to Waffo.

```json theme={null}
{
  "billingContact": {
    "countryCode": "US",
    "givenName": "wz",
    "familyName": "w",
    "postalCode": "20001",
    "addressLines": ["dk", "dh"],
    "administrativeArea": "AL",
    "locality": "djj"
  },
  "token": {
    "paymentMethod": {
      "network": "MasterCard",
      "type": "credit",
      "displayName": "MasterCard 4444"
    },
    "transactionIdentifier": "e392617d9e2f7938ca727c6fd063dc7915e42f546bca810ea43f7c2759c52a26",
    "paymentData": {
      "data": "<encrypted_data>",
      "signature": "<signature>",
      "header": {
        "publicKeyHash": "<public_key_hash>",
        "ephemeralPublicKey": "<ephemeral_public_key>",
        "transactionId": "<transaction_id>"
      },
      "version": "EC_v1"
    }
  }
}
```

| Field                         | Description                                                                                                                                 |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `token.paymentData`           | The encrypted payment data, which the Merchant currently decrypts with the certificate private key                                          |
| `token.paymentMethod.network` | The card network, such as `MasterCard` or `Visa`                                                                                            |
| `billingContact`              | The billing contact returned when Apple Pay JS requests `requiredBillingContactFields`; it supplies the cardholder name and billing address |

## Decrypt and validate the token

In the token returned by Apple Pay JS or PassKit, `token.paymentData` contains the encrypted payment data. On your server:

<Steps>
  <Step title="Select the decryption key">
    Use the private key that matches the Payment Processing Certificate.
  </Step>

  <Step title="Validate the token">
    Verify the token signature and certificate chain according to Apple's specification.
  </Step>

  <Step title="Decrypt the payment data">
    Decrypt `token.paymentData.data` according to the token `version`, then parse the UTF-8 result as JSON.
  </Step>

  <Step title="Validate the transaction">
    Confirm that `transactionId` has not been processed, and compare the decrypted currency and amount with the order.
  </Step>

  <Step title="Build the Waffo request">
    Put the decrypted JSON in `token.decryptedPaymentData`, then submit it to Waffo.
  </Step>
</Steps>

Follow Apple's [Payment token format reference](https://developer.apple.com/documentation/PassKit/payment-token-format-reference) for the complete cryptographic procedure and field definitions. See [Setting up Apple Pay](https://developer.apple.com/documentation/PassKit/setting-up-apple-pay) for certificate setup.

<Warning>
  Decrypted data contains the device account number and payment cryptogram. Do not decrypt it in the browser or log the complete token, device account number, private key, or payment cryptogram.
</Warning>

## Decrypted payload structure

Decrypting `token.paymentData` produces the payment token payload defined by Apple:

```json theme={null}
{
  "applicationPrimaryAccountNumber": "5555555555554444",
  "applicationExpirationDate": "270831",
  "currencyCode": "156",
  "transactionAmount": 10,
  "deviceManufacturerIdentifier": "050110030273",
  "paymentDataType": "3DSecure",
  "paymentData": {
    "onlinePaymentCryptogram": "AORgiMGqVyeCAAt1LKSuAoABFA==",
    "eciIndicator": ""
  }
}
```

MPAN scenarios for Subscription payments also include Merchant Token information such as `merchantTokenIdentifier`.

| Field                                 | Description                                                                        |
| ------------------------------------- | ---------------------------------------------------------------------------------- |
| `applicationPrimaryAccountNumber`     | Device account number (DPAN)                                                       |
| `applicationExpirationDate`           | Card expiration date as six digits in `YYMMDD` format                              |
| `paymentData.onlinePaymentCryptogram` | 3DS cryptogram used for payment verification; it may be empty                      |
| `paymentDataType`                     | Payment data type: `3DSecure` or `EMV`                                             |
| Other fields                          | Supporting data such as the device identifier, ECI, and Merchant Token information |

## Pass-through format

The decrypted payload alone is insufficient. It does not contain the card network, and an Apple Pay DPAN BIN generally cannot be used to determine the network. `billingContact` is also outside the encrypted data and is the only source of the cardholder name and billing address. Preserve the outer structure returned by Apple Pay and add `token.decryptedPaymentData` inside `token`. You may also keep `token.paymentData`.

The following JSON is the content of the [`paymentTokenData`](/docs/api-reference/order-create/create-new-order#body-payment-token-data) field in [`/api/v1/order/create`](/docs/api-reference/order-create/create-new-order):

```json theme={null}
{
  "billingContact": {
    "countryCode": "US",
    "givenName": "wz",
    "familyName": "w",
    "postalCode": "20001",
    "addressLines": ["dk", "dh"],
    "administrativeArea": "AL",
    "locality": "djj"
  },
  "token": {
    "paymentMethod": {
      "network": "MasterCard",
      "type": "credit",
      "displayName": "MasterCard 4444"
    },
    "transactionIdentifier": "e392617d9e2f7938ca727c6fd063dc7915e42f546bca810ea43f7c2759c52a26",
    "decryptedPaymentData": {
      "applicationPrimaryAccountNumber": "5555555555554444",
      "applicationExpirationDate": "270831",
      "currencyCode": "156",
      "transactionAmount": 10,
      "deviceManufacturerIdentifier": "050110030273",
      "paymentDataType": "3DSecure",
      "paymentData": {
        "onlinePaymentCryptogram": "AORgiMGqVyeCAAt1LKSuAoABFA==",
        "eciIndicator": ""
      }
    }
  }
}
```

[`paymentTokenData`](/docs/api-reference/order-create/create-new-order#body-payment-token-data) is a `String` in the create-order API. Serialize the complete object as a JSON string before submitting the request:

```typescript theme={null}
const paymentTokenData = JSON.stringify(decryptedApplePayPayload);
```

When Waffo detects `token.decryptedPaymentData`, it prioritizes the decrypted token and skips platform decryption.

## Field requirements

| Field                                                            | Requirement | Description                                                                                                                                 |
| ---------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `token.decryptedPaymentData.applicationPrimaryAccountNumber`     | Required    | Device account number (DPAN)                                                                                                                |
| `token.decryptedPaymentData.applicationExpirationDate`           | Required    | Six digits in `YYMMDD` format                                                                                                               |
| `token.paymentMethod.network`                                    | Required    | Card network copied unchanged from the outer structure of the original token                                                                |
| `billingContact`                                                 | Recommended | Source of the cardholder name and billing address; pass the complete object when Apple Pay returns it                                       |
| `token.decryptedPaymentData.paymentData.onlinePaymentCryptogram` | Optional    | 3DS payment cryptogram; pass it unchanged when present                                                                                      |
| Other fields in `token.decryptedPaymentData`                     | Optional    | Pass fields such as `paymentDataType`, `deviceManufacturerIdentifier`, `eciIndicator`, and `merchantTokenIdentifier` unchanged when present |

<Note>
  Only Apple Pay accepts decrypted token pass-through. Google Pay tokens must be submitted in encrypted form.
</Note>
