NAV
java php

一、TopPay API Reference

本文档面向具有开发能力的技术人员 欢迎您联系我们,请在Telegram Messenger 👨‍💻 Cindy 欢迎咨询.

二、说明

统一请求方式

HTTP POST

ContentType

application/json

签名sign

右侧阴暗区域为签名工具类

import com.google.gson.JsonObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 *  TopPay RSA签名工具类
 * </p>
 *
 * @author TopPay
 */
public class TopPayRequestUtil {

  /**
   * 验证签名
   * @param params
   * @return
   */
  public static boolean verifySign(JsonObject params, String publickey) throws InvalidKeySpecException, NoSuchAlgorithmException {
    String platSign = params.remove("platSign").getAsString(); // 签名
    List<String> paramNameList = new ArrayList<>(params.keySet());
    Collections.sort(paramNameList);

    StringBuilder stringBuilder = new StringBuilder();
    for (String name : paramNameList) {
      stringBuilder.append(params.get(name).getAsString());
    }
    System.out.println("keys:" + stringBuilder);

    String decryptSign  = publicDecrypt(platSign, getPublicKey(publickey));
    System.out.println("decryptSign:" + decryptSign);

    return stringBuilder.toString().equals(decryptSign);
  }

  /**
   * 私钥加密
   * @param data
   * @param privateKey
   * @return
   */

  public static String privateEncrypt(String data, RSAPrivateKey privateKey){
    try{
      Cipher cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.ENCRYPT_MODE, privateKey);
      return Base64.encodeBase64String(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes("UTF-8"), privateKey.getModulus().bitLength()));
    }catch(Exception e){
      throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
    }
  }

  /**
   * 公钥解密
   * @param data
   * @param publicKey
   * @return
   */

  public static String publicDecrypt(String data, RSAPublicKey publicKey){
    try{
      Cipher cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.DECRYPT_MODE, publicKey);
      return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), "UTF-8");
    }catch(Exception e){
      throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
    }
  }

  /**
   * 得到私钥
   * @param privateKey 密钥字符串(经过base64编码)
   */
  public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
    //通过PKCS#8编码的Key指令获得私钥对象
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
    RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
    return key;
  }

  /**
   * 得到公钥
   * @param publicKey 密钥字符串(经过base64编码)
   */
  public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
    //通过X509编码的Key指令获得公钥对象
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
    RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
    return key;
  }

  private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
    int maxBlock = 0;
    if(opmode == Cipher.DECRYPT_MODE){
      maxBlock = keySize / 8;
    }else{
      maxBlock = keySize / 8 - 11;
    }
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int offSet = 0;
    byte[] buff;
    int i = 0;
    try{
      while(datas.length > offSet){
        if(datas.length-offSet > maxBlock){
          buff = cipher.doFinal(datas, offSet, maxBlock);
        }else{
          buff = cipher.doFinal(datas, offSet, datas.length-offSet);
        }
        out.write(buff, 0, buff.length);
        i++;
        offSet = i * maxBlock;
      }
    }catch(Exception e){
      throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);
    }
    byte[] resultDatas = out.toByteArray();
    IOUtils.closeQuietly(out);
    return resultDatas;
  }

  public static String doPost(String url,String json) throws IOException {
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(url);
    StringEntity s = new StringEntity(json);
    s.setContentEncoding("UTF-8");
    s.setContentType("application/json");//发送json数据需要设置contentType
    post.setEntity(s);
    HttpResponse res = client.execute(post);
    if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
      return EntityUtils.toString(res.getEntity());// 返回json格式:

    }
    return null;
  }
}

签名统一生成规则:

基于RSA的签名验证方式 将所有非空参数的key按照ASCII排序后,取参数值(不包含Key)进行拼接后 采用RAS算法对字符串计算,算出签名字符串

参数示例值

参数 类型
merchantCode S820211021094748000001
orderNum T1642592278863
payMoney 150.60
notifyUrl your notify ur
expiryPeriod 1440

拼接字符串

示例 首先根据参数Key按照ASCII排序,排序后加密字符串 StrA = 2022-01-01 10:55:00test1440S820211021094748000001014JackMayour notify urlT1642593166888150.60082122965511Test Pay

计算签名

使用您在TopPay商户后台配置的密钥对,用您的私钥进行加密计算RSA(StrA)获取到最终的签名字符串 sign = IMLn23c4orM+7pZhHoRmbjrol4X33jeAqFxbZuQ+pnznBIGhb6Ail3qQPmKwcuhNCt536nmldpbWI72 k1lDxd0zZ95ZHElcNzwTFHFKtd8063uy6rFaxaW6DQ47t4U/95dpGfHAZe0GiIFAQ6xQquaoLINyQa4QqL+cpB JFEg1dyW6GYLFSdJnx7ycQvFYllmOpGZmdPLny62GvrCWvkiIARUsmc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQ bYDxZ5WBuU1GZeiJjPuzSxvzWP6VoQBsfpwTI5kdJs6aQCekGO2/YScD+tGgrm2J89Pc/axPcb1xZzsi5SxpWh feabQ\u003d\u003d

三、配置商户公钥信息

1.商户后台地址

https://bra-mch.toppay.asia

2.绑定谷歌验证码

登录商户后台->个人中心->安全信息,使用谷歌验证器扫描页面二维码绑定您的账号

3.RSA密钥对生成地址

POST http://pay.hehebo.com:15082/index-rsa.jsp

https://www.bchrt.com/tools/rsa/

http://www.usey.cn/rsa

4.配置公钥

登录商户后台->收付款配置->API配置,填入您的公钥信息并保存.配置完成

5.保存平台公钥

登录商户后台->收付款配置->API配置,将其中展示的平台公钥进行保存,用于验签解密。

四、法币(BRL)代收下单

1.代码示例

代码示例仅供参考,具体参数说明请参考请求参数说明


import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Map;
import java.util.TreeMap;

public class TopPayDemo {

  private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  // 平台公钥
  private static final String MCH_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJU8gKFKD0luIYx7X8+JRdCIE0UDBctS6LjXxWLEv/EO7jDBTid6zYP1KmNgpd2DAWWtBFBSQ+gcNwVZZSBHJiSDqVvvJVs2FEbeBvfdv4X93+IYRAXksBasSW5Tpdshbo82pVL4V7wuKCuFLk9UxBHbpQjWAbfyF66RmwIbZD71AgMBAAECgYBjPe7UU2nDDSfmQg0++CyjNjqKRC5QPfxhH6w1uF1kMueXKJWOj42n2RutJpJmsj31nY8m0u4xpsG4HvCu/GGSFhhKZCHLvzp41oY2ubYj9nuFNU//81LycQjulWo2y0UUBY0k2piEt+SwPaiUNbT6nMxNMjlnjRe2okp/3rw+KQJBANG3YlZWoVbCEqzy64bJJLxiPsCA5ErGB0NzRGitq44xkhqGtR8ZZQyVz40pruNa58d73O2xyJSy5+fmZGn4E+sCQQC2LBnguj0CSCKub0mPDcunTTz9V79VXBBZdlB1/YGmRUx2s4sQrJNZS7rL4EqBQ3maIRnG+s+AXCSTfsYrV6CfAkEAxugnVfpelhoGepEAgNuggyivmgfl/2Gpm/jk5l/qOjib+ZrQiQmeBPzGWX4yiSM8eMDrP2sC8r5pJFMp5DRONwJBAJ4n4XuSFJ9jgwCPy3vvzSv9SYLk6E6yM9uHdUlKgoGYzk6Lh6M9QFuY/J49plFdBDiEnj16yCU3WeXXfTJpzB8CQQDMNMR/rIOTE9xGybS3mlQbt22AUnO6XhupWcckEKW4nPGxATwYBQzCY3i/9FTGN0vA+9ZPC2cwHtNxI2kXf3Vp";  // 商户私钥
  private static final String payUrl = "https://bra-openapi.toppay.asia/gateway/prepaidOrder";
  private static final String cashUrl = "https://bra-openapi.toppay.asia/gateway/cash";
  private static final String payNotify = "your notify url";

  public static void main(String[] args) throws Exception {
    // 代收
    pay();
  }
  private static void pay() throws Exception {
    Map<String, String> requestParams = new TreeMap<>();
    requestParams.put("merchantCode", "S820211021094748000001");//商户ID
    requestParams.put("orderType", "0"); // 订单类型(0-法币(BRL)交易)
    requestParams.put("orderNum", "T1642592278863"); // 商户订单号
    requestParams.put("notifyUrl", payNotify);// 回调地址
    requestParams.put("description", "PAY"); // 描述
    requestParams.put("name", "AAA"); // 用户名

    StringBuilder stringBuilder = new StringBuilder();
    for (String key : requestParams.keySet()) {
      stringBuilder.append(requestParams.get(key));  // 拼接参数
    }

    String keyStr = stringBuilder.toString();  // 得到待加密的字符串
    System.out.println("keyStr:" + keyStr);
    String signedStr = TopPayRequestUtil.privateEncrypt(keyStr, TopPayRequestUtil.getPrivateKey(MCH_PRIVATE_KEY));  // 私钥加密
    requestParams.put("sign", signedStr);

    String postJson = new Gson().toJson(requestParams);
    System.out.println("Post Json Params:" + postJson);

    String responseJson = TopPayRequestUtil.doPost(payUrl, postJson);  // 发送 post json请求
    System.out.println("Response Msg:" + responseJson);
  }
}


