Skip to content

Apple Pay Integration

Accept Apple Pay payments using the Widget SDK.

How It Works

The SDK renders an Apple Pay button directly on your checkout page. When the customer clicks it, the native Apple Pay payment sheet opens with the amount you specified. After the customer authorizes, the SDK delivers a token via onTokenizationComplete. There is no separate tokenize() call — the button click is the trigger. For complete reference, see SDK reference.

The SDK automatically loads the Apple Pay JS SDK, so you don't need to include it separately. On non-Safari browsers (Chrome, Edge, including Windows), the payment sheet is replaced by a code the customer scans with their iPhone (iOS 18+) to authorize the payment there.

Prerequisites

  • A registered Apple Pay merchant identifier
  • Domain verification with Apple — you must host the Apple domain verification file at /.well-known/apple-developer-merchantid-domain-association on the domain that serves your checkout page. The SDK automatically uses your page's hostname for merchant validation, so the page must be served from the verified domain.

Step 1: Load the SDK

<script src="https://cdn.<env>.nelnetpay.com/sdk/v1.0.0/widget-sdk.js"></script>

Step 2: Add a Container

<div id="apple-pay-button"></div>

Step 3: Initialize the SDK

Create the Widget with your callbacks, then set the session token with updateSessionToken. The session token must be set before the customer clicks the Apple Pay button.

const wg = new Widget({
  // ...additional options — see UI SDK Reference

  onTokenizationComplete: (result) => {
    // result.responseCode === '0', result.paymentMethod === 'applePay'
    // Forward result.token to your backend
  },

  onCancel: (payload) => {
    // Customer dismissed the Apple Pay sheet
    // { responseCode: 'E402', responseMessage: 'PAYMENT_CANCELLED', ... }
  },

  onError: (error) => {
    // Errors are reported as
    // { responseCode, responseMessage, description } — see Error Codes in the SDK reference
  }
});

wg.updateSessionToken('<SESSION_TOKEN>');

Step 4: Render the Apple Pay Button

Call mount() with the container selector, paymentMethod: 'applePay', and the payment options in the applePay object. The SDK renders the button and wires up the Apple Pay flow.

wg.mount('#apple-pay-button', {
  paymentMethod: 'applePay',
  applePay: {
    total: {
      label: 'Nelnet Campus Commerce',   // shown next to the total on the sheet
      amount: '75.00'
    },
    partnerInternalMerchantIdentifier: '<MERCHANT_IDENTIFIER>'
  }
});

When the customer clicks the button, the native Apple Pay sheet opens with the amount. After they authorize, onTokenizationComplete is invoked with the token. If the customer dismisses the sheet, onCancel is invoked.

The country and currency are always US and USD. Supported card networks are Visa, Mastercard, American Express, and Discover.

applePay Options

OptionRequiredDescription
totalYes{ label, amount } — the payment sheet total. Both fields are required; amount is a string greater than zero.
displayNameNoMerchant name shown during merchant validation. Defaults to total.label.
partnerInternalMerchantIdentifierNoYour merchant identifier, used during Apple merchant validation.
lineItemsNoItemized breakdown shown on the sheet above the total: [{ label, amount }].
multiTokenContextsNoMulti-merchant payment contexts — see below.
recurringPaymentRequestNoRecurring payment details — see below.

Step 5: Process the Payment

Send the token to your backend. Your server submits it to the Payments API to process the charge.

Multi-merchant payment

For platforms that split a single checkout across multiple merchants. Apple Pay generates one token per merchant.

Requirements:

  • The customer's device must support Apple Pay version 14 or later; otherwise the SDK reports an error via onError.
  • Each context requires partnerMerchantIdentifier, entityId, and amount.
  • The sum of the context amounts cannot exceed total.amount.
  • multiTokenContexts cannot be combined with recurringPaymentRequest.

Optionally, each context accepts merchantName (shown on the sheet, defaults to the total label) and merchantDomain (defaults to your page's hostname).

wg.mount('#apple-pay-button', {
  paymentMethod: 'applePay',
  applePay: {
    total: { label: 'Total Amount', amount: '110.00' },
    lineItems: [
      { label: 'AAA University', amount: '100.00' },
      { label: 'BBB Service Fee', amount: '10.00' }
    ],
    multiTokenContexts: [
      {
        partnerMerchantIdentifier: 'TESTCLIENT_a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6',
        entityId: 'A-123',
        merchantName: 'AAA University',
        amount: '100.00'
      },
      {
        partnerMerchantIdentifier: 'TESTCLIENT_a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6',
        entityId: 'B-456',
        merchantName: 'BBB Service Fee',
        amount: '10.00'
      }
    ]
  }
});

The merchant session is validated under the partnerInternalMerchantIdentifier if provided; otherwise the SDK uses the partnerMerchantIdentifier from the first context.

Recurring payment

For subscriptions and other repeat billing. Pass a recurringPaymentRequest describing the recurring payment; the payment sheet shows it to the customer before they authorize. The resulting NPS token is reusable — your backend charges it through the Payments API on your own schedule. The recurring payment plan (billing schedule, agreement, and any trial pricing) is managed by NPS, not Apple — Apple does not initiate any charges itself.

Requirements:

  • The customer's device must support Apple Pay version 14 or later; otherwise the SDK reports an error via onError.
  • recurringPaymentRequest requires paymentDescription, regularBilling (with label and amount), and managementURL; the SDK rejects the request with an error if any are missing.
  • Cannot be combined with multiTokenContexts.
FieldRequiredDescription
paymentDescriptionYesPlain-language description of the recurring payment, shown on the payment sheet.
regularBillingYesThe recurring line item: label and amount.
managementURLYesA page on your site where the customer can manage or cancel the subscription. Apple links to it from the Wallet app, so it must be a real, working URL.

Set total.amount (the sheet total) to the recurring amount in regularBilling.

wg.mount('#apple-pay-button', {
  paymentMethod: 'applePay',
  applePay: {
    total: { label: 'Meal Plan Subscription', amount: '9.99' },
    partnerInternalMerchantIdentifier: '<MERCHANT_IDENTIFIER>',
    recurringPaymentRequest: {
      paymentDescription: 'Campus Meal Plan — billed monthly',
      regularBilling: {
        label: 'Meal Plan Subscription',
        amount: '9.99'
      },
      managementURL: 'https://checkout.example.com/account/subscriptions'
    }
  }
});

The customer authorizes once. onTokenizationComplete returns the reusable token; store it and submit a Payments API charge each billing cycle.

Complete example (one-time)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Checkout</title>
</head>
<body>
  <h1>Checkout</h1>
  <div id="apple-pay-button"></div>

  <script src="https://cdn.nelnetpay.com/sdk/v1.0.0/widget-sdk.js"></script>
  <script>
    const wg = new Widget({
      onTokenizationComplete: (result) => {
        // Forward result.token to your backend
      },

      onCancel: (payload) => {
        // Customer dismissed the Apple Pay sheet
      },

      onError: (error) => {
        // Handle errors
      }
    });

    wg.updateSessionToken(window.__SESSION_TOKEN__);

    wg.mount('#apple-pay-button', {
      paymentMethod: 'applePay',
      applePay: {
        total: { label: 'Checkout Total', amount: '75.00' },
        partnerInternalMerchantIdentifier: '<MERCHANT_IDENTIFIER>'
      }
    });
  </script>
</body>
</html>