当用户支付成功后跳转到成功页面 当返回异常时跳转到错误页面
实现思路:
我们通过 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 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 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"
用表达式显示金额
支付金额:¥{{getMoney()}}元