<?php
    // 平台公钥,从密钥配置中获取
    // platform public key, from Secret key config
    $platPublicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiaKBgQCcEUIvQ/5L+SWbHOeR8VFeZvLbUk7V7OeEAQlQwIVLSZMTef3KtsOKKAsUYPf/aAcKRzZZXECODsPQiDPcdZvM/rFkgrFWkR7lPjTj5SiPxGaiK2Z2sne7A8aDF7fV/D7lfmEwNdZ7FWKVEB84/81BHnlGUwb5HpRTISG+boSO6wIDAQAB';
    // 商户私钥,商户自己生成(这里只是测试案例)
    $mchPrivateKey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMigm7rtWnTeNagwFzGTH+Uw1ypbiy7VhIoFJbgSYSSHdCaXWdT/l2+2fQlEYgAETVZ/IXB29MCnrf3O0dwRFXiipIbsm5zyqSLiS6cKXe8zN1/PlQWUbEt5wyWm0GADB/4bV6eu6gA7sGXmjQqrzfKZkcie3aK7+7ry1NFxTI51AgMBAAECgYEAklqXQAVlt1tiSQ7L3J425jp6u6uMHN4lkYmvuleuBbfKQ1yla3wIPLYjAF+iHeEFidOz0Rb19JRdmIkHDkJoJg2W27LvO6RdUwzgRnsuA3OuNz97w08B3aXXbPmB91nTFjKSlUsbh3IQWP71noxW+iKn844EW5hC5Gvn4L3quAECQQDrz1r0VKIbBSBB2aLuz1XyD/TBT2aRhvOKf0XtTRiQhNjtJxoQmvNbbhvUwj8an7HyCuihAbdbrC2ymFFyOSDZAkEA2c4Yudi48C6COrroi1cWgPlEFeGJXP/V1k5loZ1n2vstYAGPhAB4wUnFBLDvMqaBzWJt7MRkiazT8KnBQCDY/QJAMXpNlEyZwt+deBOpO0BnwSWV7mWxmMFfImU4D+WITPbC7aexsWBBxaJh1o93XCe715RwYTAR//stj3akSDoyaQJAa4FKuxC51/Nc3Fg9R+modeiTLqmv/3NXvPvdNjRXesLX1rduex0wfVdII9ShfEKrdxDKaT9W0NyzD+r6NAkCkQJBAMAnTgPYf0f7rh417GdoP7R7Nwi8KBKwPHlmfRukibOQlKt9xjqpsKJwglLn8pcnXbYbswXIdqzuBvIGAe3OWNg=';
    // 商户ID,从商户信息中获取
    $merchantCode = 'S820211021094748000001';
     //订单类型(0-法币(BRL)交易)
    $orderType = '0';
     // 商户订单号
    $orderNum = 'TEST1231231231';
    // 用户名
    $name = 'AAA';
    // 描述
    $description = 'PAY;
    // 回调地址
    $notifyUrl = 'http://123/callback';
    $params = array(
        'merchantCode' => $merchantCode,
        'orderType' => $orderType,
        'orderNum' => $orderNum,
        'description' => $description,
        'name' => $name,
        'notifyUrl' => $notifyUrl,
    );

    ksort($params);
    $params_str = '';
    foreach ($params as $key => $val) {
        $params_str = $params_str . $val;
    }


    $sign = pivate_key_encrypt($params_str, $mchPrivateKey);

    $params['sign'] = $sign;

    $params_string = json_encode($params);
    $url = 'https://bra-openapi.toppay.asia/gateway/prepaidOrder';
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($params_string))
    );
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

    //execute post
    $request = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if($httpCode == 200)
    {
        $result = json_decode($request, true);
        echo "platRespCode :". $result['platRespCode'] . "\n";
        echo "platRespMessage :". $result['platRespMessage'] . "\n";
        echo "platOrderNum :". $result['platOrderNum'] . "\n";
        echo "orderNum :". $result['orderNum'] . "\n";
        echo "description :". $result['description'] . "\n";
        echo "url :". $result['url'] . "\n";
        echo "platSign :". $result['platSign'] . "\n";

        $decryptStr = public_key_decrypt($result['platSign'], $platPublicKey);
        echo "decryptStr :". $decryptStr . "\n";
    }
    else {
        echo $httpCode;
    }

    function pivate_key_encrypt($data, $pivate_key)
    {
        $pivate_key = '-----BEGIN PRIVATE KEY-----'."\n".$pivate_key."\n".'-----END PRIVATE KEY-----';
        $pi_key = openssl_pkey_get_private($pivate_key);
        $crypto = '';
        foreach (str_split($data, 117) as $chunk) {
            openssl_private_encrypt($chunk, $encryptData, $pi_key);
            $crypto .= $encryptData;
        }

        return base64_encode($crypto);
    }

    function public_key_decrypt($data, $public_key)
    {
        $public_key = '-----BEGIN PUBLIC KEY-----'."\n".$public_key."\n".'-----END PUBLIC KEY-----';
        $data = base64_decode($data);
        $pu_key =  openssl_pkey_get_public($public_key);
        $crypto = '';
        foreach (str_split($data, 128) as $chunk) {
            openssl_public_decrypt($chunk, $decryptData, $pu_key);
            $crypto .= $decryptData;
        }

        return $crypto;
    }

2.请求地址

我们提供了两种代收下单模式,一种是通过我们的收银台进行获取支付信息,一种是直接请求API获取返回信息,您可以根据自身需求,自行选择。

收银台 : POST https://bra-openapi.toppay.asia/gateway/prepaidOrder

注:所有的参数中,不要填写中文!!!

3.请求参数

收银台:

参数 类型 必填 描述 示例
merchantCode string(32) Y 商户ID,在商户平台获取 S820211021094748000001
orderType string(10) Y 订单类型 0-法币(BRL)交易
orderNum string(32) Y 商户订单号 ASD12312312331
payMoney string(10) Y 付款金额(只允许两位小数位) 20.54
name string(32) N 客户名称 customer name
description string(50) N 描述 description
notifyUrl string(100) Y 订单支付成功异步通知地址(用来接收订单交易成功后的通知) https://host:port/notifyUrl
sign string(255) Y 签名 fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+XxO2jo92dyjKHFU9/4hNECilMooOcH

4.请求报文示例

请求参数示例


{
    "merchantCode": "S820211021094748000001",
    "orderType": "0",
    "orderNum": "T1642593166888",
    "notifyUrl": "your notify url",
    "description": "description",
    "sign": "fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+Xxd1yc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQbYDxZ5WBuU1GZeiJ"
}

``

5.响应参数

参数 类型 必填 描述 示例
platRespCode String Y 请求业务是否成功 FAIL:失败\SUCCESS:成功
platRespMessage String Y 接口响应信息提示 Request Transaction Success
platOrderNum String Y 平台订单号 PI1453242857400963072
orderNum String Y 商户订单号 23645782
name String N 客户名称 customer name
payMoney string(10) N 付款金额(只允许两位小数位) 直联模式(模式2),'platRespCode'为SUCCESS时返回
url String N 收银台链接 请求收银台下单(模式1),'platRespCode'为SUCCESS时返回
payData String N 响应参数 直联模式(模式2),'platRespCode'为SUCCESS时返回

6.成功响应报文示例

下单成功响应报文示例

响应报文示例


{
    "platRespCode": "SUCCESS",
    "platRespMessage": "Request Transaction Success",
    "platOrderNum": "PRE1483771634191044608",
    "orderNum": "T1642593166888",
    "name": "customer name",
    "description": "description",
    "url": "https://bra-openapi.toppay.asia/..."
}

失败响应报文示例

{
    "platRespCode": "FAIL",
    "platRespMessage": "Error message..."
}

7.代收异步通知

进行验签时,要用 商户后台-收付款配置-API配置中提供的平台公钥进行解密!!!

进行验签时,要按照实际回调的参数进行验签,不要使用固定参数

接受异步通知后,需响应 SUCCESS 字符串

否则TopPay将继续发起5次通知。


import com.google.gson.JsonObject;

public class TopPayNotify {
    // 测试账号
    private static final String MCH_CODE = "S820211021094748000001";  // 商户号
    private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  // 平台公钥
    public static void main(String[] args) throws Exception {
        // 代收
        JsonObject notifyBody = new jsonObject();
        boolean verifyResult = TopPayRequestUtil.verifySign(notifyBody,PLAT_PUBLIC_KEY);
        if (verifyResult) {
            // ... 签名验证通过,处理正常的业务逻辑
        } else {
            // ... 签名验证错误
        }
    }
}

<?php

$res = json_decode(file_get_contents('php://input'), true);
$platSign = $res['platSign'];
unset($res['platSign']);
$public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFJ/AmUV4Z8udG8aOBUt/kEwc/DbxF5Gtfw6Y00NHQ4Pz2X2x9IxjUZxn2dnFxmrmhqKNlfwXOqyejhBzi0pSHyGoI4XP9IEfZGO6YkSb9DCY1ZxX8fDl2G+tPCbWYTVO4JutFmzTWgk1Uhhu6L9dlOMUHvZf3/6czA/a9C7azXwIDAQAB';
$decryptSign = public_key_decrypt($platSign, $public_key);

$params = $res;
ksort($params);
$params_str = '';
foreach ($params as $key => $val) {
    $params_str = $params_str . $val;
}

if($params_str == $decryptSign) {
    if($res['code'] == '00') {
        echo 'success';
    }
    else {
        echo 'fail';
    }
}
else {
    echo 'fail';
}

function public_key_decrypt($data, $public_key)
{
    $public_key = '-----BEGIN PUBLIC KEY-----'."\n".$public_key."\n".'-----END PUBLIC KEY-----';
    $data = base64_decode($data);
    $pu_key =  openssl_pkey_get_public($public_key);
    $crypto = '';
    foreach (str_split($data, 128) as $chunk) {
        openssl_public_decrypt($chunk, $decryptData, $pu_key);
        $crypto .= $decryptData;
    }

    return $crypto;
}
参数 必填 描述 示例
code Y 响应状态 00
msg Y 响应信息 SUCCESS
method Y 支付方式 PIX
status Y 支付结果 INIT_ORDER:订单初始化
NO_PAY:未支付
SUCCESS:支付成功
PAY_CANCEL:撤销
PAY_ERROR:支付失败
platOrderNum Y 平台订单号 BK_1563278763273
orderNum Y 商户订单号 T1231511321515
payMoney Y 代收金额 100.12
payFee Y 手续费金额 5.32
name N 客户名称 customer name
description N 描述 description
platSign Y 平台签名 ja6R8eukQY9jc8zrhtf34654ungj7u8sdgdfjfs

