《独立开发者的商业指南·合同、应收与风险》9.3 渠道合同与退出

渠道退出的成本不在解约那一刻,而在库存回购、未结佣金、客户归属和竞业限制四条条款里。本节用 Nord 从 55% 转介绍切到直销的完整退出账,算出 141,125 美元退出成本、98,625 美元第一年缺口与 26 个月回收期,并对照经销商模式 41 个月的回收期。

以下情境为教学假设,人物与数字不代表经核实的真实案例。

渠道合同最容易只写“怎么开始”,不写“怎么结束”。开始时的条款决定渠道能带来多少收入,结束时的条款决定厂商能不能走、走的时候要付多少钱。很多渠道合作不是败在分成比例,而是败在退出:库存压在手里、佣金没结清、客户带不走、竞业期不能卖。

这一节把退出拆成四类条款:库存回购、未结佣金、客户归属、竞业限制。然后用 Nord 从 55% 转介绍切换到直销的场景,算一次完整的退出账。所有金额和期限都是教学假设,不是真实合同报价;它们的作用是让“退出成本”从一句感觉变成一张表。

退出条款的四个钱包

退出条款之所以贵,是因为它同时打开四个钱包:库存、佣金、客户和收入空档。

条款触发时付什么Nord 的教学假设金额
库存回购未售库存或预付项目按约定价买回3 个项目预付款,每笔 $4,250$12,750
未结佣金已成交但未结算的佣金3 笔 × $4,675$14,025
客户归属存量客户在归属期内的续约佣金或转让费12 家 × $8,500 × 55%$56,100
竞业限制过渡期内不能在某区域销售6 个月旧渠道净得$38,250

库存回购在服务型渠道里不一定是实物库存。Nord 的转介绍方可能预付了三个项目的启动款,每个项目 4,250 美元,合计 12,750 美元;退出时厂商要么退回这笔预付款,要么用未来项目抵扣。对经销商来说,库存回购就是未售出的许可证、实物或备件,按进货价或成本价买回。条款要写清回购价、可售状态和付款期限,否则“回购”会变成“按什么价回购”的长期争议。

未结佣金是已经成交、还没结算的部分。3 笔 × 4,675 美元 = 14,025 美元。条款的关键是佣金什么时候“赚到”:按签约确认,还是按客户付款确认。按签约确认,厂商在退出时就要付;按付款确认,厂商可以等客户付款后再付。两种写法在正常年份差别不大,在退出时差别很大。

客户归属是最容易被低估的一项。Nord 的假设是 12 家存量客户,年项目额 8,500 美元,转介绍方在退出后 12 个月内继续拿 55% 的续约佣金,合计 56,100 美元。这笔钱不是“分手费”,而是客户归属条款的延续:客户是转介绍方带来的,合同约定它在多长时间内继续分享这些客户的收入。客户归属可以写成尾佣、不得主动联系、转让费或交接期,四种写法的成本差别很大,尾佣通常最贵,因为它跟着客户收入走。

竞业限制不是一笔现金支出,而是一段收入空档。Nord 的假设是 6 个月内不能在原区域直接销售,旧渠道年净得 76,500 美元,6 个月就是 38,250 美元。竞业期越长、区域越大,空档越贵。条款要写清区域、客户范围、期限和补偿;没有补偿的竞业限制,在不少司法辖区本身就难以执行,但本书不展开法律分析。

四个钱包加起来,Nord 的一次性支出是 12,750 + 14,025 + 56,100 = 82,875 美元,再加上 20,000 美元的过渡与法律费用,合计 102,875 美元;如果把 6 个月的收入空档也算进去,总退出成本是 141,125 美元。

Nord 的退出账:141,125 美元与 26 个月

Nord 当前的转介绍渠道,一年做 20 笔 8,500 美元的项目,厂商净得 45%,即 76,500 美元。切换到直销后,同样 20 笔,厂商净得 95%,即 161,500 美元,年增益 85,000 美元。

退出成本分两层。第一层是过渡期的收入缺口:旧渠道停止,新渠道还没跑起来,6 个月没有收入,按旧渠道净得算是 38,250 美元。第二层是一次性支出:未结佣金 14,025 美元、客户尾佣 56,100 美元、预付款回购 12,750 美元、过渡与法律费用 20,000 美元,合计 102,875 美元。

