微信小程序接入微信支付(四):接收支付结果通知与沙箱测试

代码主体写完后,还有不可或缺的部分需要补充完整,即接收支付结果通知,官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8

目录:

微信小程序接入微信支付(一):大概流程与准备需知
微信小程序接入微信支付(二):后台调用统一下单接口
微信小程序接入微信支付(三):小程序端调用支付接口
微信小程序接入微信支付(四):接收支付结果通知与沙箱测试

支付结果通知:

微信支付官方会调用我们“notify_url” 提供地接口来进行异步地通知每笔订单的支付结果。如果我们提供的接口出现问题,则会按照一定的频率多次通知过来。此外当我们接收到通知后,需要根据通知内容进行处理,并及时把结果回调给微信支付官方。

简单提供下我的代码:

	/**
	 * 暂定为 获取支付结果通知接口 ,根据接收到的通知,处理支付结果
	 * 
	 * @return
	 * @throws Exception 
	 */
	@PostMapping("/getresult")
    @ResponseBody	
	public String getResult(@RequestBody String res) throws Exception {
		String errMsg = "Unknown error";
		String xmlMsg = "<xml>"+
						"<return_code>"+"FAIL"+"</return_code>"+
						"<return_msg>"+errMsg+"</return_msg>"+
						"</xml>";
		
		//接收到的xml格式字符串转map
		Map<String, String> resultMap = xmlToMap(res);
		String return_code;
        if (resultMap.containsKey("return_code")) {
            return_code = resultMap.get("return_code");
        }
        else {
        	errMsg = "No 'return_code' in XML";
            throw new Exception(String.format("GETRESULT No `return_code` in XML: %s", res));
        }
        
        if (return_code.equals("FAIL")) {
        	errMsg = "return_code is FAIL";
        	throw new Exception("GETRESULT return_code : fail from wx_pay :" + res);
        }
        else if (return_code.equals("SUCCESS")) {
        	LOG.info("----getresult success order_no: " + resultMap.get("out_trade_no"));
    		//TODO 签名验证支付结果通知
    		//查询本地该订单
    		Order order =orderservice.selectOrdersByExample(Long.parseLong(resultMap.get("out_trade_no")), null, null, null).get(0);
    		
    		if(order.getOrder_state() != 0 && resultMap.get("time_end") != null) {
    			//订单状态--已支付, 微信通知支付结果--支付成功 返回成功
    			xmlMsg ="<xml>"+
						"<return_code>"+"SUCCESS"+"</return_code>"+
						"<return_msg>"+"OK"+"</return_msg>"+
						"</xml>";
    			return xmlMsg;
    		}else if(order.getOrder_state() != 0 && resultMap.get("time_end") == null) {
    			//订单状态--已支付, 微信通知支付结果--支付未成功 不做操作返回成功
    			xmlMsg ="<xml>"+
						"<return_code>"+"SUCCESS"+"</return_code>"+
						"<return_msg>"+"OK"+"</return_msg>"+
						"</xml>";
    			return xmlMsg;
    		}else if(order.getOrder_state() == 0 && resultMap.get("time_end") != null){
    			//订单状态--待付款, 微信通知支付结果--支付成功 更改订单状态为1--待发货 返回成功
    			orderservice.updateOrder(Long.parseLong(resultMap.get("out_trade_no")), null, 1);
    			xmlMsg ="<xml>"+
						"<return_code>"+"SUCCESS"+"</return_code>"+
						"<return_msg>"+"OK"+"</return_msg>"+
						"</xml>";
    			return xmlMsg;
    		}else {
    			//其余情况,先按已处理解决,返回成功
    			xmlMsg ="<xml>"+
						"<return_code>"+"SUCCESS"+"</return_code>"+
						"<return_msg>"+"OK"+"</return_msg>"+
						"</xml>";
    			return xmlMsg;
    		}
    		//TODO 处理数据时建议使用数据锁进行并发控制
        }   
        
		return xmlMsg;
	}

相关外部方法可在前面章节中查看:微信小程序接入微信支付(二):后台调用统一下单接口
建议对接受的通知进行签名认证,处理数据时使用数据锁进行并发控制。

沙箱测试:

当我们代码写完后需要进行测试,微信支付官方提供专门的沙箱环境用于测试,不会产生金额交易。
官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=23_1&index=2

我们只需要在调用接口的URL地址中加入/sandboxnew,
例如统一下单接口:https://api.mch.weixin.qq.com/pay/unifiedorder
可改为https://api.mch.weixin.qq.com/sanboxnew/pay/unifiedorder 就能访问到沙箱环境,但是使用沙箱环境时,我们不能使用商户自己的key,而是通过后台调用-获取验签秘钥API接口来获取沙箱环境专用的key。

		//沙箱环境下需先请求获取key
		Map<String, String> testMap = new HashMap<>();
		testMap.put("mch_id", mchId);
		testMap.put("nonce_str",getRandomString());
		//生成符合规格的签名串
		String stringTestSignTemp = getParamStr(testMap,realKey);
		//进行MD5运算,并转为大写,获得sign参数的值
		String signTestValue = MD5(stringTestSignTemp.toString()).toUpperCase();
		//把sign放入map中
		testMap.put("sign",signTestValue);
		//map转义为xml格式
		String requestTestParam = mapToXml(testMap);
		LOG.info("request sandbox API key - [parameters]:" +requestTestParam);
		System.out.println("request sandbox API key - [parameters]:" +requestTestParam);
		//发送请求
		String testResult = sendPostParam(sandBoxUrl, requestTestParam);
		System.out.println("request sandbox API key - [results]:" +testResult);
		LOG.info("request sandbox API key - [results]:" +testResult);
		//将返回的结果从xml字符串转义为map
		Map<String, String> testResultMap = xmlToMap(testResult);
		if(testResultMap.get("return_code") != null && testResultMap.get("return_code") == "SUCCESS") {
			sandKey = testResultMap.get("sandbox_signkey");
			System.out.println("----sandbox key: " + sandKey);
			LOG.info("---sandbox key:" + sandKey);
		}else {
			return null;
		}

!注意:

我们可以根据沙箱环境的反馈来修改我们的代码以及参数,但是当我们发现自己明明没有什么错误时,沙箱环境依旧报错,那么我们可以转到正式环境去测试了。。。。。。就像有些网友说的,这个沙箱环境一步一个坑,bug满天飞。当转到正式环境时,你就会发现原来自己没错。。。。。。说多了都是泪

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值