8.异步通知报文示例

{
    "code": "00",
    "msg": "SUCCESS",
    "status": "SUCCESS",
    "method": "PIX",
    "platOrderNum": "PRE1483771634191044608",
    "orderNum": "T1642593166888",
    "payMoney": "150",
    "payFee": "150",
    "name": "customer",
    "description": "description",
    "platSign": "ja6R8eukQY9jc8zrhtf34654ungj7u8sdgdfjfs"
}

五、数字代收下单

代收下单支持法币(BRL)与数字货币(USDT/BTC/ETH/TRX)交易 如果您想使用数字货币交易,请设置orderType=1;

通过商户用户ID来区分不同用户的交易

我们的数字代收订单分两个模式:有单模式和无单模式

Ex: 收银台版本(v1.0和v3.0属于有单模式版本;v2.0和v4.0属于无单模式)

Ex: v1.0、v2.0-只展示支付地址

Ex: v3.0、v4.0-展示二维码和支付地址两种方式

使用数字货币进行交易时,币种和链网络是必传项,您需要告诉我们您想使用何种数字货币和链网络(TRC20/BEP20/OMNI/ERC20/TRX)进行交易 我们后续会推出其他币种和网络的交易,敬请期待

1.代码示例

代码示例仅供参考,具体参数说明请参考请求参数说明


import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Map;
import java.util.TreeMap;

public class TopPayDemo {
  // 测试账号
  private static final String MCH_CODE = "S820211021094748000001";  // 商户号
  private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  // 平台公钥
  private static final String MCH_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJU8gKFKD0luIYx7X8+JRdCIE0UDBctS6LjXxWLEv/EO7jDBTid6zYP1KmNgpd2DAWWtBFBSQ+gcNwVZZSBHJiSDqVvvJVs2FEbeBvfdv4X93+IYRAXksBasSW5Tpdshbo82pVL4V7wuKCuFLk9UxBHbpQjWAbfyF66RmwIbZD71AgMBAAECgYBjPe7UU2nDDSfmQg0++CyjNjqKRC5QPfxhH6w1uF1kMueXKJWOj42n2RutJpJmsj31nY8m0u4xpsG4HvCu/GGSFhhKZCHLvzp41oY2ubYj9nuFNU//81LycQjulWo2y0UUBY0k2piEt+SwPaiUNbT6nMxNMjlnjRe2okp/3rw+KQJBANG3YlZWoVbCEqzy64bJJLxiPsCA5ErGB0NzRGitq44xkhqGtR8ZZQyVz40pruNa58d73O2xyJSy5+fmZGn4E+sCQQC2LBnguj0CSCKub0mPDcunTTz9V79VXBBZdlB1/YGmRUx2s4sQrJNZS7rL4EqBQ3maIRnG+s+AXCSTfsYrV6CfAkEAxugnVfpelhoGepEAgNuggyivmgfl/2Gpm/jk5l/qOjib+ZrQiQmeBPzGWX4yiSM8eMDrP2sC8r5pJFMp5DRONwJBAJ4n4XuSFJ9jgwCPy3vvzSv9SYLk6E6yM9uHdUlKgoGYzk6Lh6M9QFuY/J49plFdBDiEnj16yCU3WeXXfTJpzB8CQQDMNMR/rIOTE9xGybS3mlQbt22AUnO6XhupWcckEKW4nPGxATwYBQzCY3i/9FTGN0vA+9ZPC2cwHtNxI2kXf3Vp";  // 商户私钥
  private static final String payUrl = "https://bra-openapi.toppay.asia/gateway/prepaidOrder";
  private static final String cashUrl = "https://bra-openapi.toppay.asia/gateway/cash";
  private static final String payNotify = "your notify url";
  private static final String cashNotify = "your notify url";

  public static void main(String[] args) throws Exception {
    // 代收
    pay();
  }
  private static void pay() throws Exception {
    Map<String, String> requestParams = new TreeMap<>();
    requestParams.put("merchantCode", MCH_CODE);
    requestParams.put("orderType", "1"); // 订单类型(1-数字货币交易)
    requestParams.put("mchUserId", "100001"); // 商户用户ID
    requestParams.put("method", "USDT"); // 数字货币类型USDT/BTC/ETH/TRX(可不传)
    requestParams.put("orderNum", "T1642592278863"); // 商户订单号(有单模式必传,无单模式不传)
    requestParams.put("payMoney", "1.000001");  // 订单金额(最大支持6位小数)
    requestParams.put("name", "JackMa");// 客户名称
    requestParams.put("notifyUrl", payNotify);// 回调地址
    requestParams.put("currency", "USDT"); // 数字货币币种(如果指定了method,则必传)
    requestParams.put("netWork", "TRC20"); // 链网络(如果指定了method,则必传)
    requestParams.put("orderVersion", "v1.0"); // 收银台版本(v1.0和v3.0属于有单模式版本;v2.0和v4.0属于无单模式)

    StringBuilder stringBuilder = new StringBuilder();
    for (String key : requestParams.keySet()) {
      stringBuilder.append(requestParams.get(key));  // 拼接参数
    }

    String keyStr = stringBuilder.toString();  // 得到待加密的字符串
    System.out.println("keyStr:" + keyStr);
    String signedStr = TopPayRequestUtil.privateEncrypt(keyStr, TopPayRequestUtil.getPrivateKey(MCH_PRIVATE_KEY));  // 私钥加密
    requestParams.put("sign", signedStr);

    String postJson = new Gson().toJson(requestParams);
    System.out.println("Post Json Params:" + postJson);

    String responseJson = TopPayRequestUtil.doPost(payUrl, postJson);  // 发送 post json请求
    System.out.println("Response Msg:" + responseJson);
  }
}


<?php
    // 平台公钥,从密钥配置中获取
    // platform public key, from Secret key config
    $platPublicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiaKBgQCcEUIvQ/5L+SWbHOeR8VFeZvLbUk7V7OeEAQlQwIVLSZMTef3KtsOKKAsUYPf/aAcKRzZZXECODsPQiDPcdZvM/rFkgrFWkR7lPjTj5SiPxGaiK2Z2sne7A8aDF7fV/D7lfmEwNdZ7FWKVEB84/81BHnlGUwb5HpRTISG+boSO6wIDAQAB';
    // 商户私钥,商户自己生成
    // mchchant private key
    $mchPrivateKey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMigm7rtWnTeNagwFzGTH+Uw1ypbiy7VhIoFJbgSYSSHdCaXWdT/l2+2fQlEYgAETVZ/IXB29MCnrf3O0dwRFXiipIbsm5zyqSLiS6cKXe8zN1/PlQWUbEt5wyWm0GADB/4bV6eu6gA7sGXmjQqrzfKZkcie3aK7+7ry1NFxTI51AgMBAAECgYEAklqXQAVlt1tiSQ7L3J425jp6u6uMHN4lkYmvuleuBbfKQ1yla3wIPLYjAF+iHeEFidOz0Rb19JRdmIkHDkJoJg2W27LvO6RdUwzgRnsuA3OuNz97w08B3aXXbPmB91nTFjKSlUsbh3IQWP71noxW+iKn844EW5hC5Gvn4L3quAECQQDrz1r0VKIbBSBB2aLuz1XyD/TBT2aRhvOKf0XtTRiQhNjtJxoQmvNbbhvUwj8an7HyCuihAbdbrC2ymFFyOSDZAkEA2c4Yudi48C6COrroi1cWgPlEFeGJXP/V1k5loZ1n2vstYAGPhAB4wUnFBLDvMqaBzWJt7MRkiazT8KnBQCDY/QJAMXpNlEyZwt+deBOpO0BnwSWV7mWxmMFfImU4D+WITPbC7aexsWBBxaJh1o93XCe715RwYTAR//stj3akSDoyaQJAa4FKuxC51/Nc3Fg9R+modeiTLqmv/3NXvPvdNjRXesLX1rduex0wfVdII9ShfEKrdxDKaT9W0NyzD+r6NAkCkQJBAMAnTgPYf0f7rh417GdoP7R7Nwi8KBKwPHlmfRukibOQlKt9xjqpsKJwglLn8pcnXbYbswXIdqzuBvIGAe3OWNg=';
    // 商户ID,从商户信息中获取
    // merchent ID from idntask, from User info
    $merchantCode = 'YOUR_MERCHANT_CODE_HERE';
    // 商户用户ID 
    $mchUserId = 'YOUR_MERCHANT_USDR_ID';
    // 支付金额 pay money(最大支持6位小数)
    $payMoney = '1.000001';
    // 支付方式 参考: (USDT/BTC/ETH/TRX)
    $method = 'USDT';
    //订单类型(1-数字货币交易)
    $orderType = '1';
    // 商户订单号
    $orderNum = 'T'.date("YmdHis",time());
    // 在付款确认页面显示的转账对象
    // Display name on bank confirmation display
    $name = 'Neo';
    // 回调地址
    // url for callback
    $notifyUrl = 'http://example.com/callback';
    // 订单过期时间 Order expiration time
    // 数字货币币种(如果指定了method,则必传)
    $currency = 'USDT';
    // 链网络(如果指定了method,则必传)
    $netWork = 'TRC20';
    // 收银台版本(v1.0和v3.0属于有单模式版本;v2.0和v4.0属于无单模式)
    $orderVersion = 'v1.0';
    $params = array(
        'merchantCode' => $merchantCode,
        'orderType' => $orderType,
        'mchUserId' => $mchUserId,
        'method' => $method,
        'orderNum' => $orderNum,
        'payMoney' => $payMoney,
        'name' => $name,
        'notifyUrl' => $notifyUrl,
        'currency' => $currency,
        'netWork' => $netWork,
        'orderVersion' => $orderVersion
    );

    ksort($params);
    $params_str = '';
    foreach ($params as $key => $val) {
        $params_str = $params_str . $val;
    }


    $sign = pivate_key_encrypt($params_str, $mchPrivateKey);

    $params['sign'] = $sign;

    $params_string = json_encode($params);
    $url = 'https://bra-openapi.toppay.asia/gateway/prepaidOrder';
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($params_string))
    );
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

    //execute post
    $request = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if($httpCode == 200)
    {
        $result = json_decode($request, true);
        echo "platRespCode :". $result['platRespCode'] . "\n";
        echo "platRespMessage :". $result['platRespMessage'] . "\n";
        echo "mchUserId :". $result['mchUserId'] . "\n";
        echo "platOrderNum :". $result['platOrderNum'] . "\n";
        echo "orderNum :". $result['orderNum'] . "\n";
        echo "method :". $result['method'] . "\n";
        echo "name :". $result['name'] . "\n";
        echo "url :". $result['url'] . "\n";
        echo "payMoney :". $result['payMoney'] . "\n";
        echo "currency :". $result['currency'] . "\n";
        echo "netWork :". $result['netWork'] . "\n";
        echo "orderVersion :". $result['orderVersion'] . "\n";
        echo "platSign :". $result['platSign'] . "\n";

        $decryptStr = public_key_decrypt($result['platSign'], $platPublicKey);
        echo "decryptStr :". $decryptStr . "\n";
    }
    else {
        echo $httpCode;
    }

    function pivate_key_encrypt($data, $pivate_key)
    {
        $pivate_key = '-----BEGIN PRIVATE KEY-----'."\n".$pivate_key."\n".'-----END PRIVATE KEY-----';
        $pi_key = openssl_pkey_get_private($pivate_key);
        $crypto = '';
        foreach (str_split($data, 117) as $chunk) {
            openssl_private_encrypt($chunk, $encryptData, $pi_key);
            $crypto .= $encryptData;
        }

        return base64_encode($crypto);
    }

    function public_key_decrypt($data, $public_key)
    {
        $public_key = '-----BEGIN PUBLIC KEY-----'."\n".$public_key."\n".'-----END PUBLIC KEY-----';
        $data = base64_decode($data);
        $pu_key =  openssl_pkey_get_public($public_key);
        $crypto = '';
        foreach (str_split($data, 128) as $chunk) {
            openssl_public_decrypt($chunk, $decryptData, $pu_key);
            $crypto .= $decryptData;
        }

        return $crypto;
    }

