com.github.binarywang.weixin-java-pay对接微信V3支付
泛域名ssl证书 239元1年送1个月、单域名39元1年,Sectigo(原Comodo证书)全球可信证书,强大的兼容性,高度安全性,如有问题7天内可退、可开发票
加微信VX 18718058521 备注SSL证书
【腾讯云】2核2G4M云服务器新老同享99元/年,续费同价
作者的demo中使用的是v2版本的配置,没有使用V3配置,这里记录一下V3版本的配置
v3支付, 相对之前的版本来说, 更为安全, 也相对繁琐一些, 而且请求和响应都使用了json格式的数据
1. 配置
发起支付所需的配置有三个证书文件, 在商户后台申请
apiclient_cert.p12
apiclient_key.pem
apiclient_cert.pem
这三个文件放到resources目录下,和application.yml在同一级
完整配置
2. 发起支付
小程序端 pay.weixin.qq.com/wiki/doc/ap…
ini复制代码@ApiOperation("统一下单,并组装所需支付参数") @PostMapping("/createOrderV3") public Result<Object> createOrderV3(String outTradeNo) throws WxPayException { WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount(); amount.setTotal(100); amount.setCurrency("CNY"); request.setAmount(amount); request.setOutTradeNo(outTradeNo); request.setDescription("测试商品"); WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer(); payer.setOpenid("ocnvkfwekclemvlkfdnveiwdawlecY"); request.setPayer(payer); request.setNotifyUrl("https://xxxxxx.com/notify/order"); // 原生下单方法 WxPayUnifiedOrderV3 result = this.wxService.unifiedOrderV3(TradeTypeEnum.JSAPI, request); // JSAPI返回方法 WxPayUnifiedOrderV3Result.JsapiResult result = wxService.createOrderV3(TradeTypeEnum.JSAPI, request); return Result.ok(result); }
在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
3. 回调处理
less复制代码/** * 解析支付结果通知 * 通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m * * @param notifyData 通知数据 * @return * @throws WxPayException */ @ApiOperation("支付回调通知处理") @PostMapping("/notify/order") public String parseOrderNotifyResult(@RequestBody String notifyData, HttpServletRequest request) throws WxPayException { log.info("【支付回调通知处理】:{}", notifyData); WxPayOrderNotifyV3Result result = this.wxService.parseOrderNotifyV3Result(notifyData, this.getRequestHeader(request)); // 解密后的数据 WxPayOrderNotifyV3Result.DecryptNotifyResult notifyResult = result.getResult(); if (WxPayConstants.WxpayTradeStatus.SUCCESS.equals(notifyResult.getTradeState())) { orderService.orderNotifyUpdate(notifyResult.getOutTradeNo(), notifyResult.getTransactionId(), result.toString()); log.info("【支付回调通知处理成功】"); } if (WxPayConstants.WxpayTradeStatus.PAY_ERROR.equals(notifyResult.getTradeState())) { log.error("【支付回调通知失败】:{}", result); throw new WxPayException("微信支付-回调失败!"); } return WxPayNotifyResponse.success("OK"); } /** * 获取回调请求头:签名相关 * * @param request HttpServletRequest * @return SignatureHeader */ public SignatureHeader getRequestHeader(HttpServletRequest request) { // 获取通知签名 String signature = request.getHeader("Wechatpay-Signature"); String nonce = request.getHeader("Wechatpay-Nonce"); String serial = request.getHeader("Wechatpay-Serial"); String timestamp = request.getHeader("Wechatpay-Timestamp"); SignatureHeader signatureHeader = new SignatureHeader(); signatureHeader.setSignature(signature); signatureHeader.setNonce(nonce); signatureHeader.setSerial(serial); signatureHeader.setTimeStamp(timestamp); return signatureHeader; }
SignatureHeader内的属性都可以在文档内找到获取方法
注意
支付通知http应答码为200或204才会当作正常接收,当回调处理异常时,应答的HTTP状态码应为500,或者4xx。
这个是官方文档原文, 如果应答报文code为fail, 但http状态码为200, 微信也认为你是正常处理, 不会重试回调
注意
遇到NoClassDefFoundError、NoSuchMethodError或ClassNotFoundException等异常的解决办法
先找到对应方法或类所在的jar包,通过在
IDE
开发环境或在线搜索均可轻易获得;确认对应jar包是否确实已经部署到运行时环境中;
检查本地项目对应的jar包版本,是否与本SDK所依赖的版本(【点此处查看pom文件】)一致,一般来说是由于部分jar包版本过低导致;
最常见的是:
httpclient
、commons-lang3
、xstream
等第三方jar包的版本过老,请检查并核实;还有一种情况是,你项目里使用了
WxJava
的多个模块,但是彼此版本不同,比如如果你是用了3.1.0
的weixin-java-pay
模块,同时使用了3.6.0
的weixin-java-mp
模块,就有可能会导致weixin-java-commmon
版本不一致,从而出现部分方法或类找不到,解决办法:使用同一版本即可。手动在自己项目的
pom
文件中指定对应jar
包maven
依赖和正确的版本号。resources目录下没有证书apiclient_cert.p12
后端java 返回得 小程序前端发起支付得参数
JSONObject resJSON = JSON.parseObject(response); String timestamp = String.valueOf(System.currentTimeMillis() / 1000L); String nonceStr = SignUtils.genRandomStr(); String prepayId = resJSON.getString("prepay_id"); Map<String, String> payInfo = new HashMap<>(8); String appid = wxPayConfig.getAppId(); payInfo.put("appId", appid); payInfo.put("timeStamp", timestamp); payInfo.put("nonceStr", nonceStr); payInfo.put("package", "prepay_id=" + prepayId); payInfo.put("signType", "RSA"); String beforeSign = String.format("%s\n%s\n%s\n%s\n", appid, timestamp, nonceStr, "prepay_id=" + prepayId); payInfo.put("paySign", SignUtils.sign(beforeSign, PemUtils.loadPrivateKey(new FileInputStream(wxPayConfig.getPrivateKeyPath())))); // 签名以后在增加prepayId参数 payInfo.put("prepayId", prepayId);
SignUtils 全路径是 com.github.binarywang.wxpay.v3.util.SignUtils 2个参数,1个参数是加签字符串,第二个参数是私钥,可以从wxPayService得到config,从config 得到私钥
小程序前端发起微信支付 (后端可以直接返回给前端如下代码)
wx.requestPayment( { "timeStamp":"", "nonceStr": "", "package": "", "signType": "RSA", "paySign": "", "success":function(res){}, "fail":function(res){}, "complete":function(res){} })