美文网首页
支付通知思路

支付通知思路

作者: wanggs | 来源:发表于2021-10-14 14:29 被阅读0次

    支付通知思路

    MQ延时消息投递异步通知

    场景

    在第三方支付中,例如支付宝、或者微信,对于订单请求,第三方支付系统采用的是消息同步返回、异步通知+主动补偿查询的补偿机制

    1. 商户请求交易接口成功。

    2. 接受银行的异步通知。

    3. 处理业务,将通知URL和通知的数据放到队列中。通知队列是常驻的。

    4. 如果通知商户成功/失败更新通知状态。如果通知失败,根据通知间隔重新把通知数据放到通知队列里。

    伪代码

    /**
     * 接收MQ消息
     * 业务: 支付订单商户通知
     */
    @Slf4j
    @Component
    public class PayOrderMchNotifyMQReceiver implements PayOrderMchNotifyMQ.IMQReceiver {
    
        @Autowired
        private PayOrderService payOrderService;
        @Autowired
        private MchNotifyRecordService mchNotifyRecordService;
        @Autowired
        private IMQSender mqSender;
    
        @Override
        public void receive(PayOrderMchNotifyMQ.MsgPayload payload) {
    
            try {
                log.info("接收商户通知MQ, msg={}", payload.toString());
    
                Long notifyId = payload.getNotifyId();
                MchNotifyRecord record = mchNotifyRecordService.getById(notifyId);
                if (record == null || record.getState() != MchNotifyRecord.STATE_ING) {
                    log.info("查询通知记录不存在或状态不是通知中");
                    return;
                }
                if (record.getNotifyCount() >= record.getNotifyCountLimit()) {
                    log.info("已达到最大发送次数");
                    return;
                }
    
                //1. (发送结果最多6次)
                Integer currentCount = record.getNotifyCount() + 1;
    
                String notifyUrl = record.getNotifyUrl();
                String res = "";
                try {
                    res = HttpUtil.createPost(notifyUrl).timeout(20000).execute().body();
                } catch (Exception e) {
                    log.error("http error", e);
                    res = "连接[" + UrlBuilder.of(notifyUrl).getHost() + "]异常:【" + e.getMessage() + "】";
                }
    
                //支付订单 & 第一次通知: 更新为已通知
                if (currentCount == 1 && MchNotifyRecord.TYPE_PAY_ORDER == record.getOrderType()) {
                    payOrderService.updateNotifySent(record.getOrderId());
                }
    
                //通知成功
                if ("SUCCESS".equalsIgnoreCase(res)) {
                    mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_SUCCESS, res);
                    return;
                }
    
                //通知次数 >= 最大通知次数时, 更新响应结果为异常, 不在继续延迟发送消息
                if (currentCount >= record.getNotifyCountLimit()) {
                    mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_FAIL, res);
                    return;
                }
    
                // 继续发送MQ 延迟发送
                mchNotifyRecordService.updateNotifyResult(notifyId, MchNotifyRecord.STATE_ING, res);
                // 通知延时次数
                //        1   2  3  4   5   6
                //        0  30 60 90 120 150
                mqSender.send(PayOrderMchNotifyMQ.build(notifyId), currentCount * 30);
    
                return;
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return;
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:支付通知思路

          本文链接:https://www.haomeiwen.com/subject/gbfuoltx.html