KappS 知识库 · 博客

Google Play 订阅基础方案与优惠 2026 实操教程

博客 2026-08-01 教程
Google Play 订阅基础方案与优惠 2026 实操教程

Google Play 订阅里有两个问题决定用户到底付多少钱,而它们是在两个不同的地方回答的。基础方案(base plan)回答的是:按什么计费周期、什么价格、自动续订还是预付费?优惠(offer)回答的是:谁有资格以更低的价格开始订阅、优惠持续多久?把模型理解错了,最典型的结果就是——市场部每要一次免费试用,你就新建一个订阅商品,目录越堆越乱、报表被拆散,而那些已经有人买过的旧商品再也删不掉。

下面按 Play Console 与 Billing Library 实际强加给你的顺序展开:创建订阅商品、配置基础方案、添加带资格条件的优惠、在客户端读取 offer token、用正确的替换模式处理升降级,最后在服务器一侧校验权益。末尾几节专讲上线之后才会暴露的坑:区域定价缺口、永远不会被展示的优惠、以及悄悄变成第二个基础方案的改价。


一、三层模型:商品、基础方案、优惠

一个 Google Play 订阅由三层组成,三层的寿命完全不一样,这决定了你今天的决定几年后还能不能改。

  • 订阅商品(product)——目录里的那一行,由商品 ID 标识。商品 ID 一经创建就不能修改;已经有人买过的商品不能删除,只能停用。所以命名要在第一天就想清楚:产品线名 + 周期语义之外的稳定标识,不要用「首月半价」这种会过期的词。
  • 基础方案(base plan)——真正决定计费的那一层:周期(周/月/3 个月/6 个月/年)、续订类型(自动续订或预付费)、各个国家与地区的价格、宽限期与账号保留设置。同一个商品下可以有多个基础方案,这就是你同时卖月付和年付的正确方式,不需要建两个商品。
  • 优惠(offer)——挂在某个基础方案之下的一次性价格待遇,例如免费试用、首期折扣价、老用户回流价。优惠带资格条件,谁符合条件谁才看得见。

一个关键的技术后果:客户端购买时使用的 offerToken 是「某个基础方案 + 某个优惠」这一组合的凭证。商品下只要存在多个基础方案或多个优惠,就必须显式把某一个的 token 传给购买流程,没有默认值。理解这一点,第五节那些报错就不会再莫名其妙。

二、第一步:创建订阅商品

在 Play Console 里进入 通过 Play 创收 → 商品 → 订阅,点「创建订阅」。这一步只做四件事,但每一件都不可逆或不便宜。

  1. 商品 ID:小写字母、数字与下划线,全应用范围内唯一,创建后不可更改,删除过也不能复用。改名只能新建商品,而新建商品意味着新的商品 ID 与新的购买链路。
  2. 名称:这是你自己在后台辨认用的,用户在支付面板看到的是 Play 根据基础方案与优惠生成的信息。
  3. 说明与权益:写清订阅包含什么,这段文字会出现在部分界面,也是审核与客服的依据。
  4. 保存:保存的是草稿,商品要等基础方案配好、并且至少有一个基础方案处于启用状态,才真正可售。

一个常见误区是把「月付」和「年付」建成两个商品。结果是要维护两套购买逻辑、两份订阅状态、两种取消路径,而 Play 的后台本来就把它们设计成同一个商品下的两个基础方案。迁移代价很高,所以第一次就建对。

三、第二步:配置基础方案

基础方案是订阅的经济学所在。每个商品下至少一个,通常两个(月付 + 年付)。

先选续订类型。自动续订方案在周期结束时自动扣款,符合大多数内容与工具类订阅;预付费方案(prepaid)是用户一次买断一个周期、到期后需要再次充值,适合低客单价市场与不想绑定自动扣款的用户。两者不可混用:预付费方案没有续订、没有宽限期概念,也不能挂免费试用。如果你的增长方案依赖试用,主方案必须是自动续订。

再配周期与价格。周期决定计费节奏,价格按国家与地区分别填写。这里最容易出事:Play 允许你只填部分地区的价格,而没有价格的地区等于不可售。用户在那里点购买,看到的是「商品在你所在国家/地区不可用」,客服单就这样产生了。上线前请把目标市场的价格表补全,并核对含税展示是否符合当地要求。

最后是生命周期设置,它们决定扣款失败之后发生什么,而不是扣款成功时发生什么:

  • 宽限期(grace period):扣款失败后的一段时间内用户仍保有权,换取支付方式修复的时间。
  • 账号保留(account hold):宽限期结束仍未付款时,暂停权益但保留订阅记录,用户回来付款可以恢复。
  • 重新订阅:允许已取消的用户在原方案上恢复,而不是必须重新走一遍购买流程。

