# 1.Merchant access

    # 1.1 Online service address

    https://openplatform.gateapi.io
    

    # 1.2 Configure new applets

    • Log in to the merchant background, via the background address:https://www.gate.io/zh/merchant#/get-started
    • Fill in the basic information and apply to become a merchant
    • Configure the new application on the configuration page
    • View the list of configured applications and obtain the applicationClientId

    # 1.3 Generate payment key

    • Enter the developer page and generate a "Payment API Secret Key" for calculating signature verification
    • Enter the developer page and generate an "Authorize Secret Key" for calculating signature verification

    # 1.4 Key parameters

    • Payment API key, used to request a signature
    • ClientId, used to identify the identity and verify the signature together with the payment API key

    # 2. Security requirements

    # 2.1Protocol rules

    # 2.1.1 The following rules must be followed when the merchant accesses and calls API:

    Parameter name Description
    Transmission mode To ensure transaction security, HTTPS transmission is adopted and TLS1.2 or higher is used
    Data format Both submission and return data are in JSON format
    Signature algorithm HMAC-512 algorithm
    Signature requirement Signature verification is required for both requesting and receiving data, refer to Interface Signature
    Judgmental logic First judge the return of the protocol field, then judge the return of the business, and finally judge the transaction status

    # 2.1.2 Response format

    All interface returns are in JSON format, and users need to convert and extract data by themselves

    Parameter name Type Description
    status string The request processing result: SUCCESS means processing succeeds, FAIL means processing fails
    code string The defined error code, see the chapter on error codes for the specific meaning
    label string Defined error name, which is returned only when processing fails
    errorMessage string Defined error description
    data string Request return content in JSON format

    Return successfully:

    {
        "status": "SUCCESS",
        "code": "000000",
        "errorMessage": "",
        "data": {
            "prepayId": "43013197477711872",
            "merchantId": 10002,
            "merchantTradeNo": "13683379532935164644",
            "currency": "USDT",
            "totalFee": "1.6",
            "merchant_name": "MINIAPP PAYMENT TEST",
            "goods_name": "NFT",
            "status": "PENDING",
            "qrcode": "http://openplatform.gate.io/qr/P_6uSR4icI56VUdM2lbYdVihLxR_SsrcNfbdzNzfgp0=",
            "create_time": 1672216745425,
            "expire_time": 1672220345420
        }
    }
    

    Error return:

    {
      "status": "FAIL",
      "code": "400002",
      "label": "INVALID_SIGNATURE",
      "errorMessage": "Incorrect signature result",
      "data": {}
    }
    

    # 2.2 Parameter specification

    # 2.2.1 Merchant's order number

    The merchant can customize the order number, which should be a combination of English half-width characters such as letters, numbers, dash-, and underscore_, but should not contain Chinese characters or full-width characters. A unique order number should be generated for each deal (it is recommended to generate the order number based on the current system time plus in a random sequence). To initiate a repayment, the original order number should be submitted to avoid repeated payments.

    # 2.2.2 Amount

    All amount parameters are transmitted in strings with an accuracy of 8 decimal places, such as order amount, refund amount, etc. The minimum transaction amount of a single transaction amount is 0.0001, and the maximum is 5000000.

    # 2.2.3 Currency type

    For the currencies supported by GatePay, refer to supported currencies section

    # 2.2.4 Time

    Unless otherwise specified, all time fields should be in the form of millisecond-level Unix timestamps.

    # 2.3 API protocol header specification

    In order to ensure that the request received by GatePay API comes from an authorized legal third-party platform, the GatePay API interface will check the required fields of the HTTP request header and perform a verification signature of the request.

    # 2.3.1 New V2 Version Protocol Header

    The new version of the protocol header, which uses the secret key generated in the merchant's background to calculate the signature.

    Head field To ensure transaction security, use HTTPS transmission
    X-GatePay-Certificate-ClientId The clientId assigned to the merchant when registering the application
    X-GatePay-Timestamp The UTC timestamp when the request was generated, in milliseconds. Please note that GatePay does not process requests with a time gap of more than 10 seconds between the time of receiving the request and this timestamp
    X-GatePay-Nonce The string had better in length shorter than 32 characters and should consist of numbers and letters
    X-GatePay-Signature Request signature. GatePay determines whether the request is legal depending upon this signature

    # 2.4 Interface signature

    # 2.4.1 Signature specification

    Constructing signature string rules

    We expect the merchant's technical developers to construct the signature string according to the rules agreed in the current documentation. GatePay will construct the signature string in the same way. If the merchant constructs the signature string in the wrong way, the signature verification will not pass. The specific format of the signature string is explained first.

    Each line has one parameter. The end of the line is terminated by \n (a line feed, ASCII value 0x0A). If the parameter itself ends with \n, an additional \n is also required.

    timestamp\nnonce\nbodyString\n

    # 2.4.2 Signature algorithm

    Examples of signature algorithms are shown on the right

    GO

    import (
    "crypto/hmac"
    "crypto/sha512"
    "encoding/hex"
    "fmt"
    )
    // GenerateSignature: generate request signature
    // timestamp: UTC timestamps converted to strings with millisecond precision
    // nonce: random string
    // body: request body
    // secretKey: api_secret provided by GateIO
    // return: string signature
    func GenerateSignature(timestamp string, nonce string, body string, secretKey string) string {
      payload := fmt.Sprintf("%s\n%s\n%s\n", timestamp, nonce, body)
      mac := hmac.New(sha512.New, []byte(secretKey))
      mac.Write([]byte(payload))
      signature := mac.Sum(nil)
      return hex.EncodeToString(signature)
    }
    

    JAVA

    import javax.crypto.Mac;
      import javax.crypto.spec.SecretKeySpec;
      import java.security.InvalidKeyException;
      import java.security.NoSuchAlgorithmException;
      import java.util.Formatter;
      
      public class Main {
      
          private static final String HMAC_SHA512 = "HmacSHA512";
      
          private static String toHexString(byte[] bytes) {
              Formatter formatter = new Formatter();
              for (byte b : bytes) {
                  formatter.format("%02x", b);
              }
              return formatter.toString();
          }
      
          public static String calculateHMAC(String data, String key)
                  throws  InvalidKeyException, NoSuchAlgorithmException {
              SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), HMAC_SHA512);
              Mac mac = Mac.getInstance(HMAC_SHA512);
              mac.init(secretKeySpec);
              return toHexString(mac.doFinal(data.getBytes()));
          }
      
          public static void main(String[] args) throws Exception {
              String timeStamp = "1673613945439";
              String nonce = "3133420233";
              String body = "{\"code\":\"ac8B7Pl7C-XgfH6zxtd3SidYt7XIfWKU\",\"grant_type\":\"authorization_code\",\"redirect_uri\":\"https://gate.bytetopup.com\",\"client_id\":\"2Ugf9YGMCFRk85Yy\"}";
              String data = String.format("%s\n%s\n%s\n", timeStamp, nonce, body);
              String key = "zgsN5DntmQ2NCQiyJ4kJLyyEO25ewdDHydOSFIHdGrM=";
              String hmac = calculateHMAC(data, key);
              System.out.println(hmac);
          }
      }
    

    Python

    import hashlib
      import hmac
      def generate_signature(timestamp: string, nonce: string, body string, secret: string) -> string:
          '''
          generate request signature
          :param timestamp: UTC timestamps converted to strings with millisecond precision
          :param nonce: random string
          :param body: request body
          :param secret: api_secret provided by GatePay
          :return: return the string signature
          '''
          payload = '%s\n%s\n%s\n' % (timestamp, nonce, body)
          signed = hmac.new(secret.encode(), payload.encode(), hashlib.sha512)
          return signed.digest().hex()
    

    PHP

    <?php
    function generateSignature($timestamp, $nonce, $body, $secretKey) {
        $payload = "$timestamp\n$nonce\n$body\n";
        $signature = hash_hmac('sha512', $payload, $secretKey, true);
        return bin2hex($signature);
    }
    $timestamp = "1631257823000";
    $nonce = "abcd1234";
    $body = 'the post request body content';
    $secretKey = "your_secret_key";
    $signature = generateSignature($timestamp, $nonce, $body, $secretKey);
    echo "Signature: " . $signature;
    

    # 3. Payments

    # 3.1 Introduction

    The GatePay refers to when the user purchases goods or services on the mobile webpage outside the GateApp client and confirms the payment by using GatePay, the merchant calls GatePay to process the payment.

    # 3.2 Application scenario

    The operation process on the user side is as follows: Step 1: The user purchases the product on the merchant's webpage from a non-GatePay browser, and selects GatePay as the payment method. Step 2: Enter GateApp to confirm the transaction and enter the payment password. Step 3: After the payment is completed, a notification will be sent to the user and the merchant’s background

    # 3.3 Flow chart

    gatepay时序图

    The main process is as follows:

    1. The user places an order in the merchant's app and initiates payment.
    2. After the merchant server receives the payment request, it generates an order on the merchant platform.
    3. The merchant server generates the merchant order number and requests the GatePay interface to create a prepaid order (6.1 Create a prepaid order).
    4. The merchant server sends the generated prepaid order request to the Gate prepaid order creation interface. The Gate interface verifies the prepaid order request, and if verification passes, generates a prepaid order and returns the prepaid order information.
    5. After the merchant server receives the prepaid order information, it enters the process of requesting user confirmation and authorization for payment. For the H5 merchant application embedded in GatePay, the merchant app needs to call the js method provided by Gate to request the user's in-app authorization (refer to 6.2 payment interface).
    6. After the user confirms the payment on GateApp, GateApp will communicate user authorization information with GatePay service, and GatePay service will perform Token authorization verification and payment password verification (PassFund).
    7. After the GatePay payment verification passes, it will send the request to the callback address of the merchant's application server to notify the payment result, and receive the confirmation reply (6.9 Asynchronous notification of order status).
    8. After the processing of GatePay, the user will be redirected to the payment result address provided by the merchant, and the merchant will display the payment result.
    9. If the notification in step 7 fails to reach the merchant service callback address or no replay from the merchant server is obtained, GatePay background will try to notify the merchant repeatedly. Merchant can also query the payment result status through the payment query interface (6.5 Order Status Query).

    # 3.4 API interface list

    API list Description
    /v1/pay/order Create prepaid order
    /v1/pay/order/close Close prepaid order
    /v1/pay/order/query Order status inquiry
    /v1/pay/order/refund Create a refund order
    /v1/pay/order/refund/query Refund order inquiry
    /v1/pay/batch/transfer Create batch transfers
    /v1/pay/batch/transfer/query Query the status of batch transfer orders

    # 3.4.1 Create prepaid order

    Function: After the user successfully places an order on the third-party platform and chooses GatePay as the payment method, the third-party platform needs to send the order information to the GatePay platform first, create a prepaid order, and obtain the prepaid order prepayId.

    • Data type: JSON (content-type: application/json)

    • Request method:POST

    • PATH: /v1/pay/order

    • Request body content:

    Parameter Name Type Must or not Description
    merchantTradeNo string Yes Merchant's order number, composed of numbers and letters
    currency string Yes Payment currency, capitalized, such as USDT, BTC, etc.
    orderAmount string Yes Transaction amount, accurate to 8 decimal places at most, ranging from 0.0001-5,000,000
    env Env type Yes Transaction source
    goods goods type Yes Product description
    orderExpireTime int64 No Order expiration time, UTC timestamp, in millisecond. If it is not set,1 hour is the default. 1 hour is the maximum expiration time.
    returnUrl string No Jump address after the payment for an order is done; maximum 256 characters. The system will jump to this URL only after payment is done on an independent page.
    cancelUrl string No apiDoc.cancelUrl
    channelId string No Client channel name

    Env type

    Parameter Name Type Must or not Description
    terminalType string Yes Transaction source, optional values:APP、WEB、WAP、MINIAPP、OTHERS

    Goods type

    Parameter Name Type Must or not Description
    goodsName string Yes Product name, up to 160 characters
    goodsDetail string Yes Product description, up to 256 characters

    Example of request:

    curl --location --request POST 'https://openplatform.gateapi.io/v1/pay/order' \
    --header 'X-GatePay-Certificate-ClientId: 4186d0c6-6a35-55a9-8dc6-5312769dbff8' \
    --header 'X-GatePay-Signature: 672d5650dcc9bb22ebf25fa16c28d03c0e159d742a9176d4340a5da326d75dc8a2ec24c97fa6fc5d1533dd6e968863747e1d86a45e562cbe899f9ed7e9ca7f77' \
    --header 'X-GatePay-Timestamp: 1672905655498' \
    --header 'X-GatePay-Nonce: 9578' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "merchantTradeNo":"22212345678555",
        "env":{
            "terminalType":"APP"
        },
        "currency":"GT",
        "orderAmount":"1.21",
        "goods":{
            "goodsType":"312221",
            "goodsName":"NF2T",
            "goodsDetail":"123444"
        },
        "returnUrl":"http://47.99.158.63:8205/payment/redirect",
        "channelId": "123456"
    }'
    

    Example of return:

    {
        "status": "SUCCESS",
        "code": "000000",
        "data": {
            "prepayID": "1647557960944",
            "terminalType": "MINIAPP",
            "expireTime": 1647557975944
        },
        "errorMessage": ""
    }
    
    Return type:
    Parameter Name Type Must or not Description
    status string Yes SUCCESS or FAIL
    code string Yes error code
    data OrderResult No return data, no return when an error occurs
    errorMessage string No error message, empty string if operation is successful

    data field data

    Parameter Name Type Must or not Description
    prepayID string Yes prepaid order id
    terminalType2 string Yes The type of terminal from which the transaction was initiated
    expireTime int64 Yes Order expiration timestamp, in millisecond

    # 3.4.2 Payment interface

    After the prepaid order is successfully created and the prepaid order id is obtained, the applet running in the GateIO App can initiate payment through the Javascript method provided by the GateIO App Note: The initiate method is performed in Gate.io (opens new window) App, which does not support browsers. Method name:gatepay

    Parameter:

    merchantId: string, Gate UID used to apply for a merchant account
    merchantTradeNo: string, merchant order number
    prepayId: string, prepaid ID
    totalFee: string, payment amount
    currency: string, payment currency
    

    Android calling method

      var merchantId = "666123"
      var tradeNo = "56236"
      var prepayId = "1647557960944"
      var totalFee = "1.91"
      var currency = "BTC"
      window.gateio.gatepay(merchantId,tradeNo,prepayId,totalFee,currency);
    

    iOS calling method. Note: all parameters should be passed as string type.

     var params = {
          "merchantId": "666123",
          "merchantTradeNo": "56236",
          "prepayId": "1647557960944",
          "totalFee": "1.91",
          "currency": "BTC"
      };
      window.webkit.messageHandlers.gatepay.postMessage(params);
    
    Return: After the function is executed, the user will be redirected to the returnUrl or cancelUrl specified when creating the order.
    ### 3.4.3 Close prepaid order When the merchant order is canceled, the merchant can initiate a request to GatePay to close an unpaid order. (The order that is not closed can only wait for expiration.) - Data type: JSON (content-type: application/json)
    • Request method: POST

    • PATH: /v1/pay/order/close

    • Request body content: Request type

    Parameter Name Type Must or not Description
    merchantTradeNo string No
    prepayId string No provide either of prepayId or merchant TradeNo

    Example of request:

    curl --location --request POST 'https://openplatform.gateapi.io/v1/pay/order/close' \
    --header 'Content-Type: application/json' \
    --header 'X-GatePay-Certificate-ClientId: zb6WUrBDZlRAT7qz' \
    --header 'X-GatePay-Timestamp: 1674030602958' \
    --header 'x-GatePay-Nonce: 8565041750' \
    --header 'x-GatePay-Signature: 35d07c9f368164cd601a973e1d777c41fea4582d18b97fcfaa5c7b6ebacbb8f88c006818f721aab5d5a450771846792ae1429cb9050c073121230aae0a43866b' \
    --data-raw '{"prepayId": "50620368071692288"}'
    

    Example of return:

    {
        "status": "SUCCESS",
        "code": "000000",
        "data": {
            "result": "SUCCESS"
        },
        "errorMessage": ""
    }
    

    Return type:

    Parameter Name Type Must or not Description
    status string Yes SUCCESS or FAIL
    code string Yes error code
    data close result type Yes close results
    errorMessage string No error message, empty string if operation is successful

    close result type:

    属性名 Type Must or not Description
    result string Yes SUCCESSFAIL

    # 3.4.4 Refund interface

    Merchants can initiate a refund for an order that has been successfully paid for. To execute a refund, it does not require confirmation from the merchant and user. Refund will be executed after the refund order is created. After the refund is successful, the GatePay will send a notification to notify the refund result. Please note: Refunds cannot be canceled, withdrawn, or rolled back.

    • Data type: JSON (content-type: application/json)

    • Request method: POST

    • PATH: /v1/pay/order/refund

    • Request body content:

    Parameter Name Type Must or not Description
    refundRequestId string Yes The refund order id generated by the merchant. Refund order id must be unique,and limited to 32 characters
    prepayId string Yes Information of prepaid order that has been paid
    refundAmount string Yes Information of prepaid order that has been paid
    refundReason string No The reason for the refund, not exceeding 256 characters

    Example of request:

    curl --location --request POST 'https://openplatform.gateapi.io/v1/pay/order/refund' \
    --header 'Content-Type: application/json' \
    --header 'X-GatePay-Certificate-ClientId: zb6WUrBDZlRAT7qz' \
    --header 'X-GatePay-Timestamp: 1674030602958' \
    --header 'x-GatePay-Nonce: 8565041750' \
    --header 'x-GatePay-Signature: 35d07c9f368164cd601a973e1d777c41fea4582d18b97fcfaa5c7b6ebacbb8f88c006818f721aab5d5a450771846792ae1429cb9050c073121230aae0a43866b' \
    --data-raw '{
        "refundRequestId": "156123911",
        "prepayId": "1647438500687506",
        "refundAmount": "0.8"
    }'
    

    Example of return:

    {
        "status": "SUCCESS",
        "code": "000000",
        "data": {
            "refundRequestId": "156123911",
            "prepayId": "1647438500687506",
            "orderAmount": "1.91",
            "refundAmount": "0.8"
        },
        "errorMessage": ""
     }
    

    Return type:

    Parameter Name Type Must or not Description
    status string Yes SUCCESS or FAIL
    code string Yes error code
    data refund data type Yes refund order information
    errorMessage string No error message, empty string if operation is successful

    refund data type

    Parameter Name Type Must or not Description
    refundRequestId string Yes refund order id
    prepayId string Yes prepaid order id
    orderAmount string Yes order amount
    refundAmount string Yes refund amount applied

    # 3.4.5 Order status inquiry

    In order to facilitate merchants to synchronize order information, GatePay provides an interface for them to query order status.

    • Data type: JSON (content-type: application/json)

    • Request method: POST

    • PATH: /v1/pay/order/query

    • Request body content:

    Parameter Name Type Must or not Description
    prepayId string No prepaid order information
    merchantTradeNo string No Merchant order id. Provide either of the prepaid order id or this id

    Example of request:

    curl --location --request POST 'https://openplatform.gateapi.io/v1/pay/order/query' \
    --header 'Content-Type: application/json' \
    --header 'X-GatePay-Certificate-ClientId: zb6WUrBDZlRAT7qz' \
    --header 'X-GatePay-Timestamp: 1674030602958' \
    --header 'x-GatePay-Nonce: 8565041750' \
    --header 'x-GatePay-Signature: 35d07c9f368164cd601a973e1d777c41fea4582d18b97fcfaa5c7b6ebacbb8f88c006818f721aab5d5a450771846792ae1429cb9050c073121230aae0a43866b' \
    --data-raw '{  
        "merchantTradeNo": "93840202212210003"
    }'
    

    Inquiry for order details in non-specified revenue currency, response example:

    {
        "status": "SUCCESS",
        "code": "000000",
        "errorMessage": "",
        "data": {
            "prepayId": "56335302571069440",
            "merchantId": 10002,
            "merchantTradeNo": "118223456798",
            "transactionId": "",
            "goodsName": "NF2T",
            "currency": "USDT",
            "orderAmount": "1.9",
            "status": "EXPIRED",
            "createTime": 1675392982792,
            "expireTime": 1675396480000,
            "transactTime": 0,
            "order_name": "MiniApp-Payment#118223456798",
            "pay_currency": "",
            "pay_amount": "0",
            "expectCurrency": "BTC",
            "rate": "0",
            "channelId": "123456"
        }
    }
    

    Inquiry for order details in specified revenue currency, unsettled, response example:

    {
        "status": "SUCCESS",
        "code": "000000",
        "errorMessage": "",
        "data": {
            "prepayId": "56335302571069440",
            "merchantId": 10002,
            "merchantTradeNo": "118223456798",
            "transactionId": "",
            "goodsName": "NF2T",
            "currency": "USDT",
            "orderAmount": "1.9",
            "status": "EXPIRED",
            "createTime": 1675392982792,
            "expireTime": 1675396480000,
            "transactTime": 0,
            "order_name": "MiniApp-Payment#118223456798",
            "pay_currency": "",
            "pay_amount": "0",
            "expectCurrency": "BTC",
            "rate": "0",
            "channelId": "123456"
        }
    }
    

    Inquiry for order details in specified revenue currency, settled, response example:

    {
        "status": "SUCCESS",
        "code": "000000",
        "errorMessage": "",
        "data": {
            "prepayId": "56416503889661952",
            "merchantId": 10002,
            "merchantTradeNo": "1182234567119",
            "transactionId": "56416503889661952",
            "goodsName": "NF2T",
            "currency": "GT",
            "orderAmount": "1",
            "status": "PAID",
            "createTime": 1675412342695,
            "expireTime": 1675414420000,
            "transactTime": 1675412385904,
            "order_name": "MiniApp-Payment#1182234567119",
            "pay_currency": "BTC",
            "pay_amount": "1",
            "expectCurrency": "USDT",
            "actualCurrency": "USDT",
            "actualAmount": "1",
            "rate": "1",
            "channelId": "123456"
        }
    }
    
    Example of return:
    Parameter Name Type Must or not Description
    status string Yes SUCCESS or FAIL
    code string Yes error code
    data query order return type No Payment order information
    errorMessage string No error message, empty string if operation is successful

    Query order return type

    Parameter Name Type Must or not Description
    prepayId string Yes Prepaid order id
    merchantId int64 Yes Gate UID used to apply for a merchant account
    merchantTradeNo string Yes Merchant order id
    transactionId string Yes Payment transaction id
    goodsName string Yes Product name
    currency string Yes Payment currency
    orderAmount string Yes Payment amount
    status string Yes Order status
    createTime int64 Yes Prepaid order creation time, UTC timestamp, in millisecond
    expireTime int64 Yes Prepaid order expiration time, UTC timestamp, millisecond
    transactTime int64 Yes Payment completion time, UTC timestamp, in millisecond
    order_name string Yes Order name
    pay_currency string Yes Actual payment currency of user
    pay_amount string Yes Actual payment amount of user
    expectCurrency string No Settlement currency specified by the merchant when creating the order. Note: Only returned in the order details for orders where the merchant has specified a settlement currency.
    actualCurrency string No Currency actually settled to the merchant's account by Gate backend after the order is paid. Note: Only returned in the order details after Gate has settled the order with the merchant.
    actualAmount string No Amount of the currency actually settled to the merchant's account by Gate backend after the order is paid. Note: Only returned in the order details after Gate has settled the order with the merchant.
    rate string Yes Exchange rate when the convert-pay order was paid.
    channelId string No Client channel name.

    About order status

    Value Description
    PENDING Order pending payment status
    PAID Payment successful
    PROCESS Used for address payments. The order is valid after payment of a sufficient amount, but is not confirmed in the chain.
    EXPIRED Order expired
    CANCELLED Merchant calls to close the interface to cancel the order
    ERROR An error occurred in the payment of an order

    # 3.4.6 Query refund order

    • Data type: JSON (content-type: application/json)

    • Request method: POST

    • PATH: /v1/pay/order/refund/query

    • Request body content:

    Parameter Name Type Must or not Description
    refundRequestID string Yes The refund form id generated by the merchant

    Example of request:

    curl -X POST -H "Content-Type:application/json"
      -H "x-gateio-payment-certificate-ClientId: 79899d8b-c6ba-5630-b52d-087956213mf43"
      -H "x-gateio-payment-timestamp: 1647556285603"
      -H "x-gateio-payment-nonce: OBBHcyeIQn"
      -H "x-gateio-payment-signature: 1f020e1ee70a7ced14de42f4293592d43f8a74eab5ba4c3771dc6d215278d889fd0ecd398c1026a003b1351752b34c24cd8288afa7ff7552ca06a2aea992a897"
      -d '{ "refundRequestId": "156123911"}'  https://openplatform.gateapi.io/v1/pay/order/refund/query
    

    Example of response:

    {
        "status": "SUCCESS",
        "code": "000000",
        "data": {
           "refundRequestId": "156123911",
           "prepayId": "1647557960944",
           "orderAmount": "1.91",
           "refundAmount": "0.8",
           "refundStatus": "SUCCESS"
        },
        "errorMessage": ""
     } 
    
    Response type:
    Parameter Name Type Must or not Description
    status string Yes SUCCESS or FAIL
    code string Yes error code
    data query refund return type No Payment order information
    errorMessage string No error message, empty string if operation is successful

    Query refund return type

    Parameter Name Type Must or not Description
    refundRequestID string Yes The refund order id generated by the merchant
    prepayId string Yes Order id, generated by GatePay backend
    orderAmount string Yes Order amount
    refundAmount string Yes Refund amount applied
    refundStatus string Yes Refund order status. SUCCESS: Refund success. FAIL: Refund failed.

    # 3.4.7 Create merchant batch transfer

    • Data type: JSON (content-type: application/json)

    • Request method: POST

    • PATH: /v1/pay/batch/transfer

    • Request body content:

    Parameter Name Type Must or not Description
    merchant_batch_no string Yes A unique order number is generated on the merchant’s side, and different orders should have different order numbers
    merchant_id string Yes Merchant ID
    currency string Yes Current currency
    name string No Batch transfer name
    description string No Batch transfer description
    bizscene string Yes There are following transfer scenarios: DIRECT_TRANSFER,REWARDS,REIMBURSEMENT,MERCHANTPAYMENT,OTHERSPAYMENT
    batchorderList array Yes Batch order list
    channelId string No Client channel name

    batchorderList Single item data field

    Parameter Name Type Must or not Description
    user_id int64 Yes User id
    amount string Yes Transfer amount to user

    Example of request:

    curl --location --request POST 'https://openplatform.gateapi.io/v1/batch/transfer'
      -H 'Content-Type: application/json'
      -H "x-gateio-payment-certificate-ClientId: 79899d8b-c6ba-5630-b52d-087956213mf43"
      -H "x-gateio-payment-timestamp: 1647556285603" 
      -H "x-gateio-payment-nonce: OBBHcyeIQn" 
      -H "x-gateio-payment-signature:  1f020e1ee70a7ced14de42f4293592d43f8a74eab5ba4c3771dc6d215278d889fd0ecd398c1026a003b1351752b34c24cd8288afa7ff7552ca06a2aea992a897"
    --data-raw '{
      "merchant_batch_no": "1234567828038",
      "merchant_id": 10001,
      "currency": "BTC",
      "name ": "batch-transfer",
      "description ": "batch-transfer",
      "bizscene" : "REWARDS",
      "batchorderList": [
          {
              "user_id": 10000,
              "amount": "2.1"
          }
      
      ]
    }'
    

    Example of response: Success:

      {
          "status": "SUCCESS",
          "code": "000000",
          "errorMessage": "",
          "data": {
              "merchant_batch_no": "abcde-1234-a",
              "batch_id": "1652242252406410"  
          }
      }
    

    Fail:

      {
        "status": "FAIL",
          "code": "400623",
          "errorMessage": "payment in other currencies is not supported",
          "data": {  
          }
      }
    

    Error code:

      ErrCodeatchTransferDuplicated              = "500000"  // Duplicate batch transfer
      ErrCodeatchTransferAmountLimit             = "500001"  // Single transfer amount exceeds the limit
      ErrCodeatchTransferNumPlayerLimit          = "500002"  // Number of people in a single transfer exceeds the limit
      ErrCodeBatchTransferTimesLimit             = "500003"  // Number of transfers for the day exceeds the limit
      ErrCodeBatchTransferQuotaNotFound          = "500004"  // Transfer configuration quota information not found
      ErrCodeBatchTransferBizSceneNotFound       = "500005"  // Incorrect batch transfer scene type
      ErrCodeBatchTransferNegative               = "500006"  // Negative batch transfer amount
      ErrCodeBatchTransferAmountExecpt           = "500007"  // Incorrect batch transfer amount
    
    Response type:
    Parameter Name Type Must or not Description
    status string Yes SUCCESS or FAIL
    code string Yes error code
    data json No Batch transfer response data
    errorMessage string No error message, empty string if operation is successful
    Type Parameter name Must or not Description
    string merchant_batch_no Yes A unique order number is generated on the merchant’s side, and different orders should have different order numbers
    string batch_id No Batch order number generated by GatePay

    Note:

    1.After the merchant’s batch transfer order is created, the backend will process the orders one by one. The batch order cannot be canceled until processed in full. You can query the status of each order by calling the merchant batch transfer order query interface.

    2.Merchants need to communicate with GatePay to set the quota for batch transfer. There are three quotas in total: the maximum number of users for a single transfer, the maximum amount for a single transfer, and the maximum number of transfers per day. (Quota to be determined after communication between merchants and GatePay)

    # 3.4.8 Merchant batch transfer order query

    After the merchant creates a batch transfer interface, it is recommended to call this interface to query the batch transfer order status 5 seconds after the interface is created.

    • Data type:JSON (content-type:application/json)

    • Request method: POST

    • PATH: /v1/pay/batch/transfer/query

    • Request body content:

    Parameter Name Type Must or not Description
    batch_id string Yes batch order number generated by GatePay
    detail_status string Yes Order type parameters: ALL: Query all sub-order information
    PROCESSING: Query unprocessed sub-order information
    SUCCESS: Query successfully processed sub-order information
    FAIL: Query failed sub-order information

    Example of request:

    curl --location --request POST 'https://openplatform.gateapi.io/v1/admin/internal/pay/batch/transfer/query' \
    --header 'Content-Type: application/json' \
    --header 'X-GatePay-Certificate-ClientId: zb6WUrBDZlRAT7qz' \
    --header 'X-GatePay-Timestamp: 1674112025012' \
    --header 'x-GatePay-Nonce: 8554948758' \
    --header 'x-GatePay-Signature: fcf88f964e301f2931076fb8a0d1a26fa2756df0b91f578bb0bd3f692e082f4a0526cc7b400504b93b15c8497a35793bb4cea2786c9b099b75dab48c2154d7ac' \
    --data-raw '{"batch_id":"1655704726384127","merchant_batch_no":"123456782801","detail_status":"ALL"}'
    

    Example of response:

    {
        "status": "SUCCESS",
        "code": "00000",
        "errorMessage": "",
        "data": {
            "batch_id": "1655704726384127",
            "merchant_id": 10002,
            "merchant_batch_no": "123456782801",
            "status": "PROCESSING",
            "currency": "USDT",
            "orders_list": [
                {
                    "receiver_id": 10000,
                    "amount": "1.21000000",
                    "currency": "USDT",
                    "status": "SUCCESS",
                    "reward_id": "2312334342423",
                    "create_time": 1674113185137
                }
            ],
          "channelId": "123456"
        }
    }
    

    # 4. OAuth Authorization

    # 4.1 Introduction

    With the user’s authorization, developers can obtain tokens which are used in the exchange for user information based on the international standard OAuth2.0 authorization mechanism. After the user's authorization token is obtained, the relevant information can be acquired by calling the interface provided by the open platform (Please refer to Open Platform API).

    # 4.2 Flow chart

    oauth授权流程图

    # 4.3 Time diagram

    oauth授权时序图
    • Splice the URL link of the authorization page according to the rules, and guide the user to jump to the link.
    • After the user confirms to give the authorization on the authorization page, it will jump to the callback page specified by the developer with the code.
    • Through /oauth/token (get the authorization access token interface), developers exchange code for access_token, refresh_token, expired and so on.
    • After the third-party application obtains the user's access token, it needs to put the token in the Authorization attribute of the HTTP header when accessing the Gate open platform service. The platform will check the access token to determine the user’s identity and access validity and provide services to him.
    • The access token will expire. When it happens, users can use the refresh_token to obtain a new access token.

    # 4.4 Integration steps

    # 4.4.1 Step 1: Apply for authorization

    When the user first enters the MiniApp homepage, a global authorization disclaimer window will pop up

    Example of authorization page:

    授权页面

    # 4.4.2 Step 2: Get the code

    After the user clicks the**Global Authorization“I Accept”**button and the authorization is successful, the Gate App will request aCode. The Gate Authorization Service will return response parameters in the callback page request, includingcode, stateparameters. It is important to note that the Gate OAuth Service only guarantees the validity of thecodeparameter. Upon receiving the response, the Gate App will redirect the user to theredirect_uriaddress provided by the third-party merchant.

    # 4.4.3 Exchange for access_token

    After getting the code, the developer exchanges the code for an access_token through /oauth/token (the interface for exchanging authorized access tokens). The code, as the credential for exchange of access_token, will be returned each time user authorization is obtained, and the different code will be returned each time. The code can only be used once, and it will automatically expire if it is not used within 24 hours. Exchange token API

    # 4.4.4 Step 4: Call the development platform interface

    After obtaining the user access token, the third-party service can obtain and process user information through GateIO's open API interface as the user. When using the GateIO open platform service, the access token should be added to the Authorization attribute of the HTTP header.

    Obtaining user information

    curl https://openplatform.gateapi.io/api/user_profile \
    -H "Authorization: Bearer e2f8c8e136c73b1e909bb1021b3b4c29"
    

    # 4.5 After the access token expires, use the refresh token to exchange for a new access token

    After the access token expires, one can use the refresh token to exchange for a new access token, with a new refresh token returned at the same time. The token obtained after a refresh has the same rights as the original one. Refresh API

    # 4.6 Descriptions of open platform permission

    Scope definition and description:

    scope定义 details Description
    read_profile [] Authorization to obtain user information, excluding Email.
    read_email [] Authorization to obtain user information, including Email.
    read_wallet ["SUPE", "USDT"] Authorization to get information about user’s currency and balance, and details must specify which currencies can be read.
    read_tier [] Get user information including VIP tier information.
    read_nft ["GATENFT"] Authorization to obtain the user's NFT information, and details must specify NFT token information that can be read in detail.
    app_jump {"scheme": {"ios": "unitydl://cyberpop", "android": "unitydl://cyberpop"}} Whether the app can jump to an external URL, and details must describe the specific URL to which it can jump.

    # 4.7 Authorization FAQ

    1.What is code?

    Answer: The third party can use code to get the access_token. The code will stay valid for 10 minutes, and one code can only be used once and will become invalid after it is exchanged for an access_token. All these natures of the code will increase the security of the authorized login. The third party can also use the https and state parameters to add another layer of security protection in the authorized login.

    2.What is the scope?

    The scope represents the interface authority licensed by the user to the third party. The third-party application needs to apply to the Gate open platform for permission to use the corresponding scope, and then request authorization from the user through the method described in the document. After the user’s authorization is obtained and the corresponding access_token is received, the third-party application can use the interface.

    # 4.8 Authorization API

    # 4.8.1 Authorization - get page

    • Data type:query
    • Request method:GET
    • PATH: /oauth/authorize

    Header content:

    Parameter Must or not Description
    Content-Type Yes Currently only supportscode
    User-Agent Yes Proxy client type, Android:gateio/android, IOS:gateio/ios

    Request body content:

    Parameter Must or not Description
    client_id Yes Client_id is obtained when the third-party application is registered
    response_type Yes Authentication return type: Currently, for third-party applications, only code is supported
    redirect_uri Yes The uri address returned after obtaining the user’s authorization, and it is must be exactly the same as the callback address provided when the third-party application is registered
    scope Yes Authorizations that third-party applications need to obtain, such as read_profile, read_wallet
    state No Merchant-defined parameters. After obtaining user’s authorization, they will be sent back to the merchant as they are when redirecting to redirect_uri to prevent CSRF attacks. It is recommended to insert the state parameter when requesting authorization. The parameter should be unpredictable, can prove that the client is related to the login authentication status of the current third-party website, and should not contain any Chinese characters. Notes: Users define the parameter by themselves and the format of the parameter should be state=XXXXX, in the maximum length of 32 bits.

    Example of request:

    curl --location 'https://openplatform.gateapi.io/oauth/authorize?response_type=code&client_id=mZ96D37oKk-HrWJc&redirect_uri=http://www.miniapp.com/oauth/redirect&scope=read_profile,read_email,read_wallet,create_apikey,subsite_login&state=123456' \
    --header 'Content-Type: code' \
    --header 'User-Agent: gateio/android'
    

    Response: HTML authorization page

    Error code:

    Status code Error code Description Resolution
    400 invalid_request Param error Please check the request parameters based on the detailed information returned by the interface.
    403 invalid_client client_id invalid Please check if the client_id is correct.
    400 invalid_grant invalid_grant invalid Please check if the application permission and redirect_uri parameters are correct.

    # 4.8.2 Exchange for access_token

    • Data type:application/json

    • Request method:POST

    • PATH: /oauth/token

    • Request body content:

    Parameter name Must or not Description
    grant_type Yes grant_type: authorization type, currently only authorization_code (authorization token exchange access token) and refresh_token (renewal access token) are supported for third-party applications
    code Yes code: authorization token, and the code value is received in the above step
    redirect_uri Yes Callback address: the callback address registered by the third-party application; GateIO OAuth will also use the callback address to verify the request

    Example of request:

    curl --location 'https://openplatform.gateapi.io/oauth/token' \
    --header 'X-GatePay-Certificate-ClientId: mZ96D37oKk-HrWJc' \
    --header 'X-GatePay-Timestamp: 1697517106839' \
    --header 'X-GatePay-Nonce: 3867712705' \
    --header 'X-GatePay-Signature: 9f0532870be67e51ccf5adb3f7ce4532d7b0ec692b53ed94654f8b5c6fb257d8c1e60d1d074ea783c7f10ea2dc479e43b4989ff8efaed22aec5c67e797424b93' \
    --header 'Content-Type: application/json' \
    --data '{
        "grant_type":"authorization_code",
        "code":"eX1zkwFztywaoOJJjpeYwXgkxeReTzFt",
        "redirect_uri":"http://121.40.213.39:8208/oauth/redirect"
    }'
    

    Example of response result:

    {
        "access_code": "e2f8c8e136c73b1e909bb1021b3b4c29",
        "refresh_token": "23248e136c73b1e909bb1021b3b4c29",
        "scope": "read_profile,read_wallet",
        "token_type": "Bearer",
        "expired_in": 86400
    }
    
    

    Response parameter description:

    Parameter name Description
    access_code Access token. This field refers to access_token
    refresh_token After the access token expires, the refresh token is used to obtain a new access token
    scope Authorized permissions, a comma-separated array
    token_type Bearer Token type: only bearer returned for the third party currently
    expired_in Time to take for the access token to expire, counted in the seconds

    Error code:

    Status Code Error Code Description Solution
    400 invalid_request Invalid parameter Please check the request parameters based on the detailed information returned by the API
    403 invalid_client Invalid client_id Please check if the client_id is correct
    400 invalid_grant Invalid request permission Please check if the applied permission and redirect_uri parameter are correct
    400 unsupported_grant_type Unsupported grant_type Grant_type should be: authorization_code, refresh_token

    # 4.9 Open Platform API

    After the user has been granted authorization, they can use the access_token to request the development platform interface.

    # 4.9.1 Get user information (excluding Email)

    • Request method:GET
    • PATH: /api/user_profile
    • Get user information (excluding Email)

    Example of request:

    curl https://openplatform.gateapi.io/api/user_profile
    -H "Authorization: Bearer e2f8c8e136c73b1e909bb1021b3b4c29"
    

    Example of response:

    {
          "uid":10000,
          "nickname":"Customer service 1",
          "avatar":"https://gavatar.gateimg.com/groupchat/avatar-dd253c609c-8bf188bd01-3a8241-faeac4",
          "user_verified":true
    }
    

    Error code:

    Status code Code Description Solution
    403 3 Invalid access token Please check if the access token is valid
    403 6 Access token expired The token has expired, please refresh the token
    403 4 Insufficient permissions Please check if the current token has the read_profile permission
    403 5 Invalid uid Please check if the token is correct and if the uid exists

    # 4.9.2 Get user information (including Email)

    • Request method:GET
    • PATH: /api/user_email
    • Get user information (including Email)

    Example of request:

      curl https://openplatform.gateapi.io/api/user_email
      -H "Authorization: Bearer e2f8c8e136c73b1e909bb1021b3b4c29"
    

    Example of response:

    {
        "status":"SUCCESS", "code":0,
        "data":{
        "uid":10000,
        "nickname":"Customer service 1",
        "avatar":"https://gavatar.gateimg.com/groupchat/avatar-dd253c609c-8bf188bd01- 3a8241-faeac4",
        "email":"66487@gate.com", "user_verified":true
      }
    }
    

    Error code:

    Status code Code Description Solution
    403 3 Invalid access token Please check if the access token is valid
    403 6 Access token expired The token has expired, please refresh the token
    403 4 Insufficient permissions Please check if the current token has the read_profile permission
    403 5 Invalid uid Please check if the token is correct and if the uid exists

    # 4.9.3 Get user information (including tier)

    • Request method: GET
    • PATH: /api/user_tier
    • Get user information (including tier)

    Example of request:

      curl https://openplatform.gateapi.io/api/user_tier
      -H "Authorization: Bearer e2f8c8e136c73b1e909bb1021b3b4c29"
    

    Example of response:

    {
        "status":"SUCCESS", 
        "code":0,
        "data":{
            "uid":10000,
            "nickname":"Customer service 1",
            "avatar":"https://gavatar.gateimg.com/groupchat/avatar-dd253c609c-8bf188bd01-   3a8241-faeac4",
            "tier": "15", 
            "user_verified":true
         }
    }
    

    Error code:

    Status code Code Description Solution
    403 3 Invalid access token Please check if the access token is valid
    403 6 Access token expired The token has expired, please refresh the token
    403 4 Insufficient permissions Please check if the current token has the read_profile permission
    403 5 Invalid uid Please check if the token is correct and if the uid exists

    # 4.9.4 Get user currency and balance

    • Request method: GET
    • PATH: /api/wallet
    • Get user currency and balance

    Example of request:

    curl https://openplatform.gateapi.io/api/wallet
    -H "Authorization: Bearer e2f8c8e136c73b1e909bb1021b3b4c29"
    

    Example of response:

      {
          "status":"SUCCESS",
          "code":0,
          "data":{
            "SUPE":"0",                        
            "USDT":"56929.67222108781"
          }    
      }
    

    Error code:

    Status code Code Description Solution
    403 3 Invalid access token Please check if the access token is valid
    403 6 Access token expired The token has expired, please refresh the token
    403 4 Insufficient permissions Please check if the current token has the read_profile permission
    403 5 Invalid uid Please check if the token is correct and if the uid exists

    # 4.9.5 Obtain user’s NFT information

    • Request method: GET

    • PATH: /api/user_nft

    • Obtain user’s NFT information

    Parameter name Must or not Description
    token Yes NFT information platform token to be queried
    token_id No The specific id value of the NFT to be queried

    Example of request:

    curl 'openplatform.gateapi.io/api/user_nft?token=GATENFT&token_id=openpunk1644'
    -H "Authorization: Bearer FaVhWbar5uEeKGqmgEv8Uz-DVrBREUj8"
    

    Example of response:

    {
        "status":"SUCCESS",
        "code":0,
        "data":[
            {
               "token":"GATENFT",
               "token_id":"openpunk1644"
          }
        ]
    }
    

    # 5. Asynchronous notification of order status

    # 5.1 Asynchronous notification of order status

    1. When the order status changes, for example, the payment is successful, the payment time is exceeded, the order is canceled, etc., the GatePay background will send an order status notification to the merchant. The notification address is the callback URL parameter provided by the merchant during registration. The callback URL must not contain special characters like “#”.
    2. If the notification fails due to network or other unknown reasons, GatePay backend will retry 10 times every 3 seconds. If the retry also fails, the merchant can get the order status by calling the order status inquiry interface.
    3. Merchants receive asynchronous notification messages and must verify the message signature parameter to validate the message legitimacy.

    # 5.2 Message structure

    Parameter name Type Description
    bizType string Describe the notification category, see table BizType
    bizId string Order id
    bizStatus string Order status, see table BizStatus
    client_id string client_id of merchant who created the order
    data json The content of the message, which varies according to the bizType

    Example message structure:

    {
        "bizType":"PAY",
        "bizId":"6948484859590",
        "bizStatus":"PAY_SUCCESS",
        "client_id":"cdhu-fgrfg44-5ggd-cdvsa",
        "data":"{...Json format data...}"
    }
    

    After the merchant receives the asynchronous callback message, they need to acknowledge receipt of the message. Example message structure:

    {
        "returnCode": "SUCCESS",
        "returnMessage": ""
    }
    

    bizType enumeration value

    Value Description
    PAY Non-address payment order status change notification, such as PAY success, timeout, failure or payment error, etc.
    PAY_REFUND Refund order status change notification, such as refund success or failure
    PAY_BATCH Batch pay order status change notification
    TRANSFER_ADDRESS Address Payment Order Funds Arrival Notification
    RECEIVED_CONVERT_DELAY_ADDRESS Processing notification for delayed payment order (address payment)
    PAY_ACTUALLY Notification of order payment, for which currency is designated by the merchant

    BizStatus enumeration value

    Value Description
    PAY_SUCCESS Order paid successfully
    PAY_ERROR Order payment encountered an error
    PAY_CLOSE The order was closed by the merchant or timed out
    REFUND_SUCCESS successful refund
    REFUND_REJECTED Refund is denied
    PAY_EXPIRED_IN_PROCESS Status notification on commencement of PROCESS of address payment order
    PAY_EXPIRED_IN_EXCHANGE_FLUCTUATION Payment failure in address-pay convert-pay order due to exchange rate fluctuations
    TRANSFERRED_ADDRESS_PAID Successful address transfer
    TRANSFERRED_ADDRESS_EXPIRE Expired address transfer
    TRANSFERRED_ADDRESS_DELAY Delayed payment transfer
    CONVERT_ADDRESS_PAY_DELAY Delayed payment notification for convert-address-pay order

    Data structure corresponding to bizType

    Parameter name Type Description
    merchantTradeNo string Merchant trade ID
    productType string goodsType when the order was created
    productName string GoodsName when the order was created
    tradeType string terminalType when the order was created
    goodsName string GoodsName when the order was created
    terminalType string terminalType when the order was created
    currency string Order currency
    totalFee string Order amount
    orderAmount string Order amount
    payCurrency string Actual payment currency of the user
    payAmount string Actual payment amount of the user
    expectCurrency string Designated payment currency by the merchant
    actualCurrency string The currency with which Gate makes a settlement with the merchant. If Gate converts the order currency into the currency required by the merchant, actualCurrency is the expectCurrency, otherwise, actualCurrency is currency.
    actualAmount string The amount calculated based upon the actualCurrency
    payerId int64 UID of the payer
    createTime int64 Order creation time
    channelId string Client channel name

    bizType is one of the PAY, TRANSFER_ADDRESS, RECEIVED_CONVERT_DELAY_ADDRESS sending formats:

    Non-address payment order status notification bizType=PAY

    {
        "bizType":"PAY",
        "bizId":"6948484859590",
        "bizStatus":"PAY_SUCCESS",
        "client_id":"cdhu-fgrfg44-5ggd-cdvsa",
        "data":{
            "merchantTradeNo":"gateio_withdraw6331782520222",
            "productType":"NFT",
            "productName":"ka",
            "tradeType":"APP",
            "goodsName":"ka",
            "terminalType":"APP",
            "currency":"USDT",
            "totalFee":"1.2",
            "orderAmount":"1.2",
            "createTime":1664123708000,
            "transactionId":"24344545",
            "channelId": "123456"
        }
    }
    

    Address payment order status notification bizType=TRANSFER_ADDRESS

    {
        "bizType":"TRANSFER_ADDRESS",
        "bizId":"6948484859590",
        "bizStatus":"TRANSFERRED_ADDRESS_PAID",
        "client_id":"cdhu-fgrfg44-5ggd-cdvsa",
        "data":{
            "merchantTradeNo":"gateio_withdraw6331782520222",
            "productType":"NFT",
            "productName":"ka",
            "tradeType":"APP",
            "goodsName":"ka",
            "terminalType":"APP",
            "currency":"USDT",
            "totalFee":"1.2",
            "orderAmount":"1.2",
            "createTime":1664123708000,
            "transactionId":"24344545",
            "transferAmount":"0.8",
            "channelId": "123456"
        }
    }
    

    Address payment order status notification bizType=RECEIVED_CONVERT_DELAY_ADDRESS

    {
        "bizType":"RECEIVED_CONVERT_DELAY_ADDRESS",
        "bizId":"6948484859598",
        "bizStatus":"TRANSFERRED_ADDRESS_PAID",
        "client_id":"cdhu-fgrfg44-5ggd-cdvsa",
        "data":{
            "merchantTradeNo":"gateio_withdraw6331782520222",
            "productType":"NFT",
            "productName":"ka",
            "tradeType":"APP",
            "goodsName":"ka",
            "terminalType":"APP",
            "currency":"USDT",
            "totalFee":"1.2",
            "orderAmount":"1.2",
            "createTime":1664123708000,
            "transactionId":"24344545",
            "transferAmount":"0.8",
            "channelId": "123456"
        }
    }
    

    bizType=PAY_REFUND

    {
        "bizType":"PAY_REFUND",
        "bizId":123289163323899904,
        "bizStatus":"REFUND_SUCCESS",
        "data":{
            "merchantTradeNo":"56236",
            "orderAmount":"1.91",
            "refundInfo":{
                "orderAmount":"1.91",
                "prepayId":"1647438500687506",
                "refundRequestId":"156123911",
                "refundAmount":"0.8"
            },
            "currency":"BTC",
            "productName":"NFT",
            "terminalType":"MINIAPP",
            "channelId": "123456"
        }
    }
    

    bizType=PAY_BATCH

    {
        "bizType":"PAY_BATCH",
        "bizId":"1234567999800",
        "bizStatus":"REFUND_SUCCESS",
        "client_id":"JaBxopuhY",
        "data":{
            "merchant_batch_no":"6678554A99000",
            "currency":"",
            "channelId": "123456",
            "order_list":[
                {
                    "receiver_id":10000,
                    "amount":"1.3",
                    "currency":"USDT",
                    "status":"PAID",
                    "reward_id":"50888456789213330",
                    "create_time":1676336326072,
                    "channel_id": "123456"
                },
                {
                    "receiver_id":10001,
                    "amount":"5.7",
                    "currency":"USDT",
                    "status":"PAID",
                    "reward_id":"50888456789215557",
                    "create_time":1676336326072,
                    "channel_id": "123456"
                }
            ]
        }
    }
    

    bizType=PAY_ACTUALLY

    {
        "bizType":"RECEIVED_CONVERT_DELAY_ADDRESS",
        "bizId":"577886948403339870",
        "bizStatus":"CONVERT_ADDRESS_PAY_DELAY",
        "client_id":"cdhu-fgrfg44-5ggd-cdvsa",
        "data":{
            "merchantTradeNo":"2345677666545556",
            "productType":"NFT",
            "productName":"NFT",
            "tradeType":"WEB",
            "goodsName":"NFT2",
            "terminalType":"APP",
            "currency":"USDT",
            "totalFee":"2.35",
            "orderAmount":"2.35",
            "payCurrency":"USDT",
            "payAmount":"2.36",
            "expectCurrency":"",
            "actualCurrency":"",
            "actualAmount":"",
            "payerId":10000,
            "createTime":1676343810430,
            "transactionId":"59847585498494",
            "channelId": "123456"
        }
    }
    

    # 6. Best practices

    # 6.1 Payment callback and order query implementation guidelines

    Background: Due to network issues or system fluctuations, the merchant side may fail to receive the payment result notification even if the user completes the payment, and the order might be displayed as unpaid. This is the case that will give rise to user complaints and even repeated payments.

    Target: The purpose is to let the merchant get the payment status of the order in a timely and accurate manner even when it fails to receive the payment result notification, so as to improve the robustness of the merchant system and reduce user complaints caused by out-of-sync notification of order status.

    Merchant backend service processing: The merchant background needs to accurately and efficiently process the asynchronous payment result notification sent by GatePay, and return the processing result to GatePay according to the interface specification.

    Regular polling query: If the merchant fails to receive the payment result notification for a long time, the merchant’s background should initiate the regular polling query (order status query interface/v1/pay/order/query ) to query the order status.

    Plan A

    Based on the time when the order is successfully placed, query the order status by calling the order status query interface (/v1/pay/order/query) every 5 seconds/10 seconds/30 seconds/1 minute/3 minutes/5 minutes/10 minutes/30 minutes. If no successful payment notice returns at the last query, stop the query, and call the closing order interface (/v1/pay/order/close) to close the order. (merchants can set the interval and times for polling query flexibly according to their own business scenarios)

    Plan B

    The regular polling query is performed every 30 seconds to find out the orders that have been created and not paid in the last 10 minutes, and the order status query interface is called (/v1/pay/order/query) to query the order status. The system records the number of order inquiries, and if no successful payment notice returns after 10 inquiries, stops the query, and calls the closing order interface (/v1/pay/order/close) to close the order. (merchants can set the interval and times for polling query flexibly according to their own business scenarios)

    Note: After the payment is completed, GatePay will send the relevant payment result to the merchant in the form of a data stream, and the merchant needs to receive and process it, and return a response according to the specification.

    1. The same notification may be sent to the merchant system multiple times, so the merchant system must be able to handle repeated notifications.
    2. When interacting with asynchronous notifications in the background, if GatePay receives a response from the merchant that does not meet the specifications or fails to receive the response in the agreed time, the system will determine that the notification failed to be sent and then will resend the notification until it is successfully sent. (GatePay will send the notice 10 times every 5 seconds until it is sent successfully)

    # 6.2 Implementation guidelines for the refund process

    1. The merchant calls the refund interface (/v1/pay/order/refund) to create a refund order,Note that the refund is an asynchronous process, and the success of calling this interface does not represent the successful completion of the refund.
    2. Wait for the refund callback notification. If merchants receive the GatePay asynchronous callback notification and get the refund result, they don’t need to call the query interface
    3. If the refund status notification is not received within 10s, call the (/v1/pay/order/refund/query) interface to query the status of the refund order You can refer to4.6.1 Payment callback and inquiry implementation guide

    # 6.3 Best security practices

    # Data transmission

    Use HTTPS to ensure network transmission security. Do not use insecure protocols and algorithms such as SSL, it is recommended to use TLS1.2. No self-developed encrypted transmission algorithm is recommended because they will have security issues.

    # Data storage

    Sensitive information should not be contained in the log. Those that must be used should be desensitized. Sensitive data in the cache and DB needs to be encrypted. Key authentication such as passwords must be stored in salted encryption.

    # Data access

    External requests for data access must be authenticated. Internal data access should be strictly controlled to reduce the risk of user information leakage.

    # Prevent vulnerabilities caused by improper logic processing

    GatePay signature verification is required for the successful payment callback notification to avoid malicious attacks. Implement merchant price validation logic in the backend to prevent client-side price tampering that could lead to merchant losses. Merchant Securekey should not appear in App or website pages.

    # 7. Common error code

    http状态码 ErrCode Description solution
    500 300000 system error System exception, please call again with the same parameters
    500 300001 internal error System exception, please call again with the same parameters
    500 400000 unknown error System exception
    200 400001 Request parameter error Please check the request parameters according to the detailed information returned by the interface
    200 400002 signature error Please check whether the signature parameters and methods meet the signature algorithm requirements
    200 400003 timestamp expired he timestamp field in the head has expired, regenerate the timestamp
    200 400007 data format error Please check the request data format, to see whether it conforms to the interface specification
    200 400020 signature nonce error Please check if the nonce is empty
    200 400201 Repeated merchant order number Please check whether the merchant order number has been submitted repeatedly
    200 400202 order does not exist Please check whether a transaction has been initiated under the order or whether the order number is correct
    200 400203 Merchant number does not exist Please check whether the merchant number is correct
    200 400204 Order status is incorrect Check if the order is expired, and open it if it is closed
    200 400304 Refund order ID does not exist Check the requested refund order ID
    200 400305 Merchant channelId not found Please check the request parameters channelId
    200 400604 Refund related transaction is invalid Please check whether the refund order is completed
    200 400605 Insufficient account balance for payment Please check the balance of the payment account.
    200 400607 Exceeded refund limit The number of refunds exceeds the limit.
    200 400608 Abnormal refund amount Please check the refund amount.
    200 400620 Duplicate payment for the order Please verify if the merchant order number has been submitted repeatedly.
    200 400621 Incorrect payment amount Please check the requested amount.
    200 400622 Exchange rate fluctuation causes currency exchange failure You can retry the application.
    200 400623 Unsupported currency for payment Please check the payment currency.
    200 400624 Invalid notification address for order status Please check if the callback address provided by the merchant is valid.
    200 500008 Corresponding merchant not found Please check if the requested merchant ID is correct.
    200 500100 Payment QR code has expired Please place a new order to generate a new QR code.
    200 500101 Duplicate payment for the QR code Please verify the status of the order.
    200 500103 Error in currency for address payment It is affected by the exchange rate.
    200 500203 Unable to query order details for address payment Please check if the address is correct.
    200 500204 Invalid refund recipient ID for refund order Please confirm that the refund recipient is a Gate user.
    200 500205 Currency matching error for refund order Please ensure that the refund currency is one of the order currency or user payment currency.
    200 500206 Refund amount exceeds limit Please check the refund amount of the order.
    200 500207 Unable to query refund order for address payment Please confirm if the refund was successfully initiated or check if the address is correct.
    200 500208 Cannot refund an order without a conversion address using a conversion address Please confirm the type of refund order.

    # 8. List of supported currencies

    "BTC","USDT","GT","ETH","EOS","DOGE","DOT","SHIB","LTC","ADA","BCH","FIL","ZEC","BNB","UNI","XRP","STEPG","SUPE","LION","FROG","EEG"
    

    21 currencies are supported for payment:

    "BTC","USDT","GT","ETH","EOS","DOGE","DOT","SHIB","LTC","ADA","BCH","FIL","ZEC","BNB","UNI","XRP","STEPG","SUPE","LION","FROG","EEG"
    

    # 9. FAQ

    # Q: How long is the QR code generated through the pre-order API valid?

    A: Merchants can specify the order expiration time, with the maximum and default validity period being one hour.

    # Q: How to distinguish orders initiated from different platform channels?

    A: The useragent field can identify users from the Gate.io channel: Android :“isPhone/1 GateIO/Android” iOS :“isPhone/1 GateIO/iOS”

    # Q: How to test?

    A: Steps:

    1. Merchants register the application and fill in the test UID in the merchant backend.
    Mini App Registration

    Whitelist UID format (comma-separated, no spaces): UID1,UID2,UID3

    1. After adding to the allowlist, you can log in to the Gate App with the allowlisted UID account and see your merchant mini app in the Gate Life application list, then proceed with the authorization process and payment test.

    2. Start integration testing: After adding to the allowlist, you can log in to the Gate App with the allowlisted UID account and see your merchant mini app in the "App Home Page → Gate Life → Featured" merchant application list. Then proceed with the authorization process and payment test.