Google Play Developer API 的 subscriptionId 是什么?
结论
是的。对于在 Google Play Billing 中创建的订阅商品,SkuDetails.getSku() 返回的 productId,就是 purchases.subscriptions.get API 的 subscriptionId 参数。
subscriptionId 不是 Billing Client 返回的另一个 JSON 字段,而是服务端 API 对订阅商品 ID 的称呼。不同版本的 API 和 Billing Library 使用了不同术语:
- Billing Client 旧版:
SKU、SkuDetails.getSku() - Billing Client 新版:
productId、ProductDetails.getProductId() - Android Publisher API:
subscriptionId
在这里,这些名称都指 Google Play Console 中配置的订阅商品 ID,例如 monthly001。
调用时需要哪些参数
旧版 purchases.subscriptions.get 接口通常需要三个值:
packageName
subscriptionId
token
对应关系如下:
| API 参数 | 值的来源 |
|---|---|
packageName | 应用包名,例如 com.example.app |
subscriptionId | SkuDetails.getSku(),或新版 ProductDetails.getProductId() |
token | 用户完成购买后返回的 purchase token |
其中,subscriptionId 表示用户购买的订阅商品,token 对应这一次具体的订阅购买,packageName 则表示该订阅所属的 Android 应用。
订单号、base plan ID、offer ID 和 purchase token 都不能代替 subscriptionId。
Billing Client 旧版示例
使用旧版 SkuDetails 时,可以这样获取订阅商品 ID:
String subscriptionId = skuDetails.getSku();
购买完成后,还要从 Purchase 中获取 purchase token:
String purchaseToken = purchase.getPurchaseToken();
然后将这些值发送到自己的服务器:
JSONObject payload = new JSONObject();
payload.put("packageName", context.getPackageName());
payload.put("subscriptionId", skuDetails.getSku());
payload.put("purchaseToken", purchase.getPurchaseToken());
服务器使用服务账号凭据调用 Android Publisher API。Java 服务端的调用形式如下:
SubscriptionPurchase subscriptionPurchase =
androidPublisher
.purchases()
.subscriptions()
.get(packageName, subscriptionId, purchaseToken)
.execute();
假设 Play Console 中的订阅商品 ID 是 monthly001,最终传入的参数大致是:
packageName: com.example.app
subscriptionId: monthly001
token: <purchase-token>
Billing Client 新版示例
较新的 Google Play Billing Library 用 ProductDetails 代替了 SkuDetails,并使用 productId 这个名称:
String subscriptionId = productDetails.getProductId();
也可以从 Purchase 获取购买记录中的商品 ID。由于一次购买的数据结构可能包含多个商品 ID,需要根据实际购买项处理:
List<String> productIds = purchase.getProducts();
String subscriptionId = productIds.get(0);
String purchaseToken = purchase.getPurchaseToken();
即使列表通常只有一个元素,也不应在所有业务场景中直接默认取第一个。如果应用允许购物车、多商品,或者后续 Billing Library 改变相关行为,应按照实际商品逐项匹配。
为什么字段名称不一致
SkuDetails 内部 JSON 使用的是 productId:
{
"productId": "monthly001"
}
旧版 Billing Library 则通过 getSku() 方法返回这个值:
/** Returns the product Id. */
public String getSku() {
return mParsedJson.optString("productId");
}
Android Publisher API 将同一个值命名为 subscriptionId,因为该接口只处理订阅购买。名称不同,并不意味着还要查找另一个字段。
它们之间的关系可以写成:
SkuDetails.productId
= SkuDetails.getSku()
= ProductDetails.getProductId()
= purchases.subscriptions.get 的 subscriptionId
前提是这些值都对应 Google Play Console 中配置的同一个订阅商品。
注意事项
不要把 subscriptionId 与 purchase token 混淆
两者用途不同:
subscriptionId = monthly001
purchaseToken = 一段由 Google Play 返回的购买令牌
只有 subscriptionId 无法验证某个用户的购买。调用接口时,还必须提供对应的 purchase token。
不要使用订单号
下面这种 Google Play 订单号:
GPA.1234-5678-9012-34567
既不是 subscriptionId,也不能代替 purchase token。
区分订阅商品、base plan 和 offer
Google Play 的新订阅模型还包括:
- subscription product ID
- base plan ID
- offer ID
对于问题中的旧版 purchases.subscriptions.get 接口,subscriptionId 指订阅商品的 product ID,不是 base plan ID 或 offer ID。
优先在服务端验证
Android Publisher API 需要使用受保护的服务账号凭据,不应由 Android 客户端直接调用。通常按以下流程处理:
- 客户端通过 Billing Client 完成购买。
- 客户端将 product ID、purchase token 和必要的用户关联信息发送到业务服务器。
- 服务器调用 Android Publisher API 验证购买状态。
- 服务器根据验证结果授予或撤销订阅权益。
如果使用较新的 purchases.subscriptionsv2.get 接口,其参数结构与旧版接口不同,通常通过 purchase token 查询订阅状态,不能直接套用旧版 purchases.subscriptions.get 的参数说明。
备注:内容仅供参考。
