Apple Pay & Native Pay Methods

Apple pay

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

If you need to collect specific billing data from the user during the payment process and use it as part of the billing data, you can configure the collectibleBillingData accordingly.

Configuring Apple Pay to Collect Billing Data (Optional)

const moneyHash: MoneyHash<"payment"> = new MoneyHash({
  type: "payment",
  applePay: {
    collectibleBillingData: ["email"], // (Optional) [] to disable auto collection, Defaults to ["email"]
  },
});

  • collectibleBillingData is an array of NativeCollectibleBillingData currently email is available.
  • To disable billing data collection, you can pass an empty array [].

Approaches for Apple Pay Payments

You can handle Apple Pay payments in two different ways:

  1. Approach #1: Directly use payWithApplePay (requires an intentId upfront).
  2. Approach #2: Generate an Apple Pay receipt first, then submit the receipt later (no intentId initially required).

Approach #1: Direct Payment with payWithApplePay

If you already have your intentId, you can directly display the Apple Pay sheet and complete the payment in one step using payWithApplePay.

Billing data is provided while creating the intent

In this case, rendering Apple pay button with onClick handler that calls moneyHash.payWithApplePay directly should show Apple Pay dialog allowing the customer to pay.

🚧

payWithApplePay uses ApplePaySession native method under the hood that exits in safari browsers, which requires ApplePaySession to be called right after gesture handler.

moneyHash.payWithApplePay({
  intentId,
  amount: <<TOTAL_PRICE>>,
  currency: "CURRENCY",
  countryCode: "<<COUNTRY_CODE>>",
  onCancel: () => {},
  onError: () => {

  },
})
 .then(() =>  console.log("COMPLETE"))
 .catch(error => {
   console.log(error);
      // error.message | string
      // Native apple pay button need to be triggered from click event directly
      // - Must create a new ApplePaySession from a user gesture handler.

      // intent requires billing data to proceed with the native integration
      // - Billing data is missing while calling payWithApplePay
      //  error | Record<string, string>
      //  {email: "Enter a valid email address."}
 });

📘

If there are any missing billing data while trying to call payWithApplePay, MoneyHash SDK will throw an error Billing data is missing while calling payWithApplePay

Billing data is not provided while creating the intent

Pass billing data while calling payWithApplePay

MoneyHash informs you beforehand, the required billing data in expressMethods, the payload shows as follows:

{
  "id": "APPLE_PAY",
  "title": "Apple Pay",
  "icons": [
    "https://cdn.moneyhash.io/images/checkout_icons/ApplePay.svg"
  ],
  "isSelected": false,
  "confirmationRequired": false,
  "requiredBillingFields": [
    {
      "type": "EmailField",
      "field_name": "email",
      "value": "",
      "choices": null,
      "label": "Email",
      "max_length": null,
      "help_text": "Customer's email address",
      "required": true,
      "min_length": null,
      "read_only": false,
    }
  ]
}

Notice requiredBillingFields which you can use to pass the required billing data to payWithApplePay

moneyHash.payWithApplePay({
  intentId,
  amount: totalPrice,
  currency,
  countryCode: "AE",
  onCancel: () => {},
  billingData: {
    // pass required billing data here
    email: "[email protected]"
  },
  onError: () => {},
});

📘

requiredBillingFields is a dynamic set of fields that varies from a provider to another, make sure all billing fields mentioned are passed, other wise MoneyHash SDK will throw an error Billing data is missing while calling payWithApplePay

Approach #2: Generate a Receipt First, Then Submit the Receipt

This new approach does not require an intentId up front. Instead, you generate an Apple Pay receipt, and once you have or create an intentId, you submit that receipt.

Step 1: Generate the Apple Pay Receipt

Use generateApplePayReceipt to show the Apple Pay sheet, collect payment data, and generate a NativePayReceipt without requiring an intentId:

// under button on click event 
const applePayReceipt = await moneyHash.generateApplePayReceipt({
  nativePayData: applePayNativeData,
  onCancel: () => console.log('Closed applePay sheet'),
});

console.log({ applePayReceipt });

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

const { expressMethods } = await moneyHash.getMethods({
  currency: 'usd',
  // ... your options
});
const applePayNativeData = expressMethods.find(m => m.id === 'APPLE_PAY')
?.nativePayData!;
console.log({ applePayNativeData });

Step 2: Submit the Payment Receipt

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

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

Google pay

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

If you need to collect specific billing data from the user during the payment process and use it as part of the billing data, you can configure the collectibleBillingData accordingly.