这几个开关的默认值不一定适合你。工具类应用通常给宽限期、给账号保留;内容类应用可能希望更快降级。无论怎么选,都要让服务器读到的订阅状态与你的权益判断一致——状态字段本身会告诉你用户正处在宽限期还是保留期。

四、第三步:添加优惠与资格条件

优惠是转化工具,也是计费逻辑里最容易配错的一层。每个优惠至少包含三样东西:优惠 ID、价格阶段(phases)、资格条件。

价格阶段决定优惠在时间上怎么展开。一个阶段可以是免费试用(价格为 0,指定天数),也可以是折扣价(指定期数与每期价格)。多个阶段可以叠加,例如「7 天免费 + 首月 5 折」,但阶段顺序即用户实际付费的顺序,写反了就是先收钱再免单——审核与用户投诉都会来找你。

资格条件是优惠能不能被看见的开关,Play 提供三类:

  • 新订阅者(new subscriber):从未订阅过该商品的人。这是免费试用最常用的条件。
  • 升级(upgrade):当前持有另一个订阅、且符合升级关系的人。
  • 回流(win-back):曾经订阅过、后来取消或过期的人。用它做召回比再发一张通用折扣券精确得多,也不会污染新用户的价格。

优惠标签(offer tags)不是装饰。它随购买记录回传,是你之后在报表与服务器逻辑里区分「试用转化」与「原价直购」的唯一干净手段;不打标签,三个月后你无法回答「试用用户留存到底如何」。

优惠是「只影响新购买」的。修改或停用某个优惠,不会改变已经在优惠期内的订阅者的计费安排;反过来,想让存量用户享受新价格,必须走价格变更流程,而不是新建一个优惠。

还有两个边界要记住:一是每个基础方案能挂的优惠数量有上限,促销排期应当复用而不是无限新建;二是基础方案本身处于停用状态时,其下所有优惠都不可售——排查「优惠不显示」时,先看基础方案的状态,再看资格条件,最后才怀疑客户端代码。

五、第四步:在客户端读取正确的 offer token

商品详情返回的是一个列表,不是单个价格。查询订阅商品时,你会拿到 subscriptionOfferDetails,其中每一项对应一个「基础方案 + 优惠」组合,并带有 basePlanId、offerId(优惠可能为空,表示该基础方案本身的原价购买路径)与 offerToken。

购买时必须把这个列表里的一项显式传给计费流程:调用流程参数时构造 ProductDetailsParams,并把选中的 offerToken 一并设置。规则很简单,但违反它的代价很直接:

  • 商品只有一个基础方案、没有优惠时,token 可以省略(部分版本仍建议显式传)。
  • 商品存在多个基础方案,或任何一个优惠时,不传 token 就会失败——这正是「月付能买、年付报错」这类问题的根因。
  • 界面上要展示的价格必须取自你选中的那一项,而不是列表里的第一个:用户看到 $4.99、实际扣的是 $49.99 的年付,是最贵的 bug。

选择逻辑应当明确写出来,而不是依赖列表顺序:先按你能识别的 basePlanId 找到方案,再在其中挑选符合当前用户资格、且优先级最高的优惠;没有任何优惠可用时,回退到该基础方案的原价项。资格判断由 Play 完成——客户端看到的列表本身就是「这个用户此刻能买的东西」,所以不要在本地再写一套资格规则去猜。

测试阶段请用许可测试账号,并注意资格条件会真实生效:一个已经订阅过的测试账号看不到「新订阅者」优惠,这是预期行为,不是代码坏了。验证试用展示,最省时间的办法是一个干净的新账号。

六、第五步:升降级与替换模式

用户从月付切到年付、或从基础版切到高级版,走的是「替换」而不是「再买一次」。替换的行为由替换模式决定,选错的后果是用户被重复收费,或者你在两个周期里少收钱。

  • 按时间折算(with time proration):立即生效,把旧订阅剩余时间的价值折算到新订阅里,用户当场按差额补付。
  • 按比例即时收费(charge prorated price):立即生效并立刻按折算金额扣款,常用于降级,避免用户先享受再补差价。
  • 按全价收费(charge full price):立即生效并立刻收取新方案的全价,剩余价值不折算,适合单价极低、折算成本高于收益的场景。
  • 不折算(without proration):立即切换,新订阅从下一个周期开始计费,旧订阅剩余时间自然走完。对用户最友好,对你最不划算,适合作为降级的默认值。

