实现退款功能涉及到订单状态的更新、退款记录的保存、与支付服务的对接,以及确保退款操作的幂等性和可靠性。
1、首先使用一个事务保存以下数据
(1)更新订单状态。
(2)保存取消订单记录,记录取消的原因等信息。
(3)保存退款记录。
2、事务提交后先启动一个线程请求支付服务的退款接口
3、定时任务扫描退款记录表,对未退款的记录请求支付服务进行退款,退款成功更新订单的退款状态。
说明:
第2步的作用为了第一时间申请退款,因为定时任务会有一定的延迟。
第3步的作用是由定时任务去更新退款的状态,因为调用了退款接口只是申请退款了,退款结果可能还没有拿到,通过定时任务再次请求支付服务的退款接口,拿到退款结果,更新订单的退款状态,并删除退款记录。
1. 退款功能实现的整体流程
退款功能一般是在订单取消或其他原因触发退款时进行,主要包括以下步骤:
- 更新订单状态:订单被取消或需要退款时,更新订单状态为“待退款”或“退款中”。
- 保存取消订单记录:保存订单取消的原因及时间,便于后续查看订单的取消历史。
- 保存退款记录:记录退款的相关信息,包括退款金额、申请时间、退款渠道、退款状态等。
- 调用支付服务的退款接口:使用独立线程或异步任务立即请求支付服务的退款接口。
- 定时任务扫描未完成退款的记录:定时任务负责轮询退款记录,重新请求支付服务获取退款结果,并更新订单的退款状态。
2. 数据表设计
为了实现退款功能,通常需要设计以下几张表:
2.1 订单表 (orders
)
订单表保存订单的基础信息,包括订单状态字段,需要增加退款状态相关的字段。
id
:订单 ID。status
:订单状态(如待支付、已支付、已取消、待退款、退款成功等)。refund_status
:退款状态(如退款中、退款成功、退款失败等)。refund_amount
:退款金额。pay_channel
:支付渠道(如微信支付、支付宝等)。
2.2 退款记录表 (refund_record
)
记录每次退款的详细信息。
id
:退款记录 ID。order_id
:关联的订单 ID。refund_amount
:退款金额。refund_channel
:退款渠道(微信支付、支付宝等)。refund_status
:退款状态(如退款中、退款成功、退款失败等)。apply_time
:退款申请时间。refund_time
:退款成功时间。refund_reason
:退款原因。retry_count
:重试次数(用于定时任务追踪退款状态)。
2.3 取消订单记录表 (cancel_order_record
)
记录订单取消的信息,包括取消的原因等。
id
:取消记录 ID。order_id
:关联的订单 ID。cancel_reason
:取消原因。cancel_time
:取消时间。
3. 详细退款流程
3.1 发起退款申请
- 用户在前端取消订单时,业务系统会调用后端接口执行取消订单并发起退款。
- 在这个过程中,系统会更新订单状态为“退款中”,并保存取消订单记录和退款记录。
- 同时,会异步调用支付服务的退款接口,发起退款请求。
3.2 退款状态更新
- 如果退款请求成功,支付服务会返回退款结果,系统将订单状态更新为“退款成功”,同时更新退款记录。
- 如果退款请求失败或超时,系统会将退款状态设置为“退款中”,定时任务会定期重新请求退款。
3.3 定时任务轮询
- 定时任务负责扫描退款记录表中的未完成退款记录,重新调用支付服务获取退款结果,并更新订单状态。
- 如果退款成功,订单状态更新为“退款成功”,退款记录表中的记录也会被删除或标记为完成。
4. 并发与幂等性处理
- 幂等性:退款接口的设计必须确保幂等性,避免重复退款。例如,通过
orderId
和refundRecordId
进行唯一性校验。 - 事务控制:保存订单、取消记录和退款记录的操作需要放在一个事务中,确保所有数据一致性。如果任何一步失败,整个操作会回滚。