Haorong Mall 支付逻辑分析
本文档详细解析了 haorong-mall 项目中用户从下单到支付成功,以及订单状态同步的完整技术实现流程。
1. 核心流程概览
整个购物支付流程涉及 haorong-order (订单服务) 和 haorong-pay (支付服务) 两个核心模块,采用 Dubbo 进行远程调用,RocketMQ 进行异步消息通知。
主要步骤:
- 创建订单:用户提交订单,系统校验库存、优惠券,生成订单记录。
- 预支付:用户发起支付请求,订单服务调用支付服务,获取第三方支付参数 (如微信 PrepayID)。
- 用户支付:用户在客户端 (App/小程序) 完成支付。
- 支付回调:第三方支付平台 (微信/支付宝) 回调支付服务。
- 状态同步:支付服务更新内部状态,并通过 RocketMQ 通知订单服务更新订单状态。
- 超时取消:通过延迟消息或定时任务处理未支付订单。
2. 详细实现逻辑
2.1 下单流程 (Order Creation)
- 入口:
AppOrderInfoController.createOrder - 核心服务:
OrderInfoServiceImpl.createOrder
关键步骤:
- 参数校验: 检查收货地址、商品 SKU 是否存在。
- 库存扣减:
orderStockHandler调用商品服务扣减库存。 - 优惠计算:
orderCouponHandler计算优惠券折扣。 - 运费计算:
orderFreightHandler计算运费。 - 订单保存: 保存
OrderInfo(订单主表) 和OrderItemEntity(订单明细表)。 - 事务控制: 使用
@GlobalTransactional(Seata) 保证分布式事务一致性。
2.2 预支付与支付发起 (Pre-payment)
- 入口:
AppOrderInfoController.prepay - 核心逻辑:
OrderInfoServiceImpl.prepay
交互流程:
- 校验订单: 检查订单是否存在、是否已支付。
- 构建参数: 创建
CreateOrderReqDTO,设置mqNotifyUrl为RocketMqConstants.PAY_NOTIFY_TOPIC(关键!用于后续回调通知)。javaJSONObject extraParams = new JSONObject(); extraParams.put("mqNotifyUrl", RocketMqConstants.PAY_NOTIFY_TOPIC); // 告诉支付服务回调通知哪个 Topic createOrderReqDTO.setExtra(extraParams.toJSONString()); - 远程调用: 通过 Dubbo 调用
RemotePayService.createOrder。 - 支付服务分发:
RemotePayServiceImpl根据tradeType(支付方式) 使用策略模式分发给具体的PayOrderHandler。AliPayAppPayHandler/AlipayH5PayHandlerWechatAppPayHandler/WechatJsApiPayHandler
- 返回参数: 返回给前端用于调起支付 SDK 的参数。
2.3 支付回调 (Callback Handling)
- 模块:
haorong-pay - 入口:
PayNotifyRecordController- 微信:
/notify/wx/{tenantId}/{terminalType} - 支付宝:
/notify/alipay/{tenantId}/{terminalType}
- 微信:
处理逻辑 (PayNotifyRecordServiceImpl):
- 验签: 验证第三方平台回调签名的合法性。
- 去重: 使用 Redis (
setIfAbsent) 防止重复处理同一笔回调。 - 更新支付单: 更新
pay_trade_order表状态为支付成功 (PayStatus= YES)。 - 记录日志: 保存
PayNotifyRecord。 - 发送 MQ 通知: 解析
extra字段中的mqNotifyUrl,发送 RocketMQ 消息。java// 发送消息通知订单服务 rocketMQTemplate.syncSend(json.getString("mqNotifyUrl"), new GenericMessage<>(jsonObject), ...);
2.4 订单状态同步 (Status Update)
- 模块:
haorong-order - 消费者:
HuanxingPayListener
处理逻辑:
- 监听消息: 监听
RocketMqConstants.PAY_NOTIFY_TOPIC。 - 更新订单: 接收到支付成功消息后,将
order_info表状态更新为已支付 (PayStatus= YES)。 - 后续操作:
- 增加商品销量。
- 更新优惠券状态 (如已使用)。
- 发送订单支付成功事件 (
ORDER_PAY_SUCCESS_NOTIFY_TOPIC)。
2.5 订单超时取消 (Timeout Cancellation)
为了防止库存被长期占用,系统实现了订单超时自动取消机制。
机制一:定时任务 (兜底方案)
- 类:
OrderJobHandler - 任务:
orderCancelJobHandler(@XxlJob) - 逻辑: 每隔一段时间扫描
WAITING_FOR_PAYMENT状态且创建时间超过 30 分钟的订单,执行取消逻辑。
机制二:延迟队列 (实时方案)
- 消费者:
OrderCancelListener - 逻辑: 监听
ORDER_CANCEL_TOPIC。下单成功后发送延迟消息 (如 30 分钟延迟),消息到达时如果订单仍未支付,则触发取消。 - 取消动作:
OrderInfoServiceImpl.cancelOrder- 更新订单状态为
CANCELED。 - 回滚库存: 调用商品服务回滚 SKU 库存。
- 回滚优惠券: 恢复优惠券为未使用状态。
- 更新订单状态为
3. 核心类与文件索引
| 模块 | 关键类 | 路径 | 说明 |
|---|---|---|---|
| Order | AppOrderInfoController | haorong-order/.../AppOrderInfoController.java | C 端订单接口 (创建、预支付) |
| Order | OrderInfoServiceImpl | haorong-order/.../OrderInfoServiceImpl.java | 订单核心业务逻辑 |
| Order | HuanxingPayListener | haorong-order/.../HuanxingPayListener.java | 支付成功 MQ 消息消费者 |
| Order | OrderJobHandler | haorong-order/.../OrderJobHandler.java | 订单超时取消定时任务 |
| Pay | RemotePayServiceImpl | haorong-pay/.../RemotePayServiceImpl.java | 支付 Dubbo 服务实现 |
| Pay | PayNotifyRecordController | haorong-pay/.../PayNotifyRecordController.java | 支付回调 HTTP 接口 |
| Pay | PayNotifyRecordServiceImpl | haorong-pay/.../PayNotifyRecordServiceImpl.java | 回调处理与 MQ 发送 |
| Pay | AbstractPayOrderHandler | haorong-pay/.../AbstractPayOrderHandler.java | 支付处理器模板基类 |