项目计算金额
过渡期收入缺口76,500 × 6 ÷ 12$38,250
未结佣金3 × 4,675$14,025
客户归属尾佣12 × 8,500 × 55%$56,100
预付款回购3 × 4,250$12,750
过渡与法律费用教学假设$20,000
退出总成本38,250 + 102,875$141,125

第一年的现金结果不是“年增益 85,000 美元”,而是“半年新渠道收入减一次性支出”:

第一年净现金 = 161,500 × 6 ÷ 12 − 102,875 = −22,125 美元

第一年不仅没有赚到 85,000 美元,还倒亏 22,125 美元。和继续留在旧渠道相比,第一年的差距是 76,500 − (−22,125) = 98,625 美元。这就是渠道切换的“J 形曲线”:先下后上,下沿的深度由退出条款决定。

年份继续旧渠道切换后差额
第 1 年$76,500−$22,125−$98,625
第 2 年$76,500$161,500+$85,000
两年合计$153,000$139,375−$13,625

两年合计仍然是负的:切换后的 139,375 美元比继续旧渠道的 153,000 美元少 13,625 美元。回收期要把过渡期算进去:

满负荷回收期 = 141,125 ÷ (85,000 ÷ 12) = 19.9 个月,取整 20 个月

从切换日算 = 6 个月过渡 + 20 个月 = 26 个月

20 个月是“新渠道达到满负荷之后”的回收期,26 个月是从切换当天算起的真实回收期。很多渠道切换的方案只报 20 个月,把 6 个月的过渡期藏在脚注里;对现金流紧张的一人公司,这 6 个月往往是决定成败的部分。

如果新渠道的爬坡比假设慢,回收期会更长。假设第一年只做到 15 笔而不是 20 笔,新渠道年净得是 121,125 美元,第一年半年只有 60,562.50 美元,减掉 102,875 美元的一次性支出,第一年净现金是 −42,312.50 美元,回收期超过 30 个月。渠道切换的模型一定要做“爬坡不及预期”的情景,不能只用满负荷数字。

换成经销商:库存回购把回收期拉到 41 个月

同样的切换,如果旧渠道是经销商而不是转介绍方,退出账会更重。经销商年做 20 笔,厂商净得 60%,即 102,000 美元;切换到直销后净得 161,500 美元,年增益 59,500 美元,比转介绍场景少 25,500 美元。

退出成本的结构也不同。经销商手里有未售库存,假设 10 笔 × 5,100 美元 = 51,000 美元;未结返点是 15% × 170,000 = 25,500 美元;客户归属的成本是 8 家客户无法在 12 个月内转为直销,每家损失 2,975 美元(直销净得 8,075 − 经销净得 5,100),合计 23,800 美元;过渡与法律费用 20,000 美元。一次性支出合计 120,300 美元。

项目代理转直销经销转直销
旧渠道年净得$76,500$102,000
新渠道年净得$161,500$161,500
年增益$85,000$59,500
过渡期缺口(6 个月)$38,250$51,000
未结佣金/返点$14,025$25,500
客户归属成本$56,100$23,800
库存/预付款回购$12,750$51,000
过渡与法律$20,000$20,000
退出总成本$141,125$171,300
满负荷回收期20 个月35 个月
从切换日算26 个月41 个月

经销商场景的退出总成本是 171,300 美元,比代理场景高 30,175 美元;年增益却少 25,500 美元。分子更大、分母更小,回收期从 26 个月拉到 41 个月。第一年净现金是:

161,500 × 6 ÷ 12 − 120,300 = −39,550 美元

和继续旧渠道相比,第一年差距是 102,000 − (−39,550) = 141,550 美元。对一家年收入 154,320 美元的两人工作室,这个缺口接近一年的收入。

这张表说明一个反直觉的结论:渠道介入库存和客户越深,退出可能越贵。转介绍方不压库存,退出主要是佣金和客户尾佣;经销商压库存、拿返点、掌握终端客户,退出时要回购库存、结清返点、放弃客户转换。深度的代价不只在平时的净得里,也在退出时的回购价里。

