PAYATHON 2026

如何让软件用户接受 card payments 并收取平台费?

支付阿杰

结论

有。适合这种业务的做法,不是先用一个自建的总 merchant account 归集款项,再手工分账,而是采用支付服务商提供的 platform payments、marketplace payments 或 PayFac(支付便利商)方案。

常见产品包括 Stripe Connect + Stripe Terminal、Adyen for Platforms + Terminal API,以及其他同时支持线下读卡、商户入驻和自动分账的平台型收单服务。通常可以实现以下流程:

  1. 用户通过你的软件完成商户入驻和身份验证;
  2. 软件向读卡器下发收款金额;
  3. 支付服务商处理 card payment;
  4. 自动扣除 merchant processing fee;
  5. 将约 0.1% 的 application fee 或 platform fee 计入你的平台余额;
  6. 将剩余资金结算到用户的银行账户。

不过,用户拿到读卡器后完全不做任何设置,通常无法实现。每个实际收款企业仍要完成 KYC/KYB、银行账户验证,并确认服务条款。平台可以把这些步骤嵌入软件,尽量减少用户操作,但不能合法绕过。

为什么不应自行归集再转账

如果所有客户款项先进入你名下的普通 merchant account,再由你转给各个用户,可能带来这些问题:

  • 普通 merchant agreement 往往禁止商户替第三方收款;
  • 你可能被认定为 payment aggregator、payment facilitator、merchant of record,甚至受到资金传输或支付机构相关监管;
  • chargeback、退款、负余额和欺诈责任会集中到你的公司;
  • 如果收单机构发现商户名称、实际商品提供者和资金接收者不一致,可能冻结账户或延迟结算;
  • 由你维护商户余额并安排提款,会大幅增加合规、审计和对账的复杂度。

平台型支付产品解决的正是这些问题。支付服务商负责持牌收单、商户审核和资金结算,平台则通过其支持的分账机制收取费用。

推荐的业务结构

每个软件用户都应在支付服务商内部拥有一个 connected account、sub-merchant account 或 balance account。用户不一定需要登录支付服务商的网站,可以通过 hosted onboarding 或 embedded onboarding,直接在你的软件中创建账户。

典型资金流如下:

持卡人
  │
  │ card-present payment
  ▼
支付服务商
  ├── processing fee
  ├── platform fee → 你的平台余额
  └── net amount   → 用户的 connected account
                         │
                         ▼
                    用户银行账户

资金分配应由支付服务商的账本和 API 完成。你的服务器只保存交易标识和分账结果,不直接保管用户资金。

实施步骤

1. 申请平台型支付账户

向候选支付服务商完整说明业务模式,不要只申请普通 merchant account。至少需要说明:

  • 用户所在的国家或地区;
  • 用户经营的行业;
  • 每位用户预计每年约 $250,000 的 card volume;
  • 平均每天约 15 笔交易;
  • 平均客单价;
  • 是否涉及高风险行业、订阅、押金或延迟交付;
  • 业务会使用线下 card reader;
  • 平台计划收取 10 basis points,也就是 0.1%;
  • 由谁负责退款、chargeback 和负余额。

服务商会根据这些信息判断你适合 marketplace、PayFac、referral、ISO,还是其他合作模式。不同国家对资金流和责任划分的要求不同,选型时不能只看 API 是否具备相应功能。

2. 为用户建立 connected account

用户仍需提交企业和实际控制人的资料,例如:

  • 企业名称、注册地址和注册编号;
  • 法定代表人或受益所有人的信息;
  • 收款银行账户;
  • 税务信息;
  • 身份证明;
  • 接受支付服务条款的记录。

建议优先使用支付服务商托管或嵌入式的 onboarding 页面,避免自行收集和保存身份证件。

3. 注册读卡器

不要让自己的后端接触 PAN、磁道数据或 PIN。应使用服务商认证的 EMV reader 和官方 Terminal SDK。

读卡器通常需要关联到:

  • 某个 connected account;
  • 某个门店或 location;
  • 某台 POS 设备;
  • 对应的操作员或软件用户。

读卡器能否在多个 connected accounts 之间切换,以及是否必须按门店注册,取决于服务商和终端型号。这些限制应在选型阶段确认清楚。

4. 创建付款并设置平台费

下面使用 Stripe Connect 风格的 Node.js 代码说明资金拆分方式。这只是结构示例。账户类型、国家、API 版本和 Terminal 集成方式都会影响可用参数,实际实施时应以支付服务商的当前文档和审核结果为准。

import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

function calculatePlatformFee(amountInCents) {
  // 0.1% = 10 basis points
  return Math.round((amountInCents * 10) / 10_000);
}