2.请求地址

POST https://bra-openapi.toppay.asia/gateway/prepaidOrder

注:所有的参数中,不要填写中文!!!

3.数字代收请求参数

参数 类型 必填 描述 示例
merchantCode string(32) Y 商户ID,在商户平台获取 S820211021094748000001
orderType string(10) Y 订单类型 1-数字货币交易
mchUserId string(32) Y 商户用户ID(您的用户唯一标识,请勿传特殊字符、空格等) 100001
method string(10) N 支付方式(如果需要指定支付方式,可以在右侧的示例支付方式列表中选择其一;如果不指定支付方式,则可不传该参数,可以在我们的收银台页面中选择某个支付方式。) USDT
BTC
ETH
TRX
(备注:数字货币对应的支付方式)
currency string(14) N 数字货币币种(如果指定支付方式,则必传) USDT
netWork string(30) N 链网络(如果指定支付方式,则必传) TRC20
orderNum string(32) N 商户订单号(有单模式必传,无单模式不传) TEST123456789
payMoney int(10) Y 付款金额(最大允许6位小数) 1.000001
notifyUrl string(100) Y 订单支付成功异步通知地址(用来接收订单交易成功后的通知) https://host:port/notifyUrl
name string(16) Y 客户名称 Jack
orderVersion string(10) N 收银台模式必传
API模式不传
收银台版本(v1.0和v3.0属于有单模式版本;v2.0和v4.0属于无单模式)
v1.0
sign string(255) Y 签名 fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+XxO2jo92dyjKHFU9/4hNECilMooOcH

4.请求报文示例

{
    "merchantCode": "S820211021094748000001",
    "mchUserId": "100001",
    "orderType": "1",
    "method": "USDT",
    "currency": "USDT",
    "netWork": "TRC20",
    "orderNum": "T1642593166888",
    "payMoney": "1.000001",
    "notifyUrl": "your notify url",
    "name": "JackMa",
    "sign": "fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+Xxd1yc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQbYDxZ5WBuU1GZeiJ"
}

5.响应参数

参数 类型 必填 描述 示例
platRespCode String Y 请求业务是否成功 FAIL:失败\SUCCESS:成功
platRespMessage String Y 接口响应信息提示 Request Transaction Success
mchUserId String Y 商户用户ID(唯一标识) 10001
platOrderNum String Y 平台订单号 PI1453242857400963072
orderNum String Y 商户订单号 23645782
currency String Y 币种 USDT
netWork String Y 链网络 TRC20
payMoney string Y 支付金额 1.000001
url String Y 支付连接 'platRespCode'为'SUCCESS'时返回

6.成功响应报文示例

{
  "platRespCode": "SUCCESS",
  "url": "https://id-openapi.toppay.asia/cashier?orderNum=PRE1626161123977859130123",
  "mchUserId": "10001",
  "platOrderNum": "PRE1626161123977859130",
  "payMoney": "1.000001",
  "currency": "USDT",
  "netWork": "TRC20",
  "platSign": "U79dat+VITTQ8xAI1wsxtFlK2DwcVvZ6ypC+QFIDaEy4oNxZECRy+INAcqIWZHL1m6/pge1SOEbVss8ZZPsZbtRZiefhtH+6qyu99MU+1rGdu+oSXSNhP4+2aDucg/SylS3+TkjKJf+IowTX7d2TJEbDh011JLOc9zglkhqVEc0FVIbBmKInZ/+TaLhDfFt6Sqmf85GCP7V5JwW1arIUwUjlGkCs3TtvHfpDVaMi2fl+cfNGYSrCOZfursVwjiwJmka+44FyaGrrEOE9tKwODiZo/jg9FLZnp2eRZwIIwef8CFg7eqx13uo/y61g0D9pzH17IVcr7Mc8BrweO7X4Pw==",
  "platRespMessage": "Request Transaction Success"
}

失败响应报文示例

{
    "platRespCode": "FAIL",
    "platRespMessage": "the orderNum already exists"
}

7.数字代收异步通知

请注意:当前业务只有在订单支付成功的时候才有回调通知接收到。

数字货币有两种特殊情况:无单模式以及支付金额与下单金额不符,为此我们将异步通知进行了调整,如下:

1.如果是上述特殊情况,我们会生成一笔新的成功订单进行通知,您需要根据通知的信息进行验证,并生成新的订单;

2.根据通知的商户订单号(orderNum)查询是否您的系统存在该订单,建议您在下单成功时同时存储我们的平台订单号(platOrderNum),做双步校验;

3.根据通知的参数specialStatus(0-默认,1-特殊状态)判断,如果为1则判断为上述特殊情况.

TopPay结果异步通知后,需响应 SUCCESS字符串,不包含引号,不是Json格式。

否则TopPay将继续向下游发起5次通知。


import com.google.gson.JsonObject;

public class TopPayNotify {
    // 测试账号
    private static final String MCH_CODE = "S820211021094748000001";  // 商户号
    private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  // 平台公钥
    public static void main(String[] args) throws Exception {
        // 代收
        JsonObject notifyBody = new jsonObject();
        boolean verifyResult = TopPayRequestUtil.verifySign(notifyBody,PLAT_PUBLIC_KEY);
        if (verifyResult) {
            // ... 签名验证通过,处理正常的业务逻辑
        } else {
            // ... 签名验证错误
        }
    }
}

<?php

$res = json_decode(file_get_contents('php://input'), true);
$platSign = $res['platSign'];
unset($res['platSign']);
$public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFJ/AmUV4Z8udG8aOBUt/kEwc/DbxF5Gtfw6Y00NHQ4Pz2X2x9IxjUZxn2dnFxmrmhqKNlfwXOqyejhBzi0pSHyGoI4XP9IEfZGO6YkSb9DCY1ZxX8fDl2G+tPCbWYTVO4JutFmzTWgk1Uhhu6L9dlOMUHvZf3/6czA/a9C7azXwIDAQAB';
$decryptSign = public_key_decrypt($platSign, $public_key);

$params = $res;
ksort($params);
$params_str = '';
foreach ($params as $key => $val) {
    $params_str = $params_str . $val;
}

if($params_str == $decryptSign) {
    if($res['code'] == '00') {
        echo 'success';
    }
    else {
        echo 'fail';
    }
}
else {
    echo 'fail';
}

function public_key_decrypt($data, $public_key)
{
    $public_key = '-----BEGIN PUBLIC KEY-----'."\n".$public_key."\n".'-----END PUBLIC KEY-----';
    $data = base64_decode($data);
    $pu_key =  openssl_pkey_get_public($public_key);
    $crypto = '';
    foreach (str_split($data, 128) as $chunk) {
        openssl_public_decrypt($chunk, $decryptData, $pu_key);
        $crypto .= $decryptData;
    }

    return $crypto;
}
参数 描述 示例
code 响应状态 00
msg 响应信息 SUCCESS
mchUserId 商户用户ID(唯一标识) 10001
platOrderNum 平台订单号 BK_1563278763273
orderNum 商户订单号 T1231511321515
method 支付方式 USDT
currency 币种 USDT
netWork 链网络 TRC20
status 支付结果 INIT_ORDER: 订单初始化
NO_PAY: 未支付
SUCCESS: 支付成功
PAY_CANCEL: 撤销
PAY_ERROR: 支付失败
payMoney 代收金额 100000
payFee 手续费 500
hashCode 交易哈希 5e5c356af0ewrhgnf3d757h8a6a5506cc66354620
sendAddress 发送地址 TDBbbeAB32WE576DVGE82GEC5BhsZs4
specialStatus 特殊状态(0-默认,1-特殊状态) 0
platSign 平台签名 ja6R8eukQY9jc8z

