售后系统升级:让用户安心,也让系统可扩展
做电商最难的,往往不是卖货,而是售后。
用户希望流程简单透明,客服希望处理高效有据可查,技术团队则需要一套能长期演进的架构。
这次我们把售后能力做了一次完整升级:前台支持 仅退款、退货退款、换货,后台提供统一审核与处理入口;同时在技术上完成了模型、状态机和服务层的重构,让“业务体验”和“工程质量”同步提升。
先看结果:用户体验有什么变化?
用户现在可以在 个人中心 -> 我的订单 -> 订单详情 直接发起售后,不需要额外联系客服找入口。
并且支持两种粒度:
- 按单个商品发起;
- 按整单发起。
提交时,用户填写:
- 售后理由(必填);
- 详细说明(选填)。
提交后可在订单页直接查看售后记录与进度,核心信息(类型、状态、时间、理由、说明)一目了然,减少反复沟通成本。
再看后台:客服处理为什么更顺手?
后台新增了售后管理页,客服可按订单号、用户、类型、状态等维度筛选并批量处理。
常见动作包括:
- 审核通过;
- 审核拒绝;
- 标记完成;
- 取消售后。
同时支持填写内部备注,用于团队协作和过程留痕。该备注默认只在后台可见,避免对用户暴露内部沟通信息。
技术架构:我们怎么把这件事“做稳”?
这次不是“多加几个字段和按钮”,而是采用了分层设计,核心是把业务规则从页面中抽离出来。
1. 数据模型层
新增独立售后实体 after_sales,并与订单域核心对象建立关联:
order_id:关联订单;order_item_id:关联订单行;product_id:关联商品;warehouse_id:关联仓库;user_id:关联发起用户。
这样做的价值是:售后成为一等业务对象,后续统计、审计、扩展都不再依赖“订单备注式”存储。
2. 领域与服务层
通过 AfterSale 模型承载关系映射与状态定义,通过 AfterSaleService 统一处理关键动作:
- 创建售后;
- 审核(通过/拒绝);
- 完成;
- 取消;
- (预留)退货物流更新。
页面只负责交互,规则由服务层集中维护,避免“前台一套规则、后台一套规则”的分裂问题。
3. 交互层(Livewire)
前台用户申请与后台客服处理都使用 Livewire 组件,保持交互一致、反馈及时,减少传统多控制器分散逻辑带来的维护负担。
状态机设计:保证流程可追踪、可回放
售后单状态流转
pending -> approved -> completedpending -> rejectedapproved / in_return -> canceled
订单状态联动
- 发起售后或审核通过:订单置为
after_sale; - 售后完成:订单置为
after_sale_done; - 特定取消场景:订单可回退为
completed。
联动由服务层统一触发,保证状态一致性,降低脏数据概率。
关键约束:支持“多次申请”,但不允许“超量申请”
真实业务里,同一订单常常会多次发起售后(例如分批发现问题)。
我们支持这一能力,但加了硬约束:
- 基于
order_id + order_item_id聚合已占用售后数量; - 排除已取消、已拒绝的记录;
- 新申请数量 + 已占用数量 <= 购买数量。
这样既满足业务灵活性,也守住了风控边界。
为什么说这套架构“能继续长”?
本次版本先打通主流程,但关键扩展位已预留,后续可以平滑升级:
refund_amount:对接支付网关做自动退款;exchange_product_id:接入换货目标 SKU 与补发链路;logistics_company / tracking_number:闭环退货物流追踪;images:支持凭证图片上传与审核。
也就是说,当前我们实现的是“流程可用”,下一步可以逐步演进到“资金流 + 物流流 + 库存流”协同的一体化售后系统。
小结
这次售后升级,本质上做了两件事:
- 对用户:把售后变成看得见、跟得上、可追踪的服务体验;
- 对系统:把售后从页面功能升级为可扩展的业务能力。
短期提升体验,长期降低维护成本。
这也是我们在业务迭代中始终坚持的原则:先让流程跑通,再让架构跑远。