Integration
This guide walks you through embedding the Alipay button on your page. The flow is:
- Load the component script.
- Add a container element.
- Define event handlers.
- Build the
paymentDataobject. - Call
init(options).
For a copy-paste-ready end-to-end snippet, jump to the Full Example.
Step 1: Add the Alipay Component script
Include the component bundle in the <head> of your HTML page.
Sandbox / Test:
<script src='https://test-pay.dnapayments.com/components/alipay-wechat-pay/alipay-wechat-pay-component.js'></script>
Production:
<script src='https://pay.dnapayments.com/components/alipay-wechat-pay/alipay-wechat-pay-component.js'></script>
The script exposes window.DNAPayments.AlipayComponent.
Step 2: Create the container element
<div id='alipay-btn-container' style='width: 100%; height: 46px;'></div>
Apply the desired width and height to the container: the button takes the container's dimensions.
Step 3: Define event handlers
Provide callbacks via the events object passed to init(). The full list is in the Events section. The most common four are shown here.
function onClick() {
console.log('Alipay button has been clicked');
}
function onError(error) {
// error is { code, message, additionalInfo? }, see the Handling Error Codes page
console.error('Alipay error:', error);
}
function onCancel() {
console.log('Payment was cancelled by the user');
}
function onPaymentSuccess(result) {
console.log('Payment processed successfully', result);
// redirect to a success page, persist invoiceId, etc.
}
const events = {
onClick,
onError,
onCancel,
onPaymentSuccess,
};
Step 4: Build paymentData
paymentData carries the order details. Top-level fields and nested structures are described in paymentData reference.
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'
}]
};
Step 5: Initialize the button
Pass the container, paymentData, events and your access token to init():
async function renderAlipay() {
window.DNAPayments.AlipayComponent.init({
containerElement: document.getElementById('alipay-btn-container'),
paymentData,
events,
token: 'YOUR_ACCESS_TOKEN',
});
}
window.addEventListener('load', renderAlipay);
The OAuth token endpoint returns an object (access_token, expires_in, token_type, ...). Pass only the access_token string to the component. See Authentication for the token flow and the scopes required for the seamless component.
Payment flow
Alipay is QR-based. The flow looks like this:
- The customer taps the Alipay button.
- The component opens a modal with the Alipay QR code and a countdown driven by
paymentTimeoutInSeconds(default 15 minutes). - The customer scans the QR with their Alipay app and completes the payment on their phone.
- On success,
onPaymentSuccessfires and the modal closes. - If the customer closes the modal before scanning,
onCancelfires. - If the countdown runs out before the payment completes,
onError({ code: 1006 })fires. - If anything else goes wrong during the flow (network failure, invalid
paymentData, expired token, backend rejection),onError({ code, message, additionalInfo? })fires with the relevant code from Handling Error Codes.
API reference
The component exposes the following functions on window.DNAPayments.AlipayComponent:
| Method | Description |
|---|---|
init(options) | Render the button and return the component instance. |
create(...) | ⚠️ Deprecated: use init() instead. |
init(options)
const component = await window.DNAPayments.AlipayComponent.init(options);
Renders the Alipay button into containerElement and returns the initialized component instance.
options fields
| Property | Type | Required | Description |
|---|---|---|---|
containerElement | HTMLElement | ✅ | DOM node where the button is rendered. |
events | object | ✅ | Event handler map, see Events. |
paymentData | object | ✅ | Payment request, see paymentData reference. Must include at least amount, currency and paymentSettings.terminalId. |
token | string | ✅ | OAuth2 access token (the access_token string returned by Authentication). |
language | string | - | Language of the QR modal UI. Allowed values: 'en', 'is', 'pt', 'es', 'de'. Defaults to 'en'. |
paymentTimeoutInSeconds | number | - | How long the QR code stays valid. Defaults to 900 (15 minutes). |
environment | string | - | Either 'sandbox' or 'production'. Optional, defaults to the environment baked into the bundle. |
create(...) (deprecated)
create() is kept for backwards compatibility and will be removed in a future version. Use init(options) instead.
Migration:
// Before: positional arguments
window.DNAPayments.AlipayComponent.create(container, events, payload);
// After: single options object
window.DNAPayments.AlipayComponent.init({
containerElement: container,
events,
paymentData: payload.paymentData,
token: payload.token,
language: payload.language,
paymentTimeoutInSeconds: payload.paymentTimeoutInSeconds,
});
Events
The component emits the following events. All handlers are attached via the events map passed to init().
| Event | Signature | Fires when |
|---|---|---|
onClick | () => void | The user taps the Alipay button, before the QR modal is shown. |
onLoad | () => void | Fires after the button has been rendered and mounted into containerElement. |
onBeforeProcessPayment | async () => { paymentData?, token?, paymentTimeoutInSeconds? } | Fires after the click but before the QR is requested. The handler may return refreshed paymentData, token and paymentTimeoutInSeconds: this is the canonical CMS pattern where the order (and invoiceId) is created server-side at this moment. Locked fields (amount, currency, delivery address) must match the init() values, otherwise the component fires 1011. See Deferred values via onBeforeProcessPayment. |
onPaymentSuccess | (result) => void | The payment has been processed successfully on the Alipay side. See onPaymentSuccess payload. |
onCancel | () => void | The user closed the QR modal before completing the payment. |
onError | (error) => void | Any error during initialization or processing. See onError payload and Handling Error Codes. |
Deferred values via onBeforeProcessPayment
onBeforeProcessPayment fires after the customer taps the button and before the QR is requested. The handler can return { paymentData, token, paymentTimeoutInSeconds } to swap in server-side values (typically invoiceId and a freshly issued access token):
const events = {
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,
paymentTimeoutInSeconds: 600 // optional override
};
}
};
Locked fields (amount, currency, delivery address) must match the values passed at init(). Returning a paymentData whose locked fields differ fires 1011 PAYMENT_DATA_MISMATCH. Use onBeforeProcessPayment to add server-side fields, not to change the displayed total. If the cart amount can change, re-initialize the component instead.
onClick is deprecatedEarlier versions allowed returning { paymentTimeoutInSeconds } from onClick. This path still works but is deprecated and logs a console.warn in the SDK. Return refreshed values from onBeforeProcessPayment instead.
onPaymentSuccess payload
{
id: string,
reference: string,
success: boolean
}
The object may include additional fields when applicable.
onError payload
{
code: number,
message: string,
additionalInfo?: any
}
additionalInfo carries the underlying cause when available (the original exception, or the response body from the DNA Payments backend), useful for logging and debugging. See Handling Error Codes for the full list of code values.
paymentData reference
The most commonly used fields of paymentData:
| Field | Required | Description |
|---|---|---|
amount | ✅ | Total transaction amount as a decimal number. |
currency | - | ISO 4217 currency code (e.g. 'GBP'). Defaults to 'GBP'. |
invoiceId | - | Your internal order / invoice identifier. |
description | - | Human-readable description shown on receipts. |
paymentSettings.terminalId | ✅ | Your DNA Payments terminal ID. |
paymentSettings.callbackUrl | - | Server-to-server success callback. |
paymentSettings.failureCallbackUrl | - | Server-to-server failure callback. |
customerDetails.accountDetails.accountId | - | Stable customer ID on your side. |
customerDetails.email | - | Customer email. |
customerDetails.mobilePhone | - | Customer phone. |
customerDetails.billingAddress | - | Billing address object (firstName, lastName, addressLine1, postalCode, city, country, ...). |
customerDetails.deliveryDetails.deliveryAddress | - | Shipping address object (same shape as billingAddress). |
orderLines | - | Array of line items (name, quantity, unitPrice, taxRate, totalAmount, totalTaxAmount, imageUrl, productUrl). |