Links

支付API

请求说明

  • 本文档适用于已经在SWFT官方申请过渠道号channelId与私钥的合作方
  • 合作方要求:提供渠道名称、在SWFT注册账户

流程图

接入流程:

①开发者调用SWFT创建支付订单接口,创建支付订单;
②SWFT返回支付页面链接,用户进行付款;
③获取支付结果,以下两种方式都可行:
ⅰ开发者提供支付完成通知接口,用户完成支付后,SWFT调用该接口进行通知;
ⅱ 开发者调用查询订单状态接口,获取订单支付结果状态。

接口列表

请求类型
请求方法
描述
接口示例
POST application/json
api/pay/createPayOrder
创建支付订单
代码示例
POST application/json
api/pay/queryPayOrder
查询订单状态
代码示例
POST application/json
由开发者提供
支付完成通知

创建支付订单

api/pay/createPayOrder

说明

合作方调用该接口,创建收款订单

请求参数

参数名称
是否必须
数据类型
描述
默认值
取值范围
channelId
String
渠道编号
由SWFT官方提供,eg:payaaa201903212028
channelName
String
渠道名称简写
开发者提供给SWFT官方,eg:xxMall
sign
String
签名
参见签名生成
timestamp
Long
时间戳
毫秒时间戳
channelOrderId
String
渠道订单Id
开发者自定义
channelUserNo
String
渠道用户名
开发者自定义
coinCode
String
付款币种名称
eg:SWFTC
amount
String
付款金额
eg:2000
remark
String
备注
订单备注

响应参数

{
"data": {
"amount": "2",
"channelOrderId": "channelorder001",
"channelUserNo": "xxMall_zhangsan",
"coinCode": "SWFTC",
"payId": "jpedyB3T",
"payUrl": "{host}/swft-v3/PayAPI.html?payID=jpedyB3T",
"remark": "zhangsan pay to xxMall"
},
"resCode": "800",
"resMsg": "成功"
}

data说明

{
"amount": "付款金额",
"channelOrderId": "渠道订单号",
"channelUserNo": "渠道用户名",
"coinCode": "付款币种",
"payId": "支付订单号",
"payUrl": "支付页面链接",
"remark": "备注"
}

查询订单状态

api/pay/queryPayOrder

说明

查询支付订单状态接口

请求参数

参数名称
是否必须
数据类型
描述
默认值
取值范围
payId
String
支付订单Id
eg : Nlt0OnQP
channelId
String
渠道编号
eg:payaaa201903212028
sign
String
签名
参见签名生成
timestamp
String
时间戳
毫秒时间戳

响应参数

{
"data": {
"amount": "2",
"channelId": "payaaa201903212028",
"channelName": "xxMall",
"coinCode": "SWFTC",
"createTime": "2019-03-22 17:11:38",
"payId": "XMdqbM8Q",
"remark": "zhangsan pay to xxMall",
"sign": "DB99639E8B9EC419F88C94355DF1C483ACD420B7366C27CAB8E86A6D7B84CB52",
"status": "complete",
"timestamp": 1553838107450,
"transType": "PAY_IN",
"userNo": "5****@qq.com"
},
"resCode": "800",
"resMsg": "成功"
}

data说明

{
"amount": "付款金额",
"channelOrderId": "渠道订单号",
"channelUserNo": "渠道用户名",
"coinCode": "付款币种",
"createTime": "创建时间",
"payId": "支付订单号",
"remark": "备注",
"sign": "签名",
"status": "支付订单状态",
"timestamp": 时间戳,
"transType": "订单类型",
"userNo": "第三方在swft开户账号"
}

支付完成通知

说明

订单支付完成通知接口

请求参数

参数名称
是否必须
数据类型
描述
默认值
取值范围
payId
String
支付订单号
eg: Nlt0OnQP
status
String
支付订单状态
状态: valid-有效,complete-支付完成,invalid-超时无效
sign
String
签名
timestamp
String
时间戳
毫秒时间戳

响应参数

{
"data": “响应完成”,
"resCode": "800",
"resMsg": "成功"
}

data说明

{
"data": “响应信息”,
"resCode": "返回状态码",//800:表示成功,其他表示失败
"resMsg": "返回结果信息"
}

错误码说明

HTTP请求错误码

错误码
含义
说明
200
成功
403
资源不可用
header头信息错误或不全
404
资源未找到
url错误
405
请求方式错误
GET、POST方式替换
500
服务器错误
需联系平台客服

接口返回数据resCode码

错误码
含义
说明
800
成功
请求成功
900
服务器错误
服务器错误
213
非法请求
签名认证失败
214
币种不存在
币种与SWFT官方币种不一致
216
金额数量不合法
付款金额不合法
907
必填字段为空
参数请求不全
1002
订单不存在
支付订单未创建或订单号错误
1017
第三方渠道未在SWFT开户或SWFT账号不存在
需要检查是否在SWFT开户
1018
第三方渠道SWFT账号未配置
需要联系SWFT官方进行配置
1019
第三方渠道号未配置
需要联系SWFT官方进行配置
1031
备注长度超出50个字符
备注长度超限
1032
第三方渠道支付页面地址未配置
需要联系SWFT官方进行配置

生成签名

按照ASCII码的顺序对参数名进行排序,转化为json字符串,使用私钥签名,采用HMAC-SHA256加密方式。

签名生成步骤说明

第一步:
设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特别注意以下重要规则:
  1. 1.
    参数名ASCII码从小到大排序(字典序);
  2. 2.
    app_id,timestamp为必填参数;timestamp为最近五分钟时间戳,超过5分钟失效;
  3. 3.
    如果参数的值为空不参与签名;
  4. 4.
    参数名区分大小写;
  5. 5.
    传送的sign参数不参与签名,将生成的签名与该sign值作校验。
第二步:
在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行HMAC-SHA256运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。
伪代码举例
假设传送的参数如下: channelId: mttest timestamp : 1516320000 body : test
第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:
stringA="app_id=mttest&body=test&timestamp=1516320000";
第二步:拼接API密钥:
stringSignTemp=stringA+"&secret=my_test_secret"
sign=hash_hmac("sha256",stringSignTemp,key).toUpperCase()="6A9AE1657590FD6257D693A078E1C3E4BB6BA4DC30B23E0EE2496E54170DACD6" //注:HMAC-SHA256签名方式
示例代码
@Test
public void deductBalance() throws IOException {
JTextField field ;
String url = "http://localhost:8088/channel/deductBalance";
TreeMap<String,Object> params = Maps.newTreeMap();
params.put("orderId","my_order_id");
params.put("channelId","test91021071617412");
long timestamp = System.currentTimeMillis();
params.put("timestamp",timestamp);
String channelSign = getChannelSign(params, secret);
params.put("sign",channelSign);
System.out.println(url);
System.out.println(JSON.toJSONString(params));
String result = HttpUtils.sendRequestBody(url, params);
System.out.println(result);
}
public static String getChannelSign(Map<String, Object> params,String secret) {
StringBuilder result = new StringBuilder();
if (params != null) {
for (Object key : params.keySet()) {
Object value = params.get(key);
result.append(key).append("=").append(value).append("&");
}
String tempString = result + "secret=" + secret;
try {
System.out.println(tempString);
String sign = EncryptUtils.sha256_HMAC(tempString, secret).toUpperCase();
System.out.println(sign);
return sign;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
代码中参与加密的参数及顺序为:channelId=test91021071617412&orderId=my_test_id&timestamp=1547987604644&secret=my_secret