微信PC扫码支付(四)-支付异步回调通知,退款异步回调通知

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cl11992/article/details/86712519

一、介绍

本文介绍了微信支付异步回调通知,退款异步回调通知的代码实例,如有不足的请提出,我会做出改正。

二、官方文档

支付异步回调通知:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8

退款异步回调通知:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_16&index=11

三、微信SDK安装方法

微信PC扫码支付(一)-maven本地仓库安装:微信支付sdk

四、回调通知所需工具类

WeixinPayUtil.java

public class WeixinPayUtil {
	
	/** 
     * 密钥算法 
     */  
    private static final String ALGORITHM = "AES";  
    /** 
     * 加解密算法/工作模式/填充方式 
     */  
    private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";
    
	
    private static Logger logger = LoggerFactory.getLogger(WeixinPayUtil.class);
	
	/**
	 * 获取请求参数
	 * @param request
	 * @return
	 */
	public static String readData(HttpServletRequest request){
		BufferedReader br = null;
		try {
			StringBuilder ret;
			br = request.getReader();
			String line = br.readLine();
			if(line != null) {
				ret = new StringBuilder();
				ret.append(line);
			}else{
				return "";
			}
			while ((line = br.readLine()) != null) {
				ret.append('\n').append(line);
			}
			return ret.toString();
		}catch (IOException e) {
			throw new RuntimeException(e);
		}finally {
			if(br != null) {
				try {
					br.close();
				}catch (IOException e){
					logger.error(e.getMessage(), e);
				}
			}
		}
	}
	
	/** 
     * AES解密 
     * @param 微信返回的加密数据 
     * @return 
     * @throws Exception 
     */  
    public static String decryptData(String data) throws Exception {  
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING,"BC");
        WeixinConfig weixinConfig = new WeixinConfig();
        SecretKeySpec key = new SecretKeySpec(MD5.encrypt(weixinConfig.getKey()).toLowerCase().getBytes(), ALGORITHM); 
        cipher.init(Cipher.DECRYPT_MODE, key);  
        return new String(cipher.doFinal(Base64Utils.decode(data.getBytes())));  
    } 
	
}

五、支付异步通知

注意:

  1. 在处理业务逻辑的时候,必须能够正确处理重复的通知。例如:通知之后修改完订单状态,下次在进行回调就不需要修改了。
  2. 一定要安装这个格式返回给微信,要不微信会一直回调你。
  • 下文PayException为自定义异常类
  • 下文WeixinConfig为微信需要固定参数类
public Object payCallBack(){
	String fail="<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
	String success="<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
	try {
		String xmlMsg = WeixinPayUtil.readData(R.getRequest());
		logger.info("微信回调通知参数:---"+xmlMsg);
		if(StringUtils.isBlank(xmlMsg)){
			return fail;
		}
		Map<String, String> paramMap = WXPayUtil.xmlToMap(xmlMsg);
		//验证签名
		WeixinConfig weixinConfig=new WeixinConfig();
		WXPay wxPay=new WXPay(weixinConfig);
		Boolean flag=wxPay.isPayResultNotifySignatureValid(paramMap);
		logger.info("微信支付通知-验签:"+flag);
		if(!flag){
			logger.info("微信支付通知-验签失败");
			return fail;
		}
		/**
		 * 业务逻辑:修改订单状态
		 */
		return success;
	} catch (Exception e) {
		logger.info("微信支付回调发生错误:",e);
		return fail;
	}
}

六、退款异步回调通知

注意:

  1. 在处理业务逻辑的时候,必须能够正确处理重复的通知。例如:通知之后修改完退款订单状态,下次在进行回调就不需要修改了。
  2. 一定要安装这个格式返回给微信,要不微信会一直回调你。
  3. 下面代码如报java.security.InvalidKeyException: Illegal key size or default parameters这个错请看这篇文章来进行解决https://blog.csdn.net/cl11992/article/details/86703694
  • 下文PayException为自定义异常类
  • 下文WeixinConfig为微信需要固定参数类
public Object refundCallBack() throws PayException {
	String fail="<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
	String success="<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
	try {
		String xmlMsg = WeixinPayUtil.readData(R.getRequest());
		if(StringUtils.isBlank(xmlMsg)){
			return fail;
		}
		Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlMsg);
		//状态码
		String return_code  = resultMap.get("return_code");
		logger.info("微信退款通知-return_code:"+return_code);
		if (!("SUCCESS").equals(return_code) || StringUtils.isBlank(return_code)) {
			return fail;
		}
		String base64Result = resultMap.get("req_info").toString();
		logger.info("微信退款-base64Result:"+base64Result);
		Security.addProvider(new BouncyCastleProvider()); 
		String result = WeixinPayUtil.decryptData(base64Result);
		Map<String, String> map = WXPayUtil.xmlToMap(result);
		if(map.isEmpty()){
			return fail;
		}
		//状态码
		String refund_status  = map.get("refund_status");
		logger.info("微信退款通知-refund_status:"+refund_status);
		if (!("SUCCESS").equals(refund_status) || StringUtils.isBlank(refund_status)) {
			return fail;
		}
		/**
		 * 业务逻辑:修改退款订单状态
		 */
		return success;
	} catch (Exception e) {
		logger.info("微信退款回调发生错误:",e);
		return false;
	}
}

猜你喜欢

转载自blog.csdn.net/cl11992/article/details/86712519