委托创作(约稿)支付方案:初步分析
日期:2026-10-03(2026-10-04 更新:约稿单改为任意一方建单、双方确认;验收由委托人点按钮;约稿单和订单页改为通过通用嵌入组件以 iframe 嵌进论坛,跳转 Stripe 时在顶层打开) 范围:论坛内的约稿交易,从谈妥价格到付款、验收、放款、纠纷处理 前提:站点面向北美;开站初期采用邀请制;架构上人工优先,论坛已有功能能模拟的环节就不写代码,只把必须由程序执行的部分放进一个外接小服务 关联文档:
discourse-extension-report.md(三个功能的总体扩展方案)、embed-adapter-report.md(站外服务嵌入论坛)
一、结论摘要
- 方向可行。约稿流程里只有钱的流动和支付入口必须由程序完成。展示、沟通、谈价、验收确认、纠纷仲裁都可以先靠论坛功能加人工完成。
- 资金走 Stripe Connect 的 separate charges and transfers 模式:委托人付款时钱进平台账户,验收后平台再转给创作者。运营团队自己接的单直接进公司账户,不转账。两种订单共用一张订单表、一套流程。
- 支付按钮由约稿单自动生成,不需要运营介入:委托人或创作者任意一方建单,双方填写条款、各自点同意后,委托人那边出现付款按钮。金额只存在服务端,按钮上只带 id,只有指定的委托人能付款。
- 外接小服务只做五件事:约稿单、Checkout、webhook 记账(并在论坛建任务帖)、验收放款、退款。登录复用论坛账号(DiscourseConnect)。
- 开工前要确认的主要是合规和规则,技术上难度不大:资金托管的法律定性、销售税、拒付风险由谁承担、自营单出纠纷时谁来仲裁。
二、职责划分
| 环节 | 承担方 | 方式 |
|---|---|---|
| 作品展示 | 论坛 | 专门分类,创作者开帖;用标签区分画种、价位、档期 |
| 沟通、谈价 | 论坛 | 私信或跟帖,不限形式 |
| 约稿单、生成支付按钮 | 小服务 | 任意一方建单,双方填写条款、各自同意后,系统自动生成只有委托人能用的支付入口 |
| 付款 | Stripe Checkout | Stripe 托管的支付页,卡号不经过我们 |
| 记账、建任务帖 | 小服务 | 接收 webhook,验签、去重,订单状态从 open 改为 paid;通过论坛 API 建任务帖 |
| 交付 | 论坛 | 在任务帖里交付 |
| 验收、放款 | 小服务 | 委托人点“确认验收”,或运营仲裁后点放款;调用 Stripe 转账给创作者,自营单只改状态 |
| 纠纷、仲裁 | 论坛 + 人工 | 在任务帖里召唤运营;结论由运营在小服务后台执行退款或放款 |
| 拆分复杂需求 | 人工 | 运营介入,把大单拆成几个阶段,每个阶段单独建约稿单、单独验收 |
| 激励 | 小服务 → 论坛 API | 放款后发徽章、加用户组 |
小服务的后台只给运营用,初期可以非常简陋,有一个订单列表和几个按钮就够了。
三、资金流
3.1 选型:separate charges and transfers
平台必须托管资金、保证履约,所以“付款时钱直接给创作者”的方案不考虑。
Stripe Connect 有三种收款方式,符合“验收后才放款”这一需求的是下面两种:
| 方式 | 钱在验收前放在哪 | 验收时的操作 | 验收前退款 | 评价 |
|---|---|---|---|---|
| separate charges and transfers(推荐) | 平台余额 | 创建 transfer 转给创作者 | 直接退款,不涉及创作者 | 钱在验收前不碰创作者账户;自营单就是“不转账”的特例,模型统一 |
| destination charge + 创作者账户手动提现 | 创作者的 Stripe 余额(提现被冻结) | 允许创作者提现 | 退款时要同时撤回转账(reverse transfer) | Stripe 文档里推荐用于“担心退款时延迟付给对方”的场景;但钱进了创作者余额,创作者会看到一笔暂时提不了的钱 |
预授权(先授权、后扣款)不适合作为托管手段:线上卡支付的授权一般只保留 7 天(Visa 的商户发起交易约为 4 天 18 小时),过期就自动作废。改用上面的方式,付款时立即扣款,就没有 7 天限制了。
运营介入、把复杂需求拆成几个阶段的做法仍然值得保留,但理由已经变了:每笔金额更小,拒付时损失也更小;分阶段验收,纠纷也更好判。
3.2 订单状态
open ───付款成功──▶ paid ──验收──▶ released
│ │
└──过期/取消──▶ void └──仲裁退款──▶ refunded
-
状态变更全部用带前置条件的原子 UPDATE,和检票防重放的写法相同:
UPDATE orders SET status = 'released', released_at = now(), released_by = ? WHERE id = ? AND status = 'paid'影响行数为 0 就说明这笔订单已经处理过,不再调用 Stripe。这样同一笔钱不会被放款两次,也不会放完款又被退款。
-
先改状态,再调 Stripe。Stripe 调用失败就把状态回滚,并报警给运营人工处理。初期单量很小,不需要自动重试队列。
-
部分退款、部分放款(比如仲裁结果是退一半)初期由运营在 Stripe 后台手工操作,再在小服务里备注。等这种情况真的多了,再做成按钮。
3.3 放款时的注意点
- transfer 一定要带
source_transaction(对应的那笔 charge)。不带的话,转账会从平台的可用余额里扣,平台余额已经自动提现到银行时就会失败。带上之后,这笔转账会等那笔付款的资金到账后再执行。 - 平台账户的自动提现要谨慎设置。 托管中的钱和平台自己的收入(抽成、自营单收入)在同一个余额里。建议平台账户改为手动提现,由运营定期只提走已经确认属于平台的部分。Stripe 有一个“资金隔离”功能(funds segregation)能把托管资金单独存放,但目前还是 private preview,以后可以关注。
- separate charges and transfers 模式下,退款不会自动撤回已经发出的转账。放款后再出纠纷,要另外发起 transfer reversal,而且前提是创作者的 Stripe 余额里还有钱。
3.4 自营单
运营团队成员接的单,收款方就是公司:
- 订单的
payee_account为空,表示自营单,付款直接进平台余额。 - 验收时只把状态改为
released,不转账。 - 团队成员的报酬走公司自己的薪酬或外包付款流程,和 Stripe 无关。
3.5 抽成
平台抽成 = 收款金额 − 转给创作者的金额,余下的留在平台余额里。Stripe 手续费从平台余额里扣,所以抽成至少要覆盖手续费,而且这笔手续费退款时不会退还。这个比例是运营决策,代码只需要在建单时把它算好、存下来。
四、约稿单与支付入口
需求:谈妥之后,系统必须能自动给出付款按钮,不依赖运营;平台必须托管资金、保证履约。
4.1 约稿单:任意一方建单,双方确认
条款是双方谈出来的,谈的形式不限,由谁来建单也不限。委托人和创作者任何一方都可以建一张约稿单,另一方查看、补充、修改:
- 任意一方在小服务里建单:选模板,指定对方(论坛用户名),声明自己是委托人还是创作者。两个参与人和各自的角色建单后不可修改。
- 双方都可以编辑条款,即模板里的字段:金额、简述、截稿日、对应的私信或帖子链接等。每改一次,版本号加一。
- 所有必填字段都通过服务端校验后,双方各自点“同意”。同意记录的是当时的版本号,所以之后任何修改都会让之前的同意自动失效,需要重新同意,不用另写“修改后重置同意”的逻辑。
- 两人都同意了当前版本:约稿单变为
agreed,条款冻结。约稿模块按条款调用支付模块的create_order,委托人那边出现付款按钮。 - 冻结后要改条款:作废这张单(同时作废对应的支付订单,关闭可能已打开的 Checkout Session),复制一张新草稿重新谈。不支持“撤回同意”,这样就不会出现“付款进行到一半,条款被对方改了”的情况。
- 委托人付款。付款成功后,约稿模块在事务提交后调用论坛 API 建一个任务帖,后续交付、讨论、召唤运营都在这个帖里进行。
commission_drafts
id
client_id, creator_id # 建单时确定,之后不可改
created_by # 建单人,可能是任意一方
template, fields (json)
version
client_ok_version # 委托人同意时的 version
creator_ok_version # 创作者同意时的 version
status # draft | agreed | void
order_id # agreed 后由 create_order 得到;之后的付款、放款、退款状态看这笔订单
topic_id # 付款后建的任务帖
协商、同意、验收都是约稿模块自己的概念,支付模块不知道它们的存在,只在双方同意之后收到一次 create_order。
4.2 安全约束(不能省)
- 按钮或链接上只带 id,金额只从服务端存的条款里读,同意、建单时都不接受浏览器传来的金额。
- 只有约稿单的两个参与人能查看、编辑、同意;只有其中的委托人能付款,其他人拿到链接只会看到“无权限”。
- 字段按模板在服务端校验,至少检查金额范围、必填项、日期格式。
- 收款方只能是约稿单里的创作者(Connect 账户),或者平台(自营单)。创作者点同意时就检查他的 Connect 账户能否收款,不能的话不允许同意。
- 草稿和支付订单都设有效期(比如 7 天),过期作废,防止拖了很久之后按旧价格付款。
- 创建 Checkout Session 时把订单 id 写进 metadata,webhook 按 session id 去重。
4.3 验收与放款
- 委托人在订单页点“确认验收”:约稿模块调用
release,钱转给创作者。自营单的release只改状态,流程和普通单一样。 - 委托人在任务帖里召唤运营:运营仲裁。判创作者胜诉,运营在后台点同一个放款按钮;判退款,运营调用
refund。部分退款在 Stripe 后台手工操作,小服务通过 webhook 同步,并在任务帖里自动回复一条。 - 委托人一直不点验收:交付后 N 天内无异议,由运营放款(N 见待定事项)。单量上来后再做成定时任务。
不托管的方案已排除(付款时钱直接进创作者账户,即 destination charge 不冻结提现)。履约保障是平台的责任,钱必须在验收前留在平台。
4.4 界面形式:链接,以后由通用嵌入组件显示成 iframe
约稿单和支付按钮都是小服务的页面链接。之后装上通用嵌入组件(见 embed-adapter-report.md),这些链接在帖子和私信里会直接显示成 iframe,双方不用离开论坛就能看到约稿单的实时状态、点“同意”或“验收”。
- 小服务部署在论坛主域名的子域下(比如
svc.<论坛域名>),浏览器认为两者属于同一站点,iframe 里的 cookie 不会被拦截,登录状态能保持。 - Stripe Checkout 不能在 iframe 里打开,所以只有“付款”这一步跳到顶层页面。
- 首次登录(DiscourseConnect)不能在 iframe 里完成,iframe 里显示“登录”按钮,用弹窗登录。
后端接口固定不变,界面可以分阶段换:
| 阶段 | 形式 | 需要动论坛吗 |
|---|---|---|
| 起步 | 用论坛账号登录小服务,建约稿单,把链接贴进私信 | 不需要 |
| 进一步 | 通用嵌入组件:把私信或帖子里的约稿单链接显示成 iframe,付款时跳到顶层 | 主题组件,后台安装即可,不用 rebuild。以后接其他服务不用再改 |
| 再进一步 | 编辑器里加一个“建约稿单”按钮,弹窗填写后自动插入链接 | 给通用嵌入组件加一个编辑器入口(一次性改动,其他服务也能用) |
起步阶段已经满足“系统自动给出支付入口”这一要求,后面两步只是改善体验。
五、和论坛的对接点
| 对接 | 方式 |
|---|---|
| 登录 | 论坛开启 DiscourseConnect provider,小服务通过它登录,拿到论坛的用户 id 和用户名 |
| 判断谁是创作者 | 只有某个论坛用户组(比如 creators)的成员能作为创作者参与约稿单。加入这个组由运营人工审核 |
| 激励 | 放款后调用 Discourse API 发徽章(POST /user_badges.json)或加入用户组 |
| 通知 | 付款成功、放款后,通过 Discourse API 发私信通知双方(可选;起步阶段 Stripe 收据邮件就够了) |
小服务只需要一个 Discourse 管理员 API key,存在服务端,权限尽量收窄。
六、风险与开放问题
6.1 合规(需要找律师或会计确认)
- 托管资金的法律定性。 Stripe 文档明确写了,它不提供 escrow 服务(escrow 在法律上有严格定义)。美国各州对“为他人代管资金”有牌照要求。市场类平台的常见做法是:平台作为交易的商户方或收款代理,条款里不写 “escrow”“担保交易” 这类词。站规和服务条款的措辞要请律师审一遍。
- 销售税。 数字作品、委托创作在美国各州的销售税规定不一样,加拿大另有 GST/HST。可以考虑用 Stripe Tax。
- 1099-K。 给创作者开 Express 类型的连接账户时,身份验证和税表可以交给 Stripe 处理。具体配置要在接入时确认。
- 自营单的收入申报,是公司常规的会计事务。
6.2 拒付(chargeback)
- 这个模式下,拒付扣的是平台余额,同时还要付一笔争议手续费。
- 委托人确认验收、平台已经放款之后,委托人仍然可以找发卡行拒付,窗口期通常在 120 天左右,各卡组织规定不一。论坛的仲裁结论对发卡行没有约束力。
- 应对:
- 验收要留下证据:委托人点“确认验收”的记录、任务帖里的交付和确认。应对拒付时这是主要证据。
- 大单拆成几个阶段,控制单笔风险。
- 站规里写明:拒付成功后,平台有权向创作者追回已经放出的款,并对恶意拒付的委托人封号。
- 邀请制本身就能过滤掉大部分恶意用户。
6.3 利益冲突
运营团队既是仲裁者,又自己下场接单。自营单一旦出了纠纷,要事先定好由谁仲裁(比如由没参与这单的成员处理,或者引入社区评审),并写进公开的站规。
6.4 刷单
邀请制阶段风险很低。长期来看,激励规则建议:
- 按完成单数发徽章,不按金额发经验值。
- 设置上限。
- 同一对委托人和创作者之间反复交易,计入激励时打折。
上线时先不做这些限制,记作待观察事项。
七、实施顺序
- Stripe 账户:开通 Connect,测试模式下跑通“平台收款 → 转账给一个测试连接账户 → 退款”的完整链路。
- 小服务最小版本:DiscourseConnect 登录、约稿单(双方同意)、订单页、Checkout、webhook 记账和建任务帖、验收按钮。先只支持自营单,不涉及 Connect,就可以开始实际接单。
- 接入 Connect:创作者开通连接账户(Express);运营后台加放款、退款按钮。
- 激励:放款后自动发徽章。
- 界面嵌入:安装通用嵌入组件,帖子里的约稿单和订单链接直接显示成 iframe(见
embed-adapter-report.md)。
第 2 步完成后,自营单就能真实跑起来,这也是检验整套流程最便宜的方式。
八、待定事项
- 平台抽成比例,以及 Stripe 手续费由谁承担
- 约稿单草稿、支付订单的有效期
- 任务帖的形式:初步定为一单一个私信帖,默认不公开,由运营转换公开状态(见
commission-task-topic.md) - 验收超时规则:交付后委托人多少天不回应视为自动验收(初期由运营人工判断)
- 拒付发生后,向创作者追款的规则
- 自营单出纠纷时的仲裁人选
- 创作者准入规则(
creators组怎么加入) - 律师对托管资金和服务条款措辞的意见;销售税方案
参考
- Stripe:How charges work in a Connect integration
- Stripe:Separate charges and transfers
- Stripe:Using manual payouts(含 “Stripe doesn’t provide escrow services” 的说明,以及美国连接账户手动提现最长 2 年的规定)
- Stripe:Place a hold on a payment method(预授权有效期)