Apple Pay & Native Pay Methods

Apple Pay

In JS SDK, Apple Pay can process payments with a smooth and native experience.

We'll discuss how to generate an Apple Pay receipt first, then submit the receipt later (no intentId initially required).

1. Apple Pay JS SDK must be loaded into your app

https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js

use your preferred way to load the script

<script src="https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js"></script>

2. TypeScript projects (optional)

install @types/applepayjs for type safety.

3. Render ApplePay button

Render your button with your styles or you can render the Apple Pay button through their guide.

4. Generate an Apple Pay receipt

ApplePaySession is the entry point for Apple Pay on the web. All the steps of the payment process for a single transaction occur in a session.

Add the click handler on the button with the following code to generate an Apple Pay receipt

applePayNativeData can be found with each express method under nativePayData property
Get available methods

// Create apple pay session
const session = new ApplePaySession(3, {
  countryCode: applePayNativeData.country_code,
  currencyCode: applePayNativeData.currency_code,
  supportedNetworks: applePayNativeData.supported_networks,
  merchantCapabilities: ["supports3DS"],
  total: {
    label: "Apple Pay",
    type: "final",
    amount: `${applePayNativeData.amount}`,
  },
  requiredShippingContactFields: ["email"], // collect email while paying with ApplePay
});

// Validate the merchant
session.onvalidatemerchant = e =>
moneyHash
  .validateApplePayMerchantSession({
  methodId: applePayNativeData.method_id,
  validationUrl: e.validationURL,
})
  .then(merchantSession =>
        session.completeMerchantValidation(merchantSession),
       )
  .catch(error => {
  console.log(error); // merchant validation request failed
  session.completeMerchantValidation({}); // fallback to show payment failed and close the sheet
});

// Get the receipt from ApplePay
session.onpaymentauthorized = e => {
  const applePayReceipt = {
    receipt: JSON.stringify({ token: e.payment.token }),
    receiptBillingData: {
      email: e.payment.shippingContact?.emailAddress,
    },
  };
  session.completePayment(ApplePaySession.STATUS_SUCCESS);
  console.log(applePayReceipt);
};

// Optional - Listen to cancelling the sheet
session.oncancel = () => {
  console.log("ApplePay Sheet was closed.");
};

// start the ApplePay session and show the sheet
session.begin();

After that, you will have applePayReceipt which you can use to pay with for the intent

5. Submit the receipt

// select ApplePay method for the intent
await moneyHash.proceedWith({
  type: 'method',
  id: 'APPLE_PAY',
  intentId,
});
// Submit ApplePay receipt collected before
const intentDetails = await moneyHash.submitPaymentReceipt({
  nativeReceiptData: applePayReceipt,
  intentId,
});
console.log({ intentDetails });

Full Code

const session = new ApplePaySession(3, {
  countryCode: applePayNativeData.country_code,
  currencyCode: applePayNativeData.currency_code,
  supportedNetworks: applePayNativeData.supported_networks,
  merchantCapabilities: ["supports3DS"],
  total: {
    label: "Apple Pay",
    type: "final",
    amount: `${applePayNativeData.amount}`,
  },
  requiredShippingContactFields: ["email"],
});

session.onvalidatemerchant = e =>
moneyHash
  .validateApplePayMerchantSession({
  methodId: applePayNativeData.method_id,
  validationUrl: e.validationURL,
})
  .then(merchantSession =>
        session.completeMerchantValidation(merchantSession),
       )
  .catch(() => {
  session.completeMerchantValidation({});
});

session.onpaymentauthorized = async e => {
  const applePayReceipt = {
    receipt: JSON.stringify({ token: e.payment.token }),
    receiptBillingData: {
      email: e.payment.shippingContact?.emailAddress,
    },
  };
  session.completePayment(ApplePaySession.STATUS_SUCCESS);

  await moneyHash.proceedWith({
    type: "method",
    id: "APPLE_PAY",
    intentId,
  });

  const intentDetails = await moneyHash.submitPaymentReceipt({
    nativeReceiptData: applePayReceipt,
    intentId,
  });
  console.log({ intentDetails });
};

session.oncancel = () => {
  console.log("ApplePay Sheet was closed");
};

session.begin();

Google Pay

