PAYATHON 2026

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
subscriptionIdSkuDetails.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 客户端直接调用。通常按以下流程处理:

  1. 客户端通过 Billing Client 完成购买。
  2. 客户端将 product ID、purchase token 和必要的用户关联信息发送到业务服务器。
  3. 服务器调用 Android Publisher API 验证购买状态。
  4. 服务器根据验证结果授予或撤销订阅权益。

如果使用较新的 purchases.subscriptionsv2.get 接口,其参数结构与旧版接口不同,通常通过 purchase token 查询订阅状态,不能直接套用旧版 purchases.subscriptions.get 的参数说明。

备注:内容仅供参考。