经销商合同里还有两个容易漏掉的条款。第一,库存回购的定价基准:按进货价、成本价还是建议零售价折扣,三种基准可能差 30% 以上。第二,返点的结算截止日:退出当年的返点按全年进货额算,还是按已结算月份算;如果按全年算,厂商可能在退出时还要补一笔返点。

把退出写成代码

下面的 channel-exit.ts 把退出账拆成两层:过渡期收入缺口和一次性支出。channelExit 返回旧渠道年净得、新渠道年净得、年增益、过渡缺口、一次性成本、总退出成本、第一年净现金、第一年差距、满负荷回收期和从切换日算的回收期。

// file: src/contract/channel-exit.ts
// tier: L1
// verify: node --test test/contract/channel-exit.test.ts

import { type Cents } from "../core/money.ts";
import { type Bps, applyRate } from "../core/rate.ts";
import { type Result, fail, ok } from "../core/result.ts";

export type ExitInput = {
  annualDeals: number;
  grossPerDealCents: Cents;
  oldNetRateBps: Bps;
  newNetRateBps: Bps;
  transitionMonths: number;
  unpaidCommissionCents: Cents;
  customerTailCents: Cents;
  inventoryBuybackCents: Cents;
  transitionCostCents: Cents;
};

export type ExitOutcome = {
  oldAnnualNetCents: Cents;
  newAnnualNetCents: Cents;
  annualGainCents: Cents;
  transitionGapCents: Cents;
  oneTimeCostCents: Cents;
  totalExitCostCents: Cents;
  firstYearNetCents: Cents;
  firstYearGapCents: Cents;
  fullRatePaybackMonths: number;
  paybackMonths: number;
  paybackPossible: boolean;
};

function checkAmount(value: Cents, label: string): string | null {
  if (!Number.isInteger(value) || value < 0) {
    return `${label} must be a non-negative integer amount in cents`;
  }
  return null;
}

function checkBps(value: Bps, label: string): string | null {
  if (!Number.isInteger(value) || value < 0 || value > 10000) {
    return `${label} must be between 0 and 10000 bps`;
  }
  return null;
}

/**
 * Exit cost has two layers. The one-time layer is paid at termination:
 * unpaid commissions, customer-tail payments, inventory buyback and the
 * transition project. The recurring layer is the old channel's net revenue
 * that disappears while the new channel is being built.
 */
export function channelExit(input: ExitInput): Result<ExitOutcome> {
  if (!Number.isInteger(input.annualDeals) || input.annualDeals <= 0) {
    return fail("annual deals must be a positive integer");
  }
  if (
    !Number.isInteger(input.grossPerDealCents) ||
    input.grossPerDealCents <= 0
  ) {
    return fail("gross per deal must be a positive integer amount in cents");
  }
  for (const [value, label] of [
    [input.oldNetRateBps, "old net rate"],
    [input.newNetRateBps, "new net rate"],
  ] as Array<[Bps, string]>) {
    const error = checkBps(value, label);
    if (error) {
      return fail(error);
    }
  }
  if (
    !Number.isInteger(input.transitionMonths) ||
    input.transitionMonths < 0 ||
    input.transitionMonths > 12
  ) {
    return fail("transition months must be an integer between 0 and 12");
  }
  for (const [value, label] of [
    [input.unpaidCommissionCents, "unpaid commission"],
    [input.customerTailCents, "customer tail"],
    [input.inventoryBuybackCents, "inventory buyback"],
    [input.transitionCostCents, "transition cost"],
  ] as Array<[Cents, string]>) {
    const error = checkAmount(value, label);
    if (error) {
      return fail(error);
    }
  }

  const annualGrossCents = input.grossPerDealCents * input.annualDeals;
  const oldAnnualNetCents = applyRate(annualGrossCents, input.oldNetRateBps);
  const newAnnualNetCents = applyRate(annualGrossCents, input.newNetRateBps);
  const annualGainCents = newAnnualNetCents - oldAnnualNetCents;
  const transitionGapCents = Math.round(
    (oldAnnualNetCents * input.transitionMonths) / 12,
  );
  const oneTimeCostCents =
    input.unpaidCommissionCents +
    input.customerTailCents +
    input.inventoryBuybackCents +
    input.transitionCostCents;
  const totalExitCostCents = transitionGapCents + oneTimeCostCents;
  const firstYearNetCents =
    Math.round(
      (newAnnualNetCents * (12 - input.transitionMonths)) / 12,
    ) - oneTimeCostCents;
  const firstYearGapCents = oldAnnualNetCents - firstYearNetCents;
  const monthlyGainCents = annualGainCents / 12;
  const paybackPossible = monthlyGainCents > 0;
  const fullRatePaybackMonths = paybackPossible
    ? Math.ceil(totalExitCostCents / monthlyGainCents)
    : 0;

  return ok({
    oldAnnualNetCents,
    newAnnualNetCents,
    annualGainCents,
    transitionGapCents,
    oneTimeCostCents,
    totalExitCostCents,
    firstYearNetCents,
    firstYearGapCents,
    fullRatePaybackMonths,
    paybackMonths: paybackPossible
      ? input.transitionMonths + fullRatePaybackMonths
      : 0,
    paybackPossible,
  });
}

