@olo/pay-digital-wallets-js
v0.6.11
Published
[**Pay Digital Wallets JS Examples**](https://pay-examples.olo.com/?path=/docs/pay-digital-wallets-js-introduction--docs)
Keywords
Readme
@olo/pay-digital-wallets
Pay Digital Wallets JS Examples
Introduction
A web library that enables Digital Wallets across various payment processors. It renders and hooks up Google Pay and Apple Pay buttons with a common interface.
Installation
NPM
npm install @olo/pay-digital-walletsYarn
yarn add @olo/pay-digital-walletsTypeScript
@olo/pay-digital-wallets exports types for use in TypeScript. You can import them from the root of the package:
import type { GooglePayButtonStyles, ApplePayButtonStyles } from '@olo/pay-digital-wallets';If you are using a version of TypeScript before 3.8, you can simply omit type from your import:
import { GooglePayButtonStyles, ApplePayButtonStyles } from '@olo/pay-digital-wallets';DigitalWallets Usage Examples
The DigitalWallets class is the main entry point for the library. Constructing a new instance of the DigitalWallets is as simple as passing in the current environment (either "development" or "production").
const environment = 'development'; // Can be 'development' or 'production'
const digitalWallets = new DigitalWallets(environment);Environment
The environment will be passed on to Google Pay. See their docs on environment for more information. NOTE: Passing in "development" to the DigitalWallets constructor is translated to TEST in Google Pay.
DigitalWallets methods
initialize
This should be called immediately after creating a new DigitalWallets instance. Please note that this method is async (returns a Promise) so you'll need to use await or .then in your code in order to get the resulting CanMakePayment value.
Signature
async initialize(params: DigitalWalletsInitParams): Promise<CanMakePayment>Parameter Types
type SupportedCountries =
| 'US' // United States
| 'CA'; // Canada
type SupportedCurrencies =
| 'USD' // Unite Stats Dollars
| 'CAD'; // Canadian Dollars
type SupportedCardNetworks =
| 'AMEX' // American Express
| 'DISCOVER' // Discover
| 'MASTERCARD' // Mastercard
| 'VISA'; // Visa
type DisplayItemType =
| 'LINE_ITEM' // Regular line item.
| 'SUBTOTAL' // Subtotal of all regular items.
| 'TAX' // Item for the collected tax.
| 'DISCOUNT' // Item for a discount.
| 'SHIPPING_OPTION'; // Item for shipping option
type DisplayItemStatus =
| 'FINAL' // DisplayItem is final and the item displays the value in price.
| 'PENDING'; // DisplayItem does not display value in price but instead display as "pending"
type DisplayItem = {
// The label to be displayed for the item.
label: string;
// Price of this item.
// The format of this string should follow the regular expression format:
// `^[0-9]+(\.[0-9][0-9])?$` (e.g., `"10.45"`)
price: string;
// Type of displayed line item, this will be used for analysis purpose.
type: DisplayItemType;
// Optional. The default value is `FINAL` if not provided.
status?: DisplayItemStatus | undefined;
};
type PaymentOptions = {
// The currency code for the currency that the payment will use.
currencyCode: SupportedCurrencies;
// The country code for where this payment is being sent to.
countryCode: SupportedCountries;
// The total price for the payment.
// This can be changed after initialization with the `updatePaymentOptions` method.
totalPrice: string;
// All the items that make up the order. See the DisplayItem type above.
displayItems?: DisplayItem[];
};
type BillingContactFields =
| 'email' // The user's email
| 'name' // The user's name
| 'phone' // The user's phone number
| 'postalAddress' // The user's billing address
| 'postalCode'; // The user's billing postal code
type MerchantValidationConfig = {
// Your backend URL for verifying your merchant with Apple Pay.
url: string;
// Any additional headers that need to be sent to your backend during merchant verification with Apple Pay.
// Unless overridden, we will send `'Content-Type': 'application/json'` in the headers.
headers: Record<string, string>;
// Any additional properties in the body that need to be sent to your backend
// during merchant verification with Apple Pay. NOTE: This will be sent as JSON.
body: Record<string, string>;
};
type DigitalWalletsInitParams = {
// See the PaymentOptions type above.
paymentOptions: PaymentOptions;
// Card networks allowed for this order.
cardNetworks: SupportedCardNetworks[];
// Whether or not a billing address is required
billingAddressRequired: boolean;
// Which billing address fields are required.
// See the BillingContactFields type above.
requiredBillingContactFields?: BillingContactFields[];
googlePayGateway: {
// The `gateway` sent to your payment gateway tokenization service.
name: string;
// The `gatewayMerchantId` sent to your payment gateway tokenization service.
merchantId: string;
};
merchant: {
// User facing name for your merchant.
name: string;
// Your Apple pay merchantId
applePayMerchantId: string;
// Your Google pay merchantId
googlePayMerchantId: string;
// Configuration options for calling your Merchant Validation API
// Used by Apple Pay. See MerchantValidationConfig type above.
validationConfig: MerchantValidationConfig;
};
};Return Type
type CanMakePayment = {
applePay: boolean; // Represents whether or not Apple Pay can be used
googlePay: boolean; // Represents whether or not Google Pay can be used
};mountButtons
Call this method after you've called initialized and your <div data-pay-buttons></div> has been rendered to the DOM. Should not be called if both CanMakePayment.applePay and CanMakePayment.googlePay are false. If either are true, the appropriate button(s) will be added to the DOM at the div you've given the data-pay-buttons attribute to (e.g. <div data-pay-buttons></div>).
Signature
mountButtons(
paymentSuccessCallback: (paymentData: PaymentData) => void,
paymentFailureCallback?: (error: unknown) => void,
buttonStyles?: ButtonStyles
): voidpaymentSuccessCallback will be called when a token has been successfully created. The callback can take in a PaymentData parameter and is expected to return void.
paymentFailureCallback is an optional parameter that will be called when there has been an error during the digital wallets processing. The error type is unknown as it could be an Error or something thrown by Google Pay or Apple Pay's SDKs.
buttonStyles is an optional parameter that allows custom styling on the Google Pay and Apple Pay buttons.
Parameter Types
type PaymentData = {
// Whether the user used Google Pay or Apple Pay to order.
walletType: 'GooglePay' | 'ApplePay';
// See the DigitalWalletPaymentData type below
paymentData: DigitalWalletPaymentData;
};
type DigitalWalletPaymentData = {
// A user facing string to describe the payment method or card used by the user.
description: string;
// The billing address of the user. See the BillingAddress type below
billingAddress: BillingAddress;
// The last 4 digits of the card used.
cardDetails: string;
// The card network of the card. e.g. Visa, Mastercard, Amex, etc.
cardNetwork: string;
// A 64-bit encoded string of the token for the payment method.
token: string;
};
type BillingAddress = {
// Address Line 1
address1?: string;
// Address Line 2
address2?: string;
// Address Line 3
address3?: string;
// The state or province
administrativeArea?: string;
// The two-letter ISO 3166 country code.
countryCode?: string;
// The city or town
locality?: string;
// The user's full name
name?: string;
// The user's phone number
phoneNumber?: string;
// The postal or zip code
postalCode?: string;
};
type ButtonStyles = {
// See GooglePayButtonStyles type below.
googlePay: GooglePayButtonStyles;
// See ApplePayButtonStyles type below.
applePay: ApplePayButtonStyles;
};
type GooglePayButtonStyles = {
// See GooglePayButtonColor type below
// Will default to `'default'`
buttonColor?: GooglePayButtonColor;
// The border radius of the button in px
// Will default to `4`
buttonRadius?: number;
// See GooglePayButtonSizeMode type below
// Will default to `'fill'`
buttonSizeMode?: GooglePayButtonSizeMode;
// See GooglePayButtonType type below
// Will default to `'pay'`
buttonType?: GooglePayButtonType;
};
type GooglePayButtonColor =
| 'default' // Google selected default. Currently Black at the time of this writing.
| 'black' // The button's background will be black.
| 'white'; // The button's background will be white.
type GooglePayButtonSizeMode =
| 'static' // Button will be a fixed width, 240px at the time of this writing.
| 'fill'; // Button's width will fill its container
type GooglePayButtonType =
| 'book' // Button will say "Book with G Pay"
| 'buy' // Button will say "Buy with G Pay"
| 'checkout' // Button will say "Checkout with G Pay"
| 'donate' // Button will say "Donate with G Pay"
| 'order' // Button will say "Order with G Pay"
| 'pay' // Button will say "Pay with G Pay"
| 'plain' // Button will say "G Pay"
| 'subscribe' // Button will say "Subscribe with G Pay"
| 'long' // Deprecated: The same as `buy`
| 'short'; // Deprecated: The same as `plain`
type ApplePayButtonStyles = {
// The width of the Apple Pay button
// Will default to `100%`
buttonWidth?: string;
// The height of the Apple Pay button
// Will default to `40px`
buttonHeight?: string;
// The border radius of the Apple Pay button. Must include units.
// Units can be any standard CSS unit (e.g. pt, px, em, etc)
// Will default to `5px`
buttonRadius?: string;
// The padding inside of the Apple Pay Button. Must include units.
// Units can be any standard CSS unit (e.g. pt, px, em, etc)
// Will default to `0`
buttonPadding?: string;
// See ApplePayButtonType type below
// The button type of the Apple Pay Button. Will default to `'check-out'`
buttonType?: ApplePayButtonType;
// See ApplePayButtonStyle type below
// The button style of the Apple Pay Button. Will default to `'black'`
buttonStyle?: ApplePayButtonStyle;
};
type ApplePayButtonType =
| 'add-money'
| 'book'
| 'buy'
| 'check-out'
| 'continue'
| 'contribute'
| 'donate'
| 'order'
| 'pay'
| 'plain'
| 'reload'
| 'rent'
| 'set-up'
| 'subscribe'
| 'support'
| 'tip'
| 'top-up';
type ApplePayButtonStyle = 'black' | 'white' | 'white-outline';Return Type
void (i.e. this method does not return anything)
unmountButtons
Use this method to remove the Digital Wallet buttons from the DOM.
Signature
unmountButtons(): voidParameter Types
None.
Return Types
void (i.e. this method does not return anything)
updatePaymentOptions
Use this method if anything under PaymentOptions or OfferInfo has changed since you called initialize.
Signature
updatePaymentOptions(options: PaymentOptions, offerInfo?: OfferInfo): voidParameter Types
type PaymentOptions = {
// The currency code for the currency that the payment will use.
currencyCode: SupportedCurrencies;
// The country code for where this payment is being sent to.
countryCode: SupportedCountries;
// The total price for the payment.
totalPrice: string;
// All the items that make up the order. See the DisplayItem type below.
displayItems?: DisplayItem[];
};
type SupportedCountries =
| 'US' // United States
| 'CA'; // Canada
type SupportedCurrencies =
| 'USD' // Unite Stats Dollars
| 'CAD'; // Canadian Dollars
type SupportedCardNetworks =
| 'AMEX' // American Express
| 'DISCOVER' // Discover
| 'MASTERCARD' // Mastercard
| 'VISA'; // Visa
type DisplayItemType =
| 'LINE_ITEM' // Regular line item.
| 'SUBTOTAL' // Subtotal of all regular items.
| 'TAX' // Item for the collected tax.
| 'DISCOUNT' // Item for a discount.
| 'SHIPPING_OPTION'; // Item for shipping option
type DisplayItemStatus =
| 'FINAL' // DisplayItem is final and the item displays the value in price.
| 'PENDING'; // DisplayItem does not display value in price but instead display as "pending"
type DisplayItem = {
// The label to be displayed for the item.
label: string;
// Price of this item.
// The format of this string should follow the regular expression format:
// `^[0-9]+(\.[0-9][0-9])?$` (e.g., `"10.45"`)
price: string;
// Type of displayed line item, this will be used for analysis purpose.
type: DisplayItemType;
// Optional. The default value is `FINAL` if not provided.
status?: DisplayItemStatus | undefined;
};Return Types
void (i.e. this method does not return anything)
Framework Examples
@olo/pay-digital-wallets can be used with any JavaScript framework you might be using. Below are a couple examples of usage in different frameworks.
React
import {
type ButtonStyles,
type DisplayItem,
type Environment,
type PaymentData,
DigitalWallets,
} from '@olo/pay-digital-wallets';
import { FC, useCallback, useEffect, useMemo } from 'react';
type Props = {
displayItems: DisplayItem[];
environment: Environment;
paymentSuccessCallback: (paymentData: PaymentData) => void;
};
const calculateTotal = (items: DisplayItem[]): string => {
return items
.reduce((sum, item) => {
if (item.type === 'DISCOUNT') {
return sum - parseFloat(item.price);
}
return sum + parseFloat(item.price);
}, 0)
.toFixed(2);
};
const buttonStyles: ButtonStyles = {
googlePay: {
buttonColor: 'default',
buttonRadius: 5,
buttonSizeMode: 'static',
buttonType: 'order',
},
applePay: {
buttonWidth: '100%',
buttonHeight: '40px',
buttonRadius: '10px',
buttonPadding: '0px',
},
};
export const DigitalWalletsButtons: FC<Props> = ({ environment, displayItems, paymentSuccessCallback }) => {
const digitalWallets = useMemo(() => new DigitalWallets(environment), [environment]);
const paymentFailureCallback = useCallback((error: unknown) => {
console.error(error);
}, []);
useEffect(() => {
const initializeAndMountButtons = async () => {
const canMakePayment = await digitalWallets.initialize({
paymentOptions: {
currencyCode: 'USD',
countryCode: 'US',
totalPrice: calculateTotal(displayItems),
displayItems,
},
cardNetworks: ['AMEX', 'VISA'],
billingAddressRequired: true,
requiredBillingContactFields: ['email', 'name', 'phone', 'postalAddress', 'postalCode'],
googlePayGateway: {
name: 'Foosburgers',
merchantId: '123456',
},
merchant: {
name: 'Foosburgers',
applePayMerchantId: 'foo',
googlePayMerchantId: 'foo',
validationConfig: {
url: '/api/merchantverification',
headers: {
foo: 'bar',
},
body: {
foo: 'bar',
},
},
},
});
if (canMakePayment.applePay || canMakePayment.googlePay) {
digitalWallets.mountButtons(paymentSuccessCallback, paymentFailureCallback, buttonStyles);
}
};
void initializeAndMountButtons();
return () => {
digitalWallets.unmountButtons();
};
// NOTE: We did not include `displayItems` or `paymentSuccessCallback` here
// since we only want to call initialize once per DigitalWallets instance.
}, [digitalWallets]);
useEffect(() => {
digitalWallets.updatePaymentOptions({
currencyCode: 'USD',
countryCode: 'US',
totalPrice: calculateTotal(displayItems),
displayItems,
});
}, [digitalWallets, displayItems]);
return <div data-pay-buttons />;
};Vue
<script setup lang="ts">
import { watchEffect, onMounted } from 'vue'
import {
type ButtonStyles,
type DisplayItem,
type Environment,
type PaymentData,
DigitalWallets,
} from '@olo/pay-digital-wallets'
const emit = defineEmits(['payment-successful'])
type Props = {
displayItems: DisplayItem[]
environment: Environment
}
const { displayItems, environment } = defineProps<Props>()
const calculateTotal = (items: DisplayItem[]): string => {
return items
.reduce((sum, item) => {
if (item.type === 'DISCOUNT') {
return sum - parseFloat(item.price)
}
return sum + parseFloat(item.price)
}, 0)
.toFixed(2)
}
const buttonStyles: ButtonStyles = {
googlePay: {
buttonColor: 'default',
buttonRadius: 5,
buttonSizeMode: 'static',
buttonType: 'order',
},
applePay: {
buttonWidth: '100%',
buttonHeight: '40px',
buttonRadius: '10px',
buttonPadding: '0px',
},
}
const digitalWallets = new DigitalWallets(environment)
const paymentFailureCallback = (error: unknown) => {
console.error(error)
}
const canMakePayment = await digitalWallets.initialize({
paymentOptions: {
currencyCode: 'USD',
countryCode: 'US',
totalPrice: calculateTotal(displayItems),
displayItems,
},
cardNetworks: ['AMEX', 'VISA'],
billingAddressRequired: true,
requiredBillingContactFields: ['email', 'name', 'phone', 'postalAddress', 'postalCode'],
googlePayGateway: {
name: 'Foosburgers',
merchantId: '123456',
},
merchant: {
name: 'foosburgers',
applePayMerchantId: 'foo',
googlePayMerchantId: 'foo',
validationConfig: {
url: '/api/merchantverification',
headers: {
foo: 'bar',
},
body: {
foo: 'bar',
},
},
},
})
onMounted(() => {
if (canMakePayment.applePay || canMakePayment.googlePay) {
digitalWallets.mountButtons(
(data: PaymentData) => emit('payment-successful', data),
paymentFailureCallback,
buttonStyles,
)
}
})
watchEffect(() => {
digitalWallets.updatePaymentOptions({
currencyCode: 'USD',
countryCode: 'US',
totalPrice: calculateTotal(displayItems),
displayItems,
})
})
</script>
<template>
<div data-pay-buttons></div>
</template>Troubleshooting
We did our best to provide helpful errors in the developer console so always check there first if something is going wrong.
My canMakePayment.applePay returned from initialize is always false
Make sure you're using HTTPS to serve your site. Apple does a check for this and won't allow the button to be rendered if http is being used.
My Apple Pay modal just spins forever
Close the modal and check your Network tab in your developer tools to see if your merchant verification request has failed. This is the most common reason for this happening.
Google Pay is giving a generic error with [OR_BIBED_06] OR_BIBED_06 in it.
Unfortunately this is a fairly generic error from Google Pay. A couple things to check is to make sure you're passing in the correct environment to the DigitalWallets constructor. As well, double check the googlePayGateway properties when calling initialize. These are a common source of problems if they don't line up with what your payment processor is expecting.
Version History
| Release Date | Version | Description | | ------------ | ------- | ---------------------- | | 2025-09-05 | 0.6.8 | Initial Public Release |
