1.什么是异步通知?
先说说同步通知,在平时我们付款的时候,特别是在银行转账的时候点击付款后一般都会给我们反馈显示付款成功,这个通知就是同步通知。同步通知仅仅代表调用支付接口成功,也就是用户付款的操作是成功的,至于转账是否到账或者付款是否真正成功并不能知道。
异步:当用户提交了付款或者转账的请求时,服务器在后端开始处理具体的支付逻辑业务,这时候就出现一些问题导致支付结果失败,所以有时候向他人转账时会在付款结束后收到短信,显示余额被冲正,转账失败,因此支付结果都是以异步通知为准。
2.如何接收异步通知?
以Native为例,微信官方文档微信支付-开发者文档 (qq.com)给出具体的请求爱参数,其中一个参数名为notify_url,这就是接收微信异步通知的地址,注意该URL必须为直接可以访问的URL,不允许携带查询串,并且必须为https开头的。
2.1 安装内网穿透NATAPP
因为我们电脑的内网是无法被外面访问的,通过natapp隧道可以将内外网打通,具体的步骤去NATAPP-内网穿透 基于ngrok的国内高速内网映射工具网站有一分钟入门教程以及常见错误排查。配置完成以后我们可以在项目中测试。注意要在natapp的网页中将默认端口80改成8080
我的软件界面如下,在浏览器中输入 http://uuc8tj.natappfree.cc和输入 127.0.0.1:8080效果是一样的。测试如下,将locast:8080替换成natapp给我们提供的网址,二者效果一样。
http://localhost:8080/pay/create?orderId=347589322&amount=0.01
http://uuc8tj.natappfree.cc/pay/create?orderId=347589322&amount=0.01
2.2支付项目中设置回调地址(Service层)
public PayResponse create(String orderId, BigDecimal amount) {
WxPayConfig wxPayConfig = new WxPayConfig();
wxPayConfig.setAppId("wxd898fcb01713c658");//采用native支付需要小程序Id
wxPayConfig.setMchId("1483469312");//商户Id
wxPayConfig.setMchKey("7mdApPMfXddfWWbbP4DUaVYm2wjyh3v3");//商户密钥
//接收支付平台异步通知的地址,这是内网ip,外网无法访问,只有局域网可以访问
//建议用https
wxPayConfig.setNotifyUrl("https://xzk.mynatapp.cc/pay/notify/");
BestPayServiceImpl bestPayService = new BestPayServiceImpl();
bestPayService.setWxPayConfig(wxPayConfig);
PayRequest request = new PayRequest();
request.setOrderName("8492084-薯片");//订单名
request.setOrderId(orderId);
request.setOrderAmount(amount.doubleValue());
request.setPayTypeEnum(BestPayTypeEnum.WXPAY_NATIVE);//设置支付为微信中的Native支付
PayResponse payResponse = bestPayService.pay(request);
return payResponse;
}
在控制层中设置好路由controller:
public class PayController {
@Autowired
PayService payService;
@GetMapping("/create")
public ModelAndView create(@RequestParam("orderId") String orderId,@RequestParam("amount") BigDecimal amount){
PayResponse payResponse = payService.create(orderId,amount);
Map map = new HashMap<>();//动态接收codeUrl
map.put("codeUrl",payResponse.getCodeUrl());
return new ModelAndView("create",map);//把参数传到视图里面
}
@PostMapping("/notify")
//因为是一组数据所以需要用body接收
public void asynNotify(@RequestBody String notifyData){
log.info(notifyData);
}
}
真个流程就是当我们在地址栏输入
https://xzk.mynatapp.cc/pay/create?orderId=347889645665669422&amount=0.01
后端根据订单号和金额请求微信支付,微信支付返回一个codeUrl,解析得到付款二维码,扫码付款后微信将回调地址发送给回调地址,然后已post的形式提交给控制器里面的asynNotify方法,最后控制台输出如下的xml信息,异步回调成功。
<xml><appid><![CDATA[wxd898fcb01713c658]]></appid>
<bank_type><![CDATA[OTHERS]]></bank_type>
<cash_fee><![CDATA[1]]></cash_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[N]]></is_subscribe>
<mch_id><![CDATA[1483469312]]></mch_id>
<nonce_str><![CDATA[8EYuWgYiwjnEhvOg]]></nonce_str>
<openid><![CDATA[oTgZpwaXTs2GzvkwMNDzbWIcrqjA]]></openid>
<out_trade_no><![CDATA[347889645665669422]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[18EE3825D2A3FD9A9DCBC60CAC131973]]></sign>
<time_end><![CDATA[20220514185750]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[NATIVE]]></trade_type>
<transaction_id><![CDATA[4200001503202205144756789400]]></transaction_id>
</xml>