# Apple Pay

Fetch Apple Pay configuration from the gateway, run the Apple Pay JS session on your payment page, and authorize the resulting token with CCAUTHCAP.

Source: https://developer.inoviopay.com/api/apple-pay.html  
Markdown: https://developer.inoviopay.com/api/apple-pay.md

## Apple Pay overview

This section covers sending credit card transactions to the gateway using Apple Pay.

To accept Apple Pay, the web pages that host your payment forms must have their domains registered with Apple. See the *Apple Pay Registration Process* document for details. The Processor and Merchant Account you use must also support Apple Pay; contact your gateway support representative to confirm this.

Customers using Apple devices (iPhone, iPad, MacBook, etc.) with an Apple browser (Safari) are able to use Apple Pay to make purchases. The rest of this page describes how to set up an Apple Pay purchase on your hosted payment page and send the resulting authorization to the gateway API.

> **Real cards required for production testing**
> Test cards will not work when testing Apple Pay in a production environment. Real cards must be used.

## Integration flow

This is the order in which you set up Apple Pay processing:

1. Fetch the Apple Pay configuration data from the gateway.
2. Update the configuration with the specific payment/order details.
3. Present the Apple Pay button.
4. Add the Apple Pay library to the payment page.
5. Create a JS function to validate your domain.
6. Create and start the Apple Pay session.
7. Get the authorized payment information from the customer's browser.
8. Send the transaction to the gateway.

Each step is discussed below with example code. The example code is illustrative only and does not represent code that can be used as-is in a production environment.

## Fetching your Apple Pay configuration

You need configuration data from the gateway to set up the Apple Pay session when the customer clicks the Apple Pay button.

**POST** `https://api.inoviopay.com/payment/applepay.cfm`

Requests must be made in JSON format.

### Request parameters

| Field Name | Description |
|---|---|
| `REQ_USERNAME` (required) | API credential username. |
| `REQ_PASSWORD` (required) | API credential password. |
| `DOMAIN_NAME` (required) | Domain name where the payment page is hosted/served from. |
| `CLIENT_ID` (required) | Client ID. |
| `REQUEST_ACTION` (required) | `APPLEPAYCONFIG`. Used to instruct the endpoint to provide the Apple Pay configuration. |

All parameters are required.

### Response

The response is a JSON-formatted string:

```json
{
    "APPLEPAY_CLI_CONF_ID": xx, // internal unique id; do not change
    "REQ_ID": 11111111111, // trace ID, used for troubleshooting
    "CLIENT_ID": 1111111, // your gateway api client_id
    "INITIATIVE": "web", // identifies e-commerce transaction
    "DISPLAY_NAME": "xxxxxxx", // Short, localized description of the merchant.
    "PARTNER_MERCH_NAME": "xxxxxx", // name of the merchant
    "PARTNER_INTERNAL_MERCH_ID": "xxxxxxxxxxxxx", // identifies the merchant to apple
    "ENCRYPT_TO": "xxxxxxxxxxxxxxxxxxxx", // merchant ID to Apple
    "DOMAIN_LIST": [ // domain registered in Inovio portal serving this page
      {
        "DOMAIN_NAME": "paymentpagedomain.com",
        "DOMAIN_STATUS": "ACTIVE"
      }
    ],
    "paymentRequest": {
      "countryCode": "US",
      "currencyCode": "USD",
      "merchantCapabilities": [
        "supports3DS"
      ],
      "supportedNetworks": [
        "visa",
        "masterCard"
      ],
      "requiredBillingContactFields": [
        "postalAddress",
        "name",
        "phoneticName",
        "phone",
        "email"
      ],
      "total": {
        "label": "", // required; a short, localized description of the line item
        "type": "final", // do not change
        "amount": 0 // must be greater than or equal to zero
      }
    },
    "fetchUrl": "https://api.inoviopay.com/apple-pay-services/api/session/create"
}
```

Provide this response on your payment page as the `merchantConfig` parameter:

```html
<script>
 this.merchantConfig = {
    "APPLEPAY_CLI_CONF_ID": 11,
    "REQ_ID": 11111111111,
    "CLIENT_ID": 1111111,
    "INITIATIVE": "web",
    "DISPLAY_NAME": "xxxxxxx",
    "PARTNER_MERCH_NAME": "xxxxxx",
    "PARTNER_INTERNAL_MERCH_ID": "xxxxxxxxxxxxx",
    "ENCRYPT_TO": "xxxxxxxxxxxxxxxxxxxx",
    "DOMAIN_LIST": [
      {
        "DOMAIN_NAME": "paymentpagedomain.com",
        "DOMAIN_STATUS": "ACTIVE"
      }
    ],
    "paymentRequest": {
      "countryCode": "US",
      "currencyCode": "USD",
      "merchantCapabilities": [
        "supports3DS"
      ],
      "supportedNetworks": [
        "visa",
        "masterCard"
      ],
      "requiredBillingContactFields": [
        "postalAddress",
        "name",
        "phoneticName",
        "phone",
        "email"
      ],
      "total": {
        "label": "",
        "type": "final",
        "amount": 0
      }
    },
    "fetchUrl": "https://api.inoviopay.com/apple-pay-services/api/session/create"
 }
</script>
```

## Updating the configuration with order details

Once `merchantConfig` is stored on your payment page, update the fields that are specific to the current purchase:

```html
<script>
  merchantConfig.total.label = "Some purchase description total";
  merchantConfig.total.amount = 49.95
</script>
```

## Adding the Apple Pay library

Add the Apple Pay library to your payment page so it can call the Apple Pay API. Source the library script in the page's HTML:

```html
<script src="https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js"></script>
```

This library also validates that the user's browser and device are eligible for Apple Pay.

## Validating your domain

The Apple Pay JS API library calls a function you define to validate the domain where your payment page is hosted. This must load directly from your servers on that domain; no proxies or iframes.

```html
<script>
 function validateMerchant(merchantConfig) {
  console.log("validateMerchant: ", merchantConfig.DOMAIN_LIST)
  const data={
   method: "POST",
   headers: {
           "Content-type": "application/json",
           "Accept": "*/*"
         },
         body: JSON.stringify({
           "merchantIdentifier": merchantConfig.PARTNER_INTERNAL_MERCH_ID,
           "displayName": merchantConfig.DISPLAYNAME,
           "initiative": merchantConfig.INITIATIVE,
           "initiativeContext": merchantConfig.DOMAIN_LIST[0].DOMAIN_NAME
          })
        };
        return fetch(merchantConfig.fetchUrl,data);
    }
</script>
```

## Presenting the Apple Pay button

Once the Apple Pay library is added, add an HTML element for the button. The element must be named `apple-pay-button`.

```html
<style>
.apple-pay-button {
  --apple-pay-button-width: 150px;
  --apple-pay-button-height: 30px;
  --apple-pay-button-border-radius: 3px;
  --apple-pay-button-padding: 0px 0px;
  --apple-pay-button-box-sizing: border-box;
}
</style>
```

## Creating and starting the Apple Pay session

After presenting the button, add an action to it that starts the session, which triggers the browser to display a dialog where the user selects their card and approves the transaction. Add an `onClick` event to the Apple Pay button. `paymentRequest` here refers to the `paymentRequest` object returned by `APPLEPAYCONFIG`.

### Handling the authorized payment

After the customer authorizes the payment in the Apple Pay overlay, Safari returns an object (the Apple Pay token) with the data needed to authorize the payment with the gateway API. Create a `session.onpaymentauthorized` method to receive this token object.

### Handling a canceled payment or error

Handle the case where the customer does not authorize the payment, or where an error is thrown, with `session.oncancel`.

The full example, combining the button click handler, merchant validation, payment authorization, and cancel handling:

```javascript
async function onApplePayClick() {
  // Check for valid ApplePay session
  if(!ApplePaySession){
    return;
  }
  // Get the paymentRequest data from the merchantConfig object
  const paymentRequest = this.merchantConfig.paymentRequest;
  // Validate the merchant.
  // Note that this.merchantConfig is defined in Step 3
  const session = new ApplePaySession(3, paymentRequest);
  session.onvalidatemerchant = async (event) => {
    const merchantSession = await
      this.validateMerchant(this.merchantConfig).then(res=>res.json());
    session.completeMerchantValidation(merchantSession);
  };
  // Handle the authorized payment
  // Note, this must come inside the onApplePayClick() function, and
  // before session.begin
  session.onpaymentauthorized = async (event) => {
    // Define ApplePayPaymentAuthorizationResult
    const result = {
      status: ApplePaySession.STATUS_SUCCESS,
    };
    var applePaymentToken = event.payment;
    var tokenEncoded = btoa(JSON.stringify(applePaymentToken));
    // Now that the payment is authorized in Apple Pay, you can
    // initiate a service call to the gateway passing the
    // applePaymentToken into the gateway API parameter: PMT_WALLET_CRYPTOGRAM
    //
    // Do that here, through your server

    // If the payment is declined at the processor, then you should
    // put an appropriate message in place to the customer
    // result.status = ApplePaySession.STATUS_FAILURE

    // Now we can gracefully complete the Apple Pay browser interaction
    session.completePayment(result);
  };
  // In case the customer cancels or in case of an unexpected error
  // Note, this must come inside the onApplePayClick() function, and
  // before session.begin
  session.oncancel = (event) => {
    // Payment canceled by WebKit
    // error handling
    console.log("Payment canceled by WebKit: "+JSON.stringify(event.error))
  }
  // now the user will interact to approve the purchase
  // Note, this must come at the END of the onApplePayClick()
  session.begin();
}
```

## Sending the authorized payment to the gateway

Once Apple Pay returns the authorized payment token, send it to the gateway as a normal `CCAUTHCAP` request, passing the token in `PMT_WALLET_CRYPTOGRAM`:

```
https://api.inoviopay.com/payment/pmt_service.cfm?request_action=CCAUTHCAP&li_count_1=1&li_prod_id_1=111&li_value_1=49.95&req_username=GATEWAY_USER&req_password=GATEWAY_PASS&site_id=11111&request_response_format=JSON&request_api_version=4.14&request_currency=USD&PMT_WALLET=applepay&PMT_WALLET_CRYPTOGRAM=xxxxxxx
```

### Important requirements for Apple Pay authorization requests

You must **not** include any of the following parameters; doing so will cause the gateway to reject the request:

- `PMT_NUMB`
- `PMT_KEY`
- `PMT_EXPIRY`
- `TOKEN_GUID`
- `PMT_ID`
- `PMT_LAST4`
- `PMT_ID_XTL`
- `PMT_NUMB_COF`
- `REQUEST_INITIATOR`

Other gateway parameters can be included, but they must match the values used in the Apple Pay session:

- `li_value_1` must match the value of `paymentRequest.total` in the `merchantConfig` data.
- `request_currency` must match the value of `paymentRequest.currencyCode` in the `merchantConfig` data.

> **The PDF gives no further Apple Pay field table beyond this**
> Section 21.11 of the source spec lists only the excluded-parameter list and the two must-match rules above; it does not provide a separate table of additional required `PMT_WALLET_*` fields, so none is invented here.

## Rebilling and card on file

The gateway response returns a `CUST_ID` and `PMT_ID` on a successful Apple Pay authorization, the same as it does for normal transactions. To authorize against the generated Apple Pay payment record, pass the same `CUST_ID` and `PMT_ID` on all subsequent rebills or unscheduled merchant-initiated card-on-file transaction requests.

> **Not in the SDKs yet**
> Apple Pay is not implemented in any of the four SDKs. A `WalletToken` variant (`walletType: 'applepay' | 'googlepay'`) is declared in each language's type system, but `PaymentMethods` only constructs `card`, `token` and `savedCard` in v1, there is no constructor that produces a wallet payment method, so `sale()`/`authorize()` cannot be handed a `PMT_WALLET_CRYPTOGRAM` token today. Send the authorization as a raw HTTP request per the example above, or see [the SDKs](https://developer.inoviopay.com/sdks/index.md). Rebilling against the resulting `CUST_ID`/`PMT_ID` does work through the SDK once you have them, using the same `SavedCard` path as [Card on File](https://developer.inoviopay.com/api/card-on-file.md).
