微信小程序使用微信支付JSAPI开发支付功能
官方文档:小程序支付
准备
- APP ID
- 商户号
- 小程序绑定商户号
- 微信官方SDK https://github.com/wechatpay-apiv3/wechatpay-java
流程

-
前端向后端发送支付请求
-
后端首先生成本地订单记录,然后向微信服务器发送下单请求并携带小程序ID、商户号、本地订单号、商品描述、金额、回调地址、用户openId等信息
String appId; // 微信小程序appId String mchId; // 商户ID String payerOpenId; // 支付者的openId PrepayRequest request = new PrepayRequest(); // 支付请求 Amount amount = new Amount(); // 金额 Payer payer = new Payer(); // 用户 amount.setTotal( (int)(dto.getPayMoney() * 100) ); // 单位:分 payer.setOpenid(payerOpenId); // 付款者的openId request.setAmount(amount); request.setPayer(payer); request.setAppid(appId); request.setMchid(mchId); request.setOutTradeNo(ownOrderNum); // 平台订单号 request.setDescription("商品描述"); request.setNotifyUrl("https://example.com/callBack"); // 用户支付成功后,微信官方会调用这个地址
-
微信官方正确响应后,会返回预支付ID
prepay_id,后端将prepay_id进行签名再返回给前端// prepayWithRequestPayment() 会对预支付ID签名并返回 PrepayWithRequestPaymentResponse PrepayWithRequestPaymentResponse response = wechatService.prepayWithRequestPayment(request); return response; // 返回给前端
-
前端页面根据签名数据调用
wx.requestPayment向微信服务器发送支付请求,微信官方给予正确响应后,前端页面会弹出支付界面响应结果包含以下数据:
参数名解释描述 timeStamp 时间戳 nonceStr 随机字符串 最多32个字符 package 扩展字符串 格式: “prepay_id=wx201410272009395522657a690389285100” signType 签名方式 RSA paySign 签名 // response.data 为响应结果 wx.requestPayment({ timeStamp: response.data.timeStamp, nonceStr: response.data.nonceStr, package: response.data.packageVal, signType: response.data.signType, paySign: response.data.paySign, success: (result) => {}, fail: () => { console.log("支付失败...") } });
-
用户支付完成后,微信会根据回调地址调用平台的POST[https]接口向平台返回支付结果
接收到微信发送的支付结果后,应该给微信返回状态码,否则微信会认为回调未成功,进而重复请求。考虑微信有重复调用的可能,该接口应当对同一条订单的信息做加锁处理,保证幂等性。
@PostMapping("callBackPayComplete") public void callBackPayComplete(HttpServletRequest request, HttpServletResponse response, @RequestBody String param) { String signature = request.getHeader("Wechatpay-Signature"); String signatureType = request.getHeader("Wechatpay-Signature-Type"); String serialNumber = request.getHeader("Wechatpay-Serial"); String nonce = request.getHeader("Wechatpay-Nonce"); String timestamp = request.getHeader("Wechatpay-Timestamp"); boolean bool = consultService.handlePayResult(signature, signatureType, serialNumber, nonce, timestamp, param); response.setStatus(bool ? 200 : 500); }注意:使用 org.springframework.web.bind.annotation 的 @Header 或 @Headers 注解获取请求头时,请求头的 key 会变成小写。这里使用HttpServletRequest.getHeader()获取