In JS SDK, Google Pay can process payments with a smooth and native experience.

We'll discuss how to generate a Google Pay receipt first, then submit the receipt later (no intentId initially required).

1. Google Pay JS SDK must be loaded into your app

There're several ways to load Google Pay SDK, Choose the most suitable one for you

📘

We recommed to use React, Angular or Web component based on your project

2. TypeScript projects (optional)

Google Pay components will come by default with the types installed, but for any reason it had a type issue you can install @types/googlepay for type safety.

3. Render GooglePay button

Please follow the guide for the framework you're using, we will post here the web components & React versions, but the rest can be found in

googlePayNativeData can be found with each express method under nativePayData property
Get available methods

Web Components

<google-pay-button environment="TEST"></google-pay-button>
import type GooglePayButton from "@google-pay/button-element";
import "@google-pay/button-element";

const button = document.querySelector("google-pay-button") as GooglePayButton;
button.paymentRequest = {
  apiVersion: 2,
  apiVersionMinor: 0,
  allowedPaymentMethods: [
    {
      type: "CARD",
      parameters: {
        allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
        allowedCardNetworks: ["MASTERCARD", "VISA"],
        billingAddressRequired: true,
      },
      tokenizationSpecification: {
        type: "PAYMENT_GATEWAY",
        parameters: {
          gateway: googlePayNativeData.gateway,
          gatewayMerchantId: googlePayNativeData.gateway_merchant_id,
        },
      },
    },
  ],
  merchantInfo: {
    merchantId: googlePayNativeData.merchant_id,
    merchantName: googlePayNativeData.merchant_name,
  },
  transactionInfo: {
    totalPriceStatus: "FINAL",
    totalPriceLabel: "Total",
    totalPrice: `${googlePayNativeData.amount}`,
    currencyCode: googlePayNativeData.currency_code,
    countryCode: googlePayNativeData.country_code,
  },
  emailRequired: true, // collect email while paying with GooglePay
};

// Optional - Listen to cancelling the sheet
button.addEventListener("cancel", () => {
  console.log("GooglePay Sheet was closed.");
});

React

import GooglePayButton from '@google-pay/button-react';

<GooglePayButton
  environment="TEST"
  paymentRequest={{
    apiVersion: 2,
    apiVersionMinor: 0,
    allowedPaymentMethods: [
      {
        type: 'CARD',
        parameters: {
          allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
          allowedCardNetworks: ['MASTERCARD', 'VISA'],
          billingAddressRequired: true, // collect email while paying with GooglePay
        },
        tokenizationSpecification: {
          type: 'PAYMENT_GATEWAY',
          parameters: {
            gateway: googlePayNativeData.gateway,
            gatewayMerchantId: googlePayNativeData.gateway_merchant_id,
          },
        },
      },
    ],
    merchantInfo: {
      merchantId: googlePayNativeData.merchant_id,
      merchantName: googlePayNativeData.merchant_name
    },
    transactionInfo: {
      totalPriceStatus: 'FINAL',
      totalPriceLabel: 'Total',
	    totalPrice: `${googlePayNativeData.amount}`,
  	  currencyCode: googlePayNativeData.currency_code,
    	countryCode: googlePayNativeData.country_code,
    },
  }}
  // Optional - Listen to cancelling the sheet
  onCancel={() => {
    console.log('GooglePay Sheet was closed.');
  }}
/>

4. Generate a Google Pay receipt

Web Components

button.addEventListener("loadpaymentdata", async event => {
  const { paymentMethodData, email } = event.detail;
  const paymentToken = paymentMethodData.tokenizationData.token;
  const googlePayReceipt = {
    receipt: paymentToken,
    receiptBillingData: {
      email,
    },
  };
  console.log(googlePayReceipt);
});

React

import GooglePayButton from '@google-pay/button-react';

<GooglePayButton
  // ... rest configuration 
  onLoadPaymentData={(paymentRequest) => {
    const { paymentMethodData, email } = paymentRequest;
    const paymentToken = paymentMethodData.tokenizationData.token;
    const googlePayReceipt = {
      receipt: paymentToken,
      receiptBillingData: {
        email,
      },
    };
    console.log(googlePayReceipt);
  }}
/>

