退款网关与退款状态查询设计
背景
退款业务,相对于支付业务,部分需求方(包括产品、市场的同事)认为退款业务不是那么紧急或重要。从业务角度分析,没有支付业务,用户无法支付或支付优惠活动无法开展,但没有退款功能,则不影响用户下单支付和开展优惠活动。用户申请退款,财务可登录第三方支付平台提供的商户管理系统进行人工退款操作。因此,目前应该还有许多电商平台的退款业务都是财务人工操作的,当公司订单到了一定规模,人工退款操作则是不可行的。这时候,则需要一一对接退款业务。
从系统安全角度分析,退款业务的重要性甚至比支付业务更要高,因为退款业务可以理解为是商户自己向用户付钱,如果多付,所造成的公司财务损失,几乎不可能追回。常见的风险有:订单申请了部分退款,由于各种原因造成多退的情况;系统退款由于操作人疏忽或其他原因造成不该退款的订单退款给用户的情况。以上两种情况,我身边确实有这样的案例,最大的一次损失,是一个下午,给公司造成了80多万的损失。鉴于此,在设计退款模块的童鞋,逻辑一定要缜密,不要有疏忽、漏洞等隐患。
退款网关
对用户主动取消的已付款订单、或者因为库存不足、无法配送等各种原因需要撤销订单的,都需要给用户进行退款操作,退款形式有原路退款、银行转账、退余额等,目前主流的都是进行原路退款。退款网关不能有用户直接访问,订单要有退款申请与审批流程,一般是在订单管理系统控制,有订单管理系统调用退款网关,发起退款请求,聚合支付系统要对退款网关做好身份验证及安全防范。
聚合支付平台退款部分,也需要异步通知处理队列,消费队列接受来自第三方异步通知、crontab主动查询或人工查询到已退款成功的订单退款数据,将其统一处理,更新退款单状态、通知订单系统等操作。
退款交易流水表,主要字段展示
Name | Field | remark |
系统订单号 | order_id | 商户订单系统的真实订单号 |
退款单号 | refund_id | 传给第三方平台的退款订单号 |
外部系统的退款单号 | out_refund_id | 一般指订单系统传来的退款单号 |
退款流水号 | refund_no | 第三方支付平台的退款流水号 |
支付方式id | payment_id | |
退款发起平台 | platform | |
订单支付金额 | total_fee | |
退款金额 | refund_fee | |
退款类型 | refund_type | 全额、部分 |
退款状态 | refund_status | enum(wait、success、failed) |
同步状态 | sync_status | enum(wait、success、failed) |
退款申请时间 | create_time | |
异步通知时间 | notify_time | |
同步订单系统时间 | sync_time |
注意点
- 不管来自哪里的退款申请,都要先查询订单支付状态,直接调用第三方支付的查单接口去查最新的订单状态、可退金额等信息,并以此为准;
- 退款金额校验,如果是全额退款,则只需验证退款金额等于支付金额,方可调用退款接口进行退款;如果是部分退款,则要计算已经成功退款的金额总额,以及已经退款申请成功,但还没收到第三方的退款成功通知这部分的金额总额,订单支付金额减掉这两部分的总金额之后的金额是可退金额;
- 对于部分退款申请处理,如本次已经申请成功了,还在处理中的退款,不要重复申请退款;
退款异步通知
同支付异步通知一样,退款异步通知也建议使用队列进行解耦,收到第三方的退款通知,只需要验签和金额校验后,则将报文数据push到退款通知队列中,有后端消费进程去更新退款单的退款状态、通知订单系统的退款状态等后续处理流程。
支付/退款状态查询
针对上一章节所遇到的问题,虽然主动对账可以处理掉绝大部分已支付订单被挂起的问题,但难免有漏网之鱼,没有被及时处理的订单,用户肯定不干,要投诉平台。鉴于此,我们开发人员需要给客服或者财务同事提供一个后台查询系统,用于处理客诉中这类问题的订单。该模块需要支持两点:
- 所有第三方支付平台的查询接口返回报文格式数据都不一样,我们需要将其组织成统一的格式返回给前端,前端再展示给客服能看得懂的信息数据;
- 如果查询订单支付成功,需要将其订单支付数据自动push到异常订单处理队列中,及时更新订单支付状态;
原文地址:https://www.cnblogs.com/jpfss/p/9909080.html