Google Play
Kasskeep 用 Play Developer API 校验购买,替你完成确认(acknowledge)和消耗(consume),并通过 Pub/Sub 推送订阅接收实时开发者通知(RTDN)。渠道 id:google_play,平台:android。
1. 服务账号
Section titled “1. 服务账号”- 在 Google Cloud 控制台选一个项目,启用 Google Play Android Developer API。
- 在 IAM & Admin → Service accounts 下创建服务账号。它不需要任何 Cloud 角色。在 Keys → Add key 下创建 JSON 密钥并下载。
- 在 Play Console 打开 Users and permissions → Invite new users,填入服务账号邮箱,在 App permissions 下添加你的 App,并授予:
- View financial data, orders and cancellation survey responses;
- Manage orders and subscriptions。
- 权限最长可能要 24 小时才生效。在此之前 API 会返回 401 或 403。
- 上传密钥:
npx @kasskeep/cli apps update --id app_xxx --android-package com.example.app --google-service-account-file ./play-service-account.jsonJSON 里必须有 client_email 和 private_key。整个文件会加密保存;GET .../credentials 只返回 client email、项目 id 和私钥指纹。
2. 实时开发者通知
Section titled “2. 实时开发者通知”- 在 Google Cloud 控制台 Pub/Sub → Create topic,比如命名为
play-rtdn。 - 在主题的权限里,给
[email protected]授予 Pub/Sub Publisher 角色。 - 在主题上创建订阅:
- 投递类型选 Push,端点填
https://api.kasskeep.com/v1/stores/google/<app_id>/rtdn; - 启用 authentication,选一个服务账号(它的邮箱就是下面的 Pub/Sub 邮箱),并设置 audience。直接用端点地址作 audience 最省事。
- 投递类型选 Push,端点填
- 把 audience 和邮箱告诉 Kasskeep。两者都设置之前,RTDN 会返回 422:
npx @kasskeep/cli apps update --id app_xxx \ --google-pubsub-audience https://api.kasskeep.com/v1/stores/google/app_xxx/rtdn \- 在 Play Console 打开你的 App,进入 Monetize → Monetization setup → Real-time developer notifications,填入完整主题名
projects/<project>/topics/play-rtdn,发送一条测试通知。
一个主题可以有多个订阅,所以别的系统可以通过自己的订阅收到同样的通知。
每次推送如何校验
Section titled “每次推送如何校验”Authorization: Bearer里的 OIDC token 必须由 Google 签名、由accounts.google.com签发、未过期,aud等于配置的 audience,且已验证的email等于配置的邮箱。否则返回 401。- 消息里的
packageName必须等于 App 的android_package。否则返回 400。 - 消息按
messageId去重。通知只当作一个信号:Kasskeep 总是先从 API 拉取当前状态,再记录。 - 成功、重复和未知 token 返回 200。API 调用失败返回 502,处理出错返回 500,好让 Pub/Sub 重新投递。
Kasskeep 记录每笔购买后都会确认或消耗它。告诉它哪些一次性商品是消耗型的;末尾的 * 表示前缀匹配:
npx @kasskeep/cli apps update --id app_xxx --google-consumable-products "coins_*,gems_100"列表里的商品会被消耗,其他一次性商品按非消耗型确认。消耗型商品如果没列进去,就会被确认而非消耗,用户将无法再次购买。传这个参数会替换整个列表;传空字符串则清空。
确认失败会在后台重试,从 1 分钟后开始,间隔逐次翻倍,最长每 2 小时一次。3 天内未确认的购买会被 Google 退款,所以如果某笔购买的确认一直失败(通常是缺少 Play 权限),需要你去处理。
- 一次性商品:Play 商品 id 就是
product_id。请启用待处理购买(pending purchases)。待处理购买在完成之前不会被记录或确认。 - 订阅:订阅 id 就是
product_id。基础方案和优惠以data.base_plan_id和data.offer_id给出。如果不同周期对应的权限不同,请使用不同的订阅 id。 - 订阅购买只读取第一个 line item;不支持附加订阅(add-on)。
- 升级和降级:带
linkedPurchaseToken的新购买会合并到原有订阅,并保留它的original_transaction_id。
- Play Billing Library 8 或更高版本。把
obfuscatedAccountId设为用户 id。SDK 会替你做。 - 把
purchaseToken提交给 Kasskeep。不要在客户端确认或消耗。
| Google 状态 | status |
|---|---|
SUBSCRIPTION_STATE_ACTIVE |
active;关闭自动续订时为 canceled |
SUBSCRIPTION_STATE_CANCELED |
到期前为 canceled,之后为 expired |
SUBSCRIPTION_STATE_IN_GRACE_PERIOD |
grace_period |
SUBSCRIPTION_STATE_ON_HOLD |
billing_retry |
SUBSCRIPTION_STATE_PAUSED |
paused |
SUBSCRIPTION_STATE_EXPIRED、SUBSCRIPTION_STATE_PENDING_PURCHASE_CANCELED |
expired |
SUBSCRIPTION_STATE_PENDING |
不记录 |
已作废(voided)或 SUBSCRIPTION_REVOKED |
revoked |
Kasskeep 还会每小时读取一次 Voided Purchases API(首次回溯 7 天,最多 30 天),并重新检查快到期的订阅,以及处于宽限期、保留期(on hold)或暂停状态的订阅。