1. 将发送或接收到的所有参数按照参数名按照ASCII码从小到大排序(a-z) sign sign_type 空值 不参与签名.
2. 将排序后的参数拼接成URL键值对的格式; 如: k1=v1&k2=v2&k3=v3..... 得到待签名字符串 strA.
3. 将签名字符串 strA 后面拼接 商户密钥 得到待签名字符串 strB.
4. 将待签名字符串 strB 进行 MD5 就得到签名值 sign.
5. 参数值不要进行url编码。
例如: sign = md5(key1=value1&key2=value2...商户密钥)
接口说明
此接口可用于用户前台直接发起支付,使用form表单跳转或拼接成url跳转。
URL地址:/submit.php
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | pid | 是 | String | 1001 | |
| 支付方式 | type | 是 | String | alipay | 找客服获取 |
| 商户订单号 | out_trade_no | 是 | String | 20160806151343349 | |
| 异步通知地址 | notify_url | 是 | String | http://www.pay.com/notify_url.php | 服务器异步通知地址 |
| 跳转通知地址 | return_url | 是 | String | http://www.pay.com/return_url.php | 页面跳转通知地址 |
| 商品名称 | name | 是 | String | VIP会员 | 如超过127个字节会自动截取 |
| 商品金额 | money | 是 | String | 1.00 | 单位:元,最大2位小数 |
| 业务扩展参数 | param | 否 | String | 没有请留空 | 支付后原样返回 |
| 签名字符串 | sign | 是 | String | 202cb962ac59075b964b07152d234b70 | 签名算法 sign = md5 (a=b&c=d&e=f+商户密钥 ) |
| 签名类型 | sign_type | 是 | String | MD5 | 默认为MD5 |
接口说明
此接口可用于服务器后端发起支付请求,会返回支付链接。
URL地址:/mapi.php
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | pid | 是 | Int | 1001 | |
| 支付方式 | type | 是 | String | alipay | 找客服获取 |
| 商户订单号 | out_trade_no | 是 | String | 20160806151343349 | |
| 异步通知地址 | notify_url | 是 | String | http://www.pay.com/notify_url.php | 服务器异步通知地址 |
| 跳转通知地址 | return_url | 否 | String | http://www.pay.com/return_url.php | 页面跳转通知地址 |
| 商品名称 | name | 是 | String | VIP会员 | 如超过127个字节会自动截取 |
| 商品金额 | money | 是 | String | 1.00 | 单位:元,最大2位小数 |
| 用户IP地址 | clientip | 是 | String | 192.168.1.100 | 用户发起支付的IP地址 |
| 设备类型 | device | 否 | String | pc | 根据当前用户浏览器的UA判断, 传入用户所使用的浏览器 或设备类型,默认为pc |
| 业务扩展参数 | param | 否 | String | 没有请留空 | 支付后原样返回 |
| 签名字符串 | sign | 是 | String | 202cb962ac59075b964b07152d234b70 | 签名算法 sign = md5 (a=b&c=d&e=f+商户密钥 ) |
| 签名类型 | sign_type | 是 | String | MD5 | 默认为MD5 |
返回结果(json)
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 1 | 1为成功,其它值为失败 |
| 返回信息 | msg | String | 失败时返回原因 | |
| 订单号 | trade_no | String | 20160806151343349 | 支付订单号 |
| 支付跳转url | payurl | String | https://www.pay.com/pay/wxpay/202010903/ | 如果返回该字段,则直接跳转到该url支付 |
| 二维码链接 | qrcode | String | weixin://wxpay/bizpayurl?pr=04IPMKM | 如果返回该字段,则根据该url生成二维码 |
| 小程序跳转url | urlscheme | String | weixin://dl/business/?ticket=xxx | 如果返回该字段,则使用js跳转该url,可发起微信小程序支付 |
接口说明
查询单个订单。
URL地址:/api.php
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 操作类型 | act | 是 | String | act | 此API固定值 |
| 商户ID | pid | 是 | String | 1001 | 系统分配的唯一商户ID |
| 商户密钥 | key | 是 | String | 89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i | 系统分配的唯一签名密钥 |
| 系统订单号 | trade_no | 否 | String | P1988492264548581376 | 系统唯一订单号 |
| 商户订单号 | out_trade_no | 否 | String | 20160806151343349 | 合作商系统中唯一订单号 |
提示:系统订单号 和 商户订单号 二选一传入即可,如果都传入以系统订单号为准!
返回结果(json)
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 1 | 1为成功,其它值为失败 |
| 返回信息 | msg | String | 失败时返回原因 | |
| 订单号 | trade_no | String | P1988492264548581376 | 系统订单号 |
| 商户订单号 | out_trade_no | String | 20160806151343349 | 商户系统内部的订单号 |
| 支付方式 | type | String | alipay | 支付方式 |
| 商户ID | pid | String | 1001 | 发起支付的商户ID |
| 创建订单时间 | addtime | String | 2016-08-06 22:55:52 | 订单下单时间 |
| 完成交易时间 | endtime | String | 2016-08-06 22:55:52 | 未支付的订单此值是空 |
| 商品名称 | name | String | VIP会员 | 下单传入的值 |
| 商品金额 | money | String | 商品金额 | 商品下单金额 |
| 支付状态 | status | Int | 0 | 1为支付成功,0为未支付 |
| 业务扩展参数 | param | String | 下单传递有值时此项才有值, 否则是空 | |
| 支付者账号 | buyer | String | 默认留空 |
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | pid | 是 | String | 1001 | 系统分配的唯一商户ID |
| 系统订单号 | trade_no | 是 | String | 89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i | 系统订单号 |
| 商户订单号 | out_trade_no | 是 | String | P1988492264548581376 | 商户下单传递的订单号 |
| 支付类型 | type | 是 | String | alipay | |
| 商品名称 | name | 是 | String | VIP | |
| 支付金额 | money | 是 | String | 10.00 | |
| 扩展参数 | param | 否 | String | 商户下单传递的扩展参数 | |
| 支付状态 | trade_status | 是 | String | TRADE_SUCCESS | TRADE_SUCCESS=支付成功;TRADE_REFUND=支付退款 |
| 签名 | sign | 是 | String | 平台回调签名值 | |
| 签名类型 | sign_type | 是 | String | MD5 | 固定值(不参与签名) |
提示:商户收到回调后需要校验签名以及订单是否处理过,以免重复上分,收到回调后请返回success
private static void postJson() {
String url = "http://127.0.0.1/mapi.php";
String appid = "17732920843";
String token = "45be38411d8747a874aebe0d667";
Map<String, String> data = new HashMap<>();
data.put("pid", appid);
data.put("type", "alipay");
data.put("out_trade_no", Long.toString(System.currentTimeMillis()));
data.put("notify_url", "http://127.0.0.1/api/notify/tm");
data.put("name", "VIP充值");
data.put("money", "10");
data.put("clientip", IpUtils.getImitationIP());
String sign = SignUtils.signStr(data);
data.put("sign", PwdUtils.getMd5Spring(sign + token));
data.put("sign_type", "MD5");
String result = HttpRequest.post(url).body(JSON.toJSONString(data)).execute().body();
System.out.println("================ POST JSON ===================");
System.out.println("请求地址:" + url);
System.out.println("请求参数:" + JSON.toJSONString(data));
System.out.println("请求返回:" + result);
}
private static void postForm() {
String url = "http://127.0.0.1/mapi.php";
String appid = "17732920843";
String token = "45be38411d8747a874aebe0d667";
Map<String, String> data = new HashMap<>();
data.put("pid", appid);
data.put("type", "alipay");
data.put("out_trade_no", Long.toString(System.currentTimeMillis()));
data.put("notify_url", "http://127.0.0.1/api/notify/tm");
data.put("name", "VIP充值");
data.put("money", "10");
data.put("clientip", IpUtils.getImitationIP());
String sign = SignUtils.signStr(data);
data.put("sign", PwdUtils.getMd5Spring(sign + token));
data.put("sign_type", "MD5");
String result = HttpRequest.post(url).formStr(data).execute().body();
System.out.println("================ POST FORM ===================");
System.out.println("请求地址:" + url);
System.out.println("请求参数:" + JSON.toJSONString(data));
System.out.println("请求返回:" + result);
}
private static void getForm() {
String url = "http://127.0.0.1/mapi.php";
String appid = "17732920843";
String token = "45be38411d8747a874aebe0d667";
Map<String, String> data = new HashMap<>();
data.put("pid", appid);
data.put("type", "alipay");
data.put("out_trade_no", Long.toString(System.currentTimeMillis()));
data.put("notify_url", "http://127.0.0.1/api/notify/tm");
data.put("name", "VIP充值");
data.put("money", "10");
data.put("clientip", IpUtils.getImitationIP());
String sign = SignUtils.signStr(data);
data.put("sign", PwdUtils.getMd5Spring(sign + token));
data.put("sign_type", "MD5");
String result = HttpRequest.get(url).formStr(data).execute().body();
System.out.println("================ GET FORM ===================");
System.out.println("请求地址:" + url);
System.out.println("请求参数:" + JSON.toJSONString(data));
System.out.println("请求返回:" + result);
}
/**
* 严格区分大小的 ascii 排序 ---> 自行移除不需要拼接的字符串
*
* @param params
* @return
*/
public static String signStr(Map<String, String> params) {
if (params == null || params.isEmpty()) {
return "";
}
return params.entrySet().stream().filter(entry -> entry.getKey() != null && !ObjectUtils.isEmpty(entry.getValue())).sorted(Map.Entry.comparingByKey())
.map(entry -> entry.getKey() + "=" + entry.getValue()).collect(Collectors.joining("&"));
}