数字货币代收下单
- 数字货币交易支持币种:(USDT/BTC/ETH/TRX),如果您想使用数字货币交易,请设置 orderType=1。
- 我们的数字货币代收订单分两个模式:有单模式和无单模式。
- 收银台版本 v1.0 和 v3.0 属于有单模式;v2.0 和v4.0 属于无单模式。
- v1.0、v2.0 只展示支付地址,v3.0、v4.0 展示二维码和支付地址两种方式。
- 使用数字货币进行交易时,如果指定了数字货币类型,则币种和链网络是必传项,您需要告诉我们您想使用何种数字货币和链网络 (TRC20/BEP20/OMNI/ERC20/TRX) 进行交易。
# 代码示例
- 代码示例仅供参考,具体参数说明请参考请求参数说明
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_ID = "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://id-openapi.toppay.asia/gateway/prepaidOrder";
private static final String cashUrl = "https://id-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_ID);
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("phone", "082122965511"); // 手机号
requestParams.put("email", "[email protected]"); // 客户邮箱
requestParams.put("notifyUrl", payNotify); // 回调地址
requestParams.put("dateTime", "20220101235959"); // 时间戳 格式 yyyyMMddHHmmss
requestParams.put("expiryPeriod", "1440"); // 过期时间 单位 (分)
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);
boolean pass = TopPayRequestUtil.verifySign(new Gson().fromJson(responseJson, JsonObject.class), PLAT_PUBLIC_KEY); // 签名验证
if (pass) {
// ... 签名验证通过,执行正常的业务逻辑
} else {
// ... 签名验证错误
}
}
}
# 请求地址
- 收银台 (模式1) : 使用收银台链接中展示的支付信息
- 请求方式 : POST
- 请求地址 : https://id-openapi.toppay.asia/gateway/prepaidOrder
- 直连 (非收银台) 模式 (模式2) : 直接获取支付信息 (适用于有自己收银台页面的商户)
- 请求方式 : POST
- 请求地址 : https://id-openapi.toppay.asia/gateway/pay
# 请求参数
注:所有的参数中,不要填写中文!!!
- 收银台模式 (模式1):
参数 | 类型 | 必填 | 描述 | 示例 |
---|---|---|---|---|
merchantCode | string(32) | Y | 商户ID,在商户平台-个人中心-个人信息中获取 | S820211021094748000001 |
orderType | string(10) | Y | 订单类型 | 1-数字货币交易 |
mchUserId | string(32) | Y | 商户用户ID(您的用户唯一标识,请勿传特殊字符、空格等) | 100001 |
method | string(10) | N | 支付方式 1.如果需要指定支付方式,可以在右侧的示例支付方式列表中选择其一。 2.如果不指定支付方式,则可不传该参数,可以在我们的收银台页面中选择某个支付方式。 | 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 |
dateTime | string(32) | Y | 时间戳 (格式:yyyyMMddHHmmss) | 20190101235959 |
expiryPeriod | int(5) | Y | 订单过期时间 (单位:分钟) | 720 |
name | string(16) | Y | 客户名称 | Jack |
string(64) | Y | 用户邮箱 | [email protected] | |
phone | string(14) | Y | 用户手机号码 | 081234567890 |
orderVersion | string(10) | Y | 收银台版本 (v1.0和v3.0属于有单模式版本;v2.0和v4.0属于无单模式) | v1.0 |
sign | string(255) | Y | 签名 | fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+XxO2jo92dyjKHFU9/4hNECilMooOcH |
- 直连 (非收银台) 模式 (模式2):
参数 | 类型 | 必填 | 描述 | 示例 |
---|---|---|---|---|
merchantCode | string(32) | Y | 商户ID,在商户平台-个人中心-个人信息中获取 | S820211021094748000001 |
orderType | string(10) | Y | 订单类型 | 1-数字货币交易 |
mchUserId | string(32) | Y | 商户用户ID(您的用户唯一标识,请勿传特殊字符、空格等) | 100001 |
method | string(10) | Y | 支付方式 | USDT BTC ETH TRX |
currency | string(14) | Y | 数字货币币种 | USDT |
netWork | string(30) | Y | 链网络 | TRC20 |
orderNum | string(32) | N | 商户订单号(有单模式必传,无单模式不传) | TEST123456789 |
payMoney | int(10) | Y | 付款金额 (最大允许6位小数) | 1.000001 |
notifyUrl | string(100) | Y | 订单支付成功异步通知地址 (用来接收订单交易成功后的通知) | https://host:port/notifyUrl |
dateTime | string(32) | Y | 时间戳 (格式:yyyyMMddHHmmss) | 20190101235959 |
expiryPeriod | int(5) | Y | 订单过期时间 (单位:分钟) | 720 |
name | string(16) | Y | 客户名称 | Jack |
string(64) | Y | 用户邮箱 | [email protected] | |
phone | string(14) | Y | 用户手机号码 | 081234567890 |
sign | string(255) | Y | 签名 | fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+XxO2jo92dyjKHFU9/4hNECilMooOcH |
# 请求报文示例
- 收银台模式(模式1):(method参数可不传)
{
"merchantCode": "S820211021094748000001",
"orderType": "1",
"mchUserId": "10001",
"method": "USDT",
"currency": "USDT",
"netWork": "TRC20",
"orderNum": "T1642593166888",
"payMoney": "1.00000001",
"notifyUrl": "your notify url",
"dateTime": "2022-01-01 10:55:00",
"expiryPeriod": "1440",
"name": "JackMa",
"email": "[email protected]",
"phone": "08123456789",
"sign": "fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+Xxd1yc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQbYDxZ5WBuU1GZeiJ"
}
- 直连(非收银台)模式(模式2):(method参数必传)
{
"merchantCode": "S820211021094748000001",
"orderType": "1",
"mchUserId": "10001",
"method": "USDT",
"currency": "USDT",
"netWork": "TRC20",
"orderNum": "T1642593166888",
"payMoney": "1.00000001",
"notifyUrl": "your notify url",
"dateTime": "2022-01-01 10:55:00",
"expiryPeriod": "1440",
"name": "JackMa",
"email": "[email protected]",
"phone": "08123456789",
"sign": "fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+Xxd1yc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQbYDxZ5WBuU1GZeiJ"
}
# 响应参数
参数 | 类型 | 必填 | 描述 | 示例 |
---|---|---|---|---|
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'时返回 |
inAddress | String | Y | API模式时,返回钱包地址 | 'platRespCode'为'SUCCESS'时返回 |
# 响应报文示例
- 模式1响应报文示例(url是收银台链接)
{
"platRespCode": "SUCCESS",
"url": "https://id-openapi.toppay.asia/cashier?orderNum=PRE1626161123977859130123",
"mchUserId": "10001",
"platOrderNum": "PRE1626161123977859130",
"payMoney": "1.00000000",
"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"
}
- 模式2响应报文示例
{
"platRespCode": "SUCCESS",
"inaddress": "T34YVS9GJ53OTJWIUFVOI",
"mchUserId": "10001",
"platOrderNum": "PRE1626161123977859130",
"payMoney": "1.00000000",
"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"
}
# 代收异步通知
- 请注意:当前业务只有在订单支付成功的时候才有回调通知接收到。
- 进行验签时,要用 商户后台-收付款配置-API配置 中提供的平台公钥进行解密!!!
- 数字货币有两种特殊情况:无单模式以及支付金额与下单金额不符,为此我们将异步通知进行了调整,如下:
- 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_ID = "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 {
// ... 签名验证错误
}
}
}
# 通知参数
参数 | 描述 | 示例 |
---|---|---|
code | 响应状态 | 00 |
msg | 响应信息 | SUCCESS |
mchUserId | 商户用户ID | 10001 |
platOrderNum | 平台订单号 | BK_1563278763273 |
orderNum | 商户订单号 | T1231511321515 |
method | 支付方式 | USDT |
currency | 币种 | USDT |
netWork | 链网络 | TRC20 |
status | 支付结果 | 查看订单状态描述 |
payMoney | 代收金额 | 100000 |
payFee | 手续费 | 500 |
hashCode | 交易哈希 | 5e5c356af0ewrhgnf3d757h8a6a5506cc66354620 |
sendAddress | 发送地址 | TDBbbeAB32WE576DVGE82GEC5BhsZs4 |
specialStatus | 特殊状态 0-默认 1-特殊状态 | 0 |
platSign | 平台签名 | ja6R8eukQY9jc8zrhtf34654ungj7u8sdgdfjfs |
# 异步通知报文示例
{
"code": "00",
"msg": "SUCCESS",
"mchUserId": "10001",
"platOrderNum": "BCA1483771634191044608",
"orderNum": "T1642593166888",
"method": "USDT",
"currency": "USDT",
"netWork": "TRC20",
"status": "SUCCESS",
"payMoney": "1.0000001",
"payFee": "0.000016",
"hashCode": "5e5c356af0ewrhgnf3d757h8a6a5506cc66354620",
"sendAddress": "TDBbbeAB32WE576DVGE82GEC5BhsZs4",
"specialStatus": "0",
"platSign": "ja6R8eukQY9jc8zrhtf34654ungj7u8sdgdfjfs"
}