5. Submit the receipt

await moneyHash.proceedWith({
  type: "method",
  id: "GOOGLE_PAY",
  intentId,
});

const intentDetails = await moneyHash.submitPaymentReceipt({
  intentId,
  nativeReceiptData: googlePayReceipt,
});

Full Code

  • Web Components
import type GooglePayButton from "@google-pay/button-element";
import "@google-pay/button-element";

const button = document.querySelector("google-pay-button") as GooglePayButton;
button.paymentRequest = {
  apiVersion: 2,
  apiVersionMinor: 0,
  allowedPaymentMethods: [
    {
      type: "CARD",
      parameters: {
        allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
        allowedCardNetworks: ["MASTERCARD", "VISA"],
        billingAddressRequired: true,
      },
      tokenizationSpecification: {
        type: "PAYMENT_GATEWAY",
        parameters: {
          gateway: googlePayNativeData.gateway,
          gatewayMerchantId: googlePayNativeData.gateway_merchant_id,
        },
      },
    },
  ],
  merchantInfo: {
    merchantId: googlePayNativeData.merchant_id,
    merchantName: googlePayNativeData.merchant_name,
  },
  transactionInfo: {
    totalPriceStatus: "FINAL",
    totalPriceLabel: "Total",
    totalPrice: `${googlePayNativeData.amount}`,
    currencyCode: googlePayNativeData.currency_code,
    countryCode: googlePayNativeData.country_code,
  },
  emailRequired: true,
};

button.addEventListener("loadpaymentdata", async event => {
  const { paymentMethodData, email } = event.detail;
  const paymentToken = paymentMethodData.tokenizationData.token;
  const googlePayReceipt = {
    receipt: paymentToken,
    receiptBillingData: {
      email,
    },
  };

  await moneyHash.proceedWith({
    type: "method",
    id: "GOOGLE_PAY",
    intentId,
  });

  const intentDetails = await moneyHash.submitPaymentReceipt({
    intentId,
    nativeReceiptData: googlePayReceipt,
  });
  console.log(intentDetails);
});

button.addEventListener("cancel", () => {
  console.log("GooglePay Sheet was closed.");
});

  • React
import GooglePayButton from '@google-pay/button-react';

<GooglePayButton
  environment="TEST"
  paymentRequest={{
    apiVersion: 2,
    apiVersionMinor: 0,
    allowedPaymentMethods: [
      {
        type: 'CARD',
        parameters: {
          allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
          allowedCardNetworks: ['MASTERCARD', 'VISA'],
          billingAddressRequired: true,
        },
        tokenizationSpecification: {
          type: 'PAYMENT_GATEWAY',
          parameters: {
            gateway: googlePayNativeData.gateway,
            gatewayMerchantId: googlePayNativeData.gateway_merchant_id,
          },
        },
      },
    ],
    merchantInfo: {
      merchantId: googlePayNativeData.merchant_id,
      merchantName: googlePayNativeData.merchant_name
    },
    transactionInfo: {
      totalPriceStatus: 'FINAL',
      totalPriceLabel: 'Total',
	    totalPrice: `${googlePayNativeData.amount}`,
  	  currencyCode: googlePayNativeData.currency_code,
    	countryCode: googlePayNativeData.country_code,
    },
  }}
    onLoadPaymentData={(paymentRequest) => {
    const { paymentMethodData, email } = paymentRequest;
    const paymentToken = paymentMethodData.tokenizationData.token;
    const googlePayReceipt = {
      receipt: paymentToken,
      receiptBillingData: {
        email,
      },
    };
      
      await moneyHash.proceedWith({
        type: "method",
        id: "GOOGLE_PAY",
        intentId,
      });

      const intentDetails = await moneyHash.submitPaymentReceipt({
        intentId,
        nativeReceiptData: googlePayReceipt,
      });
      console.log(intentDetails);
  }}
  onCancel={() => {
    console.log('GooglePay Sheet was closed.');
  }}
/>

await moneyHash.proceedWith({
  type: "method",
  id: "GOOGLE_PAY",
  intentId,
});

const intentDetails = await moneyHash.submitPaymentReceipt({
  intentId,
  nativeReceiptData: googlePayReceipt,
});

console.log({ intentDetails });