8.异步通知报文示例

{
  "code": "00",
  "msg": "SUCCESS",
  "mchUserId": "100001",
  "platOrderNum": "PRE1483771634191044608",
  "orderNum": "T1642593166888",
  "method": "USDT",
  "currency": "USDT",
  "netWork": "TRC20",
  "status": "SUCCESS",
  "payMoney": "1.0000001",
  "payFee": "0.000016",
  "hashCode": "5e5c356af0ewrhgnf3d757h8a6a5506cc66354620",
  "sendAddress": "TDBbbeAB32WE576DVGE82GEC5BhsZs4",
  "specialStatus": "0",
  "platSign": "ja6R8eukQY9jc8zrhtf34654ungj7u8sdgdfjfs"
}

六、法币(BRL)代付下单

1.代码示例

代码示例仅供参考,具体参数说明请参考请求参数说明

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.util.Map;
import java.util.TreeMap;
public class TopPayDemo {
  private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  // 平台公钥
  private static final String MCH_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJU8gKFKD0luIYx7X8+JRdCIE0UDBctS6LjXxWLEv/EO7jDBTid6zYP1KmNgpd2DAWWtBFBSQ+gcNwVZZSBHJiSDqVvvJVs2FEbeBvfdv4X93+IYRAXksBasSW5Tpdshbo82pVL4V7wuKCuFLk9UxBHbpQjWAbfyF66RmwIbZD71AgMBAAECgYBjPe7UU2nDDSfmQg0++CyjNjqKRC5QPfxhH6w1uF1kMueXKJWOj42n2RutJpJmsj31nY8m0u4xpsG4HvCu/GGSFhhKZCHLvzp41oY2ubYj9nuFNU//81LycQjulWo2y0UUBY0k2piEt+SwPaiUNbT6nMxNMjlnjRe2okp/3rw+KQJBANG3YlZWoVbCEqzy64bJJLxiPsCA5ErGB0NzRGitq44xkhqGtR8ZZQyVz40pruNa58d73O2xyJSy5+fmZGn4E+sCQQC2LBnguj0CSCKub0mPDcunTTz9V79VXBBZdlB1/YGmRUx2s4sQrJNZS7rL4EqBQ3maIRnG+s+AXCSTfsYrV6CfAkEAxugnVfpelhoGepEAgNuggyivmgfl/2Gpm/jk5l/qOjib+ZrQiQmeBPzGWX4yiSM8eMDrP2sC8r5pJFMp5DRONwJBAJ4n4XuSFJ9jgwCPy3vvzSv9SYLk6E6yM9uHdUlKgoGYzk6Lh6M9QFuY/J49plFdBDiEnj16yCU3WeXXfTJpzB8CQQDMNMR/rIOTE9xGybS3mlQbt22AUnO6XhupWcckEKW4nPGxATwYBQzCY3i/9FTGN0vA+9ZPC2cwHtNxI2kXf3Vp";  // 商户私钥
  private static final String cashUrl = "https://bra-openapi.toppay.asia/gateway/cash";
  private static final String cashNotify = "http://host:port/notify";

  public static void main(String[] args) throws Exception {
    cash();
  }
  private static void cash() throws Exception {
    Map<String, String> requestParams = new TreeMap<>();
    requestParams.put("merchantCode", "S820211021094748000001");// 商户ID
    requestParams.put("orderNum", "186888188666"); // 商户订单号
    requestParams.put("method", "DISBURSEMENT"); // 收款方式(默认传DISBURSEMENT)
    requestParams.put("orderType", "0"); // 订单类型(0-法币(BRL)交易)
    requestParams.put("money", "125.12"); // 订单金额,支持两位小数位
    requestParams.put("feeType", "0");  //  手续费类型(0-帐内扣除,1-帐外扣除)
    requestParams.put("pixType", "CPF");     // PIX类型
    requestParams.put("pixAccount", "123123123");     // PIX账号
    requestParams.put("taxNumber", "123123123");     // 税号
    requestParams.put("name", "custmener");  // 客户名称
    requestParams.put("description", "description");    // 描述
    requestParams.put("notifyUrl", cashNotify);  // 回调地址
    StringBuilder stringBuilder = new StringBuilder();
    for (String key : requestParams.keySet()) {
      stringBuilder.append(requestParams.get(key));  // 拼接参数
    }

    String keyStr = stringBuilder.toString();  // 得到待加密的字符串
    System.out.println("keyStr:" + keyStr);
    String signedStr = TopPayRequestUtil.privateEncrypt(keyStr, TopPayRequestUtil.getPrivateKey(MCH_PRIVATE_KEY));  // 私钥加密
    requestParams.put("sign", signedStr);

    String postJson = new Gson().toJson(requestParams);
    System.out.println("Post Json Params:" + postJson);

    String responseJson = TopPayRequestUtil.doPost(cashUrl, postJson);  // 发送 post json请求
    System.out.println("Response Msg:" + responseJson);

    boolean pass = TopPayRequestUtil.verifySign(new Gson().fromJson(responseJson, JsonObject.class), PLAT_PUBLIC_KEY);  // 签名验证
    if (pass) {
      // ... 签名验证通过,执行正常的业务逻辑
    } else {
      // ... 签名验证错误
    }
  }
}


<?php
    // 平台公钥,从密钥配置中获取
    // platform public key, from Secret key config
    $platPublicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiaKBgQCcEUIvQ/5L+SWbHOeR8VFeZvLbUk7V7OeEAQlQwIVLSZMTef3KtsOKKAsUYPf/aAcKRzZZXECODsPQiDPcdZvM/rFkgrFWkR7lPjTj5SiPxGaiK2Z2sne7A8aDF7fV/D7lfmEwNdZ7FWKVEB84/81BHnlGUwb5HpRTISG+boSO6wIDAQAB';
    // 商户私钥,商户自己生成
    // mchchant private key
    $mchPrivateKey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMigm7rtWnTeNagwFzGTH+Uw1ypbiy7VhIoFJbgSYSSHdCaXWdT/l2+2fQlEYgAETVZ/IXB29MCnrf3O0dwRFXiipIbsm5zyqSLiS6cKXe8zN1/PlQWUbEt5wyWm0GADB/4bV6eu6gA7sGXmjQqrzfKZkcie3aK7+7ry1NFxTI51AgMBAAECgYEAklqXQAVlt1tiSQ7L3J425jp6u6uMHN4lkYmvuleuBbfKQ1yla3wIPLYjAF+iHeEFidOz0Rb19JRdmIkHDkJoJg2W27LvO6RdUwzgRnsuA3OuNz97w08B3aXXbPmB91nTFjKSlUsbh3IQWP71noxW+iKn844EW5hC5Gvn4L3quAECQQDrz1r0VKIbBSBB2aLuz1XyD/TBT2aRhvOKf0XtTRiQhNjtJxoQmvNbbhvUwj8an7HyCuihAbdbrC2ymFFyOSDZAkEA2c4Yudi48C6COrroi1cWgPlEFeGJXP/V1k5loZ1n2vstYAGPhAB4wUnFBLDvMqaBzWJt7MRkiazT8KnBQCDY/QJAMXpNlEyZwt+deBOpO0BnwSWV7mWxmMFfImU4D+WITPbC7aexsWBBxaJh1o93XCe715RwYTAR//stj3akSDoyaQJAa4FKuxC51/Nc3Fg9R+modeiTLqmv/3NXvPvdNjRXesLX1rduex0wfVdII9ShfEKrdxDKaT9W0NyzD+r6NAkCkQJBAMAnTgPYf0f7rh417GdoP7R7Nwi8KBKwPHlmfRukibOQlKt9xjqpsKJwglLn8pcnXbYbswXIdqzuBvIGAe3OWNg=';
    // 商户ID,从商户信息中获取
    // merchent ID from idntask, from User info
    $merchantCode = 'YOUR_MERCHANT_CODE_HERE';
    // 商户订单号
    $orderNum = 'T'.date("YmdHis",time());
    // 支付方式 
    // Payment method 
    $method = 'DISBURSEMENT';
    //订单类型(0-法币(BRL)交易)
    $orderType = '0';
    // 出款金额 withdraw money
    $money = '20000';
    // 手续费类型(0-帐内扣除,1-帐外扣除)
    $feeType = '1';
    // PIX类型
    $pixType = 'CPF';
    // PIX账号
    $pixAccount = '123123123123';
    // 税号
    $taxNumber = '45324532434';
    // 描述
    $description = 'description';
    // 回调地址
    // url for callback
    $notifyUrl = 'http://example.com/callback';
    $params = array(
        'merchantCode' => $merchantCode,
        'orderType' => $orderType,
        'method' => $method,
        'orderNum' => $orderNum,
        'money' => $money,
        'feeType' => $feeType,
        'name' => $name,
        'pixType' => $pixType,
        'pixAccount' => $pixAccount,
        'taxNumber' => $taxNumber,
        'notifyUrl' => $notifyUrl,
        'description' => $description
    );

    ksort($params);
    $params_str = '';
    foreach ($params as $key => $val) {
        $params_str = $params_str . $val;
    }


    $sign = pivate_key_encrypt($params_str, $mchPrivateKey);

    $params['sign'] = $sign;

    $params['name'] = $name;
    $params['description'] = $description;

    $params_string = json_encode($params);
    $url = 'https://bra-openapi.toppay.asia/gateway/prepaidOrder';
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($params_string))
    );
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

    //execute post
    $request = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if($httpCode == 200)
    {
        $result = json_decode($request, true);
        echo "platRespCode :". $result['platRespCode'] . "\n";
        echo "platRespMessage :". $result['platRespMessage'] . "\n";
        echo "platOrderNum :". $result['platOrderNum'] . "\n";
        echo "orderNum :". $result['orderNum'] . "\n";
        echo "status :". $result['status'] . "\n";
        echo "statusMsg :". $result['statusMsg'] . "\n";
        echo "money :". $result['money'] . "\n";
        echo "feeType :". $result['feeType'] . "\n";
        echo "name :". $result['name'] . "\n";
        echo "pixType :". $result['pixType'] . "\n";
        echo "pixAccount :". $result['pixAccount'] . "\n";
        echo "taxNumber :". $result['taxNumber'] . "\n";
        echo "description :". $result['description'] . "\n";
        echo "platSign :". $result['platSign'] . "\n";

        $decryptStr = public_key_decrypt($result['platSign'], $platPublicKey);
        echo "decryptStr :". $decryptStr . "\n";
    }
    else {
        echo $httpCode;
    }

    function pivate_key_encrypt($data, $pivate_key)
    {
        $pivate_key = '-----BEGIN PRIVATE KEY-----'."\n".$pivate_key."\n".'-----END PRIVATE KEY-----';
        $pi_key = openssl_pkey_get_private($pivate_key);
        $crypto = '';
        foreach (str_split($data, 117) as $chunk) {
            openssl_private_encrypt($chunk, $encryptData, $pi_key);
            $crypto .= $encryptData;
        }

        return base64_encode($crypto);
    }

    function public_key_decrypt($data, $public_key)
    {
        $public_key = '-----BEGIN PUBLIC KEY-----'."\n".$public_key."\n".'-----END PUBLIC KEY-----';
        $data = base64_decode($data);
        $pu_key =  openssl_pkey_get_public($public_key);
        $crypto = '';
        foreach (str_split($data, 128) as $chunk) {
            openssl_public_decrypt($chunk, $decryptData, $pu_key);
            $crypto .= $decryptData;
        }

        return $crypto;
    }

