内容概述
下单功能以及支付功能的完整实现
流程图
流程分析
graph TB
subgraph "前端层"
A[用户界面] --> B[HTTP请求]
end
subgraph "Web层 (s-pay-mall-web)"
B --> C[AliPayController]
C --> D[参数验证]
end
subgraph "业务层 (s-pay-mall-service)"
D --> E[OrderServiceImpl]
E --> F[ProductRPC]
E --> G[支付宝SDK]
end
subgraph "数据层 (s-pay-mall-dao)"
E --> H[IOrderDao]
H --> I[(MySQL数据库)]
end
subgraph "外部系统"
G --> J[支付宝网关]
J --> K[支付回调]
K --> C
end
subgraph "异步处理"
E --> L[EventBus事件总线]
L --> M[OrderPaySuccessListener]
N[定时任务] --> E
end
第一阶段:用户下单请求
输入数据:
1 | POST /api/v1/alipay/create_pay_order |
处理流程:
- 前端发送 HTTP POST 请求到
AliPayController.createPayOrder() - Controller 接收
ShopCartReq对象,包含用户ID和商品ID
数据流向:前端请求 -> AliPayController -> 参数验证
第二阶段:重复订单检查
输入数据:ShopCartReq对象:
1 | public class ShopCartReq { |
处理流程:
OrderServiceImpl.createOrder()被调用- 构造查询条件:创建
PayOrder对象设置userId和productId - 调用
IOrderDao.queryUnPayOrder()查询数据库
1 | public class PayOrder { |
可能的情况:
- 返回状态为
PAY_WAIT的未支付订单- 直接返回现有的 PayOrderRes{orderId, payUrl}
- 流程结束,跳转到返回响应阶段
- 返回状态为
CREATE的订单- 需要重新创建支付单
- 调用
doPrepayOrder()方法创建支付单 - 跳转到支付单创建阶段
- 返回 null(无相关订单)
- 继续执行后续流程
数据流向:OrderServiceImpl -> IOrderDao -> MySQL数据库 -> 返回查询结果
第三阶段:商品信息查询
输入数据:productId(String 类型)
处理流程:
- 调用
ProductRPC.queryProductByProductId()- 这是一个模拟的RPC调用,实际返回固定的商品信息
输出数据:
1 | public class ProductVO { |
数据流向:OrderServiceImpl -> ProductRPC -> 返回ProductVO对象
第四阶段:订单数据持久化
输入数据:
- userId:用户ID
- productId:商品ID
- productName:从ProductVO获取的商品名称
- price:从ProductVO获取的商品价格
处理流程:
- 生成16位随机订单号:
RandomStringUtils.randomNumeric(16) - 构造
PayOrder对象:
1 | PayOrder.builder() |
- 调用
IOrderDao.insert()插入数据库 - 执行SQL:
INSERT INTO pay_order(...) VALUES(...)
输出数据:
- 数据库中新增一条订单记录,状态为
CREATE
数据流向:OrderServiceImpl -> 构造PayOrder对象 -> IOrderDao -> MySQL数据库
第五阶段:支付单创建
输入数据:
- productId:商品ID
- productName:商品名称
- orderId:订单号
- totalAmount:订单金额
处理流程:
- 调用
doPrepayOrder()方法 - 创建支付宝请求对象:
1 | AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); |
- 构造业务参数:
1 | { |
- 调用支付宝SDK:
alipayClient.pageExecute(request).getBody()
输出数据:
- 支付宝返回HTML表单字符串,包含支付页面的完整HTML代码
数据流向:OrderServiceImpl -> 构造支付宝请求 -> 支付宝SDK -> 支付宝服务器 -> 返回支付表单
第六阶段:更新订单支付信息
输入数据:
- orderId:订单号
- payUrl:支付宝返回的HTML表单
- status:新状态
PAY_WAIT
处理流程:
- 构造更新对象:
1 | PayOrder payOrder = new PayOrder(); |
- 调用
IOrderDao.updateOrderPayInfo() - 执行SQL:
UPDATE pay_order SET pay_url = ?, status = ?, update_time = now() WHERE order_id = ?
输出数据:
- 数据库订单记录更新完成,状态变为
PAY_WAIT,包含支付链接
数据流向:OrderServiceImpl -> 构造更新对象 -> IOrderDao -> MySQL数据库
第七阶段:返回支付响应
输入数据:
- orderId:订单号
- payUrl:支付链接
处理流程:
- 构造响应对象:
1 | PayOrderRes.builder() |
- 在Controller层包装成统一响应格式:
1 | Response.<String>builder() |
- 记录成功日志:”商品下单,根据商品ID创建支付单完成”
输出数据(返回给前端):
1 | { |
数据流向:OrderServiceImpl -> PayOrderRes -> AliPayController -> Response对象 -> 前端页面
第八阶段:用户支付操作
处理流程:
- 前端接收到支付表单HTML
- 用户浏览器渲染支付页面
- 用户在支付宝页面完成付款操作
- 支付宝处理支付请求并扣款
数据流向:前端页面 -> 用户操作 -> 支付宝支付页面 -> 支付宝服务器处理
第九阶段:支付回调处理
输入数据(支付宝异步回调):
1 | POST /api/v1/alipay/pay_notify |
参数包括:
- trade_status: “TRADE_SUCCESS”
- out_trade_no: “1234567890123456” (商户订单号)
- trade_no: “2021081622001234567890123456” (支付宝交易号)
- total_amount: “1.68”
- sign: “支付宝RSA256签名”
- 其他支付宝回调参数…
处理流程:
AliPayController.payNotify()接收回调- 交易状态验证:检查
trade_status是否为 “TRADE_SUCCESS” - 签名验证:
1 | String sign = params.get("sign"); |
- 记录回调日志:记录交易名称、状态、支付宝交易号、金额等信息
验证失败的输出:
- 返回字符串 “false” 给支付宝(拒绝回调)
验证成功继续处理…
数据流向:支付宝服务器 -> AliPayController.payNotify() -> 参数解析和验证
第十阶段:订单状态更新
输入数据:
- orderId:从回调参数
out_trade_no获取
处理流程:
- 调用
OrderServiceImpl.changeOrderPaySuccess() - 构造更新对象:
1 | PayOrder payOrderReq = new PayOrder(); |
- 调用
IOrderDao.changeOrderPaySuccess() - 执行SQL:
UPDATE pay_order SET status = ?, pay_time = now(), update_time = now() WHERE order_id = ?
输出数据:
- 数据库订单状态更新为
PAY_SUCCESS - 设置支付时间为当前时间
数据流向:OrderServiceImpl -> 构造更新对象 -> IOrderDao -> MySQL数据库
第十一阶段:异步事件发布
输入数据:
- 更新后的
PayOrder对象
处理流程:
- 将订单对象序列化为JSON:
JSON.toJSONString(payOrderReq) - 通过EventBus发布事件:
eventBus.post(jsonString) OrderPaySuccessListener.handleEvent()监听并处理事件
输出数据:
1 | { |
后续处理:
- 商品发货逻辑
- 积分奖励计算
- 用户通知推送
- 返利处理等
数据流向:OrderServiceImpl -> EventBus -> OrderPaySuccessListener -> 后续业务处理
第十二阶段:回调响应返回
输出数据:
- 向支付宝返回字符串 “success”(表示回调处理成功)
- 记录日志:”支付回调,支付回调,更新订单 {}”
数据流向:AliPayController -> 支付宝服务器(确认回调处理完成)
异步处理机制
定时任务处理
超时关单:
TimeoutCloseOrderJob每10分钟执行一次- 查询超过30分钟未支付的订单:
queryTimeoutCloseOrderList() - 将订单状态更新为
CLOSE
支付状态主动查询:
NoPayNotifyOrderJob每3秒执行一次- 查询超过1分钟未支付且未收到回调的订单:
queryNoPayNotifyOrder() - 主动调用支付宝接口查询订单实际支付状态
- 若支付成功则更新订单状态为
PAY_SUCCESS
事件监听器
支付成功事件监听:
OrderPaySuccessListener基于Guava EventBus实现- 通过
@Subscribe注解订阅支付成功事件 - 接收JSON格式的订单信息
- 负责处理支付成功后的异步业务逻辑(如商品发货、积分奖励等)