Apple Pay

Introduction

You can use Apple Pay as a checkout option on the payment page or as a direct checkout option on the cart page (fast checkout). After configuring your environment, load the Apple Pay button via the COPYandPAY payment widget like any other brand. In step 2, specify APPLEPAY (the Payment Orchestration Platform handles the Apple Pay token decryption) or APPLEPAYTKN (the acquirer handles the token decryption). After the consumer uses the Apple Pay button, the Apple Pay payment sheet appears on the device.

When the consumer interacts with the Apple Pay payment sheet, other events trigger. Consume these events by implementing the COPYandPAY API callback functions. The COPYandPAY API wraps all callback functions from the Apple Pay SDK, eliminating the need for direct interaction with the Apple Pay SDK.

To steer the Apple Pay payment sheet or update data on it after the consumer starts interacting, use the available options.

Configuration

Processing Apple Pay requires certificates. You can use Peach Payments' certificates or create your own. Use Peach Payments' certificates because:

  • It is easier and faster to integrate.
  • An Apple developer account is not required.
  • You do not need to manage expiring certificates. Peach Payments renews them for you.

In addition to the certificates, your server must serve pages over HTTPS. See Setting up your server for more details.

Use Peach Payments' Apple Pay certificates

  1. In Smart Payments Platform, select your merchant in the entity tree. Go to Administration -> Mobile Payment, expand the section Apple Pay Web Merchant Registration, and click Check registration status.
  2. Download the domain-verification file and host it at the specified path. This step is not mandatory for UAT.
  3. Enter your domain name and click Register.

Use your own Apple Pay certificates

With your Apple Developer account, create a merchant ID and generate two certificates: Payment Processing Certificate and Merchant Identity Certificate.

Payment processing certificate

  1. In Smart Payments Platform, select your merchant in the entity tree.
  2. Go to Administration -> Mobile Payment, expand the section Apple Pay - Payment Processing Certificate, and click Generate keys to download the CSR (certificate signing request).
  3. In Apple Developer, select the merchant ID and choose Create Certificate under Apple Pay Payment Processing Certificate. Upload the CSR from the previous step and download the certificate.
  4. Upload the certificate in Smart Payments Platform, where you created the CSR.

Merchant identity certificate

  1. In Smart Payments Platform, select your merchant in the entity tree.
  2. Go to Administration -> Mobile Payment, expand the section Apple Pay on the Web, and click Generate keys to download the CSR.
  3. In Apple Developer, select the merchant ID and choose Create Certificate under Apple Pay Merchant Identity Certificate. Upload the CSR from the previous step and download the certificate.
  4. Upload the certificate in Smart Payments Platform, where you created the CSR.

Add your domain name in Apple Developer. See Configuring your environment for more detailed instructions.

The payment page

Load the Apple Pay button via the COPYandPAY payment widget like any other brand. In step 2, specify APPLEPAY or APPLEPAYTKN (if the acquirer handles token decryption) as the brand.

See an example below.

📘

The Apple Pay button only appears on compatible devices.

<form action="https://developer.peachpayments.com/docs/oppwa-integrations-copyandpay" class="paymentWidgets" data-brands="APPLEPAY"></form>

<style>
  body {
    background-color: #f6f6f5;
  }
</style>

<script>
  var wpwlOptions = {
    applePay: {
      displayName: "MyStore",
      total: { label: "COMPANY, INC." }
    }
  };
