提现
提现申请
$url = "http://api.xxxx.com/shopapi/transfer";
$header = [
'Content-Type:application/json',
];
$params = [
"app_id" => "hxgmau9imt86qky9",
"version" => "1.0",
"time" => 1579004943,
"user_id" => "0",
"coin" => "hc",
"address" => "HsRDEePh7WBCsdJPfo1UsjfurwLBU6HD5Vi",
"amount" => "0.02",
"trade_id" => "20200114202903274786",
"sign" => "dLtK+uiPcnxt2ACKMbBqQ6wI5ttAvesOHzK5ybVID1R6hqYPDTkagl7Tsjr5iLJafehcSLTZyJLtCRI8O2CtIWQUUroGXBneHZC486NUi/4FMOQs0FaAgm17pWlbhX5/96cWXXXMVeoe3IZFKaFNYSWaA14v3RcdDU6QDE/9ixGiSJ0DIxm9NKA0+RkbIFbyYeuFn8d63OcjmUhv7tsOE6rKCc3Q2yi7Qe9i6BNAQFYMFATztb18MsxsBHKUxNqklqyVnl0ofETAHmQhfOHLmungOJQnOqAAuwfmRtg50Qci5F+R2mXeqjmIXko/u3E+DLYW1ygDBp3afKZmU4PwmA=="
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$return = curl_exec($ch);
print_r($return);
var url = "http://api.xxxx.com/shopapi/transfer"
data := map[string]interface{}{
"app_id":"hxgmau9imt86qky9",
"version":"1.0",
"time":"1579004943",
"user_id":"0",
"coin":"hc",
"address":"HsRDEePh7WBCsdJPfo1UsjfurwLBU6HD5Vi",
"amount":"0.02",
"trade_id":"20200114202903274786",
"sign":"dLtK+uiPcnxt2ACKMbBqQ6wI5ttAvesOHzK5ybVID1R6hqYPDTkagl7Tsjr5iLJafehcSLTZyJLtCRI8O2CtIWQUUroGXBneHZC486NUi/4FMOQs0FaAgm17pWlbhX5/96cWXXXMVeoe3IZFKaFNYSWaA14v3RcdDU6QDE/9ixGiSJ0DIxm9NKA0+RkbIFbyYeuFn8d63OcjmUhv7tsOE6rKCc3Q2yi7Qe9i6BNAQFYMFATztb18MsxsBHKUxNqklqyVnl0ofETAHmQhfOHLmungOJQnOqAAuwfmRtg50Qci5F+R2mXeqjmIXko/u3E+DLYW1ygDBp3afKZmU4PwmA==",
}
dataType, _ := json.Marshal(data)
resp, err := http.Post(url, "application/json", strings.NewReader(string(dataType)))
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(body))
let HTTP = require('http')
let postData = {
"app_id":"hxgmau9imt86qky9",
"version":"1.0",
"time":"1579004943",
"user_id":"0",
"coin":"hc",
"address":"HsRDEePh7WBCsdJPfo1UsjfurwLBU6HD5Vi",
"amount":"0.02",
"trade_id":"20200114202903274786",
"sign":"dLtK+uiPcnxt2ACKMbBqQ6wI5ttAvesOHzK5ybVID1R6hqYPDTkagl7Tsjr5iLJafehcSLTZyJLtCRI8O2CtIWQUUroGXBneHZC486NUi/4FMOQs0FaAgm17pWlbhX5/96cWXXXMVeoe3IZFKaFNYSWaA14v3RcdDU6QDE/9ixGiSJ0DIxm9NKA0+RkbIFbyYeuFn8d63OcjmUhv7tsOE6rKCc3Q2yi7Qe9i6BNAQFYMFATztb18MsxsBHKUxNqklqyVnl0ofETAHmQhfOHLmungOJQnOqAAuwfmRtg50Qci5F+R2mXeqjmIXko/u3E+DLYW1ygDBp3afKZmU4PwmA==",
};
let POST_OPTIONS = {
port: 80,
host: "api.xxxx.com",
path: "/shopapi/transfer",
method: 'POST',
headers: {
"Content-Type": "application/json; charset=utf-8"
}
};
const REQUEST = HTTP.request(POST_OPTIONS,function (res) {
let data = []
res.on('data', chunk => {
data.push(...chunk)
})
res.on('end', () => {
let _date = JSON.parse( new TextDecoder().decode(new Uint8Array(data)))
console.log(_date)
})
});
REQUEST.setTimeout(6000)
REQUEST.write(JSON.stringify(postData), 'utf8')
REQUEST.end()
public static void main(String[] args) {
// 完整实例请查看"签名规则"中的Java示例代码
String baseUrl = "http://api.xxxx.com/shopapi";
String priKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtdgvcfozY7fe/x6UlXR/Fff8+wX++CiG05YVRafDe90O8y5KJAMZ156TgajEUXSRyKZqASz7iVoMAcu5FqfK1KuOOdjTAg0LFe/twIZvKmAqHcCSS2pjUXk0fTpZEgQ5lmDCK12Mg07YXvr+BeHjF+kBpwRJMPMG/+DGBDYNFNeRSJqWyopt6yyF528soAykHIUQ7TTultJV5IPCrvjRQQrGdJ/QtCdE0vZg+tA09nFN7AqgraU99kIvzyS0sqysj+pP1SJRmTRSGtlVAO3mILfkXOekZl1KD60G7CF+7BIaaW83FPD55tZhAGhnbLMYyiq7OiIyU61LTRcNSaJ0tAgMBAAECggEBAIGgGKcSzxCBbMYdXLV6TPbZ/HeaRGrwyVWUu7cmc0E8CJu6iWvmb2jGzbiCwuCT5luF6ZZ8JKchvU4FlTfsE5r9TQY2IZ/Ht4s65qBaDUEts5iY3kv8HX9+ZSXDJZpV0ztqqsPmx4ZNj+NYwWXwcFiKdb5R8OmV8bgSsnPddD6wFhwewglUOBPRAjropHE4sqk1Vam6q1MlFq5kiekMn/CItyFYFFzST/ruqAtVTp7YIvazAMrfCKH+pvXWk6pYNHZmL/JZey0GglRyJ1nItiqL33X8Lji056FcbAclidq022h/KPLEJpZk6irWqYdqYZeF6YMLHtdZFDkTZ/hXY+UCgYEA5i794UTQ1Kd6K+iui/S8K5H8nGdiXb3+uZ5j5VKYfbRmzXhAdVYisYe8czeTECxhH+MeHgM4tLR4ifx9q60ylvZxl9Fav1p6EaE36YcvGVmpm7Gm3q6QDDBa4gB+X9u7CxCS4LpotV917YS1QvOIF9lnRonSj1zNzFtbXkywrN8CgYEAwOpx/mR40ZvgZxNCq9DsIdrSZYAFFKpw0xy0OtF1PpuwMaREoRabnlVw6Bb3Hofg50XA3JxemzAX6fB92ee+NfXfeL4UtC4vG1K9JyiXHtHq8p9Uw2W03ehIEeNa3xdoRRnLmD4VUpyfL19ViE2+7TM1Gd3TogjDT+AMOCSuq3MCgYBsurPH7gaq/LVT+mRAzgj4l8v4YUlwuGeTbIMJdvt7HXUWB4CDLH3U2CYnUpAQKrZyJok6ahEmIr1xiKggKP7lmmHL8eNo0icpHrtXfzi7Q8Q/PCpzs4dtioXTjaIkS5nNvzVyG/uL+RyuZmpsxrZ5dYM4KbAhchfwORMutxEZhwKBgQC5zpVw4jCEItBmNuTWO+nTScGvxTgfiXIVw+XLaQa2AJoZlhAL34yPWdffko79tv3lgweY9HsimZXO2rU8dbp8mo5c6ydhy8HPXUeWOcAkDSdv/ApWENW9jgYsRIC3swHY3Fl+Dv3Wjce8huQI3mjwaYvRmBhIToxfmHnscVhTBQKBgB9uciEHfz8hMI7ePrPo2PkyK/RbJDm3HnuWE2lFBp7MOUMlh53MXwv4dIRaYMbRrFuN1UIKEFxuKhWwTHSzZJufk/UENrha/81fpj2BoFsAKkEunKeETvaIh6fZSjec16h2+zxbzwkdS6b+yIYkSlaoAxmDYrMtae0C8G4e0YS9";
String pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2RZZISModRzproL3eTxRtvVK/nToDbeLmAVdmaVtHgNCwjXMeNCZvHySZKO7+t7XySzBd2PhhQjvAkDd8HRKB5Y0uvP6TFwvhxOMkMydTeBFcUobQWNeAI7ttRms1txSNrmyrZr0WpWfk79VIsO+yI/jFN/Pj2gxD+vh5UUKU1LD2IQq/VxgtEpf8Vs6w7SvafPwYkpdPGCKUFkRvN1FrY2+tq0j1MRVJbB2rIunWDnT8cDUh2sWLXf4yNaJVOaaTFB0zbAk/qcoicGQyW7bVG7dVW8WywKmOAPeQCCQa+SJ4BhfI1k8eEAwFVRuxz/f9Ecfog9hZJ+RgELkpS8qhQIDAQAB";
rsaSigner signer = new rsaSigner();
Map<String, Object> params = new HashMap<>();
params.put("app_id", "hxgmau9imt86qky9");
params.put("version", "1.0");
params.put("key_version", "admin");
params.put("time", Long.toString(System.currentTimeMillis() / 1000));
params.put("user_id", "1");
params.put("coin", "hc");
params.put("address", "HsRDEePh7WBCsdJPfo1UsjfurwLBU6HD5Vi");
params.put("amount", "0.02");
params.put("trade_id", "20200114202903274786");
try {
params.put("sign", signer.genSign(params, priKey));
Gson gson = new GsonBuilder().create();
System.out.println("params = " + gson.toJson(params));
String res = doPost(baseUrl + "/transfer", gson.toJson(params));
if (null == res) {
throw new RuntimeException("http error");
}
System.out.println("response = " + res);
JsonParser jp = new JsonParser();
JsonObject resEle = jp.parse(res).getAsJsonObject();
boolean retSignOK = signer.verifySign(resEle, resEle.get("sign").getAsString(), pubKey);
if (!retSignOK) {
throw new RuntimeException("verify response sign fail");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("OK");
}
返回结果示例:
{
"status":200,
"msg":"请求成功",
"data":{
"trade_id":"20200114005026028784"
},
"date_time":"2020-01-14 00:50:27",
"sign":"ib1gqr0E0gJ02yo3InXKcKGaPqIp+r1izMego+KMRvE0B4ZdkFGrLmOtxGStUBibGVMzJRGWppKyU4PzcK877AOEvQlSFiUI+hDL1z8WaZsWD3r3ykbPzU0uWo4U+6WQTpOEo1gJ/N2zJsdTRcMVgJMSC7LEAg7oib4se2NPFlw="
}
商户发起链上提币,请求此接口 开通提现功能时 ,同时需要提供 风控接口(见:风控回调api -> 商户提现订单二次复核)
HTTP Request
POST: /transfer
请求参数
| 参数名 | 必选 | 类型 | 说明 |
|---|---|---|---|
| 公共参数 | 是 | string | 公参指:签名(sign)、版本(version)、商户ID(app_id)、时间(time) |
| user_id | 否 | string | 用户ID,字母、数字和下划线组成,长度40以内 |
| coin | 是 | string | 币种简称-平台约定为准 |
| amount | 是 | string | 提现数量,超范围会出错 |
| address | 是 | string | 收款地址,超范围会出错 |
| memo | 否 | string | memo/tag 当前币为 eos及其代币时需要填写 |
| trade_id | 是 | string | 商户端交易唯一ID(建议格式:年月日时分秒+6位随机数案列:20200311202903000001) |
返回参数说明
| 参数名 | 类型 | 说明 |
|---|---|---|
| status | int | 状态码 |
| msg | string | 状态描述 |
| data | jsonObject | trade_id-由商户提供 |
| data.trade_id | string | 商户端交易唯一ID |
| date_time | string | 响应时间 |
| time_stamp | int | 无时区的秒 |
| sign | string | 签名 |
- 备注: 该接口返回成功只是接收成功,不代表转账处理成功,处理结果以通知接口返回数据为准 更多返回错误代码请看首页的错误代码描述
提现列表
$url = "http://api.xxxx.com/shopapi/transfer/list";
$header = [
'Content-Type:application/json',
];
$params = [
"version" => "1.0",
"app_id" => "hxgmau9imt86qky9",
"time" => "1578736053",
"page" => 1,
"sign" => "dLtK+uiPcnxt2ACKMbBqQ6wI5ttAvesOHzK5ybVID1R6hqYPDTkagl7Tsjr5iLJafehcSLTZyJLtCRI8O2CtIWQUUroGXBneHZC486NUi/4FMOQs0FaAgm17pWlbhX5/96cWXXXMVeoe3IZFKaFNYSWaA14v3RcdDU6QDE/9ixGiSJ0DIxm9NKA0+RkbIFbyYeuFn8d63OcjmUhv7tsOE6rKCc3Q2yi7Qe9i6BNAQFYMFATztb18MsxsBHKUxNqklqyVnl0ofETAHmQhfOHLmungOJQnOqAAuwfmRtg50Qci5F+R2mXeqjmIXko/u3E+DLYW1ygDBp3afKZmU4PwmA=="
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$return = curl_exec($ch);
print_r($return);
var url = "http://api.xxxx.com/shopapi/transfer/list"
data := map[string]string{
"version": "1.0",
"app_id": "hxgmau9imt86qky9",
"time": "1578736053",
"page": "1",
"sign": "OTA8utI8y8G93p7RPCyb4qIilFQ0B4Aq4iUjhaXWK9m2kgektqlHOASDKXT2VE7NPNysrGycYlVfjDR2WGZn1G66phHo3qa9CcCNpG9klOBEuBEMjiVbb/d8AXcxEzvQr9OCwNsikyxonyzLiY/lsNHeGm9cC5eRvlNLdUSVBipH+ajPd0lDHCayZPs1eCMfbm/xnf8e2lfy6z0UPOpHGfyX/0+hz99Ir5Xnx+0sBBzyZZJxKm4ROid5aDv/9m9guILpURae+Yw/IrkYF4uAKGX+/44cBvtTRQSdX76CAOBSiywZa6BAgDYBLRtkAPM+i+vwNzFBovqHUvI+4Ponaw==",
}
dataType, _ := json.Marshal(data)
resp, err := http.Post(url, "application/json", strings.NewReader(string(dataType)))
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(body))
let HTTP = require('http')
let postData = {
"version": "1.0",
"app_id": "hxgmau9imt86qky9",
"time": "1578736053",
"page": "1",
"sign": "OTA8utI8y8G93p7RPCyb4qIilFQ0B4Aq4iUjhaXWK9m2kgektqlHOASDKXT2VE7NPNysrGycYlVfjDR2WGZn1G66phHo3qa9CcCNpG9klOBEuBEMjiVbb/d8AXcxEzvQr9OCwNsikyxonyzLiY/lsNHeGm9cC5eRvlNLdUSVBipH+ajPd0lDHCayZPs1eCMfbm/xnf8e2lfy6z0UPOpHGfyX/0+hz99Ir5Xnx+0sBBzyZZJxKm4ROid5aDv/9m9guILpURae+Yw/IrkYF4uAKGX+/44cBvtTRQSdX76CAOBSiywZa6BAgDYBLRtkAPM+i+vwNzFBovqHUvI+4Ponaw==",
};
let POST_OPTIONS = {
port: 80,
host: "api.xxxx.com",
path: "/shopapi/transfer/list",
method: 'POST',
headers: {
"Content-Type": "application/json; charset=utf-8"
}
};
const REQUEST = HTTP.request(POST_OPTIONS,function (res) {
let data = []
res.on('data', chunk => {
data.push(...chunk)
})
res.on('end', () => {
let _date = JSON.parse( new TextDecoder().decode(new Uint8Array(data)))
console.log(_date)
})
});
REQUEST.setTimeout(6000)
REQUEST.write(JSON.stringify(postData), 'utf8')
REQUEST.end()
public static void main(String[] args) {
// 完整实例请查看"签名规则"中的Java示例代码
String baseUrl = "http://api.xxxx.com/shopapi";
String priKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtdgvcfozY7fe/x6UlXR/Fff8+wX++CiG05YVRafDe90O8y5KJAMZ156TgajEUXSRyKZqASz7iVoMAcu5FqfK1KuOOdjTAg0LFe/twIZvKmAqHcCSS2pjUXk0fTpZEgQ5lmDCK12Mg07YXvr+BeHjF+kBpwRJMPMG/+DGBDYNFNeRSJqWyopt6yyF528soAykHIUQ7TTultJV5IPCrvjRQQrGdJ/QtCdE0vZg+tA09nFN7AqgraU99kIvzyS0sqysj+pP1SJRmTRSGtlVAO3mILfkXOekZl1KD60G7CF+7BIaaW83FPD55tZhAGhnbLMYyiq7OiIyU61LTRcNSaJ0tAgMBAAECggEBAIGgGKcSzxCBbMYdXLV6TPbZ/HeaRGrwyVWUu7cmc0E8CJu6iWvmb2jGzbiCwuCT5luF6ZZ8JKchvU4FlTfsE5r9TQY2IZ/Ht4s65qBaDUEts5iY3kv8HX9+ZSXDJZpV0ztqqsPmx4ZNj+NYwWXwcFiKdb5R8OmV8bgSsnPddD6wFhwewglUOBPRAjropHE4sqk1Vam6q1MlFq5kiekMn/CItyFYFFzST/ruqAtVTp7YIvazAMrfCKH+pvXWk6pYNHZmL/JZey0GglRyJ1nItiqL33X8Lji056FcbAclidq022h/KPLEJpZk6irWqYdqYZeF6YMLHtdZFDkTZ/hXY+UCgYEA5i794UTQ1Kd6K+iui/S8K5H8nGdiXb3+uZ5j5VKYfbRmzXhAdVYisYe8czeTECxhH+MeHgM4tLR4ifx9q60ylvZxl9Fav1p6EaE36YcvGVmpm7Gm3q6QDDBa4gB+X9u7CxCS4LpotV917YS1QvOIF9lnRonSj1zNzFtbXkywrN8CgYEAwOpx/mR40ZvgZxNCq9DsIdrSZYAFFKpw0xy0OtF1PpuwMaREoRabnlVw6Bb3Hofg50XA3JxemzAX6fB92ee+NfXfeL4UtC4vG1K9JyiXHtHq8p9Uw2W03ehIEeNa3xdoRRnLmD4VUpyfL19ViE2+7TM1Gd3TogjDT+AMOCSuq3MCgYBsurPH7gaq/LVT+mRAzgj4l8v4YUlwuGeTbIMJdvt7HXUWB4CDLH3U2CYnUpAQKrZyJok6ahEmIr1xiKggKP7lmmHL8eNo0icpHrtXfzi7Q8Q/PCpzs4dtioXTjaIkS5nNvzVyG/uL+RyuZmpsxrZ5dYM4KbAhchfwORMutxEZhwKBgQC5zpVw4jCEItBmNuTWO+nTScGvxTgfiXIVw+XLaQa2AJoZlhAL34yPWdffko79tv3lgweY9HsimZXO2rU8dbp8mo5c6ydhy8HPXUeWOcAkDSdv/ApWENW9jgYsRIC3swHY3Fl+Dv3Wjce8huQI3mjwaYvRmBhIToxfmHnscVhTBQKBgB9uciEHfz8hMI7ePrPo2PkyK/RbJDm3HnuWE2lFBp7MOUMlh53MXwv4dIRaYMbRrFuN1UIKEFxuKhWwTHSzZJufk/UENrha/81fpj2BoFsAKkEunKeETvaIh6fZSjec16h2+zxbzwkdS6b+yIYkSlaoAxmDYrMtae0C8G4e0YS9";
String pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2RZZISModRzproL3eTxRtvVK/nToDbeLmAVdmaVtHgNCwjXMeNCZvHySZKO7+t7XySzBd2PhhQjvAkDd8HRKB5Y0uvP6TFwvhxOMkMydTeBFcUobQWNeAI7ttRms1txSNrmyrZr0WpWfk79VIsO+yI/jFN/Pj2gxD+vh5UUKU1LD2IQq/VxgtEpf8Vs6w7SvafPwYkpdPGCKUFkRvN1FrY2+tq0j1MRVJbB2rIunWDnT8cDUh2sWLXf4yNaJVOaaTFB0zbAk/qcoicGQyW7bVG7dVW8WywKmOAPeQCCQa+SJ4BhfI1k8eEAwFVRuxz/f9Ecfog9hZJ+RgELkpS8qhQIDAQAB";
rsaSigner signer = new rsaSigner();
Map<String, Object> params = new HashMap<>();
params.put("app_id", "hxgmau9imt86qky9");
params.put("version", "1.0");
params.put("key_version", "admin");
params.put("time", Long.toString(System.currentTimeMillis() / 1000));
params.put("page", "1");
try {
params.put("sign", signer.genSign(params, priKey));
Gson gson = new GsonBuilder().create();
System.out.println("params = " + gson.toJson(params));
String res = doPost(baseUrl + "/transfer/list", gson.toJson(params));
if (null == res) {
throw new RuntimeException("http error");
}
System.out.println("response = " + res);
JsonParser jp = new JsonParser();
JsonObject resEle = jp.parse(res).getAsJsonObject();
boolean retSignOK = signer.verifySign(resEle, resEle.get("sign").getAsString(), pubKey);
if (!retSignOK) {
throw new RuntimeException("verify response sign fail");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("OK");
}
返回结果示例:
{
"status": 200,
"msg": "处理成功",
"data": {
"page": 1,
"max_page": 1,
"count": 1,
"list": [{
"trade_id": "20200114202903274786",
"coin": "hc",
"chain": "hc",
"txid": "",
"amount": "0.02",
"fee": "0",
"total": "0.02",
"address": "HsRDEePh7WBCsdJPfo1UsjfurwLBU6HD5Vi",
"from_address": "the transaction from address",
"status": "2",
"time": "1658482253",
"type": "2",
"gas_fee": "0.1"
}]
},
"date_time": "2022-07-22 18:36:36",
"time_stamp": 1658486196,
"sign": "uuYWvmoMqM5xh7aTcxspJmW78y8op5BBjYXp0XoqcqFXe+HrSGzxN2Ls6LA7SlfsNndCtS4AX1/J+2o1MWZw/HFVfRqtxu02AEfWhM5ZSiJfEtO8f47H2/EGcsKw/eK8nxOnYAyAKwG6Ia6L4KgYIXLwsGt6Dt0VYWADu+vEQEes83/c6+Tc8QdqpdnLbs2XXXkYkl5eijoja+QEMaENbx+DHxnsVZV0iRK5FcSQH9PdOIpWmC944BA2v0tnPQWb6WDnOTsw5xoVKiL57WGIeOaxepvjo6poi1a/+HYrowT4IcejZZHi9YW0iM4eNm8MPK0tloAQ8GWY7kVs9uEwOA=="
}
通过此接口查询查询订单状态情况,可以只查一个,也可以模糊查询多个。
HTTP Request
POST: /transfer/list
请求参数
| 参数名 | 必选 | 类型 | 说明 |
|---|---|---|---|
| 公共参数 | 是 | string | 公参指:签名(sign)、版本(version)、商户ID(app_id)、时间(time) |
| trade_id | 否 | string | 如果传trade_id为精准查找,下面参数失效 |
| page | 否 | int | 1<= N <=Max,对于超过Max的取Max,小于1或没有传参数的返回1 |
| status | 否 | int | 0 待审核 1 提现成功、2 等待风控处理中、5 等待出币、10 审核不通过、20 转账失败 |
| start_time | 否 | int | 开始时间(创建时间) 格式 :时间戳 |
| end_time | 否 | int | 结束时间(创建时间) 格式 :时间戳 |
| page_size | 否 | int | 每页数量 (20 ~100),默认 20 |
| sort_num | 否 | int | 列表排序规则 默认按入系统时间正序排列( 1 正序 ; 2 倒序) |
返回参数说明
| 参数名 | 类型 | 说明 |
|---|---|---|
| status | int | 状态码 |
| msg | string | 状态描述 |
| data | jsonObject | trade_id-由商户提供 |
| data.page | int | 第几页 |
| data.count | int | 本页记录数 |
| data.list | jsonArray | 具体每条记录 |
| data.list.trade_id | string | 交易id |
| data.list.coin | string | 币种 |
| data.list.txid | string | 链上txid |
| data.list.amount | string | 总金额 |
| data.list.fee | string | 手续费 (业务规则fee不是链上gasfee),外扣模式 |
| data.list.total | string | 提现总金额 total = amount+fee |
| data.list.address | string | 提现收款地址 |
| data.list.from_address | string | 提现出款地址,正式环境2025-01-22之后接入的商户才会返回该属性 |
| data.list.chain | string | 主链币名 |
| data.list.memo | string | memo/tag 当前为 eos 及其代币 时 会回传该字段 |
| data.list.status | enum | 0 待审核、1 提现成功、2 等待风控处理中、5 等待出币、10 审核不通过、20 转账失败 |
| data.list.time | time_stamp | 状态时间,最终固定在status=1时候的时间 |
| data.list.type | string | 1站内交易 2链上交易 5中心化提现 |
| data.list.gas_fee | string | 链上消耗Gas费,正式环境2024-08-14接入的商户才会返回该属性,精度统一8位 |
| date_time | string | 响应时间 |
| time_stamp | int | 无时区的秒 |
| sign | string | 签名 |
提现结果回调通知
$url = "商家后台配置的提现回调URL";
$header = [
'Content-Type:application/json',
];
$params = [
"data" => [
"trade_id" => "this is trade_id",
"coin" => "eth",
"txid" => "this is txid",
"address" => "this is to address",
"from_address" => "this is from address"
"time" => "1591779242",
"amount" => "10.1",
"fee" => "0",
"total" => "10.1",
"status" => "1",
"msg" => "提示信息",
"type" => 1,
"gas_fee" => "0.1",
],
"sign" => "dLtK+uiPcnxt2ACKMbBqQ6wI5ttAvesOHzK5ybVID1R6hqYPDTkagl7Tsjr5iLJafehcSLTZyJLtCRI8O2CtIWQUUroGXBneHZC486NUi/4FMOQs0FaAgm17pWlbhX5/96cWXXXMVeoe3IZFKaFNYSWaA14v3RcdDU6QDE/9ixGiSJ0DIxm9NKA0+RkbIFbyYeuFn8d63OcjmUhv7tsOE6rKCc3Q2yi7Qe9i6BNAQFYMFATztb18MsxsBHKUxNqklqyVnl0ofETAHmQhfOHLmungOJQnOqAAuwfmRtg50Qci5F+R2mXeqjmIXko/u3E+DLYW1ygDBp3afKZmU4PwmA=="
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$return = curl_exec($ch);
print_r($return);
var url = "商家后台配置的提现回调URL"
data := map[string]interface{}{
"data": map[string]string{
"trade_id":"this is trade_id",
"coin":"eth",
"txid":"this is txid",
"address":"this is to address",
"from_address":"this is from address",
"time":"1591779242",
"amount":"10.1",
"fee":"0",
"total":"10.1",
"status":"1",
"msg":"提示信息",
"type":"1",
"gas_fee":"0.1",
},
"sign": "OTA8utI8y8G93p7RPCyb4qIilFQ0B4Aq4iUjhaXWK9m2kgektqlHOASDKXT2VE7NPNysrGycYlVfjDR2WGZn1G66phHo3qa9CcCNpG9klOBEuBEMjiVbb/d8AXcxEzvQr9OCwNsikyxonyzLiY/lsNHeGm9cC5eRvlNLdUSVBipH+ajPd0lDHCayZPs1eCMfbm/xnf8e2lfy6z0UPOpHGfyX/0+hz99Ir5Xnx+0sBBzyZZJxKm4ROid5aDv/9m9guILpURae+Yw/IrkYF4uAKGX+/44cBvtTRQSdX76CAOBSiywZa6BAgDYBLRtkAPM+i+vwNzFBovqHUvI+4Ponaw==",
}
dataType, _ := json.Marshal(data)
resp, err := http.Post(url, "application/json", strings.NewReader(string(dataType)))
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(body))
let HTTP = require('http')
let postData = {
"data": {
"trade_id":"this is trade_id",
"coin":"eth",
"txid":"this is txid",
"address":"this is from address",
"from_address":"this is from address",
"time":"1591779242",
"amount": "10.1",
"fee":"0",
"total":"10.1",
"status":"1",
"msg":"Prompt information",
"type":"1",
"gas_fee":"0.1",
},
"sign": "OTA8utI8y8G93p7RPCyb4qIilFQ0B4Aq4iUjhaXWK9m2kgektqlHOASDKXT2VE7NPNysrGycYlVfjDR2WGZn1G66phHo3qa9CcCNpG9klOBEuBEMjiVbb/d8AXcxEzvQr9OCwNsikyxonyzLiY/lsNHeGm9cC5eRvlNLdUSVBipH+ajPd0lDHCayZPs1eCMfbm/xnf8e2lfy6z0UPOpHGfyX/0+hz99Ir5Xnx+0sBBzyZZJxKm4ROid5aDv/9m9guILpURae+Yw/IrkYF4uAKGX+/44cBvtTRQSdX76CAOBSiywZa6BAgDYBLRtkAPM+i+vwNzFBovqHUvI+4Ponaw==",
};
let POST_OPTIONS = {
port: 80,
host: "商家后台配置的提现回调URL",
path: "",
method: 'POST',
headers: {
"Content-Type": "application/json; charset=utf-8"
}
};
const REQUEST = HTTP.request(POST_OPTIONS,function (res) {
let data = []
res.on('data', chunk => {
data.push(...chunk)
})
res.on('end', () => {
let _date = JSON.parse( new TextDecoder().decode(new Uint8Array(data)))
console.log(_date)
})
});
REQUEST.setTimeout(6000)
REQUEST.write(JSON.stringify(postData), 'utf8')
REQUEST.end()
public static void main() {
String priKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtdgvcfozY7fe/x6UlXR/Fff8+wX++CiG05YVRafDe90O8y5KJAMZ156TgajEUXSRyKZqASz7iVoMAcu5FqfK1KuOOdjTAg0LFe/twIZvKmAqHcCSS2pjUXk0fTpZEgQ5lmDCK12Mg07YXvr+BeHjF+kBpwRJMPMG/+DGBDYNFNeRSJqWyopt6yyF528soAykHIUQ7TTultJV5IPCrvjRQQrGdJ/QtCdE0vZg+tA09nFN7AqgraU99kIvzyS0sqysj+pP1SJRmTRSGtlVAO3mILfkXOekZl1KD60G7CF+7BIaaW83FPD55tZhAGhnbLMYyiq7OiIyU61LTRcNSaJ0tAgMBAAECggEBAIGgGKcSzxCBbMYdXLV6TPbZ/HeaRGrwyVWUu7cmc0E8CJu6iWvmb2jGzbiCwuCT5luF6ZZ8JKchvU4FlTfsE5r9TQY2IZ/Ht4s65qBaDUEts5iY3kv8HX9+ZSXDJZpV0ztqqsPmx4ZNj+NYwWXwcFiKdb5R8OmV8bgSsnPddD6wFhwewglUOBPRAjropHE4sqk1Vam6q1MlFq5kiekMn/CItyFYFFzST/ruqAtVTp7YIvazAMrfCKH+pvXWk6pYNHZmL/JZey0GglRyJ1nItiqL33X8Lji056FcbAclidq022h/KPLEJpZk6irWqYdqYZeF6YMLHtdZFDkTZ/hXY+UCgYEA5i794UTQ1Kd6K+iui/S8K5H8nGdiXb3+uZ5j5VKYfbRmzXhAdVYisYe8czeTECxhH+MeHgM4tLR4ifx9q60ylvZxl9Fav1p6EaE36YcvGVmpm7Gm3q6QDDBa4gB+X9u7CxCS4LpotV917YS1QvOIF9lnRonSj1zNzFtbXkywrN8CgYEAwOpx/mR40ZvgZxNCq9DsIdrSZYAFFKpw0xy0OtF1PpuwMaREoRabnlVw6Bb3Hofg50XA3JxemzAX6fB92ee+NfXfeL4UtC4vG1K9JyiXHtHq8p9Uw2W03ehIEeNa3xdoRRnLmD4VUpyfL19ViE2+7TM1Gd3TogjDT+AMOCSuq3MCgYBsurPH7gaq/LVT+mRAzgj4l8v4YUlwuGeTbIMJdvt7HXUWB4CDLH3U2CYnUpAQKrZyJok6ahEmIr1xiKggKP7lmmHL8eNo0icpHrtXfzi7Q8Q/PCpzs4dtioXTjaIkS5nNvzVyG/uL+RyuZmpsxrZ5dYM4KbAhchfwORMutxEZhwKBgQC5zpVw4jCEItBmNuTWO+nTScGvxTgfiXIVw+XLaQa2AJoZlhAL34yPWdffko79tv3lgweY9HsimZXO2rU8dbp8mo5c6ydhy8HPXUeWOcAkDSdv/ApWENW9jgYsRIC3swHY3Fl+Dv3Wjce8huQI3mjwaYvRmBhIToxfmHnscVhTBQKBgB9uciEHfz8hMI7ePrPo2PkyK/RbJDm3HnuWE2lFBp7MOUMlh53MXwv4dIRaYMbRrFuN1UIKEFxuKhWwTHSzZJufk/UENrha/81fpj2BoFsAKkEunKeETvaIh6fZSjec16h2+zxbzwkdS6b+yIYkSlaoAxmDYrMtae0C8G4e0YS9";
String pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArXYL3H6M2O33v8elJV0fxX3/PsF/vgohtOWFUWnw3vdDvMuSiQDGdeek4GoxFF0kcimagEs+4laDAHLuRanytSrjjnY0wINCxXv7cCGbypgKh3AkktqY1F5NH06WRIEOZZgwitdjINO2F76/gXh4xfpAacESTDzBv/gxgQ2DRTXkUialsqKbesshedvLKAMpByFEO007pbSVeSDwq740UEKxnSf0LQnRNL2YPrQNPZxTewKoK2lPfZCL88ktLKsrI/qT9UiUZk0UhrZVQDt5iC35FznpGZdSg+tBuwhfuwSGmlvNxTw+ebWYQBoZ2yzGMoquzoiMlOtS00XDUmidLQIDAQAB";
rsaSigner signer = new rsaSigner();
Map<String, Object> data = new HashMap<>();
data.put("trade_id","this is trade_id");
data.put("coin","eth");
data.put("txid","this is txid");
data.put("address","this is to address");
data.put("from_address","this is from address");
data.put("time","1591779242");
data.put("amount", "10.1");
data.put("fee","0");
data.put("total","10.1");
data.put("status","1");
data.put("msg","Prompt information");
data.put("type","1");
data.put("gas_fee","0.1");
try {
Map<String, Object> params = new HashMap<>();
params.put("data", data);
params.put("sign", signer.genSign(data, priKey));
Gson gson = new GsonBuilder().create();
System.out.println("params = " + gson.toJson(params));
String res;
// platform request shop callback API
// res = doPost("http://api.shophost.com/withdraw/callback", gson.toJson(params));
// if (null == res) {
// throw new RuntimeException("http error");
// }
// mock response from shop callback API
{
res = """
{
"status":200,
"sign": "A3wCWwcw1w7Ee/xDDWBpf80i2Wc1oqpcqChznv9mr7dgLcKPQAECtemvmRTPwAxsZm6SJeGSN7P3ssB8/wmyZcJiVykr1HWbcQNL/YNYb6MCJqBXpbpnOwaBSWGr+aOh/1ql1ciW04W/rhF8rHch13Se+ZQ1TmJ5/JooEssCxaIRI4EiwGM47cpFSpuMv1e0UMsozCNvudAZDhwh/fDU4eIk2n3qikFEN6uAkG2gN2Y0dseG1/ua1RLYn97lb6oU4cYTpmrlGYZCMzc+cvhDkBL83UsU1hiVYMQtTJ5jtrUe5sumkYuVqkT0VjZklszvKtDDblK/KYXtZ2kRkWn2kg==",
"data":{
"success_data":"success"
}
}
""";
}
System.out.println("response = " + res);
JsonParser jp = new JsonParser();
JsonObject resEle = jp.parse(res).getAsJsonObject();
boolean retSignOK = signer.verifySign(resEle.get("data"), resEle.get("sign").getAsString(), pubKey);
if (!retSignOK) {
throw new RuntimeException("verify response sign fail");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("OK");
}
返回结果示例:
{
"status":200,
"sign": "OTA8utI8y8G93p7RPCyb4qIilFQ0B4Aq4iUjhaXWK9m2kgektqlHOASDKXT2VE7NPNysrGycYlVfjDR2WGZn1G66phHo3qa9CcCNpG9klOBEuBEMjiVbb/d8AXcxEzvQr9OCwNsikyxonyzLiY/lsNHeGm9cC5eRvlNLdUSVBipH+ajPd0lDHCayZPs1eCMfbm/xnf8e2lfy6z0UPOpHGfyX/0+hz99Ir5Xnx+0sBBzyZZJxKm4ROid5aDv/9m9guILpURae+Yw/IrkYF4uAKGX+/44cBvtTRQSdX76CAOBSiywZa6BAgDYBLRtkAPM+i+vwNzFBovqHUvI+4Ponaw==",
"data":{
"success_data":"success"
}
}
- 异步用户提现结果通知功能,提现最终确定成功或失败均通知商户方。
- 其中因商户方原因导致的提现失败,有商户方进行处理,反之有平台方处理。
HTTP Request
POST: 具体回调地址,由商户提供给平台方
请求参数
| 参数名 | 必选 | 类型 | 说明 |
|---|---|---|---|
| data | 否 | string | 如下 |
| data.trade_id | 是 | string | 交易ID |
| data.coin | 是 | string | 币名 |
| data.chain | 是 | string | 主链币名 |
| data.txid | 是 | string | txid |
| data.address | 是 | string | 提现收款地址 |
| data.from_address | 是 | string | 交易出款地址,正式环境2025-01-22之后接入的商户才会返回该属性 |
| data.time | 是 | string | 订单最后更新时间 |
| data.amount | 是 | string | 提现数额,精度统一8位 |
| data.fee | 是 | string | 手续费,精度统一8位 |
| data.total | 是 | string | 提现总额 total=amount+fee,精度统一8位 |
| data.status | 是 | string | 提现状态 : 1 成功;5 出币处理中(此时会推送 txid,但是txid值以最终确认时为准。主要考虑前端展示对用户友好,像btc 类等链交易确认较慢);10 审核不通过;20 转账失败 ;其他错误码(参考错误码说明) |
| data.msg | 是 | string | 状态描述 |
| data.type | 是 | int | 1站内充值 2链上充值 |
| data.gas_fee | 否 | string | 链上消耗Gas费,正式环境2024-08-14接入的商户才会返回该属性,精度统一8位 |
| sign | 是 | string | 对data内数据签名 |
返回参数说明
| 参数名 | 必选 | 类型 | 说明 |
|---|---|---|---|
| status | 是 | int | 状态码 |
| sign | 是 | string | RSA对返回数据的签名 |
| data | 是 | JSONObject | 返回数据对象 |
| data.success_data | 是 | string | success 接收成功 |
- 对于转账失败的情况和处理办法
| 类型 | 内容 | 商户处理办法 |
|---|---|---|
| 成功 | 对应trade_id的status=1 | 商户端可以认为一定成功 |
| 成功后变1 | 因链故障回滚,txid变化。trade_id和状态不变 | 商户端可以认为一定成功,只需更新txid |
| 成功后变2 | 平台广播失败,平台处理 | 商户端可以认为一定成功,只需更新txid |
| 失败1 | 因商户给错地址,把btc地址给了eth | 平台不扣款,这种需要商户端重新请求 |
| 失败2 | 因用户余额不足 | 平台不扣款,这种需要商户端重新请求 |
简单来说:商户端错误导致失败,都有商户端重新请求处理。平台端错误由平台处理。对平台处理来说订单是绝对唯一的。txid是可能会变化的。
* 异步通知时间点
平台端执行发现客户端错误,或平台端确定成功后或成功后变。