Full Integration Example
Two ready-to-run snippets: pick the one that matches your backend.
- Basic: the order ID (
invoiceId) is known at page-load time. Pass it toinit()and you are done. - CMS pattern: the order does not exist yet at page-load (typical for WooCommerce, Magento, OpenCart, custom platforms). When the customer authorizes the payment, your backend creates the order and returns the resulting
invoiceIdthroughonBeforeProcessPayment.
Both snippets pass the required paymentData (with amount + currency) and token to init(). The button is only rendered on devices that can pay with Google Pay.
If the cart amount can change after the button is rendered (quantity edits, coupons, shipping recalculation), re-initialize the component with fresh paymentData and a token issued for the new amount each time the cart changes. Do not try to mutate amount inside onBeforeProcessPayment: the component rejects it with 1010 PAYMENT_DATA_MISMATCH. See Authentication for how the token is bound to amount and invoiceId.
- Basic
- CMS pattern
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src='https://test-pay.dnapayments.com/components/google-pay/google-pay-component.js'></script>
<script>
async function renderGooglePay() {
const token = 'YOUR_ACCESS_TOKEN';
const paymentData = {
amount: 24,
currency: 'GBP',
invoiceId: 'YOUR_INVOICE_ID',
description: 'Shoes',
paymentSettings: {
terminalId: 'YOUR_TERMINAL_ID',
callbackUrl: 'https://example.com/callback',
failureCallbackUrl: 'https://example.com/failure-callback'
},
customerDetails: {
accountDetails: { accountId: 'uuid000001' },
billingAddress: {
firstName: 'John', lastName: 'Doe',
addressLine1: 'Fulham Rd',
postalCode: 'SW6 1HS', city: 'London', country: 'GB'
},
email: 'example@email.com',
mobilePhone: '+441234567890'
},
orderLines: [{
name: 'Running shoe',
quantity: 1,
unitPrice: 24,
taxRate: 20,
totalAmount: 24,
totalTaxAmount: 4,
imageUrl: 'https://www.example.com/logo.png',
productUrl: 'https://www.example.com/AD6654412.html'
}]
};
const events = {
onClick: () => {
console.log('Google Pay button clicked');
},
onError: (error) => {
console.error('Google Pay error:', error);
},
onCancel: () => {
console.log('Payment cancelled');
},
onPaymentSuccess: (result) => {
console.log('Payment processed', result);
window.location.href = '/success';
}
};
window.DNAPayments.GooglePayComponent.init({
containerElement: document.getElementById('google-pay-btn-container'),
paymentData,
events,
token
});
}
window.addEventListener('load', renderGooglePay);
</script>
</head>
<body>
<div id='google-pay-btn-container' style='width: 100%; height: 46px;'></div>
</body>
</html>
Use this shape when the order is created server-side at the moment the customer commits to pay. After the customer authorizes the payment in the Google Pay sheet, onBeforeProcessPayment calls your backend to create the order, gets a freshly minted access token bound to the new invoiceId, and returns both to the component. The component then submits the payment using these refreshed values.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src='https://test-pay.dnapayments.com/components/google-pay/google-pay-component.js'></script>
<script>
async function renderGooglePay() {
// paymentData passed at init() does NOT contain invoiceId yet.
// amount and currency are required so the component can render the button
// and the access token can be bound to the correct total.
const paymentData = {
amount: 24,
currency: 'GBP',
description: 'Shoes',
paymentSettings: {
terminalId: 'YOUR_TERMINAL_ID',
callbackUrl: 'https://example.com/callback',
failureCallbackUrl: 'https://example.com/failure-callback'
},
customerDetails: {
accountDetails: { accountId: 'uuid000001' },
billingAddress: { country: 'GB' }
},
orderLines: [{
name: 'Running shoe',
quantity: 1,
unitPrice: 24,
taxRate: 20,
totalAmount: 24,
totalTaxAmount: 4
}]
};
const events = {
onClick: () => {
console.log('Google Pay button clicked');
},
// Fires after the customer authorizes in the Google Pay sheet.
// The server creates the order and issues a token bound to it,
// then returns the refreshed paymentData and token. The locked
// fields (amount, currency, delivery address) must match init().
onBeforeProcessPayment: async () => {
const { invoiceId, token } = await fetch('/api/create-order-and-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: paymentData.amount, currency: paymentData.currency })
}).then(r => r.json());
return {
paymentData: { ...paymentData, invoiceId },
token
};
},
onPaymentSuccess: (result) => {
console.log('Payment processed', result);
window.location.href = '/success';
},
onCancel: () => {
console.log('Payment cancelled');
},
onError: (error) => {
console.error('Google Pay error:', error);
}
};
window.DNAPayments.GooglePayComponent.init({
containerElement: document.getElementById('google-pay-btn-container'),
paymentData,
events,
token: 'BOOTSTRAP_ACCESS_TOKEN' // replaced by the one returned from onBeforeProcessPayment
});
}
window.addEventListener('load', renderGooglePay);
</script>
</head>
<body>
<div id='google-pay-btn-container' style='width: 100%; height: 46px;'></div>
</body>
</html>
Replace the script source with the production CDN before going live:
<script src='https://pay.dnapayments.com/components/google-pay/google-pay-component.js'></script>
See Deployment for the full go-live checklist.