2.请求地址

POST https://bra-openapi.toppay.asia/gateway/cash

3.请求参数

参数 类型 必填 描述 示例
merchantCode string Y 商户ID,在商户平台获取 S820211021094748000001
orderType string(10) Y 订单类型 0-法币(BRL)交易
method string(10) Y 收款方式 默认传DISBURSEMENT
orderNum string Y 商户订单号 10000001
money string Y 代付金额 150.12(支持两位小数点位)
feeType String Y 手续费类型 0:代付金额内扣除,1:手续费另计
name String Y 客户名称(真实姓名,增加成功率) Jack
pixType string Y PIX类型 CPF(11位数字)
CNPJ(14位数字)
PHONE(+55开头,号码10-11位)
EMAIL(邮箱格式)
EVP
pixAccount string Y PIX账号 以pixType为准,传递对应的账号即可;pixType为CPF,则pixAccount传CPF;pixType为PHONE,则pixAccount传PHONE;以此类推...
taxNumber string Y 税号 CPF/CNPJ税号
notifyUrl string Y 回调地址 https://123123.com
description string N 按请求参数返回 description
sign string Y 签名 Yg+ePvTFhiRrARcZKBcRG0l89rqisPIuZQStYqBIwSMPaqvqbc3dFevgS9jt

4.请求报文示例

{
  "merchantCode": "S820211021094748000001",
  "orderType": "0",
  "method": "DISBURSEMENT",
  "orderNum": "186888188666",
  "money": "100",
  "feeType": "1",
  "name": "test cash name",
  "pixType": "CPF",
  "pixAccount": "123456789",
  "taxNumber": "123456789",
  "notifyUrl": "your notify url",
  "description": "test cash",
  "sign": "Yg+ePvTFhiRrARcZKBcRG0l89rqisPIuZQStYqBIwSMPaqwH77qRXI1J+jElOBpa"
}

5.响应参数

参数 类型 必填 描述 示例
platRespCode String Y 请求业务是否成功 FAIL:失败\SUCCESS:成功
platRespMessage String Y 接口响应信息提示 请求成功
platOrderNum String Y 平台订单号 PI1453242857400963072
orderNum String Y 商户订单号 23645782
status int Y 订单状态 0-待处理
1-处理中
2-代付成功
4-代付失败
5-银行代付中
statusMsg String Y 订单状态信息 Apply
money string Y 代付金额 150000
feeType String Y 手续费类型 0:订单内扣除,1:手续费另计
fee String Y 手续费 500
name String Y 客户名称 Jack
pixType string Y PIX类型 CPF(11位数字)
CNPJ(14位数字)
PHONE(+55开头,号码10-11位)
EMAIL(邮箱格式)
EVP
pixAccount string Y PIX账号 以pixType为准,传递对应的账号即可;pixType为CPF,则pixAccount传CPF;pixType为PHONE,则pixAccount传PHONE;以此类推...
taxNumber string Y 税号 CPF/CNPJ税号
description String Y 按请求参数返回 代付下单
platSign String Y 签名 PI1453242857400963072

6.代付响应报文示例

{
  "platRespCode": "SUCCESS",
  "platRespMessage": "Request success",
  "platOrderNum": "W0620220119174331000001",
  "orderNum": "186888188666",
  "status": 0,
  "statusMsg": "Apply",
  "money": "50000",
  "feeType": "0",
  "fee": "1",
  "name": "test cash name",
  "pixType": "CPF",
  "pixAccount": "123456",
  "taxNumber": "123456",
  "description": "test cash",
  "platSign": "E5uNF7B9NXyhtlRo2I7/KVHN4Sbz0c3VbwCLpH3vjUpv6Cai+bmJA/Q8dVE2RJRe1+dsbzg=="
}

7.代付异步通知

进行验签时,要用 商户后台-收付款配置-API配置中提供的平台公钥进行解密!!!

TopPay结果异步通知后,需响应 SUCCESS 字符串.

否则TopPay将继续向下游发起5次通知。

参数 描述 示例
platOrderNum 平台订单号 BK_1563278763273
orderNum 商户订单号 T1231511321515
money 代付金额 150.12(支持小数点)
feeType 手续费类型 0:代付金额内扣除,1:手续费另计
fee 手续费 500
name 客户名称 Neo
pixType PIX类型 CPF(11位数字)
CNPJ(14位数字)
PHONE(+55开头,号码10-11位)
EMAIL(邮箱格式)
EVP
pixAccount PIX账号 以pixType为准,传递对应的账号即可;pixType为CPF,则pixAccount传CPF;pixType为PHONE,则pixAccount传PHONE;以此类推...
taxNumber 税号 CPF/CNPJ税号
status 订单状态 0-待处理
1-处理中
2-代付成功
4-代付失败
5-银行代付中
statusMsg 订单状态描述 Payout Success
description 订单描述 商户上传原样返回
platSign 平台签名 ja6R8eukQY9jc8...

8.异步通知报文示例

{
  "platOrderNum": "W0620220119174331000001",
  "orderNum": "186888188666",
  "money": "50000",
  "feeType": "0",
  "fee": "7",
  "name": "test cash name",
  "pixType": "CPF",
  "pixAccount": "123456",
  "taxNumber": "123456",
  "status": "2",
  "statusMsg": "SUCCESS",
  "description": "test cash",
  "platSign": "LGEpz2LjbZ6Iyvn+zLc/+t26AaH0aEhHVD62lSCdo6XIkAg86AUncCvmym62wVoE3r2+dHnv27qi/01UQDcqFK8DYioRCcydYSjB4QRVezG3fcZlhWrACmWGacnXkE7p5zChL7pK5h0HuBhbo1zKt4FunQR6QMmcBVfv7YfB3W0"

}

七、数字代付下单

代付下单支持法币(BRL)与数字货币(USDT/BTC/ETH/TRX)交易 如果您想使用数字货币交易,请设置orderType=1,并传入对应的货币币种Currency和网络netWork 使用数字货币进行交易时,币种和链网络是必传项 您需要告诉我们您想使用何种数字币和链网络(TRC20/BEP20/OMNI/ERC20/TRX)进行交易 当使用数字货币进行交易时,您需要传入您的inAddress用以收取数字货币 我们后续会推出其他币种和网络的交易,敬请期待

1.代码示例

代码示例仅供参考,具体参数说明请参考请求参数说明

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.util.Map;
import java.util.TreeMap;
public class TopPayDemo {
  private static final String MCH_CODE = "S820211021094748000001";  // 商户号
  private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  // 平台公钥
  private static final String MCH_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJU8gKFKD0luIYx7X8+JRdCIE0UDBctS6LjXxWLEv/EO7jDBTid6zYP1KmNgpd2DAWWtBFBSQ+gcNwVZZSBHJiSDqVvvJVs2FEbeBvfdv4X93+IYRAXksBasSW5Tpdshbo82pVL4V7wuKCuFLk9UxBHbpQjWAbfyF66RmwIbZD71AgMBAAECgYBjPe7UU2nDDSfmQg0++CyjNjqKRC5QPfxhH6w1uF1kMueXKJWOj42n2RutJpJmsj31nY8m0u4xpsG4HvCu/GGSFhhKZCHLvzp41oY2ubYj9nuFNU//81LycQjulWo2y0UUBY0k2piEt+SwPaiUNbT6nMxNMjlnjRe2okp/3rw+KQJBANG3YlZWoVbCEqzy64bJJLxiPsCA5ErGB0NzRGitq44xkhqGtR8ZZQyVz40pruNa58d73O2xyJSy5+fmZGn4E+sCQQC2LBnguj0CSCKub0mPDcunTTz9V79VXBBZdlB1/YGmRUx2s4sQrJNZS7rL4EqBQ3maIRnG+s+AXCSTfsYrV6CfAkEAxugnVfpelhoGepEAgNuggyivmgfl/2Gpm/jk5l/qOjib+ZrQiQmeBPzGWX4yiSM8eMDrP2sC8r5pJFMp5DRONwJBAJ4n4XuSFJ9jgwCPy3vvzSv9SYLk6E6yM9uHdUlKgoGYzk6Lh6M9QFuY/J49plFdBDiEnj16yCU3WeXXfTJpzB8CQQDMNMR/rIOTE9xGybS3mlQbt22AUnO6XhupWcckEKW4nPGxATwYBQzCY3i/9FTGN0vA+9ZPC2cwHtNxI2kXf3Vp";  // 商户私钥
  private static final String cashUrl = "https://bra-openapi.toppay.asia/gateway/cash";
  private static final String cashNotify = "http://host:port/notify";

