微信支付JSAPI下单和微信小程序调起支付(V2版本) 一、

一、前文

参考
基于WxJava实现微信支付SpringBoot后端接口的使用
微信支付—开发者文档—小程序—小程序调起支付API(V3版本)
微信支付—开发文档—小程序支付—小程序调起支付API(V2)
微信支付接口签名校验工具
微信官方文档—小程序—支付 /wx.requestPayment(V3)

  • V2版本的API,通过MD5加密(本博文主要简述)
  • V3版本的API,使用RAS加密

二、流程图

微信小程序SpringBoot后端用户点击付款按钮调用后端下单接口JSAPI统一下单微信订单数据存入数据库生成小程序调起支付所需的数据返回小程序调起支付所需的数据wx.requestPayment发起微信支付支付成功/失败回调JSAPI查询订单确认支付成功,更新数据库微信小程序SpringBoot后端
三、SpringBoot接口实现
================

2.1 微信调起支付所需数据

Md5Utils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
java复制代码/**
* Md5加密方法
*
* @author weijian
*/
public class Md5Utils
{
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);

/**
* 生成 MD5
*
* @param data 待处理数据
* @return MD5结果
*/
public static String MD5(String data) {
try {
java.security.MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}

WxPayment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
java复制代码
/**
* 微信调起支付数据 WxPayment
*
* @author weijian
*/
@ApiModel(value="WxPayment",description="微信调起支付数据")
public class WxPayment
{
@ApiModelProperty(value="wxTradeId", required = true)
@Excel(name = "wxTradeId")
private Long wxTradeId;

@ApiModelProperty(value="小程序id", required = true)
@Excel(name = "小程序id")
private String appId;

@ApiModelProperty(value="时间戳", required = true)
@Excel(name = "时间戳")
private String timeStamp;

@ApiModelProperty(value="随机字符串", required = true)
@Excel(name = "随机字符串")
private String nonceStr;

@ApiModelProperty(value="订单详情扩展字符串", required = true)
@Excel(name = "订单详情扩展字符串")
private String _package;

@ApiModelProperty(value="签名方式", required = true)
@Excel(name = "签名方式")
private String signType;

@ApiModelProperty(value="签名", required = true)
@Excel(name = "签名")
private String paySign;

public void sign(String key){
String sign = ("appId="+appId+"&");
sign += ("nonceStr="+nonceStr+"&");
sign += ("package="+_package+"&");
sign += ("signType="+signType+"&");
sign += ("timeStamp="+timeStamp+"&");
sign += ("key="+key);
System.out.println("sign="+sign);
setPaySign(Md5Utils.MD5(sign).toUpperCase());
}

public Long getWxTradeId() {
return wxTradeId;
}

public void setWxTradeId(Long wxTradeId) {
this.wxTradeId = wxTradeId;
}

public String getAppId() {
return appId;
}

public void setAppId(String appId) {
this.appId = appId;
}

public String getTimeStamp() {
return timeStamp;
}

public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}

public String getNonceStr() {
return nonceStr;
}

public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}

public String get_package() {
return _package;
}

public void set_package(String _package) {
this._package = _package;
}

public String getSignType() {
return signType;
}

public void setSignType(String signType) {
this.signType = signType;
}

public String getPaySign() {
return paySign;
}

public void setPaySign(String paySign) {
this.paySign = paySign;
}

@Override
public String toString() {
return "WxPayment{" +
"wxTradeId=" + wxTradeId +
", appId='" + appId + '\'' +
", timeStamp='" + timeStamp + '\'' +
", nonceStr='" + nonceStr + '\'' +
", _package='" + _package + '\'' +
", signType='" + signType + '\'' +
", paySign='" + paySign + '\'' +
'}';
}
}

2.2 下单接口

