当用户支付成功后跳转到成功页面
当返回异常时跳转到错误页面
实现思路:
我们通过 HttpClient 工具类实现对远程支付接口的调用。
接口链接:https://api.mch.weixin.qq.com/pay/orderquery
具体参数参见“查询订单”API, 我们在 controller 方法中轮询调用查询订单(间隔 3 秒),
当返回状态为 success 时,我们会在 controller 方法返回结果。前端代码收到结果后跳转到成
功页面。
后端代码
在 pinyougou-pay-interface 的 WeixinPayService.java 中新增方法定义
/*** 查询支付状态 * @param out_trade_no * */ public Map queryPayStatus(String out_trade_no);
在 pinyougou-pay-service 的 WeixinPayServiceImpl.java 中实现方法
@Override public Map queryPayStatus(String out_trade_no) { Map param=new HashMap();param.put("appid", appid);//公众账号 IDparam.put("mch_id", partner);//商户号 param.put("out_trade_no", out_trade_no);//订单号 param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串 String url="https://api.mch.weixin.qq.com/pay/orderquery"; try { String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey); HttpClient client=new HttpClient(url); client.setHttps(true); client.setXmlParam(xmlParam);client.post();String result = client.getContent();Map<String, String> map = WXPayUtil.xmlToMap(result);System.out.println(map); return map; } catch (Exception e) { e.printStackTrace();return null; } }
在 pinyougou-cart-web 的 PayController.java 新增方法
/*** 查询支付状态 * @param out_trade_no * @return * */ @RequestMapping("/queryPayStatus") public Result queryPayStatus(String out_trade_no){ Result result=null; while(true){ //调用查询接口 Map<String,String> map = weixinPayService.queryPayStatus(out_trade_no); if(map==null){ //出错 result=new Result(false, "支付出错"); break; } if(map.get("trade_state").equals("SUCCESS")){ //如果成功 result=new Result(true, "支付成功"); break; } try { Thread.sleep(3000);//间隔三秒 } catch (InterruptedException e) { e.printStackTrace(); } } return result;
前端代码
在 payService.js 新增方法
//查询支付状态 this.queryPayStatus=function(out_trade_no){ return $http.get('pay/queryPayStatus.do?out_trade_no='+out_trade_no); }
在 payController.js 中新增方法
//查询支付状态 queryPayStatus=function(out_trade_no){ payService.queryPayStatus(out_trade_no).success( function(response){ if(response.success){ location.href="paysuccess.html"; }else{ location.href="payfail.html"; } }); }
在 createNative 方法的回调方法中调用此查询方法
//本地生成二维码 $scope.createNative=function({ payService.createNative().success( function(response){ .......... queryPayStatus(response.out_trade_no); //查询支付状态 }); }
查询时间限制
如果用户到了二维码页面一直未支付,或是关掉了支付页面,我们的代码会一直循环调用微信接口,这样会对程序造成很大的压力。所以我们要加一个时间限制或是循环次数限制,当超过时间或次数时,跳出循环。可以这样完善代码:
修改 pinyougou-cart-web 工程 PayController.java 的 queryPayStatus 方法
@RequestMapping("/queryPayStatus") public Result queryPayStatus(String out_trade_no){ Result result=null; int x=0; while(true){ //调用查询接口....... try { Thread.sleep(3000);//间隔三秒 } catch ( InterruptedException e) { e.printStackTrace(); } //为了不让循环无休止地运行,我们定义一个循环变量,如果这个变量超过了这个值则退出循环,设置时间为 5 分钟 x++; if(x>=100){ result=new Result(false, "二维码超时"); break; } } return result; }
(2)修改 payController.js
//查询支付状态 queryPayStatus=function(out_trade_no){ payService.queryPayStatus(out_trade_no).success( function(response){ if(response.success){ location.href="paysuccess.html"; }else{ if(response.message=='二维码超时'){ $scope.createNative();//重新生成二维码 }else{ location.href="payfail.html"; } } }); }
支付成功页面显示余额
现在我们支付成功页面显示的是固定的值,怎么显示真正的支付金额呢?我们这里可以使用 angularJS 的页面传参来解决。
(1)修改 payController.js 跳转页面传参
//查询支付状态 queryPayStatus = function(out_trade_no) { payService.queryPayStatus(out_trade_no).success(function(response) { if(response.success) { location.href = "paysuccess.html#?money=" + $scope.money; } else { if(response.message == '二维码超时') { $scope.createNative(); //重新生成二维码}else{ location.href = "payfail.html"; } } }); }
(2)在 payController.js 中引入$location 服务 ,新增方法
//获取金额 $scope.getMoney=function(){ return $location.search()['money']; }
(3)修改页面 paysuccess.html ,引入 JS (与 pay.html 相同) ,body 添加指令
ng-app="pinyougou" ng-controller="payController"
用表达式显示金额
<p>支付金额:¥{{getMoney()}}元</p>