微信支付篇—用户支付订单
创建PayOrderForm.java
@Data
@ApiModel(value = "订单付款的表单")
public class PayOrderForm {
@ApiModelProperty(value = "订单ID")
@Min(1)
private Integer orderId;
}
编写WxController中的创建付款方法,用于创建支付订单
@Login
@PostMapping("/microAppPayOrder")
@ApiOperation("小程序付款")
public R microAppPayOrder(@RequestBody PayOrderForm form, @RequestHeader HashMap header) {
ValidatorUtils.validateEntity(form);
String token = header.get("token").toString();
Long userId = Long.parseLong(jwtUtils.getClaimByToken(token).getSubject());
int orderId = form.getOrderId();
UserEntity user = new UserEntity();
user.setUserId(userId);
QueryWrapper wrapper = new QueryWrapper(user);
long count = userService.count(wrapper);
if (count == 0) {
return R.error("用户不存在");
}
String openId = userService.getOne(wrapper).getOpenId();
OrderEntity order = new OrderEntity();
order.setUserId(userId.intValue());
order.setId(orderId);
order.setStatus(1);
wrapper = new QueryWrapper(order);
count = orderService.count(wrapper);
if (count == 0) {
return R.error("不是有效的订单");
}
//验证购物券是否有效
//验证团购活动是否有效
order = new OrderEntity();
order.setId(orderId);
wrapper = new QueryWrapper(order);
order = orderService.getOne(wrapper);
//向微信平台发出请求,创建支付订单
String amount = order.getAmount().multiply(new BigDecimal("100")).intValue() + "";
try {
WXPay wxPay = new WXPay(myWXPayConfig);
HashMap map = new HashMap();
map.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串
map.put("body", "订单备注");
map.put("out_trade_no", order.getCode());
map.put("total_fee", amount);
map.put("spbill_create_ip", "127.0.0.1");
map.put("notify_url", "https://127.0.0.1/test");
map.put("trade_type", "JSAPI");
map.put("openid", openId);
Map<String, String> result = wxPay.unifiedOrder(map);
String prepayId = result.get("prepay_id");
System.out.println(prepayId);
if (prepayId != null) {
order.setPrepayId(prepayId);
order.setPaymentType(1);
UpdateWrapper updateWrapper = new UpdateWrapper();
updateWrapper.eq("id", order.getId());
orderService.update(order, updateWrapper);
//生成数字签名
map.clear();
map.put("appId", appId);
String timeStamp = new Date().getTime() + "";
map.put("timeStamp", timeStamp);
String nonceStr = WXPayUtil.generateNonceStr();
map.put("nonceStr", nonceStr);
map.put("package", "prepay_id=" + prepayId);
map.put("signType", "MD5");
String paySign = WXPayUtil.generateSignature(map, key);
return R.ok().put("package", "prepay_id=" + prepayId)
.put("timeStamp", timeStamp)
.put("nonceStr", nonceStr)
.put("paySign", paySign);
}
else {
return R.error("支付订单创建失败");
}
}
catch (Exception e) {
e.printStackTrace();
return R.error("微信支付模块故障");
}
}
编写order.vue
uni.request({
url: that.url.wx.microAppPayOrder,
method: "POST",
header: {
"token": uni.getStorageSync("token")
},
data: {
"orderId": id
},
success: function(resp) {
// console.log(resp)
let timeStamp = resp.data.timeStamp
let nonceStr = resp.data.nonceStr
let pk = resp.data.package
let paySign = resp.data.paySign
}
})
微信支付接口说明
为了保证交易的安全,必须要使用HTTPS协议。
上传数据必须使用POST方式提交
提交的数据和返回的结果都是XML格式的,并且根节点叫做。这一点大家不用担心,因为上节课的最后,我说过微信平台提供了SDK程序包,在SDK程序包里面封装了生成XML文件、解析XML文件的方法。等到讲解程序的时候,我在详细说明
所有的数据必须采用UTF-8编码。
其实呢,只要我们使用微信支付的SDK程序,以上的问题都不用我们操心。
创建支付订单的接口说明
请求参数
-
appid参数是商户的公众号ID,也就是注册小程序账号时候得到的app-id
-
mch_id参数是商户号,申请微信支付的时候,可以在微信商户平台的网站上面得到商户号
-
nonce_str参数是随机字符串,这个可以用微信支付的SDK程序来生成
-
sign参数是签名字符串,签名字符串,就是我们对上传的数据做MD5计算,得到的结果就是签名字符串了。SDK程序可以帮我们完成这个功能。对上传的数据做签名,一方面预防数据丢包,另外一方面放置数据在网络传输过程中被篡改。所以微信平台收到数据之后,重新计算一下数字签名。跟提交上来的数字签名比较一下就知道了。
-
body参数是商品的概要描述,这个内容你可以随便写,是给支付订单做备注的,一般写的都是商品的名称。确认支付之前,小程序会拿着商户的支付参数,去微信平台搜索支付订单,然后用户手机上就会出现这个支付订单的信息了。其中就有订单的概要描述。这就是现在这个参数的用途
-
out_trade_no参数是商户订单号,你自己定义,或者用SDK程序生成,都是可以的
-
total_fee参数是订单金额,整数类型,单位不是元,而是分
-
spbill_create_ip参数是终端的IP地址,这里我们上传Cetus主机的IP地址即可,你写什么IP地址,都不会影响到微信支付的
-
notify_url参数是通知地址,这个参数非常重要。因为将来微信支付成功以后,微信平台会把支付成功的结果发送给cetus项目,这里写的就是cetus项目接收支付结果的URL路径。如果这个地址写错了,倒是不会影响到微信支付,只是在支付成功以后,微信平台会每隔几分钟发送一次通知请求。如果没有响应,发过若干次通知之后,微信平台就不会发送通知了。因为cetus项目还没有发布,没有固定网址,所以我们写程序的时候,这个回调地址可以先随便写一个,等将来我们把cetus项目部署在腾讯云上面,再把这个回调通知地址改成真实的网址即可。
-
trade_type参数是交易类型,固定写成JSAPI
-
openid参数也就是微信用户登陆小程序时候,传给cetus项目的参数
响应结果
以下字段在return_code为SUCCESS的时候有返回
以下字段在return_code 和result_code都为SUCCESS的时候有返回
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
<openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>