PAYATHON 2026

能否通过 OrderLineItem ID 退款 Order/Payment?

支付阿杰

结论

不能用 OrderLineItem.uid 代替 Money,对 Order 或 Payment 发起退款。

支付退款接口处理的是具体金额,通常需要提供:

  • 原支付的 payment_id
  • 退款金额 amount_money
  • 唯一的 idempotency_key

OrderLineItem.uid 只是订单中的行项目标识,用来定位商品行,不是支付退款接口接受的金额参数。

处理方式

如果需要“退款某个订单行项目”,应先通过 uid 找到对应的 OrderLineItem,计算该行实际应退的金额,再对关联的 Payment 发起等额退款。

基本流程如下:

  1. 获取原始 Order。
  2. 在 order.line_items 中找到目标 OrderLineItem.uid。
  3. 根据订单最终计价结果计算退款金额。
  4. 找到该订单关联的 payment_id。
  5. 调用支付退款接口,通过 amount_money 提交金额和币种。
  6. 在业务数据中记录 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,但这只是说明信息,不会让支付退款自动变成“按商品行退款”。
  • 如果系统还要处理商品级退款、库存恢复或财务对账,需要另行保存行项目与退款的关联。只创建支付退款,通常不足以表达完整的商品退货业务。

备注:内容仅供参考。