能否通过 OrderLineItem ID 退款 Order/Payment?
支付阿杰
结论
不能用 OrderLineItem.uid 代替 Money,对 Order 或 Payment 发起退款。
支付退款接口处理的是具体金额,通常需要提供:
- 原支付的
payment_id - 退款金额
amount_money - 唯一的
idempotency_key
OrderLineItem.uid 只是订单中的行项目标识,用来定位商品行,不是支付退款接口接受的金额参数。
处理方式
如果需要“退款某个订单行项目”,应先通过 uid 找到对应的 OrderLineItem,计算该行实际应退的金额,再对关联的 Payment 发起等额退款。
基本流程如下:
- 获取原始
Order。 - 在
order.line_items中找到目标OrderLineItem.uid。 - 根据订单最终计价结果计算退款金额。
- 找到该订单关联的
payment_id。 - 调用支付退款接口,通过
amount_money提交金额和币种。 - 在业务数据中记录
OrderLineItem.uid与退款记录的对应关系。
代码示例
下面的示例采用 Square Node.js SDK 中常见的调用形式。SDK 版本不同,具体方法名和字段结构也可能不同,请以当前版本的类型定义为准。
import crypto from "node:crypto";
const orderId = "ORDER_ID";
const targetLineItemUid = "ORDER_LINE_ITEM_UID";
const paymentId = "PAYMENT_ID";
// 1. 获取订单
const orderResponse = await client.orders.get({
orderId,
});
const order = orderResponse.order;
// 2. 查找需要退款的行项目
const lineItem = order.lineItems?.find(
(item) => item.uid === targetLineItemUid
);
if (!lineItem) {
throw new Error(`OrderLineItem not found: ${targetLineItemUid}`);
}
// 3. 使用订单最终计算后的金额
const amountMoney = lineItem.totalMoney;
if (!amountMoney?.amount || !amountMoney.currency) {
throw new Error("Unable to determine the refundable amount");
}
// 4. 对关联支付发起退款
const refundResponse = await client.refunds.refundPayment({
idempotencyKey: crypto.randomUUID(),
paymentId,
amountMoney: {
amount: amountMoney.amount,
currency: amountMoney.currency,
},
reason: `Refund for OrderLineItem ${targetLineItemUid}`,
});
console.log(refundResponse.refund);
无论 SDK 使用驼峰字段还是下划线字段,退款请求的核心都是金额:
{
"idempotency_key": "UNIQUE_IDEMPOTENCY_KEY",
"payment_id": "PAYMENT_ID",
"amount_money": {
"amount": 1250,
"currency": "USD"
},
"reason": "Refund for OrderLineItem LINE_ITEM_UID"
}
其中,amount 通常以货币的最小单位表示。例如,1250 美分代表 12.50 USD。
金额计算注意事项
不要直接把商品单价当作退款金额。一个 OrderLineItem 的最终金额可能受以下因素影响:
- 数量以及部分数量退款
- 行项目折扣
- 整单折扣的分摊
- 税费及其计税方式
- 服务费
- 已完成的部分退款
- 舍入差异
如果整行退款,可以用订单返回的行项目最终金额作为计算依据,但仍要核对其中是否包含业务上应退的税费、折扣和服务费。如果只退部分数量,则要按照原订单的计价和分摊规则计算,不能只用 base_price_money × quantity。
其他注意事项
OrderLineItem.uid不能作为payment_id使用。- 同一个订单可能关联多笔支付,需要确定退款应从哪一笔
Payment扣回。 - 退款币种通常要与原支付币种一致。
- 退款金额不能超过该支付当前剩余的可退金额。
- 重试同一笔退款时,应复用相同的
idempotency_key,以免重复退款。 - 可以在
reason中保存行项目uid,但这只是说明信息,不会让支付退款自动变成“按商品行退款”。 - 如果系统还要处理商品级退款、库存恢复或财务对账,需要另行保存行项目与退款的关联。只创建支付退款,通常不足以表达完整的商品退货业务。
备注:内容仅供参考。