把 Nord 的数字代入:20 笔、每笔 850,000 美分、旧渠道净得率 4,500 基点、新渠道 9,500 基点、过渡 6 个月、未结佣金 1,402,500 美分、客户尾佣 5,610,000 美分、预付款回购 1,275,000 美分、过渡费用 2,000,000 美分。channelExit 返回旧渠道年净得 7,650,000 美分、新渠道 16,150,000 美分、年增益 8,500,000 美分、过渡缺口 3,825,000 美分、一次性成本 10,287,500 美分、总退出成本 14,112,500 美分、第一年净现金 −2,212,500 美分、第一年差距 9,862,500 美分、满负荷回收期 20 个月、从切换日算 26 个月。

经销商场景代入旧渠道净得率 6,000 基点、未结返点 2,550,000 美分、客户归属成本 2,380,000 美分、库存回购 5,100,000 美分、过渡费用 2,000,000 美分,得到年增益 5,950,000 美分、一次性成本 12,030,000 美分、总退出成本 17,130,000 美分、第一年净现金 −3,955,000 美分、满负荷回收期 35 个月、从切换日算 41 个月。

代码里有三个刻意的限制。第一,不折现。20 个月后的 1 美元和今天的 1 美元在代码里一样重;如果资金成本高,真实回收期会更长。第二,假设旧渠道在过渡期开始时立即停止,新渠道在过渡期结束后直接达到满负荷;真实爬坡可能更慢。第三,一次性成本在退出时一次付清,不处理分期支付、库存分批回购和佣金按月结算。它足够回答“这次切换要花多少、多久回本”,但不足以替代逐条合同的现金流表。

退出条款不是“分手时再谈”的条款,而是签约时就要定价的条款。库存回购价、佣金确认时点、客户归属期、竞业期限,四项每让一步,退出成本就多一层。把四笔账在签约前算一遍,比在退出时争论更有用。

退出前的检查线

渠道退出不是越早越好,也不是越晚越好。把退出账算完之后,可以用三条线做判断。

第一条线是回收期。满负荷回收期超过 24 个月,退出就不是一个纯财务决策,而是一个战略决策;它需要新的收入来源、融资或成本削减来支撑过渡期。Nord 的代理场景是 20 个月,落在可执行区间;经销商场景是 35 个月,需要额外的现金储备。

第二条线是第一年缺口。第一年缺口 98,625 美元,对年收入 154,320 美元的 Nord 来说,相当于 7.7 个月的收入。如果账上现金不足以覆盖这个缺口,切换即使长期划算,也可能在中途被迫放弃。

第三条线是客户可触达率。客户归属条款决定退出后能不能直接接触客户;如果 60% 的客户能在 12 个月内转成直销,缺口可控;如果只有 30%,客户尾佣和收入空档会同时放大。签约前要问一句:退出后,我能不能合法地联系这些客户?

三条线都过,才值得切换;有一条不过,就应该先谈退出条款,而不是先谈分成比例。

