# 1.商户接入

    # 1.1 线上服务地址

    https://openplatform.gateapi.io
    

    # 1.2 配置新增小程序

    • 登录商户后台,商户后台地址https://www.gate.io/zh/merchant#/get-started
    • 填写基本资料,申请成为商户
    • 进入应用配置页面,配置新应用
    • 查看已配置应用列表,获取应用ClientId

    # 1.3 生成支付秘钥

    • 进入开发者页面,生成"支付API秘钥",用于计算支付接口签名验签
    • 进入开发者页面,生成"授权秘钥",用于计算授权接口签名验签

    # 1.4 关键参数

    • 支付API秘钥,⽤于请求签名
    • ClientId,用于识别身份,配合支付API秘钥进行验签

    # 2. 安全要求

    # 2.1协议规则

    # 2.1.1 表接口规则

    字段 描述
    传输方式 为保证交易安全性,采用HTTPS传输,并使用TLS1.2及以上
    数据格式 请求和响应数据都为JSON格式
    签名算法 HMAC-512算法。
    签名要求 请求和接收数据均需要校验签名,详细方法请参考,接口签名章节
    判断逻辑 先判断协议字段返回,再判断业务返回,最后判断交易状态

    # 2.1.2 响应格式

    所有接口响应返回JSON格式

    字段名 类型 说明
    status string 接口响应结果,SUCESS成功,FAIL失败
    code string 响应错误码
    label string 响应错误名称
    errorMessage string 错误描述
    data string JSON格式业务响应数据

    请求成功响应示例:

    {
        "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
        }
    }
    

    失败响应示例:

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

    # 2.2 参数规定

    # 2.2.1 商户订单号

    商户支付的订单号由商户自定义生成,仅支持使用字母、数字、中划线-、下划线_这些英文半角字符的组合,并且最长32个字节,请勿使用汉字或全角等特殊字符。GatePay要求商户订单号保持唯一性(建议根据当前系统时间加随机序列来生成订单号)。重新发起一笔支付要使用原订单号,避免重复支付。

    # 2.2.2 交易金额

    所有金额参数都采用字符串传输,精度精确到小数点后8位,单笔交易金额最小单位为0.0001,最大为5000000

    # 2.2.3 币种类型

    GatePay支持的币种请参考支持币种章节

    # 2.2.4 时间

    所有时间字段,如果没有额外说明,格式都是毫秒级的Unix时间戳

    # 2.3 API协议头规范

    为确定GatePay API收到的请求一定来自于被授权的合法第三方平台,GatePay API接口会检查HTTP请求头部的必须字段对请求进行签名验证。

    # 2.3.1 协议头

    新版协议头,使用在商户后台生成的秘钥计算签名

    Head字段 为保证交易安全性,采用HTTPS传输
    X-GatePay-Certificate-ClientId 商户在Gate商户后台注册应用时分配的clientId
    X-GatePay-Timestamp 请求生成时的UTC时间戳,milliseconds。请注意,GatePay不处理收到请求时间与这个时间戳差距大于10秒钟的请求
    X-GatePay-Nonce 随机字符串,字符符合HTTP Header头部的规范,建议长度在32个字符以内,字符串组成为数字和字母
    X-GatePay-Signature 请求签名。GatePay通过此签名来确定此请求是否合法

    # 2.4 接口签名

    # 2.4.1 签名规范

    构造签名串

    我们希望商户的技术开发人员按照当前文档约定的规则构造签名串。 GatePay会使用同样的方式构造签名串。如果商户构造签名串的方式错误,将导致签名验证不通过。下面先说明签名串的具体格式。

    每一行为一个参数。行尾以\n(换行符,ASCII编码值为0x0A)结束。如果参数本身以\n结束,也需要附加一个\n

    请求时间戳\n请求随机串\n请求报文主体\n

    # 2.4.2 签名算法

    签名算法示例见右侧

    GO语言

    import (
    "crypto/hmac"
    "crypto/sha512"
    "encoding/hex"
    "fmt"
    )
    // GenerateSignature 生成请求签名
    // timestamp: 转换成字符串的UTC时间戳,精度是millisecond
    // nonce: 随机字符串
    // body: 请求体
    // secretKey: GateIO提供的api_secret
    // return: 字符串签名
    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:
          '''
          生成请求签名
          :param timestamp: 转换成字符串的UTC时间戳,精度是millisecond
          :param nonce: 随机字符串
          :param body: 请求体
          :param secret: GatePay提供的api_secret
          :return: 返回字符串签名
          '''
          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. 支付

    # 3.1 简介

    开发平台Pay是指在GateApp客户端外的移动端网页展示商品或服务,用户在页面确认使用GatePay支付时,商户发起本服务呼起GatePay进行支付。

    # 3.2 应用场景

    用户侧使用具体操作流程如下:

    步骤一:

    用户从非GatePay浏览器导航进入商户网页,用户挑选需购买商品,选择GatePay发起购买流程。

    步骤二:

    进入GateApp确认交易,输入支付密码。

    步骤三:

    支付成功,用户端收到支付结果,同时商户后台收到支付结果的通知。

    # 3.3 流程图

    gatepay时序图

    主要流程如下:

    1. 用户在商户的应用内下单,发起支付。
    2. 商户服务器端收到支付请求后,生成商户平台订单。
    3. 商户服务器端生成商户订单号,并请求GatePay接口创建预付单(参考6.1创建预付单)。
    4. 商户服务器端将生成的预付单请求发往Gate预付单创建接口。Gate接口校验预付单请求,成功后生成预付单并返回预付单信息。
    5. 商户服务器收到预付单信息,进入用户确认并授权支付流程。针对GatePay内嵌的H5商户应用,商户应用需调用Gate提供的js方法要求用户应用内授权(参考6.2支付接口)。
    6. 用户在GateApp确认支付后,GateApp会与GatePay服务发起通信,传输用户授权信息,GatePay服务内部会进行Token的授权验证以及支付密码验证(PassFund)操作。
    7. GatePay支付验证成功后,会异步请求到商户应用服务器的回调地址,通知支付结果,并接受确认回复(参考6.9订单状态异步通知)。
    8. GatePay处理结束后会将用户重定向到商户提供的支付结果地址,由商户显示支付结果。
    9. 如果第七步GatePay 异步通知未能成功到达商户服务回调地址或未能得到商户服务器的成功回执,GatePay后台会尝试重复通知商户服务。商户服务也可以通过支付查询接口查询支付结果状态(参考6.5 订单状态查询)。

    # 3.4 API接口列表

    接口列表 描述
    /v1/pay/order 创建预付单
    /v1/pay/order/close 关闭预订单
    /v1/pay/order/query 订单状态查询
    /v1/pay/order/refund 创建退款单
    /v1/pay/order/refund/query 退款订单查询
    /v1/pay/batch/transfer 创建批量转账
    /v1/pay/batch/transfer/query 查询批量转账订单状态

    # 3.4.1 创建预付单

    作用: 当用户在第三方平台下单成功并选择GatePay支付后,第三方平台需要先发送订单信息给GatePay平台,创建预付单,并获取预付单prepayId

    • 数据类型:JSON(content-type: application/json)
    • 请求⽅式:POST
    • PATH: /v1/pay/order
    • 请求体内容:
    属性名 类型 是否必须 说明
    merchantTradeNo string 商户的订单号,由数字和字母组成,最长32字节
    currency string 支付币种,大写形式,如USDTBTC
    orderAmount string 交易金额,最高精度为8位,范围0.0001-5,000,000
    env Env type 交易来源
    goods goods type 商品说明
    orderExpireTime int64 订单过期时间,UTC时间戳,millisecond。不设置时默认为1小时,最大过期时间为1小时
    returnUrl string 订单支付成功后返回跳转地址,最长256字符
    cancelUrl string apiDoc.cancelUrl

    Env type

    属性名 类型 是否必须 说明
    terminalType string 交易来源 APPWEBWAPMINIAPPOTHERS

    Goods type

    属性名 类型 是否必须 说明
    goodsName string 商品名称,最长160字符
    goodsDetail string 商品描述,最长256字符

    请求示例:

    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"
    }'
    

    成功返回:

    {
        "status": "SUCCESS",
        "code": "000000",
        "data": {
            "prepayID": "1647557960944",
            "terminalType": "MINIAPP",
            "expireTime": 1647557975944
        },
        "errorMessage": ""
    }
    

    返回体类型

    属性名 类型 是否必须 说明
    status string SUCCESSFAIL
    code string 错误代码
    data OrderResult 返回数据,出错时不返回
    errorMessage string 错误信息,成功时为空字符串

    data字段数据

    属性名 类型 是否必须 说明
    prepayID string 预付单id
    terminalType2 string 交易发起的终端类型
    expireTime int64 订单过期时间戳,单位millisecond

    # 3.4.2 付款接口

    当预付单创建成功并获取到预付单id后,运行在GateIO App内的小程序可以通过GateIO App提供的Javascript 方法发起调起支付组件。

    注意: 调起方法是基于在Gate.io (opens new window) App内调起的,不是打开个浏览器就能支持。

    方法名:gatepay

    参数:

    merchantId: string,商户id
    merchantTradeNo: string,商户订单号
    prepayId: string,预付单号
    totalFee: string,支付金额
    currency: string,支付币种
    

    Android调用方式

      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调用方式,注意:params中都传string类型

     var params = {
          "merchantId": "666123",
          "merchantTradeNo": "56236",
          "prepayId": "1647557960944",
          "totalFee": "1.91",
          "currency": "BTC"
      };
      window.webkit.messageHandlers.gatepay.postMessage(params);
    

    返回:函数执行完毕会,会直接执行跳转,将用户重定向到创建订单时指定的returnUrl或者cancelUrl

    # 3.4.3 预付单关闭

    当商户端订单被取消时,商户可以主动发起请求要求GatePay关闭一个未支付的订单。(如果一个订单号不被关闭,只能等待过期。)

    • 数据类型:JSON(content-type: application/json)

    • 请求⽅式:POST

    • PATH: /v1/pay/order/close

    • 请求体内容:

      请求类型

    属性名 类型 是否必须 说明
    merchantTradeNo string
    prepayId string prepayId merchantTradeNo 只需提供一个

    请求示例:

    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"}'
    

    返回示例:

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

    返回类型:

    属性名 类型 是否必须 说明
    status string SUCCESSFAIL
    code string 错误代码
    data close result type 关闭结果
    errorMessage string 错误信息,成功时为空字符串

    close result type:

    属性名 类型 是否必须 说明
    result string SUCCESSFAIL

    # 3.4.4 退款接口

    关闭商户可以针对一个已成功支付的订单发起退款。退款执行并不需要付款商户和用户确认。退款订单创建后就会开始安排执行。退款成功后,GatePay后台会发送退款结果通知。

    请注意:退款不可以取消、撤回、回滚。

    • 数据类型:JSON(content-type: application/json)
    • 请求⽅式:POST
    • PATH: /v1/pay/order/refund
    • 请求体内容:
    属性名 类型 是否必须 说明
    refundRequestId string 商户生成的退款单id。退款单id必须唯一,最长32字符
    prepayId string 已支付过的预付单信息
    refundAmount string 退款金额,不能超过订单金额
    refundReason string 退款原因,最长256字符

    请求示例:

    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"
    }'
    

    返回示例:

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

    返回类型:

    属性名 类型 是否必须 说明
    status string SUCCESSFAIL
    code string 错误代码
    data refund data type 退款单信息
    errorMessage string 错误信息,成功时为空字符串

    refund data type

    属性名 类型 是否必须 说明
    refundRequestId string 退款单id
    prepayId string 预付单id
    orderAmount string 订单金额
    refundAmount string 申请退款金额

    # 3.4.5 订单状态查询

    为方便商户同步订单信息,GatePay提供了查询接口用于查询订单状态

    • 数据类型:JSON(content-type: application/json)
    • 请求⽅式:POST
    • PATH: /v1/pay/order/query
    • 请求体内容:
    属性名 类型 是否必须 说明
    prepayId string 预付单信息
    merchantTradeNo string 商户订单id。预付单id与此id提供一个即可

    请求示例:

    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"
    }'
    

    查询非指定营收币种订单详情,响应示例

    {
        "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"
        }
    }
    

    查询指定营收币种订单详情,未结算,响应示例

    {
        "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"
        }
    }
    

    查询指定营收币种订单详情,已结算,响应示例

    {
        "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"
        }
    }
    

    返回类型:

    属性名 类型 是否必须 说明
    status string SUCCESSFAIL
    code string 错误代码
    data query order return type 支付订单信息
    errorMessage string 错误信息,成功时为空字符串

    query order return type

    属性名 类型 是否必须 说明
    prepayId string 预付单id
    merchantId int64 商户user_id
    merchantTradeNo string 商户订单
    transactionId string 交易id
    goodsName string 商品名称
    currency string 订单币种
    orderAmount string 订单金额
    status string 订单状态
    createTime int64 预付单创建时间,单位毫秒
    expireTime int64 预付单过期时间,单位毫秒
    transactTime int64 支付完成时间,单位毫秒
    order_name string 订单名称
    pay_currency string 用户实际支付币种
    pay_amount string 用户实际支付金额
    expectCurrency string 商家创建订单时,指定营收币种,注:仅在商户指定结算币种的订单详情中返回
    actualCurrency string 订单支付完成后,Gate后台实际结算到商户账户的币种,注:仅在订单Gate结算给商户后才在订单详情中返回
    actualAmount string 订单支付完成后,对应Gate后台实际结算到商户账户的币种的金额,注:仅在订单Gate结算给商户后才在订单详情中返回
    rate string 闪兑支付时的汇率

    订单状态status状态含义:

    描述
    PENDING 订单待支付状态
    PAID 支付成功
    PROCESS 地址支付使用,订单有效期内支付足够金额但链上未确认完毕
    EXPIRED 订单已过期
    CANCELLED 商户侧调用关闭接口取消订单
    ERROR 订单在支付发生错误

    # 3.4.6 查询退款单

    • 数据类型:JSON(content-type: application/json)
    • 请求⽅式:POST
    • PATH: /v1/pay/order/refund/query
    • 请求体内容:
    属性名 类型 是否必须 说明
    refundRequestID string 商户侧生成的退款单id

    请求示例:

    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
    

    回应示例:

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

    请求回应类型:

    属性名 类型 是否必须 说明
    status string SUCCESSFAIL
    code string 错误代码
    data query refund return type 支付订单信息
    errorMessage string 错误信息,成功时为空字符串

    query refund return type

    属性名 类型 是否必须 说明
    refundRequestID string 商户侧生成的退款单id
    prepayId string 订单id,GatePay后端生成
    orderAmount string 订单金额
    refundAmount string 申请退款金额
    refundStatus string 退款单状态 SUCCESS:退款成功 FAIL退款失败

    # 3.4.7 创建商户批量转账

    • 数据类型:JSON(content-type: application/json)
    • 请求⽅式:POST
    • PATH: /v1/pay/batch/transfer
    • 请求体内容:
    属性名 类型 是否必须 说明
    merchant_batch_no string 商户侧生成唯一订单单号,不同订单号表示不同订单
    merchant_id string 商户ID
    currency string 当前币种
    name string 批量转账名称
    description string 批量转账描述
    bizscene string 转账场景枚举如下: DIRECT_TRANSFERREWARDSREIMBURSEMENTMERCHANTPAYMENTOTHERSPAYMENT
    batchorderList array 批量转账用户列表

    batchorderList单个item数据字段

    属性名 类型 是否必须 说明
    user_id int64 用户id
    amount string 给用户转账金额

    请求示例:

    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"
          }
      
      ]
    }'
    

    回应示例:

    成功:

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

    失败:

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

    失败错误码:

      ErrCodeatchTransferDuplicated              = "500000"  //批量转账单重复
      ErrCodeatchTransferAmountLimit             = "500001"  //单次转账金额超过上限
      ErrCodeatchTransferNumPlayerLimit          = "500002"  //单次转账人数超过上限
      ErrCodeBatchTransferTimesLimit             = "500003"  //当天转账次数超过上限
      ErrCodeBatchTransferQuotaNotFound          = "500004"  //没有找到转账配置额度信息
      ErrCodeBatchTransferBizSceneNotFound       = "500005"  //批量转账场景类型错误
      ErrCodeBatchTransferNegative               = "500006"  //批量转账金额负数
      ErrCodeBatchTransferAmountExecpt           = "500007"  //批量转账金额错误
    

    请求回应类型:

    属性名 类型 是否必须 说明
    status string SUCCESSFAIL
    code string 错误代码
    data json 批量转账响应数据
    errorMessage string 错误信息,成功时为空字符串
    属性名 类型 是否必须 说明
    merchant_batch_no string 商户侧生成唯一订单单号,不同订单号表示不同订单
    batch_id string 由GatePay生成,批量订单号

    注意:

    1.商户批量转账创建后,后端会处理每一笔子单成功或者失败,中途无法取消,可以请求商户批量转账订单查询接口获取子单状态。

    2.商户接入批量转账需要和GatePay运营沟通配置批量转账额度,额度限定有3个维度:单笔转账最大用户数,单笔转账最大金额,当天转账最大次数。(具体数据商户和运营沟通协商配置)。

    # 3.4.8 商户批量转账订单查询

    建议在请求商户创建批量转账接口5s后,调用该接口查询批量转账订单状态

    • 数据类型:JSON(content-type: application/json)
    • 请求⽅式:POST
    • PATH: /v1/pay/batch/transfer/query
    • 请求体内容:
    属性名 类型 是否必须 说明
    batch_id string 由GatePay生成,批量订单号
    detail_status string 查询订单类型参数: ALL:查询全部子单信息 PROCESSING:查询未处理子订单信息 SUCCESS:查询处理成功子订单信息 FAIL:查询处理失败子订单信息

    请求示例

    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"}'
    

    响应示例

    {
        "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
                }
            ]
        }
    }
    

    # 4. 授权

    # 4.1 简介

    开发者可以通过国际标准的 OAuth2.0 授权机制,在⽤户授权的情况下,得到⽤于换取⽤户信息的令牌。拿到⽤户的授权令牌后,通过调⽤开放平台提供的接⼝(请参考开放平台API),获取相关信息。

    # 4.2 流程图

    oauth授权流程图

    # 4.3 时序图

    oauth授权时序图
    • 按照规则拼接授权⻚⾯的URL链接,并且引导⽤户跳转⾄该链接
    • ⽤户在授权⻚⾯上确认授权后,将跳转到开发者指定的回调⻚,并且带上code
    • 开发者通过/oauth/token(换取授权访问令牌接⼝),使⽤code换取access_tokenrefresh_tokenexpired等信息
    • 第三⽅应⽤获取⽤户的访问令牌后,在后续访问 Gate开放平台服务的时候,需将令牌放在HTTP头部Authorization属性内。Gate开放平台通过对访问令牌的识别来确定⽤户身份和访问有效性,并提供服务
    • 访问令牌有有效期。如果访问令牌失效,可以⽤刷新令牌换取新的访问令牌

    # 4.4 集成步骤

    # 4.4.1 第一步:允许全局授权

    在用户第一次进入MiniApp主页会弹出全局授权免责声明界面

    授权⻚⾯示例:

    授权页面

    # 4.4.2 第⼆步:获取code码

    当⽤户点击**全局授权“我已知晓”**按钮授权成功后,Gate App会申请Code码,Gate授权服务会在回调⻚⾯请求中返回响应参数,包括codestate等参数,需要注意的是Gate OAuth服务仅保证code参数的有效性, Gate App在收到响应后会将⽤户重定向到第三⽅商户提供的redirect_uri地址。

    # 4.4.3 第三步:换取access_token

    得到 code 后,开发者通过 /oauth/token(换取授权访问令牌接⼝),使⽤ code 换取 access_tokencode 作为换取 access_token 的凭证,每次⽤户授权完成后,返回参数中的 code 将不一样,code 只能使⽤一次,24 ⼩时内未被使⽤⾃动过期

    换取token API

    # 4.4.4 第四步:调⽤开发平台接⼝

    当获得⽤户访问令牌后,第三⽅服务便可以以⽤户的身份通过 GateIO 的开放API 接⼝获取和操作⽤户信息。

    在使⽤ GateIO 开放平台服务时,需将访问令牌添加到 HTTP 头部 Authorization 属性中。

    以获取⽤户信息为例

    获取⽤户信息

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

    # 4.5 访问令牌过期后,⽤刷新令牌换取新的访问令牌

    访问令牌过期后,可以⽤刷新令牌换取新的访问令牌。新的刷新令牌也会一并返回。刷新成功后获得的令牌和原令牌拥有相同的权限。

    刷新令牌API

    # 4.6 开放平台权限说明

    scope定义说明:

    scope定义 details 说明
    read_profile [] 获取⽤户信息权限,不包括Email信息
    read_email [] 获取⽤户信息权限,包括Email信息
    read_wallet ["SUPE", "USDT"] 获取⽤户币种信息权限,details描述能读取那些币种
    read_tier [] 获取⽤户等级信息
    read_nft ["GATENFT"] 获取⽤户NFT信息权限,details描述能读取的NFT token信息
    app_jump {"scheme": {"ios": "unitydl://cyberpop", "android": "unitydl://cyberpop"}} app是否能跳转到外部URLdetails描述具体URL

    # 4.7 授权常见问题

    1.什么是授权临时票据(code)?

    答:第三⽅通过 code 进⾏获取access_token的时候需要⽤到,code的超时时间为10分钟,一个 code 只能成功换取一次access_token 即失效。code的临时性和一次保障了授权登录的安全性。第三⽅可通过使⽤https 和state参数,进一步加强⾃身授权登录的安全性。

    2.什么是授权作⽤域(scope)?

    授权作⽤域(scope)代表⽤户授权给第三⽅的接⼝权限,第三⽅应⽤需要向Gate开放平台申请使⽤相应scope 的权限后,使⽤⽂档所述⽅式让⽤户进⾏授权,经过⽤户授权,获取到相应access_token后⽅可对接⼝进⾏调⽤。

    # 4.8 授权API

    # 4.8.1 获取授权⻚⾯

    • 数据类型:query
    • 请求⽅式:GET
    • PATH: /oauth/authorize

    请求头内容:

    参数名 是否必须 描述
    Content-Type 当前仅支持code
    User-Agent 代理端类型,安卓端gateio/android,IOS端gateio/ios

    请求体内容:

    参数名 是否必须 描述
    client_id 第三⽅应⽤注册时获得的 client_id
    response_type 认证返回类型,⽬前针对第三⽅应⽤,当前仅支持code
    redirect_uri ⽤户授权成功后返回的 uri 地址,此地址必须与第三⽅应⽤注册时提供的回调地址完全⼀致
    scope 第三⽅应⽤需要获取的权限,⽐如 read_profile, read_wallet
    state 商户⾃定义参数,⽤户授权后,重定向到 redirect_uri 时会原样回传给商户为防⽌ CSRF 攻击。建议开发者请求授权时传⼊ state 参数,该参数要做到既不可预测,⼜可以证明客户端和当前第三⽅⽹站的登录认证状态存在关联,并且不能有中⽂ 说明:参数由⽤户⾃定义拼接。最后将参数拼接为 state=XXXXX 即可,最⼤⻓度 32位。

    请求示例:

    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'
    

    响应:

    HTML授权⻚⾯

    错误码:

    状态码 错误码 描述 解决⽅案
    400 invalid_request 参数错误 请根据接⼝返回的详细信息检查请求参数
    403 invalid_client client_id⽆效 请检查client_id是否正确
    400 invalid_grant ⽆效请求权限 请检查申请权限和redirect_uri参数是否正确

    # 4.8.2 换取 access_token

    • 数据类型:application/json
    • 请求⽅式:POST
    • PATH: /oauth/token
    • 请求体内容:
    参数名 是否必须 描述
    grant_type grant_type:授权类型,⽬前针对第三⽅应⽤只⽀持 authorization_code(授权令牌交换访问令牌), refresh_token(更新访问令牌)
    code code:授权令牌,第以上步中收到的 code 值
    redirect_uri 回调地址,第三⽅应⽤注册的回调地址,GateIO OAuth也会使⽤回调地址⽤于校验请求

    请求示例:

    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"
    }'
    

    响应结果示例:

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

    响应参数说明:

    参数名 描述
    access_token 访问令牌
    refresh_token 访问令牌过期后,⽤于获取新的访问令牌的刷新令牌
    scope 授权的权限,逗号分割的数组
    token_type 令牌类型,对于第三⽅⽬前只返回 Bearer
    expired_in 访问令牌过期时间。单位是秒

    错误码:

    状态码 错误码 描述 解决⽅案
    400 invalid_request 参数错误 请根据接⼝返回的详细信息检查请求参数
    403 invalid_client client_id⽆效 请检查client_id是否正确
    400 invalid_grant ⽆效请求权限 请检查申请权限和redirect_uri参数是否正确
    400 unsupported_grant_type 不⽀持grant_type grant_type类型为:authorization_code ,refresh_token

    # 4.9 开放平台API

    用户在授权成功后,可以使用access_token请求开发平台接口

    # 4.9.1 获取⽤户信息(不包括Email)

    • 请求⽅式:GET
    • PATH: /api/user_profile
    • 获取⽤户信息(不包括Email)

    请求示例:

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

    响应示例:

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

    错误码:

    状态码 Code码 描述 解决⽅案
    403 3 ⽆效access token 请检查access token是否有效
    403 6 Access token过期 token过期,请刷新token
    403 4 权限不⾜ 请检查当前token是否有read_profile权限
    403 5 ⽆效uid 检查token是否正确,以及uid是否存在

    # 4.9.2 获取⽤户信息(包括Email)

    • 请求⽅式:GET
    • PATH: /api/user_email
    • 获取⽤户信息(包括Email)

    请求示例:

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

    响应示例:

    {
        "status":"SUCCESS", "code":0,
        "data":{
        "uid":10000,
        "nickname":"客服1",
        "avatar":"https://gavatar.gateimg.com/groupchat/avatar-dd253c609c-8bf188bd01- 3a8241-faeac4",
        "email":"[email protected]", "user_verified":true
      }
    }
    

    错误码:

    状态码 Code码 描述 解决⽅案
    403 3 ⽆效access token 请检查access token是否有效
    403 6 Access token过期 token过期,请刷新token
    403 4 权限不⾜ 请检查当前token是否有read_profile权限
    403 5 ⽆效uid 检查token是否正确,以及uid是否存在

    # 4.9.3 获取⽤户信息(包括等级)

    • 请求⽅式:GET
    • PATH: /api/user_tier
    • 获取⽤户信息(包括等级)

    请求示例:

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

    响应示例:

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

    错误码:

    状态码 Code码 描述 解决⽅案
    403 3 ⽆效access token 请检查access token是否有效
    403 6 Access token过期 token过期,请刷新token
    403 4 权限不⾜ 请检查当前token是否有read_profile权限
    403 5 ⽆效uid 检查token是否正确,以及uid是否存在

    # 4.9.4 获取⽤户币种和余额

    • 请求⽅式:GET
    • PATH: /api/wallet
    • 获取⽤户币种和余额

    请求示例:

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

    响应示例:

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

    错误码:

    状态码 Code码 描述 解决⽅案
    403 3 ⽆效access token 请检查access token是否有效
    403 6 Access token过期 token过期,请刷新token
    403 4 权限不⾜ 请检查当前token是否有read_profile权限
    403 5 ⽆效uid 检查token是否正确,以及uid是否存在

    # 4.9.5 获取⽤户NFT信息

    • 请求⽅式:GET
    • PATH: /api/user_nft
    • 获取⽤户NFT信息
    参数名 是否必须 描述
    token 待查询NFT信息平台token
    token_id 待查询NFT具体id值

    请求示例:

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

    响应示例:

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

    # 5 订单状态异步通知

    # 5.1 订单状态异步通知介绍

    1. 在订单状态发生改变时,如支付成功,超出支付时间,订单取消等操作,GatePay后台会向商户发送订单状态通知。通知地址是商户注册时提供的callback url地址参数,callback url不能含有“#”这类特殊字符。

    2. 如果由于网络或者其他未知原因导致通知失败,GatePay后台会每隔3秒重试10次。如果重试也失败,商户可以主动通过调用订单状态查询接口获取订单状态。

    3. 商户接受到的异步通知信息,必须校验消息签名参数来验证消息合法性。

    # 5.2 消息结构

    字段名 类型 说明
    bizType string 描述通知类别, 见表BizType
    bizId string 订单id
    bizStatus string 订单状态,见表BizStatus
    client_id string 创建订单的商户client_id
    data json 消息内容,根据bizType不同而不同

    消息结构示例:

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

    商户在收到异步回调消息后,需响应成功收到消息,消息结构示例:

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

    bizType枚举值

    解释
    PAY 非地址支付订单状态改变通知支付成功PAY_SUCCESS
    超时或商户关闭订单 PAY_CLOSE
    支付错误PAY_ERROR
    PAY_REFUND 退款单状态改变通知,退款成功或失败
    PAY_BATCH 批量奖励订单状态改变通知
    TRANSFER_ADDRESS 地址支付订单资金到账通知
    RECEIVED_CONVERT_DELAY_ADDRESS 地址支付的延迟支付订单处理通知
    PAY_ACTUALLY 这是一个属于商户指定营收币种支付单的通知

    BizStatus枚举值

    解释
    PAY_SUCCESS 订单支付成功
    PAY_ERROR 订单支付遇到错误
    PAY_CLOSE 订单被商户关闭或订单超时
    REFUND_SUCCESS 退款成功
    REFUND_REJECTED 退款被拒绝
    PAY_EXPIRED_IN_PROCESS 地址支付订单进入PROCESS状态通知
    PAY_EXPIRED_IN_EXCHANGE_FLUCTUATION 地址支付闪因闪兑支付汇率波动导致支付失败
    TRANSFERRED_ADDRESS_PAID 成功地址单转账
    TRANSFERRED_ADDRESS_EXPIRE 过期地址单转账
    TRANSFERRED_ADDRESS_DELAY 延迟到账转账
    CONVERT_ADDRESS_PAY_DELAY 闪兑延迟支付,但未转账

    bizType对应的Data结构

    字段名 类型 说明
    merchantTradeNo string 商户交易号
    productType string 创建订单时候的goodsType
    productName string 创建订单时候的GoodsName
    tradeType string 创建订单时候的terminalType
    goodsName string 创建订单时候的GoodsName
    terminalType string 创建订单时候的terminalType
    currency string 订单币种
    totalFee string 订单金额
    orderAmount string 订单金额
    payCurrency string 用户实际支付币种
    payAmount string 用户实际支付金额
    expectCurrency string 商户指定营收币种
    actualCurrency string Gate平台向商户结算的实际币种,若Gate将订单币种转换为商户要求币种成功,则actualCurrencyexpectCurrency相同,否则actualCurrency等于currency
    actualAmount string 对应actualCurrency币种的金额
    payerId int64 支付用户的UID
    createTime int64 订单创建时间

    bizType为PAYTRANSFER_ADDRESSRECEIVED_CONVERT_DELAY_ADDRESS其中一种发送格式:

    非地址支付订单状态通知 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"
        }
    }
    

    地址支付订单状态通知 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"
        }
    }
    

    地址支付订单状态通知 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"
        }
    }
    

    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"
        }
    }
    

    bizType=PAY_BATCH

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

    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"
        }
    }
    

    # 6 最佳实践

    # 6.1 支付回调和查单实现指引

    背景: 由于网络异常或者系统的波动,可能会导致用户支付成功,但是商户侧未能成功接收到支付结果通知,进而显示订单未支付的情况。商户侧的订单状态更新不及时,容易造成用户投诉,甚至是重复支付的情况发生

    目标: 商户在未能收到支付结果通知时,也能及时、准确地获取到订单的支付状态,提升商户系统的健壮性,减少因为订单状态不同步导致的用户投诉。

    商户后端服务处理: 商户后台需要准确、高效地处理GatePay发送的异步支付结果通知,并按接口规范把处理结果返回给GatePay服务。

    定时轮询查单: 如果长时间没有收到支付结果通知,商户后台应该定时轮询调用(订单查询接口/v1/pay/order/query)去核实订单状态。

    方案一

    以订单下单成功时间为基准,每隔5秒/10秒/30秒/1分钟/3分钟/5分钟/10分钟/30分钟调用订单状态查询接口(/v1/pay/order/query) 查询一次,最后一次查询还是未返回支付成功状态,则停止后续查询 。并调用关单接口(/v1/pay/order/close)关闭订单。(轮询时间间隔和次数,商户可以根据自身业务场景灵活设置)

    方案二

    定时任务每隔30秒启动一次,找出最近10分钟内创建并且未支付的订单,调用订单状态查询接口(/v1/pay/order/query)核实订单状态。系统记录订单查询的次数,在10次查询之后状态还是未支付成功,则停止后续查询,并调用并调用关单接口(/v1/pay/order/close)关闭订单。轮询时间间隔和次数,商户可以根据自身业务场景灵活设置)

    注意:支付完成后,GatePay会把相关支付结果通过数据流的形式发送给商户,商户需要接收处理,并按文档规范返回应答。

    1. 同样的通知可能会多次发送给商户系统,商户系统必须能够正确处理重复的通知。
    2. 后台异步通知交互时,如果GatePay收到商户的应答不符合规范或超时,会判定本次通知失败,重新发送通知,直到成功为止。 (在通知一直不成功的情况下,GatePay总共会发起10次通知每次间隔5秒)

    # 6.2 退款流程实现指引

    1. 商户侧调用退款接口(/v1/pay/order/refund)创建退款单,注意退款是异步流程,该接口成功并不代表实际退款结果。

    2. 等待退款回调通知,如果收到GatePay异步回调通知获取到退款结果,不用在调用查询接口。

    3. 如果在10s内没有收到退款状态通知,调用(/v1/pay/order/refund/query)接口查询退款单状态,具体

    可参考4.6.1章节支付回调和查单实现指引

    # 6.3 最佳安全实践

    # 数据传输

    使用HTTPS确保网络传输安全性。

    禁用SSL等不安全协议和算法,建议使用TLS1.2及以上。

    不要轻易的尝试设计和实现自己的加密传输算法,几乎都会存在问题。

    # 数据存储

    敏感信息禁止出现在日志中,如确实需要,需进行脱敏处理。

    缓存和DB中的敏感数据需进行加密

    密码等关键认证必须采用加盐加密方式保存。

    # 数据访问

    外部请求数据访问必须进行鉴权操作。

    对于内部的数据访问要严加控制,降低用户信息泄露风险

    # 防止逻辑处理不当导致的漏洞

    支付成功回调通知必须验证GatePay签名,避免被恶意攻击。

    在后台进行商户价格的判断逻辑,避免客户端篡改价格导致商户损失。

    避免在App或者网站页面里面出现商户Securekey。

    # 7 常见错误码

    http状态码 错误码 描述 解决方案
    500 300000 系统错误 系统异常,请用相同参数重新调用
    500 300001 内部错误 系统异常,请用相同参数重新调用
    500 400000 未知错误 系统异常,请用相同参数重新调用
    200 400001 请求参数格式错误 检查请求数据参数和格式
    200 400002 签名校验失败 检查商户签名是否正确
    200 400003 请求时间戳超时 检查请求head里的时间戳字段
    200 400007 不支持的media type 查看接口设置的media type
    200 400020 签名随机数错误 请检查随机数是否为空
    200 400201 商户订单号重复 请核实商户订单号是否重复提交
    200 400202 订单不存在 请检查订单是否发起过交易或订单号是否正确
    200 400203 商户号不存在 请检查商户号是否正确
    200 400204 订单状态不正确 检查订单是否过期,取消被关闭状态,可调查询接口
    200 400205 无效币种 请检查下单币种类型
    200 400304 退款单ID不存在 检查请求的退款单ID
    200 400603 订单超时 请核实订单是否过期
    200 400604 退款关联交易单无效 请检查退款交易单是否为完成状态
    200 400605 支付账户余额不足 支付账户余额不足
    200 400607 退款次数太多 退款次数大于限制
    200 400608 退款金额异常 请检查退款金额
    200 400620 订单重复支付 请核实商户订单号是否重复提交
    200 400621 错误的支付金额 检查请求金额
    200 400622 汇率波动导致币种兑换失败 可以重试在次申请
    200 400623 不支持币种支付 请检查支付币种
    200 400624 无效订单状态通知地址 检查商户提供回调地址是否有效
    200 500008 未找到对应商户 检查请求商户ID是否正确
    200 500100 支付二维码过期 重新下单生成新二维码
    200 500101 二维码重复支付 请核实订单状态
    200 500103 地址支付闪兑币种错误 闪兑收汇率影响
    200 500203 地址支付无法查询到订单详情 请检查地址是否正确
    200 500204 退款单的退款接收人ID无效 请确认退款接受人为Gate用户
    200 500205 退款单币种币匹配 请保证退款币种为订单币种或用户支付币种之一
    200 500206 退款金额超过上限 请检查订单退款金额
    200 500207 地址支付无法查询到退款单 请求确认是否发起退款成功或查询地址是否正确
    200 500208 不能以转换地址的方式退还无转换地址的订单 请确认退款订单类型

    # 8 支持的支付币种

    "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 常见问题

    # Q: 通过预下单接口生成的二维码多长时间有效?

    A: 商户可指定订单过期时间,订单最大和默认有效期是一小时。

    # Q:如何区分不同平台渠道发起的订单

    A: 通过useragent字段可以识别来自gate io渠道的用户 Android :“isPhone/1 GateIO/Android” iOS :“isPhone/1 GateIO/iOS”

    # Q:如何测试

    A: 步骤如下:

    ​ 1.商户在商户后台注册应用填写测试UID

    小程序注册

    ​ 白名单UID格式(英文字符逗号,无空格): UID1,UID2,UID3

    ​ 加入白名单后,可用白名单uid账号登录Gate App, 即可在Gate Life应用列表中看到自己的商户小程序App,随后进行授权流程和支付测试。

    3.开始接入测试

    加入白名单后,可用白名单uid账号登录Gate App, 即可在 “App首页下拉 → Gate Life → 精选”商户应用列表下看到自己的商户小程序App,随后进行授权流程和支付测试。