基于APIV2的实现
分享一个之前在商城小程序中实现的微信支付功能
小程序端代码:
/**
* 创建订单
*/
async createOrder() {
try {
const totalPrice = this.data.totalPrice;
const address = this.data.address.provinceName + this.data.address.cityName + this.data.address.countyName + this.data.address.detailInfo;
const consignee = this.data.address.userName;
const telNumber = this.data.address.telNumber;
let orderDetails = [];
this.data.cart.forEach(v => orderDetails.push({
productId: v.id,
productNumber: v.num,
productPrice: v.price,
productName: v.name,
merchantId: v.merchantId
}))
const order = {
totalPrice,
address,
consignee,
telNumber,
orderDetails
}
console.log("createOrder。。。。。。。。。。。");
const res = await getApp().call({
path: "/my/order/create",
method: "POST",
data: {
...order
}
});
console.log("orderNo=" + res.orderNo);
let orderNo = res.orderNo;
// 删除缓存中,已经创建订单的商品
let newCart = wx.getStorageSync('cart');
newCart = newCart.filter(v => !v.checked);
wx.setStorageSync('cart', newCart);
const payResult=await getApp().dopay({
orderNo
});
} catch (error) {
console.log(error);
wx.showToast({
title: '创建订单失败,请稍后重试',
icon: 'none'
})
}
},
async dopay(obj) {
const payRes = await this.preparePay({
orderNo: obj.orderNo
});
console.log("payRes==", payRes);
let type = 0;
if (payRes != null) {
type = 2;
} else {
type = 1
}
wx.navigateTo({
url: '/pages/order/order?type=' + type
})
},
async preparePay(obj) {
try {
// 调用统一下单,预支付
console.log("preparePayRes。。。。。。。。。。。");
const preparePayRes = await this.call({
path: "/my/order/preparePay",
method: "POST",
data: {
orderNo: obj.orderNo
}
});
console.log("preparePayRes===", preparePayRes);
let payRes = await this.requestPay(preparePayRes);
if (payRes) {
getApp().updateOrderStatus({
orderNo:obj.orderNo,
status:1
});
}
wx.showToast({
title: '支付成功',
icon: 'none'
})
return payRes;
} catch (error) {
console.log(error);
wx.showToast({
title: '支付失败,请稍后重试',
icon: 'none'
})
return null;
}
},
updateOrderStatus(obj){
getApp().call({
path: "/my/order/updateOrderStatus",
method: "GET",
data: {
orderNo: obj.orderNo,
status: obj.status
}
});
},
java后端:
/** * 创建订单,返回订单号 * * @return */ @PostMapping("/create") @Transactional // public R create(@RequestBody Order order, @RequestHeader(value = "X-WX-OPENID") String openId){ public R create(@RequestBody Order order, @RequestHeader Map<String, String> headers) { Map<String, Object> resultMap = new HashMap<>(); // log.info("obj=="+obj); try { // 通过token获取openid // headers.forEach((key,value)->{ // //日志记录所有请求头 // log.info(String.format("Header '%s' = %s",key,value)); // }); String openId = ""; for (String key : headers.keySet()) { if ("x-wx-openid".equals(key)) { openId = headers.get(key); break; } } log.info("openId==" + openId); // 添加订单到数据库 // Claims claims = JwtUtils.validateJWT(token).getClaims(); // if(claims!=null){ // System.out.println("openid="+claims.getId()); // order.setUserId(claims.getId()); // } WxUserInfo userInfo = wxUserInfoService.getOne(new QueryWrapper<WxUserInfo>().eq("openid", openId)); log.info("order==" + order); log.info("userInfo==" + userInfo); order.setStatus(0); order.setUserId(userInfo.getId()); order.setOrderNo("YLST" + DateUtil.getCurrentDateStr()); order.setCreateDate(new Date()); List<OrderDetail> orderDetails = order.getOrderDetails(); log.info("orderDetails=" + orderDetails); orderService.save(order); // 添加订单详情到数据库 Map<Integer, Integer> merchantOrderSubNoMap = new HashMap<>(); int subNo = 0; for (OrderDetail orderDetail : orderDetails) { orderDetail.setOrderId(order.getId()); orderDetail.setSumPrice(orderDetail.getProductPrice().multiply(new BigDecimal(orderDetail.getProductNumber())).setScale(2, RoundingMode.HALF_UP)); if (!merchantOrderSubNoMap.containsKey(orderDetail.getMerchantId())) { subNo++; merchantOrderSubNoMap.put(orderDetail.getMerchantId(), subNo); orderDetail.setOrderSubNo(subNo); } else { orderDetail.setOrderSubNo(merchantOrderSubNoMap.get(orderDetail.getMerchantId())); } orderDetailService.save(orderDetail); } resultMap.put("orderNo", order.getOrderNo()); } catch (Exception e) { log.error(e.getMessage(), e); } return R.ok(resultMap); } @GetMapping("/updateOrderStatus") public R updateOrderStatus(@RequestParam("orderNo") String orderNo, @RequestParam("status") Integer status) { try { Order order = orderService.getOne(new QueryWrapper<Order>().eq("orderNo", orderNo)); order.setStatus(status); orderService.updateById(order); } catch (Exception e) { log.error(e.getMessage(), e); return R.error(); } return R.ok(); }
/** * 调用统一下单,预支付 * APIV2版本的旧支付,基于MD5加密签名,使用XML传递数据 * @return * @throws Exception */ @RequestMapping("/preparePay") public R preparePay(@RequestBody Order requestOrder, @RequestHeader Map<String, String> headers) throws Exception { Map<String, Object> payMap = new HashMap<>(); try { String openId = ""; for (String key : headers.keySet()) { if ("x-wx-openid".equals(key)) { openId = headers.get(key); break; } } log.info("requestOrder=" + requestOrder); log.info("orderNo=" + requestOrder.getOrderNo()); String orderNo = requestOrder.getOrderNo(); Order order = orderService.getOne(new QueryWrapper<Order>().eq("orderNo", orderNo)); Map<String, Object> map = new HashMap<>(); map.put("appid", weixinpayProperties.getAppid()); map.put("mch_id", weixinpayProperties.getMch_id()); map.put("nonce_str", StringUtil.getRandomString(32)); map.put("body", "ifriendshopmallpay"); map.put("out_trade_no", orderNo); // map.put("total_fee",order.getTotalPrice().movePointRight(2)); map.put("total_fee", 1); map.put("spbill_create_ip", weixinpayProperties.getSpbill_create_ip()); map.put("notify_url", weixinpayProperties.getNotify_url()); map.put("trade_type", "JSAPI"); map.put("openid", openId); map.put("sign", getSign(map)); // 参数转成xml String xml = XmlUtil.genXml(map); HttpResponse httpResponse = HttpClientUtil.sendXMLDataByPost(weixinpayProperties.getUrl().toString(), xml); String httpEntityContent = HttpClientUtil.getHttpEntityContent(httpResponse); System.out.println("httpEntityContent==" + httpEntityContent); Map resultMap = XmlUtil.doXMLParse(httpEntityContent); System.out.println("resultMap=" + resultMap); if (resultMap.get("result_code").equals("SUCCESS")) { payMap.put("appId", resultMap.get("appid")); payMap.put("timeStamp", System.currentTimeMillis() / 1000 + ""); payMap.put("nonceStr", StringUtil.getRandomString(32)); payMap.put("package", "prepay_id=" + resultMap.get("prepay_id")); payMap.put("signType", "MD5"); payMap.put("paySign", getSign(payMap)); payMap.put("orderNo", orderNo); } else { return R.error(500, "系统报错,请联系管理员"); } } catch (Exception e) { log.error(e.getMessage(), e); return R.error(500, "系统报错,请联系管理员"); } return R.ok(payMap); } /** * 微信支付签名算法sign */ private String getSign(Map<String, Object> map) { StringBuffer sb = new StringBuffer(); String[] keyArr = (String[]) map.keySet().toArray(new String[map.keySet().size()]);//获取map中的key转为array Arrays.sort(keyArr);//对array排序 for (int i = 0, size = keyArr.length; i < size; ++i) { if ("sign".equals(keyArr[i])) { continue; } sb.append(keyArr[i] + "=" + map.get(keyArr[i]) + "&"); } sb.append("key=" + weixinpayProperties.getKey()); String sign = string2MD5(sb.toString()); System.out.println("sign=" + sign); return sign; } /*** * MD5加码 生成32位md5码 */ private String string2MD5(String str) { if (str == null || str.length() == 0) { return null; } char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; try { MessageDigest mdTemp = MessageDigest.getInstance("MD5"); mdTemp.update(str.getBytes("UTF-8")); byte[] md = mdTemp.digest(); int j = md.length; char buf[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; buf[k++] = hexDigits[byte0 >>> 4 & 0xf]; buf[k++] = hexDigits[byte0 & 0xf]; } return new String(buf).toUpperCase(); } catch (Exception e) { return null; } }