  public static void main(String[] args) throws Exception {
    cash();
  }
  private static void cash() throws Exception {
    Map<String, String> requestParams = new TreeMap<>();
    requestParams.put("merchantCode", MCH_CODE);
    requestParams.put("orderNum", "186888188666"); // 商户订单号
    requestParams.put("method", "USDT"); // 收款方式(USDT/BTC/ETH/TRX)
    requestParams.put("orderType", "1"); // 订单类型(1-数字货币交易)
    requestParams.put("money", "1.000001"); // 订单金额,最大支持6位小数
    requestParams.put("feeType", "1");  //  手续费类型(0:代付金额内扣除,1:手续费另计)
    requestParams.put("name", "test cash name");  // 客户名称
    requestParams.put("description", "test cash");    // 描述
    requestParams.put("notifyUrl", cashNotify);  // 回调地址
    requestParams.put("currency", "USDT"); // 数字货币币种(当orderType=1(数字货币交易)时,是必填项,否则会无法完成交易)
    requestParams.put("netWork", "TRC20"); // 链网络(当orderType=1(数字货币交易)时,是必填项,否则无法完成交易)
    requestParams.put("inAddress", "zkif74bhvkf8934rgg6"); // 入账地址(当orderType=1(数字货币交易)时,是必填项,否则无法完成交易)

    StringBuilder stringBuilder = new StringBuilder();
    for (String key : requestParams.keySet()) {
      stringBuilder.append(requestParams.get(key));  // 拼接参数
    }

    String keyStr = stringBuilder.toString();  // 得到待加密的字符串
    System.out.println("keyStr:" + keyStr);
    String signedStr = TopPayRequestUtil.privateEncrypt(keyStr, TopPayRequestUtil.getPrivateKey(MCH_PRIVATE_KEY));  // 私钥加密
    requestParams.put("sign", signedStr);

    String postJson = new Gson().toJson(requestParams);
    System.out.println("Post Json Params:" + postJson);

    String responseJson = TopPayRequestUtil.doPost(cashUrl, postJson);  // 发送 post json请求
    System.out.println("Response Msg:" + responseJson);

    boolean pass = TopPayRequestUtil.verifySign(new Gson().fromJson(responseJson, JsonObject.class), PLAT_PUBLIC_KEY);  // 签名验证
    if (pass) {
      // ... 签名验证通过,执行正常的业务逻辑
    } else {
      // ... 签名验证错误
    }
  }
}

2.请求地址

POST https://bra-openapi.toppay.asia/gateway/cash

注:所有的参数中,不要填写中文!!!

3.请求参数

参数 类型 必填 描述 示例
merchantCode string Y 商户ID,在商户平台获取 S820211021094748000001
orderType string(10) Y 订单类型 1-数字货币交易
method string(10) Y 收款方式 USDT
BTC
ETH
TRX
orderNum string Y 商户订单号 186888188666
money string Y 代付金额 1.000001(最大支持6位小数)如果feeType选择0的话,因为涉及到手续费,所以麻烦您先以3位小数的金额进行代付下单
feeType String Y 手续费类型 0:代付金额内扣除
1:手续费另计
name String Y 客户名称 Jack
notifyUrl string Y 回调地址 1234567890
currency string(14) Y 数字货币币种 USDT
netWork string(30) Y 链网络 TRC20
inAddress string Y 入账地址 vboj3457vbiae5y35y

4.请求报文示例

{
  "merchantCode": "S820211021094748000001",
  "orderType": "1",
  "method": "USDT",
  "orderNum": "186888188666",
  "money": "1.00000001",
  "feeType": "1",
  "name": "test cash name",
  "notifyUrl": "your notify url",
  "currency": "USDT",
  "netWork": "TRC20",
  "inAddress": "vboj3457vbiae5y35y",
  "sign": "Yg+ePvTFhiRrARcZKBcRG0l89rqisPIuZQStYqBIwSMPaqwH77qRXI1J+jElOBpa"
}

5.响应参数

参数 类型 描述 示例
platRespCode String 请求业务是否成功 FAIL:失败\SUCCESS:成功
platRespMessage String 接口响应信息提示 请求成功
platOrderNum String 平台订单号 PI1453242857400963072
status String 订单状态 0
statusMsg String 订单状态信息 Apply
orderNum String 商户订单号 23645782
money string 代付金额 1.00000001
feeType String 手续费类型 0:代付金额内扣除
1:手续费另计
name String 客户名称 Jack
currency string 数字货币币种 USDT
netWork string 链网络 TRC20
platSign String 签名 PI1453242857400963072

6.响应报文示例

{
  "platRespCode": "SUCCESS",
  "platRespMessage": "Request success",
  "platOrderNum": "W0620220119174331000001",
  "orderNum": "186888188666",
  "status": "0",
  "statusMsg": "Apply",
  "money": "50000",
  "feeType": "1",
  "currency": "USDT",
  "netWork": "TRC20",
  "platSign": "E5uNF7B9NXyhtlRo2I7/KVHN4Sbz0c3VbwCLpH3vjUpv6Cai+bmJA/Q8dVE2RJRe1+dsbzg=="
}

7.数字代付异步通知

接收到结果异步通知后,需响应 SUCCESS字符串,不包含引号,不是Json格式。

否则TopPay将继续向下游发起5次通知。

参数 描述 示例
platOrderNum 平台订单号 BK_1563278763273
orderNum 商户订单号 T1231511321515
money 代付金额 1.000001(最大支持6位小数)
feeType 订单结果状态 手续费类型, 0:代付金额内扣除,1:手续费另计
fee 手续费 500
name 客户名称 Neo
status 订单状态 0-待处理
1-处理中
2-代付成功
4-代付失败
5-银行代付中
statusMsg 订单状态描述 Payout Success
hashCode 交易哈希 5e5c356af0ewrhgnf3d757h8a6a5506cc66354620
inAddress 接收地址 TDBbbeAB32WE576DVGE82GEC5BhsZs4
sendAddress 发送地址 TDBbbeAB32WE576DVGE82GEC5BhsZs4
platSign 平台签名 ja6R8eukQY9jc8...

8.异步通知报文示例

{
  "platOrderNum": "W0620220119174331000001",
  "orderNum": "186888188666",
  "money": "1.00000001",
  "feeType": "1",
  "fee": "0.0001",
  "currency": "USDT",
  "netWork": "TRC20",
  "name": "test cash name",
  "status": "2",
  "statusMsg": "SUCCESS",
  "hashCode": "5e5c356af0ewrhgnf3d757h8a6a5506cc66354620",
  "inAddress": "Twrgtehsd576gsdre876d2545C5Br23324",
  "sendAddress": "TDBbbeAB32WE576DVGE82GEC5BhsZs4",
  "platSign": "LGEpz2LjbZ6Iyvn+zLc/+t26AaH0aEhHVD62lSCdo6XIkAg86AUncCvmym62wVoE3r2+dHnv27qi/01UQDcqFK8DYioRCcydYSjB4QRVezG3fcZlhWrACmWGacnXkE7p5zChL7pK5h0HuBhbo1zKt4FunQR6QMmcBVfv7YfB3W0"
}

八、订单查询

1.订单查询


import com.google.gson.JsonObject;
public class OrderQuery {
  // 测试账号
  private static final String MCH_CODE = "S820211021094748000001";  // 商户号
  private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  // 平台公钥
  private static final String MCH_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJU8gKFKD0luIYx7X8+JRdCIE0UDBctS6LjXxWLEv/EO7jDBTid6zYP1KmNgpd2DAWWtBFBSQ+gcNwVZZSBHJiSDqVvvJVs2FEbeBvfdv4X93+IYRAXksBasSW5Tpdshbo82pVL4V7wuKCuFLk9UxBHbpQjWAbfyF66RmwIbZD71AgMBAAECgYBjPe7UU2nDDSfmQg0++CyjNjqKRC5QPfxhH6w1uF1kMueXKJWOj42n2RutJpJmsj31nY8m0u4xpsG4HvCu/GGSFhhKZCHLvzp41oY2ubYj9nuFNU//81LycQjulWo2y0UUBY0k2piEt+SwPaiUNbT6nMxNMjlnjRe2okp/3rw+KQJBANG3YlZWoVbCEqzy64bJJLxiPsCA5ErGB0NzRGitq44xkhqGtR8ZZQyVz40pruNa58d73O2xyJSy5+fmZGn4E+sCQQC2LBnguj0CSCKub0mPDcunTTz9V79VXBBZdlB1/YGmRUx2s4sQrJNZS7rL4EqBQ3maIRnG+s+AXCSTfsYrV6CfAkEAxugnVfpelhoGepEAgNuggyivmgfl/2Gpm/jk5l/qOjib+ZrQiQmeBPzGWX4yiSM8eMDrP2sC8r5pJFMp5DRONwJBAJ4n4XuSFJ9jgwCPy3vvzSv9SYLk6E6yM9uHdUlKgoGYzk6Lh6M9QFuY/J49plFdBDiEnj16yCU3WeXXfTJpzB8CQQDMNMR/rIOTE9xGybS3mlQbt22AUnO6XhupWcckEKW4nPGxATwYBQzCY3i/9FTGN0vA+9ZPC2cwHtNxI2kXf3Vp";  // 商户私钥
  private static final String orderQueryUrl = "https://bra-openapi.toppay.asia/gateway/query";

