Java微信支付-支付成功异步回调验签

接上一篇Java微信支付-统一下单API,本篇在上篇文章的基础上讲述调用统一下单API用户支付成功之后微信异步回调通知
下文中所需配置、类都在以请查看以上链接内容。

在调用微信支付-统一下单API时,会传递notify_url这个参数给微信,这个参数是用户成功支付之后微信端会向此地址进行通知,我们应该在接受到微信发来的通知时进行验签确保安全性。
注意notify_url必须为外网可访问的url,不能携带参数。测试时可以使用内网穿透进行测试,这个东西在此我就不赘述了,需要的朋友自行Google。

话不多说,直接上码

/**
 * 微信支付Controller.
 * 
 * @create: 2019-10-10 15:25
 * @author: Sun
 */
@RequestMapping(value = "/wxpay")
@RestController
@Slf4j
public class WxPayController {

    /**
     * 微信支付异步回调接口
     *
     * @return
     */
    @RequestMapping(value = "/pay/async/notify")
    public void payAsyncNotify(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
    
        log.info("[payAsyncNotify]");
        
        String resultXml = wxPayService.payAsyncNotifyVerificationSign(httpServletRequest);

        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(httpServletResponse.getOutputStream());
        bufferedOutputStream.write(resultXml.getBytes());
        bufferedOutputStream.flush();
        bufferedOutputStream.close();
    }
}
/**
 * 微信支付接口.
 * 
 * @create: 2019-10-10 15:25
 * @author: Sun
 */
public interface WxPayService {

    /**
     * 微信支付异步通知验证签名
     * @param httpServletRequest
     * @return
     */
    String payAsyncNotifyVerificationSign(HttpServletRequest httpServletRequest);
}
/**
 * 微信支付接口实现
 * 
 * @create: 2019-10-10 15:40
 * @author: Sun
 */
@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

	@Autowired
    private MyWxPayConfig myWxPayConfig;


	@Override
    public String payAsyncNotifyVerificationSign(HttpServletRequest httpServletRequest) {
    
        WXPay wxPay = new WXPay(myWxPayConfig);

        String returnXmlMessage = null;
        String notifyXmlData = null;

        try {
            notifyXmlData = readXmlFromStream(httpServletRequest);

            Map<String, String> notifyMapData = WXPayUtil.xmlToMap(notifyXmlData);
            log.info("[payAsyncNotifyVerificationSign] [xml转换为map数据成功] [notifyMapData:{}]", notifyMapData);

            // 验证签名
            boolean signatureValid = wxPay.isPayResultNotifySignatureValid(notifyMapData);
            if (signatureValid) {
                // TODO:订单支付成功之后相关业务逻辑...
			
			
                // 一切正常返回的xml数据
                returnXmlMessage = setReturnXml(WXPayConstants.SUCCESS, "OK");
                log.info("[payAsyncNotifyVerificationSign] [out_trade_no:{}] [支付成功异步消息处理成功:{}]", notifyMapData.get("out_trade_no"), returnXmlMessage);
            } else {
                returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "Verification sign failed!");
                log.info("[payAsyncNotifyVerificationSign] [out_trade_no:{}] [验签失败:{}]", notifyMapData.get("out_trade_no"), returnXmlMessage);
            }

        } catch (IOException e) {
            log.error("[payAsyncNotifyVerificationSign] [读取微信服务器返回流中xml数据时发生异常:{}] ", ExceptionUtils.getStackTrace(e));
            returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "An exception occurred while reading the WeChat server returning xml data in the stream.");
        } catch (Exception e) {
            log.error("[payAsyncNotifyVerificationSign] [xml数据:{}] [异常:{}] ", notifyXmlData, ExceptionUtils.getStackTrace(e));

            returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "Payment successful, exception occurred during asynchronous notification processing.");
            log.warn("[payAsyncNotifyVerificationSign] [支付成功异步消息处理失败:{}]", returnXmlMessage);
        }

        return returnXmlMessage;
    }

	/**
     * 从流中读取微信返回的xml数据
     *
     * @param httpServletRequest
     * @return
     * @throws IOException
     */
    private String readXmlFromStream(HttpServletRequest httpServletRequest) throws IOException {
        InputStream inputStream = httpServletRequest.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        final StringBuffer sb = new StringBuffer();
        String line = null;
        try {
            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line);
            }
        } finally {
            bufferedReader.close();
            inputStream.close();
        }

        return sb.toString();
    }
	
	/**
     * 设置返回给微信服务器的xml信息
     *
     * @param returnCode
     * @param returnMsg
     * @return
     */
    private String setReturnXml(String returnCode, String returnMsg) {
        return "<xml><return_code><![CDATA[" + returnCode + "]]></return_code><return_msg><![CDATA[" + returnMsg + "]]></return_msg></xml>";
    }
}
发布了40 篇原创文章 · 获赞 10 · 访问量 4047

猜你喜欢

转载自blog.csdn.net/qq_41693150/article/details/102518005
今日推荐