Skip to content

Drop in - GooglePay

1. API Introduction

1.1 API List

Sequence of InteractionDirectionAPI TypeAPI PATH
2.1 Obtain Initialization Info for Frontend ComponentMerchant -> PayerMaxBackend API/applyDropinSession
2.3 Create Payment, Call Frontend Component Order APIMerchant -> PayerMaxBackend API/orderAndPay
2.4.1 Asynchronous Payment Result NotificationPayerMax -> MerchantBackend API/collectResultNotifyUrl
2.4.2 Query Payment TransactionMerchant -> PayerMaxBackend 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

json
"headers": {
        "Accept": "application/json",
        "sign": "Please refer to the signing rules: https://docs-v2.payermax.com/doc-center/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.

js
{
    "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.1",
    "merchantNo": ""
}
json
{
    "msg": "",
    "code": "APPLY_SUCCESS",
    "data": {
            "sessionKey": "964bffa7c9eb4951bd5ba11a2691e5ed",
            "notSupportedComponent": [],
            "clientKey": "8eef820ecbd443b7a608c2e0863750eb"
    }
}

2.2 Render Frontend Component

  1. Include the CDN package in the relevant HTML page.
html
<script src="https://cdn.payermax.com/dropin/js/pmdropin.min.js"></script>
  1. Embed a container area for the ApplePay button on the merchant page using a div tag.
html
<div class="frame-googlepay">  
    <!-- Form Content -->
</div>
  1. Initialize PayerMax Frames and mount GooglePay.
js
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');
  1. 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 the redirectUrl to the frontend to guide the user through 3DS authentication.
SQL
googlePay.on('ready', () => {
        console.log('Component initialized');
    })
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 the request parameters using params, which must include the 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 via the PayerMax in-component popup, or open threeDSUrl in a new browser tab to complete 3DS
                            }    
                            googlePay.emit('paySuccess');// Payment successful, the Google Pay component disappears
                        } else {
                            googlePay.emit('payFail');// Payment failed, the Google Pay component 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 the returned URL (which is the 'threeDSUrl') is obtained after 'orderAndPay', use the 'handle3DS' method to invoke the popup
function handle3DS(threeDSUrl) {
  googlePay.create3DSPopup({
    url: threeDSUrl,
    // If width/height is not passed, it will be automatically calculated based on the device and viewport; it can also be explicitly passed as '80%', '400px', etc
  })
  .then(res => {
    if (res.code === '3DS_PROCESSED') {
      // 3DS flow completed, proceed with the payment process.
      console.log('3DS flow completed', res.data);
      // The merchant needs to maintain the existing logic here; the merchant side should actively query the payment result to 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 continue clicking the payment button
      showMessage('You have closed the authentication window');
    } else {
      showMessage('An exception occurred during authentication, please try again');
    }
  });
}
  1. Get the paymentToken. Once the user confirms the payment on the frontend, the frontend canMakePayment API will return the following information, which is used for the backend to initiate the payment.
Json
{
    "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

  1. Merchant Server: Call the /orderAndPay API to initiate an HTTP POST request and create a payment.
diff
{
        "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.4",
        "merchantNo": "P04010116880289"
}
json
{
    "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 Via Payment Notification

Please refer to Payment Result - Via Payment Notification.

2.4.2 Via Payment Inquiry

Please refer to Payment Result - Via Payment Inquiry.

3. API

Usage method: PMdropin.API.

APIDescriptionDetails
createInstantiate a built-in componentRefer create
mountMount instantiated component to div tagRefer mount
onListen eventsRefer on
emitTrigger eventsRefer emit

3.1 create

Used to initialize components, please use PMdropin.create(ComponentName, Options).

ComponentName Explanation

ComponentNameField TypeDescription
applepaystringApplePay Compoment

Options Explanation

OptionsRequired Or NotField TypeDefault Value
clientKeyYString-
sessionKeyYString-
sandboxNBooleanfalse
themeNStringlight
payButtonStyleNString-

3.2 mount

sed to mount initialization component instances, please use PMdropin.mount(Tag).

Tag Explanation

TagDescription
idThe value of the id element that needs to be mounted, such as PMdropin.mount('#applepay-frame')
classThe 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

TagDescriptionReturned Value
readyTriggered when the component completes loadingnull
payButtonClickTriggered when the ApplePay button is clickednull

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.

Input Parameters:

ParameterTypeRequiredDefault ValueDescription
urlstringY-The 3DS authentication page URL (obtained from the orderAndPay API).
showMaskbooleanNtrueWhether to display the background mask overlay.
widthstringNResponsivePopup width. If omitted, it will be automatically calculated based on the device/viewport.
heightstringNResponsivePopup height. If omitted, it will be automatically calculated based on the device/viewport.

Returns:

CODEDescriptionHandling Suggestions
3DS_PROCESSED3DS process has been handled.Proceed with the subsequent payment flow, and actively query the final authentication result via the API.
USER_CANCELUser closed the popup.Prompt the user that the window has been closed, and allow them to retry.
INVALID_PARAMSInvalid 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.

3.5 emit

用于调用组件内置方法,使用方法PMdropin.emit(Event, Params)

EventParams描述
canMakePaymentObject获取本次支付token
switchThemestring切换主题
setDisabledBoolean设置组件可用状态
setpayButtonConfigObject设置按钮样式

3.5.1 emit.canMakePayment

  1. Checks whether the current component status meets the conditions to initiate a payment, and returns the paymentToken after verification passes.
js
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.

  1. 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:

js
PMdropin.emit('canMakePayment', {
  totalAmount: '1.00'
})

Notes:

  • totalAmount only accepts valid numeric strings (e.g., '0.01', '99.99'). If an invalid value is passed, the API will return the error code AMOUNT_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 totalAmount passed in canMakePayment is strictly consistent with the amount during final order submission; otherwise, it may lead to payment failure or risk control interception.

canMakePayment Response:

CodeDescription
APPLY_SUCCESSSuccessfully obtained the paymentToken.
UNKNOWN_ISSUEException occurred / Internal error.
AMOUNT_INVALIDInvalid input amount format.

3.5.2 emit.setDisabled

  • Set the component available state
  • Type: Boolean
  • Default: false
js
// 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:
Go
{
  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

FieldDefault ValueTypeEnumerationDescription
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 encodingSet 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

InputEffect Preview
default
white
black
入参效果预览
default
white
black

6. buttonType Display

InputEffect Preview
"plain"
"buy"
"book"
"checkout"
"donate"
"order"
"pay"
"subscribe"

7. buttonLocale Display

InputEffect PreviewDescription
"ja"Japanese
"bg"Bulgarian

Was this page helpful?

Thank you for your help in improving PayerMax Product Docs!

Last updated:

Released under the MIT License.