今天刚将小程序的支付调通,和大家分享下(坑)
源码下载:https://pan.baidu.com/s/1skQiXPz
包括小程序端、java服务器端
和其他方式的微信支付方式区别不大,也都需要经过统一下单、支付结果通知(回调),具体流程如下:
1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API】
2、商户server调用支付统一下单,api参见公共api【统一下单API】
3、商户server调用再次签名,api参见公共api【再次签名】
4、商户server接收支付通知,api参见公共api【支付结果通知API】
5、商户server查询支付结果,api参见公共api【查询订单API】
下面结合源码详解下流程:
第一步: 获取客户的openid
统一下单中需要用到openid
小程序:
首先需要调用微信登录接口获取用户的code:
1.
var that =
this
;
2.
wx.login({
3.
success: function(res) {
4.
that.getOpenId(res.code);
5.
}
6.
});
通过code获取openid:
01.
//获取openid
02.
getOpenId: function(code){
03.
var that =
this
;
04.
wx.request({
05.
url:
'https://www.see-source.com/weixinpay/GetOpenId'
,
06.
method:
'POST'
,
07.
header: {
08.
'content-type'
:
'application/x-www-form-urlencoded'
09.
},
10.
data: {
'code'
:code},
11.
success: function(res) {
12.
var openId = res.data.openid;
13.
that.xiadan(openId);
14.
}
15.
})
16.
}
java:
1.
String code = request.getParameter(
"code"
);
2.
HttpGet httpGet =
new
HttpGet(
"https://api.weixin.qq.com/sns/jscode2session?appid="
+Configure.getAppID()+
"&secret="
+Configure.getSecret()+
"&js_code="
+code+
"&grant_type=authorization_code"
);
3.
//设置请求器的配置
4.
HttpClient httpClient = HttpClients.createDefault();
5.
HttpResponse res = httpClient.execute(httpGet);
6.
HttpEntity entity = res.getEntity();
7.
String result = EntityUtils.toString(entity,
"UTF-8"
);
8.
response.getWriter().append(result);
第二步:统一下单
调用微信的统一下单接口,返回预订单id(prepay_id)
小程序:
01.
var that =
this
;
02.
wx.request({
03.
url:
'https://www.see-source.com/weixinpay/xiadan'
,
04.
method:
'POST'
,
05.
header: {
06.
'content-type'
:
'application/x-www-form-urlencoded'
07.
},
08.
data: {
'openid'
:openId},
09.
success: function(res) {
10.
var prepay_id = res.data.prepay_id;
11.
console.log(
"统一下单返回 prepay_id:"
+prepay_id);
12.
that.sign(prepay_id);
13.
}
14.
})
java:
01.
String openid = request.getParameter(
"openid"
);
02.
OrderInfo order =
new
OrderInfo();
03.
order.setAppid(Configure.getAppID());
04.
order.setMch_id(Configure.getMch_id());
05.
order.setNonce_str(RandomStringGenerator.getRandomStringByLength(
32
));
06.
order.setBody(
"dfdfdf"
);
07.
order.setOut_trade_no(RandomStringGenerator.getRandomStringByLength(
32
));
08.
order.setTotal_fee(
10
);
09.
order.setSpbill_create_ip(
"123.57.218.54"
);
10.
order.setNotify_url(
"https://www.see-source.com/weixinpay/PayResult"
);
11.
order.setTrade_type(
"JSAPI"
);
12.
order.setOpenid(openid);
13.
order.setSign_type(
"MD5"
);
14.
//生成签名
15.
String sign = Signature.getSign(order);
16.
order.setSign(sign);
17.
18.
String result = HttpRequest.sendPost(
"https://api.mch.weixin.qq.com/pay/unifiedorder"
, order);
19.
System.out.println(result);
20.
L.info(
"---------下单返回:"
+result);
21.
XStream xStream =
new
XStream();
22.
xStream.alias(
"xml"
, OrderReturnInfo.
class
);
23.
24.
OrderReturnInfo returnInfo = (OrderReturnInfo)xStream.fromXML(result);
25.
JSONObject json =
new
JSONObject();
26.
json.put(
"prepay_id"
, returnInfo.getPrepay_id());
27.
response.getWriter().append(json.toJSONString());
Notify_url 是支付完成后就收微信的通知的,告诉你用户是否付款了
注意:Total_fee单位是分,必须是整数,不能是小数
Trade_type字段对于小程序来说固定写成JSAPI
第三步:再次签名
这是小程序的不同之处,要求对拿到的repay_id进行再次签名。
注意这里有坑了:package字段的值是个键值对,格式prepay_id=12312333333333333
小程序:
01.
var that =
this
;
02.
wx.request({
03.
url:
'https://www.see-source.com/weixinpay/sign'
,
04.
method:
'POST'
,
05.
header: {
06.
'content-type'
:
'application/x-www-form-urlencoded'
07.
},
08.
data: {
'repay_id'
:prepay_id},
09.
success: function(res) {
10.
that.requestPayment(res.data);
11.
12.
}
13.
})
java:
01.
String repay_id = request.getParameter(
"repay_id"
);
02.
SignInfo signInfo =
new
SignInfo();
03.
signInfo.setAppId(Configure.getAppID());
04.
long
time = System.currentTimeMillis()/
1000
;
05.
signInfo.setTimeStamp(String.valueOf(time));
06.
signInfo.setNonceStr(RandomStringGenerator.getRandomStringByLength(
32
));
07.
signInfo.setRepay_id(
"prepay_id="
+repay_id);
08.
signInfo.setSignType(
"MD5"
);
09.
//生成签名
10.
String sign = Signature.getSign(signInfo);
11.
12.
JSONObject json =
new
JSONObject();
13.
json.put(
"timeStamp"
, signInfo.getTimeStamp());
14.
json.put(
"nonceStr"
, signInfo.getNonceStr());
15.
json.put(
"package"
, signInfo.getRepay_id());
16.
json.put(
"signType"
, signInfo.getSignType());
17.
json.put(
"paySign"
, sign);
18.
L.info(
"-------再签名:"
+json.toJSONString());
19.
response.getWriter().append(json.toJSONString());
第四步:调起支付
最后一步调起小程序支付api
01.
wx.requestPayment({
02.
'timeStamp'
: obj.timeStamp,
03.
'nonceStr'
: obj.nonceStr,
04.
'package'
: obj.
package
,
05.
'signType'
: obj.signType,
06.
'paySign'
: obj.paySign,
07.
'success'
:function(res){
08.
},
09.
'fail'
:function(res){
10.
}
11.
})
之后就等着用户去输入支付密码完成支付了
还有个接口是查询订单,这个不是必须的,你根据需要使用