微信小程序支付
前言
前两周参与了微信小程序支付功能的开发,因为第一次接触这些,所以想写个文章记录下来,写这篇文章的时候我已经将微信小程序的支付接口做了封装,只需要传递一些指定的参数就可以进行支付了。
1.获取code
第一步我们先获取code
var that = this
//登陆获取code
wx.login({
success: function (res) {
console.log(res.code);
wx.request({
url :'http://localhost:8080/getopenid',
method: 'POST',
header: { "Content-Type": "application/x-www-form-urlencoded" },
data: {
code: res.code
},
success: function (res) {
var openid = res.data.openid
that.getprepayid(openid)
},
fail: function (err) {
console.log(err)
}
})
2.请求开发者服务器获取openid
code
>> openid
,session_key
public String getopenid(String code,String appid,String secret) {
String url = "https://api.weixin.qq.com/sns/jscode2session?"
+ "appid="+ appid
+ "&secret=" + secret
+ "&js_code=" + code
+ "&grant_type=authorization_code";
String result = new RequestUtil().sendPost(url, code);
return result;
}
3.请求开发者服务器获取支付所需要的参数
openid
,total_fee
,body
,attach
>> timeStamp
,package
(prepay_id),paySign
,signType
(‘MD5’),nonceStr
(随机数)
获取请求参数,调用支付方法
String body = getPara("body"); String attach = getPara("attach"); String openid = getPara("openid"); JSONObject jsonObject = new JSONObject(); try { jsonObject = new payAction().pay(openid, body, attach, tot); } catch (Exception e) { e.printStackTrace(); } renderJson(jsonObject);
将请求打包成map数组
Map<String, Object> sParaTemp = new HashMap(); sParaTemp.put("appid", paymentPo.getAppid()); sParaTemp.put("mch_id", paymentPo.getMch_id()); sParaTemp.put("nonce_str", paymentPo.getNonce_str()); sParaTemp.put("body", paymentPo.getBody()); sParaTemp.put("out_trade_no", paymentPo.getOut_trade_no()); sParaTemp.put("total_fee",paymentPo.getTotal_fee()); sParaTemp.put("spbill_create_ip", paymentPo.getSpbill_create_ip()); sParaTemp.put("notify_url",paymentPo.getNotify_url()); sParaTemp.put("trade_type", paymentPo.getTrade_type()); sParaTemp.put("openid", paymentPo.getOpenid());
除去map中的空值并且排序生成str和key(key是商户秘钥)通过MD5加密生成签名(详情查看文档sign加密算法)
String prestr = PayUtil.createLinkString(sParaTemp); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 System.out.println("prestr :"+ prestr); String key = "&key=秘钥"; // 商户支付密钥 //MD5运算生成签名 String mysign = PayUtil.sign(prestr, key, "utf-8").toUpperCase(); paymentPo.setSign(mysign);
拼接xml请求,调用微信统一下单接口,获取反馈信息
// 把请求参数打包成数组 map Map<String, Object> sParaTemp = new HashMap(); sParaTemp.put("appid", paymentPo.getAppid()); sParaTemp.put("mch_id", paymentPo.getMch_id()); sParaTemp.put("nonce_str", paymentPo.getNonce_str()); sParaTemp.put("body", paymentPo.getBody()); sParaTemp.put("out_trade_no", paymentPo.getOut_trade_no()); sParaTemp.put("total_fee",paymentPo.getTotal_fee()); sParaTemp.put("spbill_create_ip", paymentPo.getSpbill_create_ip()); sParaTemp.put("notify_url",paymentPo.getNotify_url()); sParaTemp.put("trade_type", paymentPo.getTrade_type()); sParaTemp.put("openid", paymentPo.getOpenid()); // 除去数组中的空值和签名参数 Map sPara = PayUtil.paraFilter(sParaTemp); String prestr = PayUtil.createLinkString(sParaTemp); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 System.out.println("prestr :"+ prestr); String key = "&key=秘钥"; // 商户支付密钥 //MD5运算生成签名 String mysign = PayUtil.sign(prestr, key, "utf-8").toUpperCase(); paymentPo.setSign(mysign); //拼接xml String formData = "<xml>"; formData += "<appid>" + appid + "</appid>"; //appid formData += "<body>" + newbody + "</body>"; formData += "<mch_id>" + mch_id + "</mch_id>"; //商户号 formData += "<nonce_str>" + nonce_str + "</nonce_str>"; //随机字符串,不长于32位。 formData += "<notify_url>" + notify_url + "</notify_url>"; formData += "<openid>" + openid + "</openid>"; formData += "<out_trade_no>" + out_trade_no + "</out_trade_no>"; formData += "<spbill_create_ip>14.23.150.211</spbill_create_ip>"; formData += "<total_fee>" + tot + "</total_fee>"; formData += "<trade_type>JSAPI</trade_type>"; formData += "<sign>" + mysign+ "</sign>"; formData += "</xml>";
解析反馈信息,将获取的参数以json格式传给wxUI
if(return_code=="SUCCESS"||return_code.equals(return_code)){ // 业务结果 String prepay_id = (String) map.get("prepay_id");//返回的预付单信息 String nonceStr=UUIDHexGenerator.generate(); JsonObject.put("nonceStr", nonceStr); JsonObject.put("package", "prepay_id="+prepay_id); Long timeStamp= System.currentTimeMillis()/1000; JsonObject.put("timeStamp", timeStamp+""); String stringSignTemp = "appId="+appid+"&nonceStr=" + nonceStr + "&package=prepay_id=" + prepay_id+ "&signType=MD5&timeStamp=" + timeStamp; //再次签名 String paySign=PayUtil.sign(stringSignTemp, "&key=秘钥", "utf-8").toUpperCase(); JsonObject.put("paySign", paySign); } return JsonObject;
4.调用统一下单接口
- 调用支付接口所用参数:
timeStamp
,package(prepay_id)
,paySign
,signType
(‘MD5’),nonceStr
(随机数)
var that = this
wx.request({
url: 'http://localhost:8080/pay',
method: 'GET',
header: {
'Accept': 'application/json'
},
data: {
//传递生成订单要用到的参数
orderInfo:
{
"aid": "xxx",
...
}
,
openid: openid,
total_fee: total_fee,
body: '花美美鲜花',
attach: '花美美'
},
success: function (res) {
console.log(res)
var timeStamp = res.data.timeStamp.toString() //时间戳
var nonceStr = res.data.nonceStr.toString() //随机数
var packages = res.data.package.toString() //prepay_id
var paySign = res.data.paySign.toString() //签名
var signType = 'MD5'
var param = {
"timeStamp": timeStamp,
"package": packages,
"paySign": paySign,
"signType": "MD5",
"nonceStr": nonceStr
}
that.pay(param);
}
})
- 完成支付
pay: function (param) {
wx.requestPayment({
timeStamp: param.timeStamp,
nonceStr: param.nonceStr,
package: param.package,
signType: param.signType,
paySign: param.paySign,
success: function (res) {
console.log(res)
wx.navigateBack({
delta: 1, // 回退前 delta(默认为1) 页面
success: function (res) {
wx.showToast({
title: '支付成功',
icon: 'success',
duration: 2000
}),
//支付成功之后将订单状态修改为已支付
wx.request({
url: 'localhost:8080/changeOrderState',
method: 'POST',
header: { "Content-Type": "application/x-www-form-urlencoded" },
data: {
msg:'用户已成功支付,修改订单状态'
},
success: function (res) {
console.log('修改完成')
//引导用户查看订单
},
fail: function (err) {
}
})
},
fail: function () {
},
complete: function () {
}
})
},
fail: function () {
console.log("支付失败")
},
complete: function () {
console.log("pay complete")
}
})
},