在 Billing Library 8 中,设置替换模式的入口已经统一为 setSubscriptionReplacementMode(早期版本里的两个旧方法名已废弃)。如果你的代码里还留着旧名字,编译期就会报错,这反而是好事——比线上打到一半才发现语义不同要便宜得多。

预付费方案不参与替换:它没有续订周期,到期即结束。设计「月付转年付」的引导时,必须把预付费用户排除在外,否则你的优惠弹窗只会给他们显示一个永远点不通的按钮。

还有一个顺序问题:替换请求要么失败、要么生效,不存在「部分成功」。所以在客户端不要先扣本地权益再发起替换,而是等服务器拿到新的购买凭证之后再放开。

七、第六步:在服务器一侧校验与确认

客户端返回的购买结果只是「用户说买了」。真正的权益判断在服务器:用购买令牌调用 Play Developer API 的订阅查询接口(purchases.subscriptionsv2),拿到权威状态与到期时间,再写进你自己的权益表。

订阅状态字段会明确告诉你用户处在哪一段:活跃、宽限期、账号保留、暂停、已取消、已过期、待处理。这直接对应权益判断的分支——宽限期通常给权益,账号保留通常收窄权益,暂停则应当停止服务但保留数据。把状态映射写死成「有效/无效」两档,等于主动放弃了 Play 提供的这些区分。

然后是两个容易漏掉的动作。一是确认(acknowledge):购买必须在三天内被确认,否则会被自动退款;用服务器端确认比依赖客户端更稳。二是实时开发者通知(RTDN):续订、取消、进入宽限期、恢复、价格变更确认等事件会通过 Pub/Sub 推给你,通知只是「去查一次」的信号,不是状态的最终来源——收到通知后仍然要调用 API 取完整状态,并且按消息 ID 去重、幂等处理。

把这三层想清楚,订阅才算闭环:客户端负责发起,服务器负责裁决,通知负责及时。

八、上线之后才会遇到的坑

下面这些问题在测试环境几乎不会出现,却会在真实流量里集中爆发。

  • 区域定价缺口:新增市场时忘记补价格,用户看到的是「不可用」。上线前用一个该地区的测试账号走一遍购买面板,比看后台表格可靠。
  • 改价的方式错了:给现有基础方案改价会触发价格变更流程,存量用户需要确认才生效;想「保留老用户老价、新用户新价」的正确做法往往不是直接改价,而是新增一个基础方案并调整售卖策略。改价前先想清楚要哪一种结果。
  • 停用带存量订阅的优惠:停用只阻止新购买,存量用户会继续按原优惠计费到周期结束。这不是 bug,但如果客服话术没准备好,就会变成投诉。
  • 把促销价做成新商品:每做一次促销就新建商品,最终你会有一堆无法删除的商品、被拆散的报表,以及一套谁也不敢动的客户端逻辑。
  • 忘记录入优惠标签:没有标签就无法区分试用转化与直接购买,也无法回答「哪个促销真的带来了留存」。
  • 测试账号看得见、真实用户看不见:资格条件对测试账号同样生效。用干净账号验证,是最快的排错路径。

九、KappS 在这里能做什么

订阅配置本身是产品决策,但它跑在一套需要长期维持合规状态的账号之上:付款资料、税务信息、开发者验证状态,任何一项出问题,收入链条会在最不该断的时候断掉。KappS 做的是准备并提交合规材料、维护账号与发布状态,让这些前置条件不再成为变量。

  • 账号与付款资料一致性:开发者身份、付款资料与实际收款主体对齐,避免结算周期卡在信息不一致上。
  • 税务与地区配置核对:W-8BEN/W-9、预扣税率与目标市场是否匹配,避免上线后才发现净收入与预期差一截。
  • 配置复核:基础方案、优惠资格与客户端读取逻辑的第二双眼睛——尤其是多商品、多地区、多语言并行的产品矩阵。

我们不提供任何绕过平台规则的服务:订阅价格与试用必须真实、优惠资格必须按 Play 的定义设置、购买必须能被服务器校验。这些既是规则要求,也是唯一能长期跑下去的做法。

资料来源(Google 官方文档):Play Console 帮助中心——创建与配置订阅、基础方案、优惠与资格、预付费方案;Android Developers——Play Billing 集成、订阅替换模式、服务器端校验、实时开发者通知。

正在规模化运营开发者账号?运维这一块交给我们。

点击选择文件 · 右键「粘贴」或按 Ctrl/⌘+V 直接粘贴截图

也可以直接拖拽文件到此处。

我们会回复你填写的邮箱,信息仅用于本次咨询。

✔ 已提交

我们已收到你的信息,会在 24 小时内回复。

也可发邮件给 expert@kapps.store
← 返回修改