Configuration

const moneyHash: MoneyHash<"payment"> = new MoneyHash({
  type: "payment",
  googlePay: {
    environment: "PRODCUTION", // (Optional)  "TEST" | "PRODUCTION"  Defaults to "PRODUCTION"
    allowedAuthMethods: ["PAN_ONLY","CRYPTOGRAM_3DS"], // (Optional)
    allowedCardNetworks: ["AMEX", "DISCOVER", "JCB", "MASTERCARD", "VISA"], // (Optional)
    collectibleBillingData: ["email"], // (Optional) [] to disable auto collection, Defaults to ["email"]
  },
});

Render native GooglePay button

  • Create an element container with id moneyHash-google-pay-button with button height needed to avoid layout shift.
<div id="moneyHash-google-pay-button" style="height: 40px;"></div>
moneyHash.renderGooglePayButton({
  onClick: () => {
    console.log("Google Pay Clicked");
  },
  // ... google pay button customization
});

  • Further button customization can be found on Google Docs

Approaches for Google Pay Payments

You can handle Google Pay payments in two different ways:

  • Approach #1: Directly use payWithGooglePay (requires an intentId upfront).
  • Approach #2: Generate a Google Pay receipt first, then submit the receipt later (no intentId initially required).

Approach #1: Direct Payment with payWithGooglePay

Billing data is provided while creating the intent

moneyHash.renderGooglePayButton({
  onClick: () =>
    moneyHash
      .payWithGooglePay({
        intentId: "<intent_id>",
        onCancel() {
          console.log("Google Dialog Closed by the user");
        },
      })
      .then(intentDetails => console.log(intentDetails))
      .catch(error => {
        console.log(error);
        // error.message | string
        // Google Dialog errors;

        // intent requires billing data to proceed with the native integration
        // - Billing data is missing while calling payWithApplePay
        //  error | Record<string, string>
        //  {email: "Enter a valid email address."}
      }),
});

📘

If there are any missing billing data while trying to call payWithApplePay, MoneyHash SDK will throw an error Billing data is missing while calling payWithApplePay

Billing data is not provided while creating the intent

Pass billing data while calling payWithGooglePay

MoneyHash informs you beforehand, the required billing data in expressMethods, the payload shows as follows

{
  "id": "GOOGLE_PAY",
  "title": "Google Pay",
  "icons": [
    "https://cdn.moneyhash.io/images/checkout_icons/GooglePay.svg"
  ],
  "isSelected": false,
  "confirmationRequired": false,
  "requiredBillingFields": [
    {
      "type": "EmailField",
      "field_name": "email",
      "value": "",
      "choices": null,
      "label": "Email",
      "max_length": null,
      "help_text": "Customer's email address",
      "required": true,
      "min_length": null,
      "read_only": false,
    }
  ]
}

Notice requiredBillingFields which you can use to pass the required billing data to payWithGooglePay

moneyHash.renderGooglePayButton({
  onClick: () =>
    moneyHash
      .payWithGooglePay({
        intentId: "<intent_id>",
        billingData: {
          // pass required billing data here
          email: "[email protected]",
        },
        onCancel() {
          console.log("Google Dialog Closed by the user");
        },
      })
      .then(intentDetails => console.log(intentDetails))
      .catch(error => {
        console.log(error);
      }),
});

📘

requiredBillingFields is a dynamic set of fields that varies from a provider to another, make sure all billing fields mentioned are passed, other wise MoneyHash SDK will throw an error Billing data is missing while calling payWithApplePay

Approach #2: Generate a Receipt First, Then Submit the Receipt

This new approach does not require an intentId up front. Instead, you generate an Apple Pay receipt, and once you have or create an intentId, you submit that receipt.

Step 1: Generate the Google Pay Receipt

Use generateGooglePayReceipt to show the Apple Pay sheet, collect payment data, and generate a NativePayReceipt without requiring an intentId

moneyHash
  .renderGooglePayButton({
    onClick: async () => {
      const googlePayReceipt = await moneyHash.generateGooglePayReceipt({
        nativePayData: googlePayNativeData,
      });
      console.log({ googlePayReceipt });
    },
  })
  .catch(console.dir);

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

const { expressMethods } = await moneyHash.getMethods({
  currency: 'usd',
  // ... your options
});
const googlePayNativeData = expressMethods.find(m => m.id === 'GOOGLE_PAY')
?.nativePayData!;
console.log({ googlePayNativeData });

Step 2: Submit the Payment Receipt

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

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

console.log({ intentDetails });