當(dāng)時(shí)做微信小程序支付真的是炸毛了?舅汀!
特此立貼爹土,記錄一下,避免再次采坑
先把流程圖放著
image.png
商戶系統(tǒng)和微信支付系統(tǒng)主要交互:
1踩身、小程序內(nèi)調(diào)用登錄接口胀茵,獲取到用戶的openid,api參見公共api【小程序登錄API】
2、商戶server調(diào)用支付統(tǒng)一下單挟阻,api參見公共api【統(tǒng)一下單API】
3琼娘、商戶server調(diào)用再次簽名,api參見公共api【再次簽名】
4附鸽、商戶server接收支付通知脱拼,api參見公共api【支付結(jié)果通知API】
5、商戶server查詢支付結(jié)果坷备,api參見公共api【查詢訂單API】
這是微信官方給出的
1.獲取用戶openid
前端代碼
image.png
重要的步驟圈起來(lái)了
- wx.login
2.進(jìn)行登錄向后端發(fā)送請(qǐng)求
后端代碼
@GetMapping("/getOpenId.json")
public PageResult getOpenId(String code) {
String sendGet = HttpUtils.sendGet("https://api.weixin.qq.com/sns/jscode2session", "appid=" + WXPayConstants.SMALL_APP_ID + "&secret=" + WXPayConstants.SMALL_APPSECRET + "&js_code=" + code + "&grant_type=authorization_code");
System.out.println("sendGet = " + sendGet);
Map<String, String> map = JSONObject.parseObject(sendGet, HashMap.class);
return new PageResult(map);
}
此處的code是調(diào)用wx.login返回的code調(diào)用https://api.weixin.qq.com/sns/jscode2session
接口獲取openid或者sessionkey
image.png
3.獲取到openid后向后端發(fā)送請(qǐng)求熄浓,讓后端請(qǐng)求微信統(tǒng)一下單
參見 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1&index=1
4.后端代碼
@GetMapping("/createOrder.json")
public PageResult createOrder(String money, String payScene, @RequestParam(required = false) String openId, HttpServletRequest request) throws Exception {
AppUser user = ThreadLocalUtil.getUser();
if ("MWEB".equals(payScene)) {
//創(chuàng)建一個(gè)map盛放微信生成的相關(guān)信息
Map map = new HashMap();
WeixinPay weixinPay = new WeixinPay();
//生成訂單號(hào)
String outTradeNo = WXPayUtil.generateNonceStr();
String sceneInfo = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"填寫你的url\",\"wap_name\": \"填寫你的名稱\"}}";
WeixinResult result = null;
String ip = "";
//獲得到用戶的真實(shí)ip地址
if (request.getHeader("x-forwarded-for") == null) {
ip = request.getRemoteAddr();
} else {
ip = request.getHeader("x-forwarded-for");
String[] ips = StringUtils.split(ip, ",");
if (ips.length > 0) {
ip = ips[0];
}
}
try {
//發(fā)起微信的統(tǒng)一下單
// result = weixinPay.createNative(outTradeNo, money, sceneInfo, payScene, com.sdworan.weChat.WXPayUtil.getIpAddr(request),"http://m.qiuxuemao.cn/handleWeixin.do",null);
Map param = new HashMap();
param.put("appid", "填寫你的appid");
param.put("mch_id", "填寫的你商戶id");
param.put("nonce_str", com.github.wxpay.sdk.WXPayUtil.generateNonceStr());
param.put("body", "填寫你的body主體");
param.put("out_trade_no", outTradeNo);
param.put("total_fee", money);
String ipAddr = WXPayUtil.getIpAddress(request);
System.out.println("ip是 = " + ipAddr);
if (org.apache.commons.lang.StringUtils.isNotBlank(ipAddr)) {
System.out.println("ipAddr="+ipAddr);
param.put("spbill_create_ip", ipAddr);
}
param.put("notify_url", "填寫的你的通知地址");
param.put("trade_type", payScene);
if (org.apache.commons.lang.StringUtils.equals("MWEB", payScene)) {
param.put("scene_info", sceneInfo);
}
param.put("attach", "{'userId':'" + user.getPkId() + "','payType':'H5'}");
try {
String xmlParam = com.github.wxpay.sdk.WXPayUtil.generateSignedXml(param, "WAWW4mogbeBFat0jxPKcczJ3V5d3vr9t");
this.logger.info("生成的xml:" + xmlParam);
com.sdworan.weixinPay.HttpClientUtils httpClient = new HttpClientUtils("https://api.mch.weixin.qq.com/pay/unifiedorder");
httpClient.setHttps(true);
httpClient.setXmlParam(xmlParam);
httpClient.post();
String xmlResult = httpClient.getContent();
this.logger.info("返回的結(jié)果:" + xmlResult);
Map<String, String> mapResult = com.github.wxpay.sdk.WXPayUtil.xmlToMap(xmlResult);
String codeUrl = "";
if (org.apache.commons.lang.StringUtils.equals("MWEB", payScene)) {
codeUrl = (String) mapResult.get("mweb_url");
} else if (org.apache.commons.lang.StringUtils.equals("NATIVE", payScene)) {
codeUrl = (String) mapResult.get("code_url");
}
result = new WeixinResult(codeUrl, outTradeNo, money);
} catch (Exception var14) {
var14.printStackTrace();
throw var14;
}
//封裝數(shù)據(jù)就行了
map.put("outTradeNo", outTradeNo);
//將CodeUrl重新進(jìn)行拼接
String codeUrl = result.getCodeUrl();
codeUrl = codeUrl + "&redirect_url="+ URLEncoder.encode("替換為你的返回地址","UTF-8");
map.put("codeUrl", codeUrl);
} catch (Exception e) {
e.printStackTrace();
}
return new PageResult(map);
} else if ("APP".equals(payScene) || "JSAPI".equals(payScene)) {
// payScene = "APP";
// payScene = "JSAPI";
MyConfig config = new MyConfig();
WXPay wxpay = new WXPay(config);
SortedMap<String, String> data = new TreeMap<>();
if ("JSAPI".equals(payScene)) {
data.put("appid", WXPayConstants.SMALL_APP_ID); // 有 小程序id
} else if ("APP".equals(payScene)) {
data.put("appid", WXPayConstants.SMALL_APP_ID); // 有 app的id
}
data.put("body", "填寫你的body主體");
String outTradeNo = WXPayUtil.generateNonceStr();
data.put("out_trade_no", outTradeNo);
data.put("device_info", "WEB");
data.put("fee_type", "CNY");
data.put("total_fee", "1");
data.put("spbill_create_ip", com.sdworan.weChat.WXPayUtil.getIpAddr(request)); //有 終端ip
data.put("notify_url", "替換為你的通知地址"); //有
data.put("trade_type", payScene); // 此處指定為掃碼支付
String productId = WXPayUtil.generateNonceStr();
data.put("product_id", productId);
data.put("mch_id", WXPayConstants.MCH_ID); // 有 商戶號(hào)
String nonceStr = WXPayUtil.generateNonceStr();
data.put("nonce_str", nonceStr); //有 隨機(jī)字符串
// data.put("signType", "MD5");
// data.put("packageValue","Sign=WXPay");
if ("JSAPI".equals(payScene)) {
data.put("openid", openId);
//加入我需要傳輸?shù)男畔? data.put("attach", "{'userId':'" + user.getPkId() + "','payType':'SP'}");
} else if ("APP".equals(payScene)) {
//加入我需要傳輸?shù)男畔? data.put("attach", "{'userId':'" + user.getPkId() + "','payType':'APP'}");
}
System.out.println("data = " + data);
//簽名
String sign = WXPayUtil.generateSignature(data, WXPayConstants.KEY);
//加入簽名
data.put("sign", sign);
// data.put("out_trade_no", outTradeNo);
// data.put("product_id", productId);
// data.put("nonce_str", nonceStr);
System.out.println("data1111111111111111 = " + data);
SortedMap<String, String> map = new TreeMap<>();
Map<String, String> resp = null;
try {
//請(qǐng)求訂單
resp = wxpay.unifiedOrder(data);
System.out.println("請(qǐng)求訂單信息" + resp);
// map.put("prepayId", resp.get("prepay_id"));
Map<String, String> mapReturn = new HashMap<>();
if ("JSAPI".equals(payScene)) {
map.put("appId", WXPayConstants.SMALL_APP_ID);
map.put("timeStamp", (System.currentTimeMillis() / 1000) + "");
map.put("nonceStr", resp.get("nonce_str"));
String packag = "prepay_id=" + resp.get("prepay_id");
map.put("package", packag);
map.put("signType", "MD5");
} else if ("APP".equals(payScene)) {
map.put("appid", resp.get("appid"));
map.put("partnerid", resp.get("mch_id"));
map.put("prepayid", resp.get("prepay_id"));
map.put("noncestr", resp.get("nonce_str"));
map.put("timestamp", (System.currentTimeMillis() / 1000) + "");
map.put("package", "Sign=WXPay");
}
System.out.println("map = " + map);
String generateSignature = WXPayUtil.generateSignature(map, WXPayConstants.KEY);
map.put("sign", generateSignature);
// map.put("timestamp",map.get("timestamp"));
// map.put("package","Sign=WXPay");
// map.put("sign", generateSignature);
System.out.println("generateSignature = " + generateSignature);
System.out.println("簽名是否正確 = " + WXPayUtil.isSignatureValid(map, WXPayConstants.KEY));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("map = " + map);
return new PageResult(map);
}
return null;
}
返回的訂單信息再返回給前臺(tái)
讓他拉起微信支付
// 僅作為示例,非真實(shí)參數(shù)信息击你。
uni.requestPayment({
provider: 'wxpay',
orderInfo:orderInfo.data.obj,
timeStamp: orderInfo.data.obj.timeStamp,
nonceStr: orderInfo.data.obj.nonceStr,
package: orderInfo.data.obj.package,
signType: orderInfo.data.obj.signType,
paySign: orderInfo.data.obj.sign,
success: function (res) {
console.log('success:' + JSON.stringify(res));
},
fail: function (err) {
console.log('fail:' + JSON.stringify(err));
}
});