背景
最近项目中需要用到服务商的分账功能,因为是服务商的分账,所以需要使用服务商的支付,其中遇到了一个支付签名错误问题,在这里记录一波。
文档 + 个人理解
支付文档链接:服务商支付链接
个人理解:根据个人接过的微信接口,几乎都是将参数放入Map,签名,然后转成XML,发送请求给微信,差不多就这样,复杂的就中间加点7788地操作,有些需要证书的就使用含有SSL的请求即可,下次可能会写
做过普通商户的看这
参数按照文档上的传,但是在第二次生成签名时,传的appId是子商户关联的appId,如果传的和第一次一样,就会出现支付签名错误,这两天在微信支付社区看了看,有这种错误但是一直没说法,所以如果有支付签名错误的可以看看是否是这个问题。
没做过普通商户的看这
直接贴代码,先把对应参数改了,得出参数然后写个按钮支付一下,支付成功再说
jar包:
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.8</version>
</dependency>
代码:
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import java.util.HashMap;
import java.util.Map;
/**
* @author: bb
* @createDate: 2020/7/7
* @version: 1.0
*/
public class PayUtil {
public static void main(String[] args) throws Exception {
unifiedorder();
}
/**
* JSAPI下单:服务商
*/
public static Map<String, String> unifiedorder() throws Exception {
Map<String, String> params = new HashMap<>();
params.put("appid", "服务商商户号的appid - 就是哪个公众号/小程序关联了这个商户号");
params.put("mch_id", "服务商户号");
params.put("sub_mch_id", "子商户号(特约商户) - 钱到账的商户号");
// 不用这个,这个是服务商关联的appid下的openId,而我们通常是需要关联到某个小程序上的openId
// params.put("openid", "该用户在服务商绑定的appid下的openid");
// 用这个
params.put("sub_appid", "服务商关联小程序的appid");
params.put("sub_openid", "小程序下");
params.put("nonce_str", WXPayUtil.generateNonceStr()); // 随机字符串
params.put("body", "消息体,就是显示在支付后微信发消息给你的那上面的标题");
String outTradeNo = IdUtil.fastSimpleUUID(); // 随机生成的订单号
params.put("out_trade_no", outTradeNo);
params.put("total_fee", "1"); // 总金额 - 单位:分
params.put("trade_type", "JSAPI"); // 我用的是JSAPI
params.put("profit_sharing", "Y"); // 允许分账,不填默认不允许
params.put("notify_url", "https://edu.zxtnet.com/"); // 回调url需添加,否则好像会报错,要是外网能访问的 - 是否需要配置看情况
String sign = WXPayUtil.generateSignature(params, "商户号的密钥");
params.put("sign", sign);
String reqXml = WXPayUtil.mapToXml(params);
String resXml = HttpRequest.post(WXPayConstants.UNIFIEDORDER_URL).body(reqXml).execute().body();
System.out.println("res:" + resXml);
Map resultMap = WXPayUtil.xmlToMap(resXml);
String prepay_id = (String) resultMap.get("prepay_id");
Map<String, String> paySignMap = new HashMap<>();
paySignMap.put("appId", (String) resultMap.get("sub_appid")); // 这里就是子商户号关联的appId,你不写,在调用下单请求后会作为sub_appid返回
paySignMap.put("nonceStr", WXPayUtil.generateNonceStr());
paySignMap.put("package", "prepay_id=" + prepay_id);
paySignMap.put("signType", "MD5");
paySignMap.put("timeStamp", String.valueOf((System.currentTimeMillis() / 1000)));
String paySign = WXPayUtil.generateSignature(paySignMap, "商户号的密钥");
paySignMap.put("paySign", paySign);
paySignMap.forEach((x, y) -> {
System.out.println(x + " --- " + y);
});
return paySignMap;
}
}
分账
支付成功后,才可以继续使用分账功能,记住要设置为允许分账,否则不可以分账
小结
服务商的JSAPI支付和普通商户的JSAPI支付,调用接口都是一样的,只不过参数不一样,根据文档来就行,不过重要的是在服务商JSAPI中获取paySign时,用的appId是子商户的,如果不知道,根据我代码中那样获取sub_appid就行,否则就会报支付签名错误,昨天晚上就是一直卡在支付签名错误这里。
而且如果遇到错误的时候,注意要看请求回来的返回值是否有提示等内容,这样可以根据里面来进行排错,像我早上就不知道到底是哪个appId,然后看到返回值中有个sub_appid我就试了一下,结果就出来了;而且这里微信好像没说明,所以就搞得很难受,吃一堑长一智。
2020-7-7 19:47