支付通知思路

2021-10-14  本文已影响0人  wanggs

支付通知思路

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;
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读