export async function createTerminalPayment({
  amountInCents,
  currency,
  connectedAccountId
}) {
  if (!Number.isInteger(amountInCents) || amountInCents <= 0) {
    throw new Error("amountInCents must be a positive integer");
  }

  const applicationFeeAmount = calculatePlatformFee(amountInCents);

  return stripe.paymentIntents.create({
    amount: amountInCents,
    currency,
    payment_method_types: ["card_present"],
    application_fee_amount: applicationFeeAmount,
    transfer_data: {
      destination: connectedAccountId
    },
    metadata: {
      connected_account_id: connectedAccountId
    }
  });
}

创建 PaymentIntent 后,再由 Terminal SDK 或服务端驱动的终端接口,通过读卡器收集并确认付款。密钥和费用计算必须放在服务器端,不能信任 POS 客户端传入的 application_fee_amount。

一种常见的结算逻辑是:

gross amount
- payment processing fee
- application/platform fee
= connected account net balance

processing fee 具体由哪一方承担,取决于采用 direct charge、destination charge,还是 separate charges and transfers 等资金模型。做账时不能只看交易成功后的入账金额,还应使用 provider 提供的 balance transaction、transfer 和 fee records。

5. 使用 webhook 更新订单状态

读卡器界面显示成功后,不能直接把订单永久标记为已付款。服务器应验证 webhook,并以服务商返回的最终支付状态为准。

export function handleWebhook(req, res, stripe) {
  let event;

  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      req.headers["stripe-signature"],
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch {
    return res.status(400).send("Invalid webhook signature");
  }

  switch (event.type) {
    case "payment_intent.succeeded": {
      const paymentIntent = event.data.object;

      // 使用 paymentIntent.id 做幂等更新。
      // 不要仅凭金额匹配订单。
      markOrderAsPaid(paymentIntent.id);

      break;
    }

    case "payment_intent.payment_failed": {
      const paymentIntent = event.data.object;
      markOrderAsFailed(paymentIntent.id);
      break;
    }
  }

  return res.sendStatus(200);
}

实际实现还要处理重复 webhook、乱序事件、退款、撤销、部分退款、chargeback 和异步终端状态。

0.1% 的经济性需要重新核算

0.1% 等于 10 个 basis points。按每位用户每年 $250,000 的 card volume 计算:

$250,000 × 0.1% = $250/年

每位用户每年只能带来约 $250 的平台交易收入。如果平均每天约 15 笔交易,一年大约有 5,475 笔,平台每笔平均收入只有约 $0.046。

这些收入需要承担:

  • 平台支付产品的额外费用;
  • 读卡器的采购、物流、更换和远程管理费用;
  • 商户审核和客服成本;
  • 退款及 chargeback 处理成本;
  • 对账、税务和财务成本;
  • 欺诈和负余额风险;
  • PCI、安全测试和系统维护成本。

因此,技术上可以扣取 10 basis points,但这笔费用未必足以覆盖业务成本。更常见的定价方式有:

  • 软件订阅费加较低的 transaction fee;
  • 每笔固定费用加百分比费用;
  • 按月收取 terminal rental;
  • 与收单机构协商批量费率,再保留一部分 margin;
  • 设置最低月度平台费。

处理费中的固定 per-transaction 部分,也不会因为平台费较低而消失。交易笔数较多且客单价较低时,这项固定费用尤其需要纳入测算。

“所有费用都加入客户付款金额”需要谨慎

如果你准备向持卡人额外收取 surcharge 或 convenience fee,需要分别确认:

  • 当地法律是否允许;
  • card network rules 是否允许;
  • debit card 是否禁止加收;
  • 是否设有费率上限;
  • 是否必须在付款前明确展示;
  • 收据上应如何列示;
  • 退款时是否必须退还这笔费用。

不能直接把 merchant processing fee 和平台费全部加到客户应付金额中。比较稳妥的默认方案,是由商户把这些费用作为经营成本承担,平台再从商户的交易结算款或月度账单中收费。如果确实需要收取 surcharge,应使用支付服务商正式支持的合规功能。

选型时必须确认的问题

签约前,应要求支付服务商书面确认以下事项:

  • 是否支持所在地区的 card-present platform payments;
  • connected merchant 的开户和 KYC 由谁负责;
  • 能否在单笔终端交易中扣取 application fee;
  • processing fee 从平台还是 connected account 扣除;
  • 读卡器的归属、配对和远程管理方式;
  • 商户名称如何显示在终端、收据和持卡人账单上;
  • 退款时平台费是否自动退回;
  • chargeback 和负余额由谁承担;
  • payout schedule 是否可以配置;
  • 是否提供逐笔 balance transaction 和 reconciliation report;
  • 是否收取平台月费、账户费、终端费,或设有最低交易量;
  • 平台能否自行设定费率,以及是否需要额外的 PayFac 审批。

最终应采用这样的结构:每个用户都是经过审核的 sub-merchant,由支付服务商自动分账。这样既能提供接近开箱即用的读卡体验,也能自动收取平台费,还可以避免用普通 merchant account 替第三方归集和转移资金。上线前,还应请支付领域的律师和会计师审查合同、资金流、税务及 surcharge 设计。

备注:内容仅供参考。