  public static void main(String[] args) throws Exception {
    // 代收
    query();
  }
  private static void query() throws Exception {
    Map<String, String> requestParams = new TreeMap<>();
    requestParams.put("merchantCode", MCH_CODE);
    requestParams.put("queryType", "CASH_QUERY"); // 支付渠道
    requestParams.put("orderNum", "186888188666"); // 商户订单号
    requestParams.put("platOrderNum", "PRE186888188666"); // 平台订单号

    StringBuilder stringBuilder = new StringBuilder();
    for (String key : requestParams.keySet()) {
      stringBuilder.append(requestParams.get(key));  // 拼接参数
    }

    String keyStr = stringBuilder.toString();  // 得到待加密的字符串
    System.out.println("keyStr:" + keyStr);
    String signedStr = TopPayRequestUtil.privateEncrypt(keyStr, TopPayRequestUtil.getPrivateKey(MCH_PRIVATE_KEY));  // 私钥加密
    requestParams.put("sign", signedStr);

    String postJson = new Gson().toJson(requestParams);
    System.out.println("Post Json Params:" + postJson);

    String responseJson = TopPayRequestUtil.doPost(orderQueryUrl, postJson);  // 发送 post json请求
    System.out.println("Response Msg:" + responseJson);
  }
}

请求地址

POST https://bra-openapi.toppay.asia/gateway/query

注:商户订单号和平台订单号两者必需传递其中一个,也可以同时传递

请求参数

参数 是否必填(Y-是,N-否) 类型 示例
merchantCode Y 商户ID S820190712000002
queryType Y 查询类型 代收:ORDER_QUERY.代付:CASH_QUERY
orderNum Y 商户订单号 T1231511321515
platOrderNum Y 平台订单号 PRE1234567890
sign Y RSA签名 ja6R8eukQ...

响应参数说明(格式参考-代收订单查询响应报文示例)

参数 类型 必填 描述 示例
success BOOLEAN Y 接口响应 true/false
code int Y 接口响应码 1000代表成功,其他的都为失败
message String Y 接口响应信息 返回具体响应信息
data Json Y 接口响应参数 以下参数都在data中返回,如失败则为null
msg String Y 订单状态详细信息 Request Transaction Success
platOrderNum String Y 平台订单号 PI1453242857400963072
amount String Y 支付金额 1500
fee string Y 手续费金额 5
orderNum String Y 商户订单号 23645782
inAddress string N 入账地址 TLRx8JXsDidC7PYVLmeD6Bhk5k5CUjnPV3
sendAddress String N 出账地址 TLRx8JcxDidC7PYVLmeD6Bhk5k5CUjnPV3
platRespCode String Y 请求业务是否成功 FAIL:失败\SUCCESS:成功
platRespMessage String Y 接口响应信息提示 Request Transaction Success
status int/String Y 订单状态 代收状态返回string类型,代付状态返回int类型

2.请求报文示例

{
  "merchantCode": "S820211021094748000001",
  "orderNum": "T1642593166888",
  "platOrderNum": "PRE1642593166888",
  "queryType": "ORDER_QUERY",
  "sign": "lGw1OJcuUL0MGaIq44U2u2bFM5dalJJuT/G6mQWbIBT9dmVAJaLwR125emPDXYYSdnOtNxja86A2VJJLf40BCg2HevHolebvt2ay3ukCQaUhwNkIGz4KF0Ud+XMUA36LoFTWZbDYv9y8vgCnWxwZFKj7ePrfLxc+TA7jpqv65lQ\u003d"
}

3.代收订单查询响应报文示例

{
  "success": true,
  "code": 1000,
  "message": "Success",
  "data": {
    "msg": "Payment Success",
    "platOrderNum": "PRE1483771634191044608",
    "amount": "150",
    "fee": "16",
    "orderNum": "T1642593166888",
    "platRespCode": "SUCCESS",
    "platRespMessage": "success",
    "status": "SUCCESS"
  }
}

4.代付订单查询响应报文示例

{
  "success": true,
  "code": 1000,
  "message": "Success",
  "data": {
    "msg": "test cash",
    "platOrderNum": "W0620220119174331000001",
    "amount": "125",
    "fee": "16",
    "orderNum": "186888188666",
    "platRespCode": "SUCCESS",
    "platRespMessage": "success",
    "status": 2
  }
}

九、账户余额查询

1.账户余额查询


import com.google.gson.JsonObject;
public class OrderQuery {
  // 测试账号
  private static final String MCH_CODE = "S820211021094748000001";  // 商户号
  private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  // 平台公钥
  private static final String MCH_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJU8gKFKD0luIYx7X8+JRdCIE0UDBctS6LjXxWLEv/EO7jDBTid6zYP1KmNgpd2DAWWtBFBSQ+gcNwVZZSBHJiSDqVvvJVs2FEbeBvfdv4X93+IYRAXksBasSW5Tpdshbo82pVL4V7wuKCuFLk9UxBHbpQjWAbfyF66RmwIbZD71AgMBAAECgYBjPe7UU2nDDSfmQg0++CyjNjqKRC5QPfxhH6w1uF1kMueXKJWOj42n2RutJpJmsj31nY8m0u4xpsG4HvCu/GGSFhhKZCHLvzp41oY2ubYj9nuFNU//81LycQjulWo2y0UUBY0k2piEt+SwPaiUNbT6nMxNMjlnjRe2okp/3rw+KQJBANG3YlZWoVbCEqzy64bJJLxiPsCA5ErGB0NzRGitq44xkhqGtR8ZZQyVz40pruNa58d73O2xyJSy5+fmZGn4E+sCQQC2LBnguj0CSCKub0mPDcunTTz9V79VXBBZdlB1/YGmRUx2s4sQrJNZS7rL4EqBQ3maIRnG+s+AXCSTfsYrV6CfAkEAxugnVfpelhoGepEAgNuggyivmgfl/2Gpm/jk5l/qOjib+ZrQiQmeBPzGWX4yiSM8eMDrP2sC8r5pJFMp5DRONwJBAJ4n4XuSFJ9jgwCPy3vvzSv9SYLk6E6yM9uHdUlKgoGYzk6Lh6M9QFuY/J49plFdBDiEnj16yCU3WeXXfTJpzB8CQQDMNMR/rIOTE9xGybS3mlQbt22AUnO6XhupWcckEKW4nPGxATwYBQzCY3i/9FTGN0vA+9ZPC2cwHtNxI2kXf3Vp";  // 商户私钥
  private static final String orderQueryUrl = "https://bra-openapi.toppay.asia/gateway/query";

  public static void main(String[] args) throws Exception {
    query();
  }
  private static void query() throws Exception {
    Map<String, String> requestParams = new TreeMap<>();
    requestParams.put("merchantCode", MCH_CODE);
    requestParams.put("currency", "BRL"); // 币种(BRL)

    StringBuilder stringBuilder = new StringBuilder();
    for (String key : requestParams.keySet()) {
      stringBuilder.append(requestParams.get(key));  // 拼接参数
    }

    String keyStr = stringBuilder.toString();  // 得到待加密的字符串
    System.out.println("keyStr:" + keyStr);
    String signedStr = TopPayRequestUtil.privateEncrypt(keyStr, TopPayRequestUtil.getPrivateKey(MCH_PRIVATE_KEY));  // 私钥加密
    requestParams.put("sign", signedStr);

    String postJson = new Gson().toJson(requestParams);
    System.out.println("Post Json Params:" + postJson);

    String responseJson = TopPayRequestUtil.doPost(orderQueryUrl, postJson);  // 发送 post json请求
    System.out.println("Response Msg:" + responseJson);
  }
}

请求地址

POST https://bra-openapi.toppay.asia/gateway/interface/getBalance

请求参数

参数 必填 类型 示例
merchantCode Y 商户ID S820211021094748000001
currency N 币种 BRL(不传展示所有货币单位的余额)
sign Y RSA签名 ja6R8eukQ...

响应参数

参数 类型 必填 描述 示例
success BOOLEAN Y 接口响应 true/false
code int Y 接口响应码 1000代表成功,其他的都为失败
message String Y 接口响应信息 返回具体响应信息
data Json Y 接口响应参数 以下参数都在data中返回,如失败则为null
mchId String Y 商户ID S8202110212321300001
mchName String Y 商户名称 test
mchNo String Y 商户ID TP123
currency string Y 币种 BRL
balance String Y 可用余额 1000.00
freeze String Y 冻结余额 10.00
waitingSettleAmount String Y 待结算金额 200.00
freezeWaitingSettleAmount String Y 冻结待结算金额 100.00
totalAmount String Y 全部金额(可用余额+冻结余额+待结算金额+冻结待结算金额) 20000.00

2.请求报文示例

{
  "merchantCode": "S8202110212321300001",
  "currency": "BRL",
  "sign": "X/o+IQUzLJqYe9Feid9Uww72mJGOvhJSJEIfo1EUChrZyVZnzGHtd61QhOqRmXCtAwk7V7k="
}

3.响应报文示例

{
  "success": true,
  "code": 1000,
  "message": "SUCCESS",
  "data": [
    {
      "mchId": "S82022091232130000001",
      "mchName": "test",
      "mchNo": "test",
      "country": "BRAZIL",
      "currency": "BRL",
      "balance": "1000000.01",
      "freeze": "10.00",
      "waitingSettleAmount": "10.00",
      "freezeWaitingSettleAmount": "20.00",
      "totalAmount": "1000040.01"
    }
  ]
}

十、可选参数附录

Ⅰ 代收业务

1 Status 参数

字段值 说明
INIT_ORDER 订单初始化
NO_PAY 未支付
SUCCESS 支付成功(最终态)
PAY_CANCEL 撤销(最终态)
PAY_ERROR 支付失败(最终态)

Ⅱ 代付业务

1 Status 参数

字段值 说明
0 待处理
1 已受理
2 代付成功(最终态)
4 代付失败(最终态)
5 银行代付中