订单逆向流程涉及到订单退款、退货或取消等场景。在这些场景下,支付金额的处理需要确保逻辑清晰、记录准确,并且能够追溯。以下是一个常见且通用的设计和流程建议:
一、设计概述
1. 支付金额类型分类
每种支付方式都单独记录,常见支付金额类型:
- 积分:通常需要考虑兑换比例和有效期。
- 余额:账户内的可用资金。
- 第三方支付(微信、支付宝等):通过外部支付渠道付款。
- 支付优惠:平台或第三方提供的优惠券或满减折扣。
- 钱包:绑定用户账户的专属支付方式。
2. 订单金额明细记录
在订单表设计中,添加独立的字段存储支付金额明细,例如:
OrderDetails
------------------------------
OrderID VARCHAR
AmountTotal DECIMAL(10,2) -- 订单总金额
AmountPaid DECIMAL(10,2) -- 实际支付金额
AmountPoints INT -- 使用积分抵扣金额
AmountBalance DECIMAL(10,2) -- 使用余额支付金额
AmountThirdParty DECIMAL(10,2) -- 第三方支付金额
AmountDiscount DECIMAL(10,2) -- 优惠金额
3. 退款明细表
记录每次退款的金额明细(支持部分退款和多次退款)。
RefundDetails
------------------------------
RefundID VARCHAR
OrderID VARCHAR -- 关联订单ID
RefundAmount DECIMAL(10,2) -- 退款总金额
RefundPoints INT -- 退回积分
RefundBalance DECIMAL(10,2) -- 退回余额
RefundThirdParty DECIMAL(10,2) -- 第三方支付退款
RefundDiscount DECIMAL(10,2) -- 优惠退款(一般为0,不退)
RefundDate DATETIME -- 退款时间
RefundStatus INT -- 退款状态(待审核、成功、失败)
4. 退款规则
- 优先顺序:根据支付来源依次退款,例如:
优惠券不退,优先退余额 -> 积分 -> 第三方支付。 - 部分退款:退款按比例或具体金额,从不同支付来源扣减。
- 原路退回:余额退回余额,积分退回积分,第三方支付通过支付网关退款。
二、退款流程
1. 退款流程图
用户申请退款 -> 系统校验退款条件 -> 计算可退金额 -> 更新退款明细 -> 调用支付网关接口退款 -> 更新退款状态
2. 详细流程步骤
- 用户申请退款
- 用户通过前端发起退款申请,选择退货或取消订单。
- 系统校验
- 验证订单状态是否允许退款(如未发货、未完成等)。
- 校验退款金额是否在合法范围内。
- 计算退款金额
- 按支付明细表的金额分配退款。
- 如果是部分退款,按比例分摊退款金额到各支付方式。
- 生成退款明细
- 创建一条退款记录,并记录退款的金额分配。
- 调用支付网关退款
- 对第三方支付的金额,通过支付网关接口发起退款。
- 更新状态
- 根据退款结果更新订单状态和退款状态。
三、数据库表结构示例
1. 订单表
CREATE TABLE Orders (
OrderID VARCHAR(20) PRIMARY KEY,
UserID VARCHAR(20),
AmountTotal DECIMAL(10, 2),
AmountPaid DECIMAL(10, 2),
AmountPoints INT,
AmountBalance DECIMAL(10, 2),
AmountThirdParty DECIMAL(10, 2),
AmountDiscount DECIMAL(10, 2),
Status INT, -- 0:待付款, 1:已支付, 2:已发货, 3:已完成, 4:已取消
CreateTime DATETIME,
UpdateTime DATETIME
);
2. 退款表
CREATE TABLE RefundDetails (
RefundID VARCHAR(20) PRIMARY KEY,
OrderID VARCHAR(20),
RefundAmount DECIMAL(10, 2),
RefundPoints INT,
RefundBalance DECIMAL(10, 2),
RefundThirdParty DECIMAL(10, 2),
RefundDiscount DECIMAL(10, 2),
RefundDate DATETIME,
RefundStatus INT, -- 0:待审核, 1:成功, 2:失败
FOREIGN KEY (OrderID) REFERENCES Orders(OrderID)
);
四、实现关键点
1. 比例计算示例
假设用户支付明细如下:
- 总金额:100
- 积分抵扣:20
- 余额支付:30
- 第三方支付:50
部分退款 60 时:
- 积分退回:( 20 \times \frac{60}{100} = 12 )
- 余额退回:( 30 \times \frac{60}{100} = 18 )
- 第三方支付退回:( 50 \times \frac{60}{100} = 30 )
2. 日志记录
- 为所有退款操作添加日志,方便后续排查问题。
3. 状态管理
- 使用状态机管理订单状态,防止并发问题。
五、扩展支持
- 多次退款:支持部分退款场景,需要累加退款明细。
- 退款失败处理:记录失败原因,支持人工介入。
- 前端展示:在用户端展示退款进度和明细,增强用户体验。
这套流程设计通用且易于扩展,适合大多数订单退款场景。
优惠券处理流程
优惠券处理的详细流程
在订单中叠加使用优惠券会引入额外的复杂性。以下是优惠券从使用到退款的详细处理流程设计。
一、优惠券在支付中的角色
1. 优惠券类型
- 满减券:达到一定金额后减免固定金额(例如满100减20)。
- 折扣券:按比例打折(例如9折)。
- 代金券:直接抵扣固定金额(例如抵扣10元)。
- 免运费券:免除配送费用。
- 限制性券:指定品类、商品或时间段使用。
2. 叠加支付
- 优惠券与其他支付方式可以组合使用,例如优惠券与积分、余额、第三方支付。
- 优惠券的减免金额从订单总金额中直接扣减,剩余部分由其他支付方式承担。
3. 优惠券使用限制
- 有效期:优惠券只能在有效期内使用。
- 适用范围:特定商品、分类或订单金额。
- 叠加规则:部分优惠券可能互斥,需校验使用规则。
二、优惠券退款规则
1. 不可退
- 优惠券通常不退回,例如满减券在退单时不会重新激活。
- 如果是促销活动的赠券,需根据平台策略决定是否返还。
2. 可退
- 特殊情况下,优惠券可以退回给用户,如代金券或限制性使用券。
- 如果订单部分退款,按比例计算退款金额,并决定是否退还优惠券。
三、数据库表设计
1. 优惠券表
记录优惠券的基本信息。
CREATE TABLE Coupons (
CouponID VARCHAR(20) PRIMARY KEY,
CouponType INT, -- 1: 满减, 2: 折扣, 3: 代金券, 4: 免运费
CouponValue DECIMAL(10, 2), -- 优惠金额或折扣值
MinOrderAmount DECIMAL(10, 2),-- 最低使用金额
StartDate DATETIME,
EndDate DATETIME,
IsActive BOOLEAN -- 是否有效
);
2. 用户优惠券表
跟踪用户持有的优惠券状态。
CREATE TABLE UserCoupons (
UserCouponID VARCHAR(20) PRIMARY KEY,
UserID VARCHAR(20),
CouponID VARCHAR(20),
IsUsed BOOLEAN, -- 是否已使用
UseDate DATETIME,
FOREIGN KEY (CouponID) REFERENCES Coupons(CouponID)
);
3. 订单表中增加优惠券字段
记录优惠券的使用情况。
ALTER TABLE Orders ADD COLUMN CouponID VARCHAR(20);
ALTER TABLE Orders ADD COLUMN CouponDiscount DECIMAL(10, 2); -- 优惠券抵扣金额
4. 退款表中增加优惠券字段
记录退款时的优惠券处理信息。
ALTER TABLE RefundDetails ADD COLUMN RefundCoupon BOOLEAN; -- 是否退回优惠券
四、优惠券处理流程
1. 下单时的处理
- 校验优惠券是否可用:
- 是否在有效期内。
- 是否满足适用条件(商品、金额、分类等)。
- 计算优惠券金额:
- 满减券:校验金额门槛,直接减去指定金额。
- 折扣券:按折扣比例计算优惠金额。
- 代金券:直接抵扣指定金额。
- 更新优惠券状态:
- 使用后将优惠券标记为“已使用”。
2. 退款时的处理
- 全额退款:
- 优惠券金额作废,是否退回优惠券视规则而定。
- 更新用户优惠券表,标记优惠券为“未使用”。
- 部分退款:
- 优惠券金额按比例分摊。
- 如果退款后订单金额不满足优惠券使用条件:
- 优惠券金额不退回。
- 可选择补充退款部分金额给用户。
3. 优惠券重置逻辑
- 原路退还:将优惠券恢复到“未使用”状态。
- 补发新券:发放等额的新优惠券。
- 不退回:优惠券直接作废,不再退回给用户。
五、详细示例
示例1:满减券
订单金额:120
优惠券:满100减20
支付方式:
- 优惠券减免:20
- 用户实际支付:100
退款:
- 全额退款:退还用户100元,优惠券作废或返还。
- 部分退款(退60元商品):
- 优惠券分摊到退款金额:( \frac{20}{120} \times 60 = 10 )
- 用户退款金额:( 60 - 10 = 50 )
- 优惠券剩余优惠金额:10,作废或按平台规则退还。
示例2:折扣券
订单金额:200
优惠券:9折
支付方式:
- 折扣金额:200 × 10% = 20
- 用户实际支付:180
退款:
- 全额退款:退还用户180元,优惠券作废或返还。
- 部分退款(退100元商品):
- 折扣分摊到退款金额:( \frac{20}{200} \times 100 = 10 )
- 用户退款金额:( 100 - 10 = 90 )
六、优惠券的边界处理
-
订单取消
- 未支付订单:优惠券直接重置为“未使用”。
- 已支付订单:按退款逻辑处理。
-
订单拆分
- 拆分后的订单按比例分配优惠券的减免金额。
- 优惠券一般不重复使用,但可以允许部分金额分摊到多个子订单。
-
组合使用
- 优惠券与其他支付方式的逻辑清晰且优先级明确。
- 优惠券的减免优先从订单总金额中扣减,其次分配其他支付方式的金额。
七、扩展支持
-
前端展示
- 清晰展示优惠券的抵扣金额及规则。
- 提供退款场景的优惠券处理说明。
-
日志记录
- 记录每张优惠券的使用、退款和状态变更。
-
优惠券活动
- 针对特殊促销或节日活动的优惠券,可定义灵活的处理策略。
这套流程既能保证优惠券使用的灵活性,又能在退款场景中清晰处理,适用于复杂的电商平台需求。