优雅的处理微信支付通知回调

本文介绍了一种优雅处理微信支付回调的方法,通过策略模式和接口设计实现了业务场景的灵活处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

优雅的处理微信支付异步回调

处理背景

​ 1.由于使用的是v2版本的微信支付,微信支付响应是xml字符串,所以处理需要对此响应进行解析成java对象

​ 1.由在业务中把微信支付进行了统一封装,如调用微信支付会在系统业务级别对操作记录进行处理,如记录业务类型,支付状态,订单号,支付结果等,导致会在支付后接收微信支付通知响应时候,需要对响应信息对微信支付操作进行回写记录等等,

初始版本的微信回调实现处理
    /**
     * 微信支付回调处理
     *
     * @param xmlData 微信回调数据
     * @return 微信响应信息 xml字符串
     */
    public String handleNotifyResult(String xmlData) {
        log.info("微信支付回调原始信息:" + xmlData);
        WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
        try {
            //解析xml串成java对象
            wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            

            ..
            ..
            ..
            业务场景处理
            
            
            //保存系统级别微信支付单记录
            updatePayOrder(wxPayOrderNotifyResult);
        } catch (WxPayException e) {
            log.error("微信支付回调异常", e);
            return  WxPayNotifyResponse.fail();
        }

        return  WxPayNotifyResponse.success();
    }

此种处理回调没有问题,但是如果场景过多,如商城订单支付,会员开通支付,续费支付等等业务场景,都需复写上述操作,

把会变化之处独立出来,把不需要变化的抽离出来,各是各,分开写

由上分析可看出这是一个典型的环绕处理,而环绕操作就是不需要变化的部分,每个支付的场景就是变化之处,可以采用切面来完成,处理方式,初步考虑基于注解来处理业务处理前置操作和后置操作,但思考过后发现缺失灵活性,于是决定采用策略模式通过接口来解决此问题

改动
1.上述代码把xml字符串单独抽离出来,已类变量方式存在,定义构建方法赋值xml字符串
public class WxNotify {
     /**
     * 微信回调数据
     */
    private String xmlData;


    /**
     * 构建微信支付回调 支付成功方法
     *
     * @param xmlData         响应xml数据
     */
   public WxNotify build(String xmlData) {
        this.xmlData = xmlData;
        return this;
    }
    
   
    public String handleNotifyResult() {
        log.info("微信支付回调原始信息:" + xmlData);
        WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
        try {
            //解析xml串成java对象
            wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            

            ..
            ..
            ..
            业务场景处理
            
            
            //保存系统级别微信支付单记录
            updatePayOrder(wxPayOrderNotifyResult);
        } catch (WxPayException e) {
            log.error("微信支付回调异常", e);
            return  WxPayNotifyResponse.fail();
        }

        return  WxPayNotifyResponse.success();
    }
}
2.定义微信回调处理接口
 
/**
 * 微信支付回调处理
 *
 * @author chenyanpeng
 * @Date: 2021/7/30 16:42
 */
public interface NotifyHandleResponse {
    /**
     * 微信支付成功
     *
     * @param wxPayOrderNotifyResult 解析结果
     * @param bllCode 业务编码
     * @return 微信服务器记录的订单回调信息
     */
    String success(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);


    /**
     * 回调支付失败
     *
     * @param wxPayOrderNotifyResult 解析结果
     * @param bllCode 业务编码
     * @return 微信服务器记录的订单回调信息
     */
    String fail(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);


    /**
     * 微信回调过程处理异常
     *
     * @param e 异常信息
     * @param bllCode 业务编码
     * @return 微信服务器记录的订单回调信息
     */
    String error(Exception e,WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);
}

3 定义处理处理结果接口,赋值xml同时在赋值接口信息,然后面向接口开发,不是面向实现类
@Component
public class WxNotify {
    
    
     /**
     * 微信回调数据
     */
    private String xmlData;
    
    
     /**
     * 通知处理响应
     */
    private NotifyHandleResponse notifyHandleResponse;


    
    /**
     * 构建微信支付回调 支付成功方法
     *
     * @param xmlData         响应xml数据
     * @param notifyInterface 通知处理接口
     */
    public WxNotify build(String xmlData, NotifyHandleResponse notifyHandleResponse) {
        this.notifyHandleResponse = notifyHandleResponse;
        this.xmlData = xmlData;
        return this;
    }
    
   
    public String handleNotifyResult() {
        log.debug("微信支付回调原始信息:" + xmlData);
        WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
        try {
            //解析xml串成java对象
            wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            //响应结果
            String message = null;
			//支付结果处理
            if (isOk(wxPayOrderNotifyResult)) {
                 //调用支付成功方法
           		 message = WxPayNotifyResponse.success(
                     notifyHandleResponse.success(wxPayOrderNotifyResult, wxPayOrderNotifyResult.getOutTradeNo())
                 );
                //此处织入支付成功后置操作
                updatePayOrder(wxPayOrderNotifyResult);
            }else{
                 //调用支付失败方法
                message =  WxPayNotifyResponse.fail(
                 		notifyHandleResponse.fail(wxPayOrderNotifyResult, wxPayOrderNotifyResult.getOutTradeNo())
                 )
                 //此处织入支付成功后置操作
				 ·····
            }
            return message;
        } catch (WxPayException e) {
            log.error("微信支付回调异常", e);
            //调用程序异常处理方法
            return	WxPayNotifyResponse.fail(
                notifyHandleResponse.error(e,wxPayOrderNotifyResult,wxPayOrderNotifyResult.getOutTradeNo())
            );   
        }
    }
    
    
    
