话不多说,先介绍一下业务背景。我是一个小白,一条有梦想的创业者,我们创业的一大方向是智能零售,“悦逛宝盒”是我们的品牌,致力于打造智能零售综合服务平台。了解智能零售的人应该知道,这里面的形式有很多,例如:售货机、智能柜、智能货架、咖啡机、无人店等等,今天介绍的这个业务场景,就是微信专门为这个行业推出的一款产品--《微信支付分》,下面就完整介绍一下,我是怎么一步步摸石头过河的。
先看一下官方给的对接流程图,通过这个流程图,我们能很清楚的了解对接流程,方便我们快速切入。常规的我就不介绍了,相信大家都能看得懂,这里我只介绍我遇到的坑点。
坑点一:微信接口规则,采用APIv3
1.所有API请求必须为HTTPS
2.微信支付API v3使用JSON作为消息体的数据交换格式。请求须设置HTTP头部:
Content-Type: application/json
Accept: application/json
3.【重点】APIv3要求所有请求必须加签名,且签名算法与API版本有区别,下面来详细列举
微信支付商户API v3要求请求通过HTTPAuthorization
头来传递签名。Authorization
由认证类型和签名信息两个部分组成。
Authorization: 认证类型 签名信息
认证类型:固定为 WECHATPAY2-SHA256-RSA2048
签名信息:
-
发起请求的商户(包括直连商户、服务商或渠道商)的商户号
mchid
-
请求随机串
nonce_str
-
时间戳
timestamp
-
签名值
signature
注:以上五项签名信息,无顺序要求。
Authorization
头的示例如下:
Authorization: WECHATPAY2-SHA256-RSA2048 mchid="1900009191",nonce_str="593BEC0C930BF1AFEB40B4A08C8FB242",signature="uOVRnA4qG/MNnYzdQxJanN+zU+lTgIcnU9BxGw5dKjK+VdEUz2FeIoC+D5sB/LN+nGzX3hfZg6r5wT1pl2ZobmIc6p0ldN7J6yDgUzbX8Uk3sD4a4eZVPTBvqNDoUqcYMlZ9uuDdCvNv4TM3c1WzsXUrExwVkI1XO5jCNbgDJ25nkT/c1gIFvqoogl7MdSFGc4W4xZsqCItnqbypR3RuGIlR9h9vlRsy7zJR9PBI83X8alLDIfR1ukt1P7tMnmogZ0cuDY8cZsd8ZlCgLadmvej58SLsIkVxFJ8XyUgx9FmutKSYTmYtWBZ0+tNvfGmbXU7cob8H/4nLBiCwIUFluw==",timestamp="1554208460",serial_no="1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C"
(1)私钥、APIv3密钥和证书
在使用APIv3接口前,一定要在微信商户后台(https://pay.weixin.qq.com)【账户中心-》API安全】设置APIv3密钥,并查看证书是否是APIv3版证书,如果不是,根据提示升级。如下图:
(2)【重点】签名算法,篇幅问题,单独写一篇,
地址:https://blog.csdn.net/w1170384758/article/details/105393505
坑点二:APIv3中,业务数据的签名算法发生改变(sign字段)
官方说明地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=4_3,
API版本采用MD5签名,APIv3采用HMAC-SHA256签名方式,篇幅问题,单独写一篇介绍java版实现代码,
地址:https://blog.csdn.net/w1170384758/article/details/105393913
步骤一:
1.【查询用户授权状态】
这一步比较简单,就是调用微信接口,GET请求,前面签名做好,没啥难度。先贴代码,然后和大家讨论一个业务场景。
//请求方式:GET
String url = "https://api.mch.weixin.qq.com/v3/payscore/user-service-state?service_id="+ param.getServiceId() +"&appid="+ param.getAppId() +"&openid=" + param.getOpenId();
HttpUrl httpUrl = HttpUrl.parse(url);
try {
String token = WxAPIV3SignUtils.getToken("GET",httpUrl,"",param.getMchId(),param.getPrivateKey(),param.getSerialNo());
logger.debug("token={}",token);
//调用微信接口
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
.url(url)
.addHeader("Content-Type","application/json")
.addHeader("Accept","application/json")
.addHeader("Authorization",token)
.build();
final Call call = okHttpClient.newCall(request);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Response response = call.execute();
String resStr = response.body().string();
logger.debug("查询用户支付分授权状态API:{}",resStr);
}catch (IOException ex){
ex.printStackTrace();
}
}
});
thread.start();
thread.join();
}catch (Exception ex){
ex.printStackTrace();
}
那么这样看下来,关于查询用户支付分授权状态就有两种方式,方式一,调用你们的接口来查询用户授权状态,方式二,将用户授权状态(开通或关闭授权回调用通知)存到我们平台,查询时从我们的库中查询,关于这两种方式,询问过微信官方,没有给出回复,个人建议,如果服务器性能可以,还是实时查询,数据库可以存储下来,作为备查资料。
2.未授权时,引导用户授权服务,这里先给出前端(小程序)代码
var extraData = res.data.data;//后台接口组装的签约信息
wx.openBusinessView({
businessType: 'wxpayScoreEnable',
extraData: extraData,
success(res) {
// 成功跳转到签约小程序
console.log("签约支付分成功:",JSON.stringify(res))
},
fail(res) {
// 未成功跳转到签约小程序
console.log("签约支付分失败",JSON.stringify(res));
//做二次校验,查询用户签约情况
var jsonData = JSON.stringify({
});
console.log("【二次确认】校验支付分签约信息接口入参:" + data)
wx.request({
url: '',
method: "POST",
data: {
data: jsonData
},
header: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
},
success: function (res) {
//打印日志
console.log("校验支付分签约信息接口调用成功");
console.log("返回参数:" + JSON.stringify(res))
var isSign = res.data.data.isSign;
if (isSign == 1) { //用户已签约
console.log("确认用户已签约微信支付分")
}
if (isSign == 0) { //用户未签约,给出提示
console.log("确认用户未签约微信支付分")
wx.showModal({
title: '温馨提示',
showCancel:false,
content: '开通微信支付分,享受便捷购物,请重新扫码开通',
confirmText: '是',
success(res) {
console.log("弹框展示成功:",JSON.stringify(res))
that.data.allowScan = 1;
wx.switchTab({
url: '../index/index',
})
},
fail(res) {
console.log("弹框展示失败:",JSON.stringify(res))
}
})
}
},
fail: function (res) {
console.log("调用获取用户免密签约信息接口出错:" + JSON.stringify(res));
}
})
},
})
这里需要注意的点是,在签约成功界面,点击返回键(安卓手机)或左上角后退键时,触发的是wx.openBusinessView的fail方法,所以个人建议,在fail方法中加个二次check逻辑。
下面给出java后台组装支付分业务数据(extraData)的代码段,签名算法前面已经给出。
out.setOut_request_no(SerialnoUtils.buildUUID());
long currentTimeMillis = System.currentTimeMillis();//生成时间戳
long second = currentTimeMillis / 1000L;//转换成秒
String seconds = String.valueOf(second).substring(0, 10);//截取前10位
out.setTimestamp(seconds);//时间戳string(10)
out.setNonce_str(WxAPIV3SignUtils.generateNonceStr());
out.setSign_type(WxAPIV3SignUtils.sign_type);
//生成签名
String sign = MapUtils.getObjectHMACSHA256Sign(out,StringUtils.isNotBlank(mch_key) ? mch_key : SystemConst.WX_KEY);
out.setSign(sign);
步骤二:【创建支付分订单】https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/payscore/chapter3_1.shtml
POST请求,代码实现上没啥难度,直接上核心代码
public static final MediaType MediaType_JSON = MediaType.parse("application/json; charset=utf-8");
//生成签名
String url = "https://api.mch.weixin.qq.com/v3/payscore/serviceorder";
HttpUrl httpUrl = HttpUrl.parse(url);
String token = WxAPIV3SignUtils.getToken("POST",httpUrl,JSON.toJSONString(wxApplyPayScoreIn),payScoreConfig.getMchId(),payScoreConfig.getPrivateKey(),payScoreConfig.getSerialNo());
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = RequestBody.create(MediaType_JSON,JSON.toJSONString(wxApplyPayScoreIn));
Request request = new Request.Builder()
.url(url)
.addHeader("Content-Type","application/json")
.addHeader("Accept","application/json")
.addHeader("Authorization",token)
.post(requestBody)
.build();
Response response = okHttpClient.newCall(request).execute();
logger.debug("【创建支付分订单API】接口返回:{},code={},message={},body={}",JSON.toJSONString(response),response.code(),response.message(),response.body().string());
if (response.isSuccessful()){//请求成功
}else{
}
POST调用本身没啥难度,这里重点介绍一个,组装请求参数时容易遇到的坑
(1)
这里的appid指的是你实际发起的客户端appid,不一定是公众号,如,我使用的是小程序,那么这个参数传递的是小程序appid
(2)
金额,对接过微信支付的都知道,微信默认的金额都是分,所以注意与商户的业务数据做好对应。
(3)
关于时间传递这块,我认为也是一个坑。大家仔细看好官方说明。
篇幅原因,这篇先写到这,后续订单完结、支付回调、退款等在下一篇介绍,地址:
https://blog.csdn.net/w1170384758/article/details/105412503
新人发帖,如有疑问或错误,欢迎大家订正。