payment gateway 能否将付款按比例存入多个账户?
结论
可以实现,但普通 payment gateway 通常不能把一笔付款直接按 90% / 10% 结算到任意两个银行账户。
一般有两种实现方式:
- 使用支付平台的 marketplace、split payment 或 connected account 功能,先在平台内部拆分资金,再结算到不同商户的银行账户。
- 先把全部款项结算到一个企业账户,再通过银行转账、资金归集或财务系统按比例分配。
如果两个银行账户属于同一家公司,第二种方式通常更简单。如果收款方是不同公司、供应商或合作方,则应优先使用支付平台提供的合规分账产品。
为什么普通 payment gateway 不能直接拆分
普通支付网关主要负责:
- 收集并加密支付信息;
- 发起授权和扣款;
- 将交易关联到一个 merchant account;
- 按约定的结算周期向绑定的银行账户付款。
在这种模式下,一笔交易通常只对应一个收款主体和一个结算账户。网关不会因为支付请求中设置了一个百分比参数,就把资金汇入多个外部银行账户。
这不只是技术设计上的限制,还涉及:
- KYC/KYB 身份与企业认证;
- 反洗钱和制裁筛查;
- 税务及财务归属;
- 退款、拒付和争议责任;
- 不同国家或地区的支付牌照要求。
能否分账,需要根据支付服务商、商户类型、账户所在地区,以及各收款方是否完成验证来判断。
推荐的实现步骤
方案一:使用支付平台的分账功能
这种方式适用于平台、市场、代理销售和供应商结算等场景。
基本流程如下:
- 为每个实际收款方创建或绑定 connected account。
- 让各收款方完成身份和银行账户验证。
- 客户付款后,在支付平台内部计算各方应得金额。
- 将相应金额转入各收款方的平台账户。
- 由支付平台分别结算到各自的银行账户。
- 保存原始付款、分账记录、手续费和退款之间的关联。
例如,一笔 100.00 元的付款需要按 90% / 10% 分配:
付款总额:100.00
账户 A:90.00
账户 B:10.00
计算时应使用最小货币单位,避免浮点数误差:
const totalAmount = 10000; // 100.00,单位为分
const accountBAmount = Math.floor(totalAmount * 10 / 100);
const accountAAmount = totalAmount - accountBAmount;
console.log(accountAAmount); // 9000
console.log(accountBAmount); // 1000
支付成功后,可以调用服务商提供的 transfer 或 split settlement API 创建分账。各平台的接口差异较大,下面的代码只用于说明通用流程,不能直接用于某一家服务商:
async function splitPayment(payment) {
if (payment.status !== "succeeded") {
throw new Error("Payment has not succeeded");
}
const total = payment.amount;
const accountBAmount = Math.floor(total * 10 / 100);
const accountAAmount = total - accountBAmount;
await paymentProvider.createTransfer({
sourcePaymentId: payment.id,
destinationAccount: "account_A",
amount: accountAAmount,
currency: payment.currency,
idempotencyKey: `${payment.id}:account_A`
});
await paymentProvider.createTransfer({
sourcePaymentId: payment.id,
destinationAccount: "account_B",
amount: accountBAmount,
currency: payment.currency,
idempotencyKey: `${payment.id}:account_B`
});
}
实际开发时应以支付服务商的官方 API 为准,并确认是否支持多个 destination account、分账手续费和跨主体结算。
方案二:结算后通过银行转账分配
如果两个银行账户都属于同一家企业,未必需要在支付阶段拆分资金。
可以让 payment gateway 先把全部资金结算到主账户,再由财务系统分配:
payment gateway
↓
企业主账户
├── 90% 保留在主账户
└── 10% 转入第二个企业账户
自动划拨可以逐笔执行,也可以每天汇总后执行。按日汇总通常可以减少转账次数和手续费。
伪代码如下:
const settledAmount = 250000; // 2500.00,单位为分
const reserveAmount = Math.floor(settledAmount * 10 / 100);
await bankApi.createTransfer({
fromAccount: "primary_business_account",
toAccount: "secondary_business_account",
amount: reserveAmount,
currency: "CNY",
reference: "Daily 10% allocation"
});
这里的 bankApi 只是示意。能否自动转账,要看开户银行是否提供企业 API、资金归集或定时划拨服务。
手续费如何处理
首先要明确,分配比例按交易总额计算,还是按扣除手续费后的净额计算。
假设客户支付 100.00 元,支付手续费为 3.00 元:
- 按总额分配:
90.00 + 10.00,手续费需要另行指定承担方; - 按净额分配:可分配金额为
97.00,分配结果为87.30 + 9.70; - 由固定一方承担:先分配
90.00 + 10.00,再从其中一个账户扣除3.00。
代码、合同和财务对账必须采用同一套规则。
退款和拒付不能忽略
付款完成分账后,如果发生退款,除了把钱退给客户,还要处理已经转入其他账户的资金。
例如,原付款按 90% / 10% 分配,之后退款 50.00 元,按原比例冲回的金额为:
账户 A 冲回:45.00
账户 B 冲回:5.00
系统至少需要记录:
- 原始付款 ID;
- 每笔 transfer 的 ID;
- 各账户收到的金额;
- 支付手续费;
- 已退款金额;
- 拒付及相关费用;
- 分账或转账失败状态。
创建付款、分账和退款请求时,还应使用 idempotency key,避免因网络重试而重复划款。
注意事项
- 不要把”分账”理解为在支付请求中填写两个银行卡号。大多数普通网关不支持这种操作。
- 如果两个外部账户属于不同法律主体,不能简单地通过企业网银代收后转付。这种做法可能涉及代收代付、税务和支付合规问题。
- connected account 通常需要完成 KYC/KYB 验证,未验证的账户可能无法收款或提现。
- 某些服务商只允许平台收取 application fee,不支持任意拆分付款。
- 百分比计算应使用整数形式的最小货币单位,不要使用浮点金额。
- 最后一方的金额应按”总额减去其他分配额”计算,用于吸收舍入差额。
- 手续费、退款、拒付和负余额由哪一方承担,需要提前确定。
- 跨币种、跨境或跨企业分账可能受到额外限制。
如果只是把同一家企业的收入按比例存入两个自有账户,可以优先考虑结算后的自动划拨。如果需要将销售款分给不同经营主体,则应选择明确支持 marketplace 或 split payment 的支付平台,并按照平台的账户验证和资金流规则实施。
备注:内容仅供参考。
