支付沙箱环境如何进行部分退款?
结论
出现“退款金额与订单金额不一致”时,通常有两种原因:支付沙箱只支持全额退款,或者沙箱要求退款金额必须与原订单金额相同。遇到这种校验,调整部分退款的金额也无法解决问题。
可以先按订单实付金额发起全额退款,确认整个退款流程是否正常。如果业务需要测试部分退款,还要确认支付平台的沙箱是否支持。若沙箱不支持,只能通过 Mock 模拟部分退款结果,或在生产环境使用小额真实订单测试。
原因分析
正常情况下,部分退款需要满足:
0 < 本次退款金额 <= 订单可退金额
其中:
订单可退金额 = 订单实付金额 - 已成功退款金额
有些支付平台的沙箱采用了更简单的校验规则:
本次退款金额 = 订单金额
这时,即使部分退款金额符合实际业务规则,沙箱仍可能返回“退款金额与订单金额不一致”。
同时,还要检查以下问题:
- 退款金额传成了商品原价,而不是订单实付金额。
- 金额单位不一致,例如订单金额使用“分”,退款金额使用“元”。
- 请求中的订单总金额与原支付订单不一致。
- 同一订单此前已有成功退款,当前退款金额超过剩余可退金额。
- 当前沙箱订单、支付渠道或退款接口不支持部分退款。
处理步骤
1. 使用全额退款验证沙箱流程
将本次退款金额设为订单实付金额。例如,订单实付 10.00 元,接口以“分”为单位,则应提交:
{
"order_amount": 1000,
"refund_amount": 1000
}
如果这笔全额退款成功,但以下部分退款请求失败:
{
"order_amount": 1000,
"refund_amount": 300
}
基本可以判断,问题出在沙箱能力或校验规则上,而不是退款请求的基本流程。
2. 核对金额字段和单位
发起退款前,应先统一金额单位,并避免直接使用浮点数计算:
const orderAmount = 10.00;
const refundAmount = 3.00;
const orderAmountInCents = Math.round(orderAmount * 100);
const refundAmountInCents = Math.round(refundAmount * 100);
const requestBody = {
order_amount: orderAmountInCents,
refund_amount: refundAmountInCents
};
不要直接依赖以下计算:
const amount = 0.1 + 0.2;
JavaScript 的浮点数计算结果可能是 0.30000000000000004。处理支付金额时,业务内部最好统一使用“分”等最小货币单位。
3. 核对原订单和累计退款金额
提交退款前,应查询或记录订单当前的退款状态:
const refundableAmount =
paidAmountInCents - succeededRefundAmountInCents;
if (refundAmountInCents <= 0) {
throw new Error("退款金额必须大于 0");
}
if (refundAmountInCents > refundableAmount) {
throw new Error("退款金额超过订单剩余可退金额");
}
如果要对同一订单进行多次部分退款,每次都应使用唯一的退款单号,并确保累计退款金额不超过订单实付金额:
第一次退款:300 分
第二次退款:200 分
累计退款:500 分
订单实付:1000 分
剩余可退:500 分
4. 确认沙箱是否支持部分退款
问题中没有说明具体的支付平台和 API,因此暂时无法判断该提示来自平台限制,还是请求参数有误。需要查看对应平台退款接口的沙箱文档,确认以下内容:
- 沙箱是否支持部分退款;
- 是否只允许发起一次全额退款;
refund_amount和订单金额分别使用什么单位;- 是否要求同时传入原订单总金额;
- 是否允许对同一订单发起多次退款;
- 测试订单是否有固定金额或固定退款规则。
如果文档没有明确说明,可以将“全额退款成功、部分退款失败”时的请求参数和响应信息提交给平台技术支持确认。
沙箱不支持时如何测试
如果平台明确说明沙箱只支持全额退款,可以这样安排测试:
- 在沙箱中完成支付、签名验证、退款请求和退款通知的全流程测试。
- 在业务测试环境中通过 Mock 返回“部分退款成功”,检查订单金额、累计退款金额和状态流转。
- 上线前在生产环境创建一笔金额可控的小额订单,完成真实的部分退款测试。
- 测试结束后,核对支付平台的退款记录、异步通知和本地账务数据。
Mock 响应可以按真实接口结构构造,但字段名称和状态值必须以支付平台文档为准。例如:
{
"refund_id": "mock_refund_001",
"refund_amount": 300,
"status": "SUCCESS"
}
注意事项
- 不要为了通过沙箱校验,将部分退款伪装成全额退款后再在本地修改金额,否则会导致平台账务与业务账务不一致。
- 退款接口需要做好幂等控制,重复提交同一个退款单号时不能重复入账。
- 订单状态应区分“未退款”“部分退款”和“已全额退款”。
- 退款结果应以支付平台确认成功或退款通知为准,不能因为接口请求已发送就认定退款完成。
- 在生产环境进行小额测试会产生真实资金变动,执行前需要确认账户、权限和对账安排。
- 如果全额退款也返回相同错误,应先检查订单实付金额、币种、金额单位、订单号和原交易状态,不能直接判断为沙箱限制。
备注:内容仅供参考。
