Drop in - GooglePay
1. API Introduction
1.1 API List
| Sequence of Interaction | Direction | API Type | API PATH |
| 2.1 Obtain Initialization Info for Frontend Component | Merchant -> PayerMax | Backend API | /applyDropinSession |
| 2.3 Create Payment, Call Frontend Component Order API | Merchant -> PayerMax | Backend API | /orderAndPay |
| 2.4.1 Asynchronous Payment Result Notification | PayerMax -> Merchant | Backend API | /collectResultNotifyUrl |
| 2.4.2 Query Payment Transaction | Merchant -> PayerMax | Backend API | /orderQuery |
1.2 Environment Information
Sandbox Environment:
https://pay-gate-uat.payermax.com/aggregate-pay/api/gateway/<API PATH>Production Environment:
https://pay-gate.payermax.com/aggregate-pay/api/gateway/<API PATH>
1.3 Request Headers
"headers": {
"Accept": "application/json",
"sign": "Please refer to the signing rules: https://docs-v2.payermax.comen/202506-version/developer/config-settings.html",//Required
"Content-Type": "application/json"
}2. Start Integration
2.1 Obtain Initialization Info for Frontend Component
The merchant server initiates an HTTP POST request through the /applyDropinSession API to obtain the client token clientKey and session token sessionKey required for frontend component initialization.
- Request Example for /applyDropinSession API:
{
"requestTime": "2024-11-20T01:56:36.753-02:00",
"keyVersion": "1",
"data": {
"country":"US",
"currency": "USD",
"totalAmount": "19.99",
"componentList": ["CARD","GOOGLEPAY"],
"userId": "1447410849000200"
},
"appId": "381ded7c863c439a9e29b4519867965a",
"version": "1.5",
"merchantNo": ""
}- Request Response Example for /applyDropinSession API:
{
"msg": "",
"code": "APPLY_SUCCESS",
"data": {
"sessionKey": "964bffa7c9eb4951bd5ba11a2691e5ed",
"notSupportedComponent": [],
"clientKey": "8eef820ecbd443b7a608c2e0863750eb"
}
}2.2 Render Frontend Component
- Include the CDN package in the relevant HTML page.
<script src="https://cdn.payermax.com/dropin/js/pmdropin.min.js"></script>- Embed a container area for the
ApplePaybutton on the merchant page using adivtag.
<div class="frame-googlepay">
<!-- Form Content -->
</div>- Initialize PayerMax Frames and mount GooglePay.
const googlePay = PMdropin.create('googlepay', {
clientKey: "8eef820ecbd443b7a608c2e0863750eb",
sessionKey: "0fdde7eda5fe4cc28ca8fdc759e28dc1",
sandbox: true,
payButtonConfig: {
buttonRadius: "12",
buttonColor: "white",
buttonType: "order",
buttonLocale: "en",
width: "240px",
height: "40px"
}
});
//Mount the button
googlePay.mount('.frame-googlepay');- Listen to the button status. Once the user completes the Google Pay authentication flow, the frontend receives the
paymentToken. The server then initiates the payment and returns theredirectUrlto the frontend to guide the user through 3DS authentication.
googlePay.on('ready', () => {
console.log('Component initialization completed');
})
googlePay.on('load', (res = {}) => {
const { code, msg } = res || {};
if (code === "SUCCESS") {
console.log('[merchant][load]success:', res)
} else {
console.log('[merchant][load]fail:', res)
}
})
googlePay.on('payButtonClick', (res) => {
googlePay.emit('setDisabled', true);
googlePay.emit('canMakePayment')
.then(paymentRes => {
console.log('canMakePayment')
if (paymentRes.code === 'APPLY_SUCCESS') {
const paymentToken = paymentRes?.data?.paymentToken;
console.log('paymentToken:', paymentToken)
// ⚠️ Initiate payment API
// The merchant requests their own backend API to place the order,
// The merchant constructs request parameters using params, which must include paymentToken
const params = { // Add params definition
token: paymentToken,
};
_postapi('orderAndPay', params)
.then(apiRes => {
const code = (apiRes || {}).code;
if (code === 'APPLY_SUCCESS') {
if(apiRes.threeDSUrl){
handle3DS(threeDSUrl)
// Complete 3DS using the PayerMax in-component popup; alternatively, open threeDSUrl in a new browser tab to complete 3DS
}
googlePay.emit('paySuccess');// Payment successful, googlePay widget disappears
} else {
googlePay.emit('payFail');// Payment failed, googlePay widget disappears
}
googlePay.emit('setDisabled', false);// ⚠️ Unfreeze the form after the payment API call completes
})
.catch(err => {
console.error('API request failed:', err);
googlePay.emit('setDisabled', false);// Unfreeze the form if an exception occurs
});
}
})
.catch(err => {
console.error('Payment capability check failed:', err);
googlePay.emit('setDisabled', false);
});
});
// If a URL (i.e., threeDSUrl) is returned after orderAndPay, use the handle3DS method to trigger the popup
function handle3DS(threeDSUrl) {
googlePay.create3DSPopup({
// width/height are not passed, they will be automatically calculated based on the device and viewport; they can also be explicitly passed, e.g., '80%', '400px', etc.
url: threeDSUrl,
// If the 3DS link does not support iframe (i.e., returns NOT_SUPPORTED, causing our popup to fail), we automatically handle it by default via window.location.href = url;
// However, if the merchant uses a WebView and restricts the behavior of window.location.href = url, the merchant needs to control the redirection manually using the custom jumpToUrlFn function.
//jumpToUrlFn: (url) => {
// window.location.href = url; // Merchant handles opening the URL manually
//}
})
.then(res => {
if (res.code === '3DS_PROCESSED') {
// 3DS process completed, proceed with the payment flow.
console.log('3DS process completed', res.data);
// The merchant needs to maintain the existing logic here. The merchant side should actively query the payment result and continue subsequent interactions.
proceedPayment(res.data);
}
})
.catch(err => {
if (err.code === 'USER_CANCEL') {
// The merchant can choose not to handle this, but should allow the user to click the payment button again
showMessage('You have closed the verification window');
} else {
showMessage('Verification exception occurred, please try again');
}
});
}- Get the
paymentToken. Once the user confirms the payment on the frontend, the frontendcanMakePaymentAPI will return the following information, which is used for the backend to initiate the payment.
{
"msg": "",
"code": "APPLY_SUCCESS",
"data": {
"paymentToken": "CPT771e98494eff41f1a03a715ebab69cc9",
"cardOrg": "VISA",
"maskCardNumber": "444433****1111",
"cardExpirationMonth": "12",
"cardType": "CREDIT",
"cardExpirationYear": "26",
"cardHolderFullName": "Jemy Cheung",
"agreementAccepted": true,
"cardBinNo": "444433",
"cardIssuingCountry": "US"
}
}2.3 Create Payment
- Merchant Server: Call the /orderAndPay API to initiate an HTTP POST request and create a payment.
- /orderAndPay API request example:
{
"requestTime": "2024-11-20T01:56:45.802-02:00",
"keyVersion": "1.5",
"data": {
"currency": "USD",
"country":"US",
"totalAmount": 19.99,
"expireTime": "3600",
"paymentDetail": {
+ "paymentToken": "dbe78b7dd4fa4b668bacfdcc7153821d",//Callback to frontend paymentDetail after the user enters card info and clicks pay
"buyerInfo": {
"clientIp": "146.75.136.237",
"userAgent": "Chrome"
},
+ "sessionKey": "abf62fdcf9c4408cb73117db6e740713"
},
"frontCallbackUrl": "https://",
"subject": "xxx Game HK Limited",
"outTradeNo": "ov1_5b89ced71d764ed9994e6882d88082f7",
"notifyUrl": "https://",
"userId": "1447410849000200",
"integrate": "Direct_Payment",
"terminalType": "WEB"
},
"appId": "381ded7c863c439a9e29b4519867965a",
"version": "1.5",
"merchantNo": "P04010116880289"
}- /orderAndPay API response example:
{
"msg": "Success.",
"code": "APPLY_SUCCESS",
"data": {
"outTradeNo": "test_da78b1f3c2f9443b966347fc89305fc9",
"tradeToken": "T2024052805951921811176",
"status": "SUCCESS"
}
}2.4 Get Payment Result
The data.status in the response of the Create Payment/orderAndPay API is not the final payment status. Therefore, merchants should not use it directly to update the payment result.
2.4.1 Payment Result Notification
See Get Payment Result Integration - Payment Result Notification.
2.4.2 Payment Result Inquiry
See Get Payment Result Integration - Payment Result Inquiry.
3. API
Usage method: PMdropin.API.
| API | Description | Details |
|---|---|---|
| create | Instantiate a built-in component | Refer3.1 create |
| mount | Mount instantiated component to div tag | Refer3.2 mount |
| on | Listen events | Refer3.3 on |
| emit | Trigger events | Refer3.5 emit |
3.1 create
Used to initialize components, please use PMdropin.create(ComponentName, Options).
ComponentName Explanation
| ComponentName | Field Type | Description |
|---|---|---|
| applepay | string | ApplePay Compoment |
Options Explanation
| Options | Required Or Not | Field Type | Default Value |
|---|---|---|---|
| clientKey | Y | String | - |
| sessionKey | Y | String | - |
| sandbox | N | Boolean | false |
| theme | N | String | light |
| payButtonStyle | N | String | - |
3.2 mount
sed to mount initialization component instances, please use PMdropin.mount(Tag).
Tag Explanation
| Tag | Description |
|---|---|
| id | The value of the id element that needs to be mounted, such as PMdropin.mount('#applepay-frame') |
| class | The value of the class element that needs to be mounted, such as PMdropin.mount('.applepay-frame') |
3.3 on
Used to listen to component built-in response events, please use PMdropin.on(Event, CallbackFunction).
Event Explanation
| Tag | Description | Returned Value |
|---|---|---|
| ready | Triggered when the component completes loading | null |
| payButtonClick | Triggered when the ApplePay button is clicked | null |
3.4 create3DSPopup
Used to open the 3DS authentication page within an in-component popup.
Language Settings Note: The SDK automatically retrieves the language from the instance configuration; there is no need to pass it separately in create3DSPopup. Important Note: 3DS_PROCESSED only indicates that the 3DS verification process has been completed; it does not mean the verification was successful. The merchant must query the final verification result (success/failure) via subsequent APIs.
Input Parameters:
| Parameter | Type | Required | Default Value | Description |
|---|---|---|---|---|
| url | string | Y | - | The 3DS authentication page URL (obtained from the orderAndPay API). |
| showMask | boolean | N | true | Whether to display the background mask overlay. |
| width | string | N | Responsive | Popup width. If omitted, it will be automatically calculated based on the device/viewport. |
| height | string | N | Responsive | Popup height. If omitted, it will be automatically calculated based on the device/viewport. |
| jumpToUrlFn | function | No | (url)=>{window.location.href = url;} | Merchant custom redirection method |
Returns:
| CODE | Description | Handling Suggestions |
|---|---|---|
3DS_PROCESSED | 3DS process has been handled. | Proceed with the subsequent payment flow, and actively query the final authentication result via the API. |
USER_CANCEL | User closed the popup. | Prompt the user that the window has been closed, and allow them to retry. |
INVALID_PARAMS | Invalid input parameters for the call. | Check the input parameters based on err.msg (e.g., ensure the URL is required, non-empty, and of the correct type), then retry after correction. |
NOT_SUPPORTED | The current issuer bank page does not support opening via an iframe popup | We will automatically downgrade to window.location.href to open the URL. If you restrict window.location.href, please use jumpToUrlFn for custom redirection. |
3.5 emit
Used to invoke the component's built-in methods, using the formatPMdropin.emit(Event, Params).
| Event | Params | Description |
|---|---|---|
| canMakePayment | Object | Obtain the token for the current payment |
| switchTheme | string | Switch theme |
| setDisabled | Boolean | Set the availability status of the component |
| setpayButtonConfig | Object | Set button styles |
3.5.1 emit.canMakePayment
- Checks whether the current component status meets the conditions to initiate a payment, and returns the
paymentTokenafter verification passes.
PMdropin.emit('canMakePayment', params?)params is an optional parameter. If the merchant server has already provided complete payment information when calling the /applyDropinSession API, you can call PMdropin.emit('canMakePayment') directly without passing parameters.
- Options Configuration:
| Options | Required | Field Type | Description |
|---|---|---|---|
| totalAmount | N | String | Payment amount, formatted as a pure numeric string (e.g., '1.00'). This is only recommended for scenarios where the merchant server did not pass the amount when calling the /applyDropinSession API to obtain pre-component initialization information. This amount is solely used for display within the Apple Pay payment sheet. |
Example:
PMdropin.emit('canMakePayment', {
totalAmount: '1.00'
})Notes:
totalAmountonly accepts valid numeric strings (e.g.,'0.01','99.99'). If an invalid value is passed, the API will return the error codeAMOUNT_INVALID.- If the merchant server has already provided the amount when calling
/applyDropinSession, the amount used during final order submission must be consistent with it; otherwise, it may lead to payment failure or risk control interception.- Please ensure that the
totalAmountpassed incanMakePaymentis strictly consistent with the amount during final order submission; otherwise, it may lead to payment failure or risk control interception.
canMakePayment Response:
| Code | Description |
|---|---|
| APPLY_SUCCESS | Successfully obtained the paymentToken. |
| UNKNOWN_ISSUE | Exception occurred / Internal error. |
| AMOUNT_INVALID | Invalid input amount format. |
3.5.2 emit.setDisabled
- Set the component available state
- Type:
Boolean - Default:
false
// Button disabled state
PMdropin.emit('setDisabled', true)
// Button enabled state
PMdropin.emit('setDisabled', false)3.5.3 emit.setpayButtonConfig
- Sets the button styles
- Type:
Object - Default:
{
buttonRadius: "12", // Sets the Google Pay button border radius. String
buttonColor: 'default', // Sets the button color. "default"/"white"/"black"
buttonType: 'plain',
buttonLocale: 'en',
width: "240px",
height: "40px",
}4. Internal Field Description
| Field | Default Value | Type | Enumeration | Description |
| width | "240px" | String | / | Set Google Pay button width |
| height | "40px" | String | / | Set Google Pay button height |
| buttonRadius | "12" | String | / | Set the border radius of the googlepay button String |
| buttonColor | 'default' | String | 'default'/'white'/ 'black' | Set button color |
| buttonType | 'plain' | String | "plain","buy","book","checkout","donate","order","pay","subscribe" | Set button type Same as GooglePay official. See Preview demo for customized button |
| buttonLocale | 'en' | String | 'en'/'ja'/'zh'/... International language encoding | Set the multi-language text on the button, the same as GooglePay official, only supports the specified type, such as "checkout", "donate", etc. |
5. Color Display
| Input | Effect Preview |
| default | ![]() |
| white | ![]() |
| black | ![]() |
| 入参 | 效果预览 |
| default | ![]() |
| white | ![]() |
| black | ![]() |
6. buttonType Display
| Input | Effect Preview |
| "plain" | ![]() |
| "buy" | ![]() |
| "book" | ![]() |
| "checkout" | ![]() |
| "donate" | ![]() |
| "order" | ![]() |
| "pay" | ![]() |
| "subscribe" | ![]() |
7. buttonLocale Display
| Input | Effect Preview | Description |
| "ja" | ![]() ![]() | Japanese |
| "bg" | ![]() ![]() | Bulgarian |