检查线判断标准Nord 代理场景经销场景
满负荷回收期不超过 24 个月20 个月35 个月
第一年缺口不超过 9 个月收入98,625 美元(7.7 个月)141,550 美元(11.0 个月)
客户可触达率不低于 50%60%40%

这张表把退出从“要不要走”变成“走得起走不起”。Nord 的代理场景三条线都过,可以走;经销场景回收期和第一年缺口都超线,客户可触达率也不足,应该先重谈库存回购和客户归属,再考虑切换。

小结

  • 渠道退出成本由四类条款构成:库存回购、未结佣金、客户归属、竞业限制。
  • Nord 的代理转直销场景,一次性支出 102,875 美元,过渡期缺口 38,250 美元,总退出成本 141,125 美元。
  • 第一年净现金是 −22,125 美元,比继续旧渠道少 98,625 美元;两年合计仍少 13,625 美元。
  • 满负荷回收期是 20 个月,从切换日算是 26 个月;过渡期不能藏在脚注里。
  • 经销商转直销场景,总退出成本 171,300 美元,满负荷回收期 35 个月,从切换日算 41 个月。
  • 渠道介入库存和客户越深,退出可能越贵:经销商的库存回购和未结返点,把回收期从 26 个月拉到 41 个月。
  • 退出前看三条线:回收期不超过 24 个月、第一年缺口不超过 9 个月收入、客户可触达率不低于 50%。
  • 退出条款要在签约时定价,不要等到分手时再谈;库存回购价、佣金确认时点、客户归属期、竞业期限,每让一步都增加退出成本。

阅读导航:上一节:9.2 返点、区域保护与价格冲突 · 下一节:10.1 云、支付、平台的关键依赖 。

常见错误与边界

  1. 只写退出通知期,不写退出成本。 通知期只解决“什么时候能走”,不解决“走的时候付多少”;库存、佣金、客户和竞业才是成本主体。
  2. 库存回购不写定价基准。 按进货价、成本价还是零售价折扣,三种基准可能差 30% 以上;不写清楚,退出时一定争议。
  3. 佣金确认时点写成“签约确认”。 退出时厂商要立即支付所有已签约佣金;如果现金流紧张,应争取按客户付款确认。
  4. 客户归属只写“客户归厂商”。 没有尾佣、不得主动联系或交接期的具体安排,“归厂商”在执行时可能是一句空话。
  5. 把竞业限制当成零成本。 竞业期是收入空档,6 个月就是 38,250 美元;期限越长、区域越大,空档越贵。
  6. 只算一次性支出,不算过渡期缺口。 一次性支出 102,875 美元,过渡期缺口 38,250 美元;只算前者,会低估总成本 27%。
  7. 用满负荷回收期做决策。 20 个月是满负荷后的回收期,从切换日算是 26 个月;只报 20 个月,会把 6 个月过渡期藏起来。
  8. 假设新渠道一上线就满负荷。 如果第一年只做 15 笔而不是 20 笔,回收期超过 30 个月;爬坡情景必须单独算。
  9. 忽略经销商库存和返点的叠加。 经销场景总退出成本 171,300 美元,比代理场景高 30,175 美元;库存和返点是主要增量。
  10. 把退出当成失败。 退出是渠道组合的常态;算清退出成本,才能在签约时争取可承受的条款,而不是在亏损时被迫接受任何条件。

本节的边界是“单一渠道、一次性切换、无折现”的静态模型。它假设旧渠道在过渡期开始即停止、新渠道在过渡期结束后达到满负荷、一次性成本在退出时付清,不含分期支付、库存分批回购、汇率、税务和诉讼周期。它足够回答“这次切换要花多少、多久回本”,但不足以替代逐条合同的现金流表。供应商切换的迁移成本,见 10.3 备选方案与迁移成本 ;渠道选择本身的净得比较,见 9.1 直销、代理、经销的选择 。本节不构成法律意见,具体退出条款请由律师审阅。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《移动游戏产品的架构·商业化与发行工程》附录 C 商业化与发行评审清单
  2. 《移动游戏产品的架构·商业化与发行工程》附录 B 双案例商业化事实表
  3. 《移动游戏产品的架构·商业化与发行工程》附录 A 商业化与发行术语速查