    /**
     * 是否支付成功
     *
     * @param wxPayOrderNotifyResult 微信支付结果
     * @return true成功
     */
    private boolean isOk(WxPayOrderNotifyResult wxPayOrderNotifyResult) {
        return
                "SUCCESS".equals(wxPayOrderNotifyResult.getResultCode()) && "SUCCESS".equals(wxPayOrderNotifyResult.getResultCode());
    }
}
4调用
@RequestMapping("/wxPay")
public class WxNotifyContrller {
    
    
    //自己实现的接口处理类,该类实现定义处理接口
    @Autowired
    private DefaultNotifyResponseImpl notifyHandleResponse;
    
    
    
    
    /**
     * 默认支付回调通知处理 demo3
     *
     * @param xmlData 响应数据
     * @return 返回给wx服务器的数据, 会显示在查询微信订单中的信息中
     */
    @GetMapping(value = "/notify/demo1")
    public String handleNotify(@RequestBody(required = false) String xmlData) {
        return wxNotify.build(xmlData, notifyHandleResponse).handleNotifyResponse();
    }
    
    
    
    
    
    /**
     * 默认支付回调通知处理 demo2
     *
     * @param xmlData 响应数据
     * @return 返回给wx服务器的数据, 会显示在查询微信订单中的信息中
     */
    @GetMapping(value = "/notify/demo2")
    public String demo2(@RequestBody(required = false) String xmlData) {
        return wxNotify.build(xmlData, new NotifyHandleResponse() {
            @Override
            public String success(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
                //业务处理
                .....
                
                return "支付成功(。。。)";
            }
            @Override
            public String fail(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
                //业务处理
                
                .....
                return "支付失败(。。。)";
            }
            @Override
            public String error(Exception e,WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
                //业务处理
                
                .....
                return "支付异常(。。。)";
            }
        }).handleNotifyResponse();
    }
    
    
}
优点

自此完成,相对之前

系统更有弹性,

调用者只需关注调用业务本身,无需关注其他

代码整洁度提高,在后期维护也更方便

### 微信小程序支付成功后的回调处理 对于微信小程序支付成功后的回调处理,确保整个流程顺畅的关键在于多个方面。当项目架构为微服务模式时,所有请求需经由网关统一调度,在此情况下应将回调接口路径设入白名单以豁免鉴权过程,从而简化微信服务器调用该接口的过程[^1]。 #### Nginx 配置调整 鉴于微信仅接受可通过公网访问的80端口作为异步通知的目标地址,而HTTPS协议默认使用443端口,通常生产环境中的API请求会通过Nginx进行转发至内部网关。因此,有必要配置Nginx监听80端口并实现HTTP到HTTPS的安全重定向,使得最终呈现给微信侧的回调URL形似`http://example.com/api/callback`的形式。 ```nginx server { listen 80; server_name example.com; location /api/callback { proxy_pass https://internal-gateway.example.com/api/callback; # 其他必要的代理设置... } } ``` #### 接口测试验证 完成上述网络层面准备工作之后,建议利用Postman或其他工具先行对接口发起模拟POST请求来检验其可达性以及稳定性,确认不会返回诸如404之类的错误状态码即可认为准备阶段顺利完成。 #### PHP 实现注意事项 如果选用PHP作为后端开发语言,则需要注意避免因为空白字符或多余输出干扰而导致无法正确接收来自微信的通知消息。任何非预期的数据流均可能导致微信判定此次投递失败进而停止尝试重新发送通知数据包[^2]。 ```php <?php // 关闭一切不必要的输出缓冲机制 while (ob_get_level() > 0) { ob_end_clean(); } header('Content-Type: text/xml'); echo '<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>'; ?> ``` #### Spring Boot 应用实践 针对Spring Boot框架构建的应用程序而言,除了遵循通用的最佳实践之外,还需特别留意如何优雅地解析XML格式的消息体,并妥善保存交易记录以便后续查询与对账操作。此外,考虑到安全性因素,应当实施严格的签名验证逻辑防止恶意伪造事件触发异常行为[^3]。 ```java @PostMapping("/wxpay/notify") @ResponseBody public String handleWxPayNotify(HttpServletRequest request){ try{ Map<String, String> params = WXPayUtil.xmlToMap(request.getInputStream()); // 进行业务逻辑处理... return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>"; }catch(Exception e){ logger.error("Failed to process WeChat Pay notification", e); return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[System Error]]></return_msg></xml>"; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值