浅析微信支付系列已经更新五篇了哟~,没有看过的朋友们可以看一下哦。
浅析微信支付:统一下单接口
浅析微信支付:微信公众号网页授权
浅析微信支付:开发前的准备
前面一章已经讲了如何调用统一下单接口和调起微信支付窗口,在调用下单接口时,我们会传入 异步接收微信支付结果通知的回调地址,顾名思义这个地址作用就是用来接收支付结果通知,当用户在前端支付成功后,微信服务器会自动调用此地址,然后商户再进行处理。
1、支付结果通知以下为接口官方解释:
支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理,并返回应答。 对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒) 注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。 特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。 技术人员可登进微信商户后台扫描加入接口报警群。支付结果通知接口文档地址:
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8需要注意的事项有以下几点:
1. 该链接是通过【统一下单API】中提交的参数notify_url设置,如果链接无法访问,商户将无法接收到微信通知。 2. 通知url必须为直接可访问的url,不能携带参数,也就是必须使用外网接口地址,不能使用本地调试地址 3. 商户需要接收处理,并返回应答。如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 4. 通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒 5. 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 6. 特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。PS:推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
关于具体的签名和接收通知代码如下:
package imall.controller.wx; package ... /** * 微信支付Controller * * @author yclimb * @date 2018/6/15 */ @Api @RestController @RequestMapping("/weixin/pay") public class WXPayController extends BaseController { // 需要注入的一些service /** * 返回成功xml */ private String resSuccessXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; /** * 返回失败xml */ private String resFailXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>"; /** * 该链接是通过【统一下单API】中提交的参数notify_url设置,如果链接无法访问,商户将无法接收到微信通知。 * 通知url必须为直接可访问的url,不能携带参数。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action” * <p> * 支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理,并返回应答。 * 对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 * (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒) * 注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 * 推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。 * 特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,防止数据泄漏导致出现“假通知”,造成资金损失。 * * @author yclimb * @date 2018/6/15 */ @ApiOperation(value = "微信支付|支付回调接口", httpMethod = "POST", notes = "该链接是通过【统一下单API】中提交的参数notify_url设置,如果链接无法访问,商户将无法接收到微信通知。") @RequestMapping("/wxnotify") public void wxnotify(HttpServletRequest request, HttpServletResponse response) { String resXml = ""; InputStream inStream; try { inStream = request.getInputStream(); ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = inStream.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } WXPayUtil.getLogger().info("wxnotify:微信支付----start----"); // 获取微信调用我们notify_url的返回信息 String result = new String(outSteam.toByteArray(), "utf-8"); WXPayUtil.getLogger().info("wxnotify:微信支付----result----=" + result); // 关闭流 outSteam.close(); inStream.close(); // xml转换为map Map<String, String> resultMap = WXPayUtil.xmlToMap(result); boolean isSuccess = false; if (WXPayConstants.SUCCESS.equalsIgnoreCase(resultMap.get(WXPayConstants.RESULT_CODE))) { WXPayUtil.getLogger().info("wxnotify:微信支付----返回成功"); if (WXPayUtil.isSignatureValid(resultMap, WXPayConstants.API_KEY)) { // 订单处理 操作 orderconroller 的回写操作? WXPayUtil.getLogger().info("wxnotify:微信支付----验证签名成功"); // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了. resXml = resSuccessXml; isSuccess = true; } else { WXPayUtil.getLogger().error("wxnotify:微信支付----判断签名错误"); } } else { WXPayUtil.getLogger().error("wxnotify:支付失败,错误信息:" + resultMap.get(WXPayConstants.ERR_CODE_DES)); resXml = resFailXml; } // 付款记录修改 & 记录付款日志 // 回调方法,处理业务 - 修改订单状态 WXPayUtil.getLogger().info("wxnotify:微信支付回调:修改的订单===>" + resultMap.get("out_trade_no")); int updateResult = ...; if (updateResult > 0) { WXPayUtil.getLogger().info("wxnotify:微信支付回调:修改订单支付状态成功"); } else { WXPayUtil.getLogger().error("wxnotify:微信支付回调:修改订单支付状态失败"); } } catch (Exception e) { WXPayUtil.getLogger().error("wxnotify:支付回调发布异常:", e); } finally { try { // 处理业务完毕 BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); out.write(resXml.getBytes()); out.flush(); out.close(); } catch (IOException e) { WXPayUtil.getLogger().error("wxnotify:支付回调发布异常:out:", e); } } } }