WxPayController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
java复制代码
@ApiOperation("微信统一下单")
// @PreAuthorize("@ss.hasPermi('wallet:update')")
@Log(title = "微信统一下单", businessType = BusinessType.UPDATE)
@PostMapping("/wx/unifiedOrder")
public AjaxResult wxUnifiedOrder(@ApiParam() Long billId) throws Exception
{
Bill bill = billService.selectBillById(billId);
if(ObjectUtil.isNull(bill)){
return AjaxResult.error("bill异常");
}

//1. JSAPI微信统一下单
WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
wxPayUnifiedOrderRequest.setOutTradeNo(IdUtils.fastSimpleUUID(16));
wxPayUnifiedOrderRequest.setTotalFee(1);
wxPayUnifiedOrderRequest.setSpbillCreateIp(IpUtils.getHostIp());
wxPayUnifiedOrderRequest.setNotifyUrl("https://www.nb.cn:8080/v1/wx/notify");
wxPayUnifiedOrderRequest.setTradeType("JSAPI");
wxPayUnifiedOrderRequest.setBody("账单支付");
wxPayUnifiedOrderRequest.setOpenid(SecurityUtils.getLoginUser().getUser().getTenantOpenId());
wxPayUnifiedOrderRequest.setAppid("wx********");
WxPayUnifiedOrderResult wxPayUnifiedOrderResult = wxService.unifiedOrder(wxPayUnifiedOrderRequest);

//2. 微信订单数据存入数据库
WxTrade wxTrade = new WxTrade();
wxTrade.setBillId(billId);
wxTrade.setUserId(SecurityUtils.getUserId());
wxTrade.setUserName(SecurityUtils.getUsername());
wxTrade.setAppId(wxPayUnifiedOrderResult.getAppid());
wxTrade.setMchId(wxPayUnifiedOrderResult.getMchId());
wxTrade.setSubMchId(wxPayUnifiedOrderResult.getSubMchId());
wxTrade.setOutTradeNo(wxPayUnifiedOrderRequest.getOutTradeNo());
wxTrade.setTotalFee(wxPayUnifiedOrderRequest.getTotalFee());
wxTrade.setBody(wxPayUnifiedOrderRequest.getBody());
wxTrade.setStatus(Constants.TRADE_UNKNOWN);
wxTradeService.insertWxTrade(wxTrade);

//3. 生成小程序调起支付所需的数据
WxPayment wxPayment = new WxPayment();
wxPayment.setWxTradeId(wxTrade.getId());
wxPayment.setAppId(wxPayUnifiedOrderResult.getAppid());
wxPayment.setTimeStamp((System.currentTimeMillis()/1000)+"");
wxPayment.set_package("prepay_id="+wxPayUnifiedOrderResult.getPrepayId());
wxPayment.setNonceStr(IdUtils.fastSimpleUUID(32));
wxPayment.setSignType("MD5");
wxPayment.sign(wxPayProperties.getMchKey());
logger.info(wxPayment.toString());

//4. 返回wxPayment
return AjaxResult.success(wxPayment);
}

2.3 支付回调接口

支付回调接口

  1. 查询该微信订单是否完成
  2. 确认支付完成,则执行具体的业务逻辑
1
2
3
4
5
6
java复制代码    /**
* 订单状态, -1:未知;0:支付失败;1:支付成功
*/
public static final int TRADE_UNKNOWN = -1;
public static final int TRADE_FAIL = 0;
public static final int TRADE_SUCCESS = 1;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
java复制代码    public int queryWxOrder(String outTradeNo){
try {
WxPayOrderQueryResult wxPayOrderQueryResult = wxService.queryOrder(null, outTradeNo);
logger.info(wxPayOrderQueryResult.toString());
if(wxPayOrderQueryResult.getTradeState().equals("NOTPAY")){
return Constants.TRADE_UNKNOWN;
}
return Constants.TRADE_SUCCESS;
}catch (Exception e){
// e.printStackTrace();
//异常,订单不存在
}
return Constants.TRADE_FAIL;
}

三、微信小程序实现

大部分的加密校验,以及与微信支付接口的交互都在Java后台操作,所以微信小程序的代码就相对简洁简单。

3.1 JSAP统一下单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
javascript复制代码  //统一下单
unifiedOrder(){
var _this = this
app.showLoading(true)
keyueliSdk.wxUnifiedOrder(
{
billId: _this.data.id,
},
(res) => {
console.log("wxUnifiedOrder", res)
_this.requestPayment(res.data.data)
},
(res) => {})
},

3.2 小程序调起支付

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
javascript复制代码  //官方标准的支付方法,调起支付界面
requestPayment(payData) {
var _this = this
wx.requestPayment({
timeStamp: payData.timeStamp,
nonceStr: payData.nonceStr,
package: payData._package,
signType: payData.signType,
paySign: payData.paySign,
success(res) {
console.log("支付成功", res)
_this.paySuccess(payData)
},
fail(res) {
console.log("支付失败", res)
app.showLoading(false)
app.showToast("支付失败")
}
})
},

3.3 支付回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
javascript复制代码  //支付成功记录
paySuccess(payData){
keyueliSdk.wxPay(
payData.wxTradeId,
(res) => {
wx.hideLoading()
console.log("wxPay", res)
if(res.data.code==200){
app.showToast("支付成功")
wx.navigateBack({
delta: 1,
})
return
}
app.showToast(res.data.msg)
},
(res) => {})
},

觉得好,就一键三连呗(点赞+收藏+关注)

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%