</script>
body {background-color:#f6f6f5;}
var wpwlOptions = {
  applePay: {
    displayName: "MyStore",
    total: { label: "COMPANY, INC." }
  }
}

Apple Pay options

Like other options, change the Apple Pay payment sheet behaviour using wpwlOptions.applePay.

ParameterRequiredDescriptionDefault valueExamples
versionNoThe Apple Pay JavaScript API version. For best compatibility, use the lowest possible version number that supports the required features. See Apple Pay on the Web Version History for details. Some selected versions and supported operating systems: 1 - macOS 10.12, iOS 10.0; 3 - macOS 10.13, iOS 11.0; 4 - macOS 10.14.1, iOS 12.1; 8 - macOS 10.15.1, iOS 13.2; 10 - macOS 11, iOS 14; 12 - macOS 12, iOS 15; 14 - macOS 13, iOS 16.1version: 3
checkAvailabilityNoSpecify the Apple Pay support detection method. Possible values: canMakePayments - checks if the device supports Apple Pay but does not verify the presence of provisioned cards; applePayCapabilities (new) - checks if the device supports Apple Pay and has at least one active card in Wallet (requires merchantIdentifier); canMakePaymentsWithActiveCard (deprecated) - checks for Apple Pay support and an active card in Wallet (requires merchantIdentifier).canMakePaymentscheckAvailability: "applePayCapabilities"
merchantIdentifierYes/NoThe merchant ID created when enrolling in Apple Pay. Required when checkAvailability is applePayCapabilities or canMakePaymentsWithActiveCard. If using Peach Payments certificates, set this option to entityId.Not applicablemerchantIdentifier: "com.company"
buttonSourceNoApple Pay button rendering option: css - use CSS (default), js - use JavaScript (recommended for advanced types).cssbuttonSource: "js"
buttonStyleNoButton style for Apple Pay: white-outline, white, black.white-outlinebuttonStyle: "black"
buttonTypeNoButton type to display for initiating transactions: add-money, book, buy, check-out, continue, contribute, donate, order, pay, plain, reload, rent, subscribe, support, tip, top-up. Note: some button types may require specific versions or may not work with buttonSource: "css.plainbuttonType: "check-out"
displayNameNoStore name for display (64 characters max). Suitable for Touch Bar on supported MacBook Pro models. Do not localise.Not applicabledisplayName: "MyStore"
totalYes/NoObject representing the payment total. Properties: label (business name for the label field), amount (checkout amount, if unspecified, it uses the checkout amount), and type (final or pending). You require this for fast checkout.amount:{checkout amount}total: { label: "COMPANY, INC." }
currencyCodeYes/NoThree-letter ISO 4217 currency code for the payment. Required for fast checkout if not specified in the checkout currency.{checkout currency}currencyCode: "USD"
countryCodeNoTwo-letter ISO 3166 country code for the merchant.wpwlOptions.localecountryCode: "US"
merchantCapabilitiesNoPayment capabilities supported by the merchant. Supported values: supports3DS (mandatory), supportsCredit, supportsDebit, supportsEMV (for China Union Pay).supports3DSmerchantCapabilities: ["supports3DS", "supportsCredit"]
supportedNetworksNoPayment networks supported by the merchant. Examples: amex, discover, masterCard, visa. Some networks require specific Apple Pay versions (for example, jcb from version 2).["amex", "discover", "masterCard", "visa"]supportedNetworks: ["amex", "chinaUnionPay", "discover", "jcb", "masterCard", "visa"]
lineItemsNoAn array of items explaining additional charges, discounts, and pending costs. Each item represents a line on the payment sheet. The item must contain: label - A short, localised description of the line item. Provide the label in title case–for example, VAT Tax, Gift Wrap and Card, or Discount. The label cannot be empty. amount - The monetary amount of the item. Note that you should provide the total separately by using the total property. Also, the array cannot be empty, if present.N/AlineItems: [{ label: "Bag Subtotal", amount: "35.00" }, { label: "Free Shipping", amount: "0.00" }, { label: "Estimated Tax", amount: "3.06" }]
shippingMethodsNoAn array of available methods for shipping physical goods. Each shipping method must contain: label - A short description of the shipping method. detail - Additional description of the shipping method. amount - The non-negative cost associated with this shipping method. identifier - A client-defined value used to identify this shipping method. dateComponentsRange - (available from version 12) The expected range of dates for shipping or picking up an item. It should contain startDateComponents and endDateComponents. Each date component can contain: years, months, days as numbers.N/AshippingMethods: [{ label: "Free Shipping", amount: "0.00", identifier: "free", detail: "Delivers in five business days" }, { label: "Express Shipping", amount: "5.00", identifier: "express", detail: "Delivers in two business days" }]
shippingTypeNoIndicate how purchased items are to be shipped. The value must be one of the followings: shipping, delivery, storePickup, servicePickup.shippingshippingType: "shipping"
supportedCountriesNoAn array that limits payment cards to those that were issued in specific countries. Indicate the supported countries by using ISO 3166 country codes. The supportedCountries list does not affect the currency used for the transaction, and it applies to all payment cards in Wallet. Available in Apple Pay JS API version 3.N/AsupportedCountries: ["US"]
supportsCouponCodeNoA boolean value that determines whether the payment sheet displays the coupon code field. Available in Apple Pay JS API version 12.falsesupportsCouponCode: true
couponCodeNoThe initial coupon code. Available in Apple Pay JS API version 12.N/AcouponCode: "DISCOUNT20"
requiredShippingContactFieldsNoThe fields of shipping information the user must provide to fulfill the order. The supported field names are: email, name, phone, postalAddress, and starting from version 3: phoneticName. You will receive the customer's name when you request postalAddress. If you don't need the customer's address, you can request the name contact field directly.N/ArequiredShippingContactFields: ["postalAddress", "email"]
shippingContactNoIf you have an up-to-date shipping address on file, you can set it here. The information you provide in shippingContact is displayed in the payment sheet as the default shipping address. The user can either keep the address you provided or select another address. Provide your user's shipping contact info only if you are requiring shipping contact information. The possible properties are: phoneNumber, emailAddress, givenName, familyName, phoneticGivenName - Typically used for transactions in Japan. Available in Apple Pay JS API version 3., phoneticFamilyName - Typically used for transactions in Japan. Available in Apple Pay JS API version 3., addressLines - The street portion of the address for the contact., subLocality - Additional information associated with the location, typically defined at the city or town level (such as district or neighborhood), in a postal address., locality - The city for the contact., postalCode - The zip code or postal code, where applicable, for the contact., subAdministrativeArea - The subadministrative area (such as a county or other region) in a postal address., administrativeArea - The state for the contact., country - The name of the country for the contact., countryCode - The contact's two-letter ISO 3166 country code.N/AshippingContact: { addressLines: ["123 Any Street"], locality: "Any Town", administrativeArea: "CA", postalCode: "95014", countryCode: "US", familyName: "COMPANY, INC." }
requiredBillingContactFieldsNoThe fields of billing information the user must provide to process the transaction. The only supported field is: postalAddress. You will receive the postal address as well as the user's name after the user authorises the transaction.N/ArequiredBillingContactFields: ["postalAddress"]
billingContactNoIf you have an up-to-date billing address on file, you can set it here. This billing address appears in the payment sheet. The user can either use the address you specify or select a different address. Note: If you supply a billing address, you must also request postalAddress in requiredBillingContactFields. See shippingContact for all available properties.N/AbillingContact: { addressLines: ["123 Any Street"], locality: "Any Town", administrativeArea: "CA", postalCode: "95014", countryCode: "US", familyName: "COMPANY, INC." }
shippingContactEditingModeNoA value that indicates whether the shipping mode prevents the user from editing the shipping address. The supported values are: enabled - The user can edit the shipping contact on the payment sheet., storePickup - The user can't edit the shipping contact on the payment sheet. Set the value to storePickup for an in-store or other pickup to prevent the user from editing the shipping address. Add postalAddress to requiredShippingContactFields to display the pickup address. Set the shippingContact to the pickup address. Available in Apple Pay JS API version 12.enabledshippingContactEditingMode: "storePickup"
submitOnPaymentAuthorizedNoAutomatically submit customer information and billing address received from Apple Pay as a part of the transaction. Possible values are: customer - data from Apple Pay is submitted to the following customer fields: customer.email, customer.phone, customer.givenName, customer.surname; billing - data from Apple Pay is submitted to the following billing fields: billing.street1, billing.street2, billing.city, billing.state, billing.postcode, billing.country. Note that this parameter must be used together with the parameter requiredBillingContactFields and requiredShippingContactFields to request email, name, phone, and postalAddress from Apple Pay.N/AsubmitOnPaymentAuthorized: ["customer", "billing"]

Callback functions

📘

When using callback functions, if the consumer updates the data in the Apple Pay payment sheet, update the COPYandPAY checkout as well.

The table below lists the available Apple Pay callback functions for use with wpwlOptions.applePay.

Callback FunctionDescriptionExample
onCancelAn event handler runs when a consumer dismisses the Apple Pay payment sheet. This function may run even after the onPaymentAuthorized event handler.onCancel: function() { /* Handle cancellation */ }
onPaymentMethodSelectedAn event handler runs when a consumer selects a new payment method. The event parameter describes the selected Apple Pay payment card.
Object Properties:
- displayName: A string suitable for display that describes the card.
- network: The name of the payment network backing the card.
- type: One of debit, credit, prepaid, store.
- billingContact: Available from version 11. See onPaymentAuthorized for the list of available properties.
onPaymentMethodSelected: function(paymentMethod) { return { newTotal: { label: "Total", amount: "42.00" }, newLineItems: [{ label: "Shipping", amount: "2.00" }, { label: "Tax", amount: "3.00" }] }; }
onCouponCodeChangedCalled when the user enters or updates a coupon code.
Returns: An object containing the updated total and optional updated line items.
Or: Return status: "ABORT to dismiss the payment sheet without completing the transaction.
onCouponCodeChanged: function(couponCode) { return { newTotal: { label: "Total", amount: "42.00" }, newLineItems: [{ label: "Shipping", amount: "2.00" }, { label: "Tax", amount: "3.00" }] }; }
onShippingContactSelectedRuns when a consumer selects a shipping contact. The event parameter provides redacted contact information.
Returns: An object containing the new total, optional updated line items, updated shipping methods, and any custom errors.
Or: Return status: "ABORT to dismiss the payment sheet.
onShippingContactSelected: function(shippingContact) { return { newTotal: { label: "Total", amount: "42.00" }, newLineItems: [{ label: "Shipping", amount: "2.00" }, { label: "Tax", amount: "3.00" }] }; }
onShippingMethodSelectedRuns when the consumer selects a shipping method.
Object Properties:
- label: Description of the shipping method.
- detail: Extra description.
- amount: The cost associated with the shipping method.
- identifier: A client-defined value for the method.
Returns: The new total and optional updated line items.
Or: Return status: "ABORT" to dismiss the payment sheet.
onShippingMethodSelected: function(shippingMethod) { return { newTotal: { label: "Total", amount: "42.00" }, newLineItems: [{ label: "Shipping", amount: "2.00" }, { label: "Tax", amount: "3.00" }] }; }
onPaymentAuthorizedCalled when the user authorises the payment with Touch ID, Face ID, or passcode.
Event Parameter: Contains shippingContact and billingContact.
Returns: status: "SUCCESS, FAILURE, or ABORT. Return errors for custom error messages on the payment sheet.
onPaymentAuthorized: function(payment) { // Save contacts from payment.shippingContact and payment.billingContact }

Promises

Your handler returns a promise if it needs to do asynchronous work. It can be any thenable object. Both JavaScript Promise and jQuery Promise work.

For example, selecting a different shipping method might change the total amount. Use onPaymentAuthorized and make an AJAX call to your server for a server-to-server request to update the checkout amount. The function returns a promise, which, when fulfilled, confirms that the call has completed.

Example:

wpwlOptions.applePay.onPaymentAuthorized = function(payment) {
    // Call your server to update the checkout
    return $.post("https://your.server", {
        amount: theNewAmount
    }).then(function() {
        return {
            status: "SUCCESS"
        };
    });
};

Options and callback example

For example, use applePay.shippingMethods to offer multiple shipping options or applePay.onShippingContactSelected to calculate the tax when the consumer selects a shipping address.

To quick start your integration, use Peach Payments' example code below as guidance (click the JavaScript tab to see the code example).

<form action="https://developer.peachpayments.com/docs/oppwa-integrations-copyandpay" class="paymentWidgets" data-brands="APPLEPAY"></form>
body {background-color:#f6f6f5;}
var subTotalAmount = 7731;
var shippingAmount = 0;
var taxAmount = 1469;
var currency = "EUR";
var applePayTotalLabel = "COMPANY, INC.";

function getAmount() {
    return ((subTotalAmount + shippingAmount + taxAmount) / 100).toFixed(2);
}

function getTotal() {
    return {
        label: applePayTotalLabel,
        amount: getAmount()
    };
}

function getLineItems() {
    return [{
        label: "Subtotal",
        amount: (subTotalAmount / 100).toFixed(2)
    }, {
        label: "Shipping",
        amount: (shippingAmount / 100).toFixed(2)
    }, {
        label: "Tax",
        amount: (taxAmount / 100).toFixed(2)
    }];
}

var wpwlOptions = {
    applePay: {
        version: 3,
        checkAvailability: "applePayCapabilities",
        merchantIdentifier: "merchant.com.test",
        buttonSource: "js",
        buttonStyle: "white-outline",
        buttonType: "buy",
        displayName: "MyStore",
        total: getTotal(),
        currencyCode: currency,
        countryCode: "US",
        merchantCapabilities: ["supports3DS"],
        supportedNetworks: ["amex", "discover", "masterCard", "visa"],
        lineItems: getLineItems(),
        shippingMethods: [{
            label: "Free Shipping",
            amount: "0.00",
            identifier: "free",
            detail: "Delivers in five business days"
        }, {
            label: "Express Shipping",
            amount: "5.00",
            identifier: "express",
            detail: "Delivers in two business days"
        }],
        shippingType: "shipping",
        supportedCountries: ["US"],
        onCancel: function () {
            console.log("onCancel");
        },
        onPaymentMethodSelected: function (paymentMethod) {
            console.log("onPaymentMethodSelected: " + paymentMethod.type);
            subTotalAmount = (["debit", "credit"].includes(paymentMethod.type)) ? 7731 : 7431;
            return {
                newTotal: getTotal(),
                newLineItems: getLineItems()
            };
        },
        requiredShippingContactFields: ["postalAddress", "email"],
        requiredBillingContactFields: ["postalAddress"],
        onShippingContactSelected: function (shippingContact) {
            console.log("onShippingContactSelected: " + JSON.stringify(shippingContact));
            taxAmount = (shippingContact.administrativeArea === "FL") ? 1269 : 1469;
            var update = {
                newTotal: getTotal(),
                newLineItems: getLineItems()
            };
            if (shippingContact.postalCode === "95014") {
                update.errors = [{
                    code: "shippingContactInvalid",
                    contactField: "postalCode",
                    message: "ZIP Code is invalid"
                }];
            }
            return update;
        },
        onShippingMethodSelected: function (shippingMethod) {
            console.log("onShippingMethodSelected: " + JSON.stringify(shippingMethod));
            shippingAmount = (shippingMethod.identifier === "free") ? 0 : 500;
            return {
                newTotal: getTotal(),
                newLineItems: getLineItems()
            };
        },
        onPaymentAuthorized: function (payment) {
            console.log("onPaymentAuthorized payment: " + JSON.stringify(payment));
        }
    }
};

Result:

Buy with Apple Pay button.

Registration tokens

You can use Apple Pay together with Tokenisation during payment by adding createRegistration=true in the checkout request. This creates a registration token that you can use for subsequent payments.

Add one of the following options to wpwlOptions.applePay to adjust the Apple Pay payment sheet:

  • automaticReloadPaymentRequest
  • recurringPaymentRequest
  • deferredPaymentRequest
📘

You can set only one of these options at a time.

ParameterDescriptionExample
automaticReloadPaymentRequestA dictionary representing a request to set up an automatic reload payment (for example, store card top-up or prepaid account). See ApplePayAutomaticReloadPaymentRequest for details.

Note: Apple Pay issues an Apple Pay Merchant Token if the user's payment network supports merchant-specific tokens; otherwise, it issues a device token.

Leave tokenNotificationURL empty. This value updates automatically during the token life cycle.
automaticReloadPaymentRequest: {paymentDescription:"Card Top-up",automaticReloadBilling: {type:"final",label:"Automatic Top-up",amount:"10.00",paymentTiming:"automaticReload",automaticReloadPaymentThresholdAmount:"2.00"},billingAgreement:"Reload when below $2",managementURL:"https://your-domain.com/token-management"}
recurringPaymentRequestA dictionary representing a request to set up a recurring payment (for example, a subscription). See ApplePayRecurringPaymentRequest for details.

Note: Apple Pay issues an Apple Pay Merchant Token if the user's payment network supports merchant-specific tokens; otherwise, it issues a device token.

Leave tokenNotificationURL empty. This value updates automatically during the token life cycle.
recurringPaymentRequest: {paymentDescription:"Subscription",regularBilling: {type:"final",label:"Subscription",amount:"20.00",paymentTiming:"recurring",recurringPaymentStartDate:new Date("2022-01-01T00:00:00"),recurringPaymentIntervalUnit:"month",recurringPaymentIntervalCount:6,recurringPaymentEndDate:new Date("2024-01-01T00:00:00")},billingAgreement:"Charge $20 every six months starting on 01/01/2022 and ending on 01/01/2024",managementURL:"https://your-domain.com/token-management"}
deferredPaymentRequestA dictionary representing a request to set up a deferred payment (for example, hotel booking or pre-order). See ApplePayDeferredPaymentRequest for details.deferredPaymentRequest: {paymentDescription:"Hotel",deferredBilling: {type:"final",label:"After Trial Period",amount:"50.00",paymentTiming:"deferred",deferredPaymentDate:new Date("2024-01-01T00:00:00")},billingAgreement:"Charge $50 on 01/01/2024",managementURL:"https://your-domain.com/token-management"}

Errors

Handlers onShippingContactSelected and onPaymentAuthorized return an array of errors if the provided shippingContact or billingContact contains an issue. Each error identifies a specific problem in a contact field. The object structure is:

ParameterDescription
codeMust be one of the following:
- shippingContactInvalid: Shipping address or contact information is invalid or missing. Use contactField to specify the exact field with the error.
- billingContactInvalid: Billing address information is invalid or missing. Use contactField to specify the exact field with the error.
- addressUnserviceable: The merchant cannot provide service to the shipping address (for example, can't deliver to a P.O. Box). This code does not require contactField.
contactFieldMust be one of the following: phoneNumber, emailAddress, name, phoneticName, postalAddress, addressLines, locality, subLocality, postalCode, administrativeArea, subAdministrativeArea, country, countryCode, if the code is shippingContactInvalid or billingContactInvalid. Otherwise, this field is optional.
messageA localised, user-facing string that describes the error.