mcpField
R
rc-purchase-flow

rc-purchase-flow

github.com/revenuecat开发76648 次安装今天更新
代码仓库

关于 rc-purchase-flow

rc-purchase-flow 面向 Android 开发者,说明如何用 RevenueCat SDK 完成购买、读取权益并处理异常。内容还涵盖交易数据检查及重装或更换设备后的购买恢复。

主要功能

  1. 01从 Offering 获取购买套餐
  2. 02执行购买并按权益状态开放访问
  3. 03处理取消与交易异常
  4. 04查看交易级数据
  5. 05恢复已购内容并检查权益

适用场景

  1. 01在付费墙中购买订阅或一次性产品
  2. 02根据 CustomerInfo 控制高级功能访问
  3. 03将交易数据用于日志或自有后端
  4. 04在重装或换设备后恢复购买

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/revenuecat/ai-toolkit --skill rc-purchase-flow

安装后在 Claude Code 中输入/rc-purchase-flow确认已加载。

详细介绍

购买流程

在 Android 上,通过 RevenueCat 购买只需两行代码。SDK 会处理计费参数、Play 购买界面、购买令牌往返、服务端验证和确认。你只需决定传入哪个套餐,以及如何处理返回的权益。

阶段 1:了解 awaitPurchase() 的作用

调用一次 Purchases.sharedInstance.awaitPurchase(params),底层会执行六个步骤。你无需编写其中任何步骤。

步骤执行内容
1根据你的 Package,使用正确的 ProductDetailsParams 构建 BillingFlowParams
2针对你传入的 activity 调用 BillingClient.launchBillingFlow()
3挂起,直到收到 PurchasesUpdatedListener 的结果
4如果结果为 OK,则将 Play 购买令牌发送到 RevenueCat 后端
5后端通过 purchases.subscriptionsv2.get 或 purchases.products.get 进行验证
6SDK 会在 Google 规定的 3 天期限内确认(订阅或非消耗型商品)或消耗(消耗型商品)

该调用会返回 PurchaseResult(storeTransaction, customerInfo)。可重试的失败会自动重试。

如需查看六步流程图和完整说明,请参阅 revenuecat.com 上的购买流程章节。

阶段 2:准备套餐

购买前,你需要从 offerings 中获取一个 Package。获取 offerings,让 UI 选择一个套餐,并保留 activity。

val offerings = Purchases.sharedInstance.awaitOfferings()
val pkg = offerings.current?.monthly ?: return

如果你需要指定优惠,而不是使用默认优惠,请解析一个 SubscriptionOption,并将它传给 PurchaseParams.Builder,而不是传入套餐。

val option = pkg.product.subscriptionOptions
    ?.firstOrNull { it.tags.contains("promo_50_off") }
    ?: pkg.product.defaultOption
    ?: return

对于欧盟的个性化定价,请在构建器上链式调用 .isPersonalizedPrice(true),以便 Play 显示定制价格提示。

阶段 3:执行购买

构建参数,等待购买完成,读取 customerInfo 以控制访问权限,并处理两个预期的错误分支。

try {
    val result = Purchases.sharedInstance.awaitPurchase(
        PurchaseParams.Builder(activity, pkg).build()
    )
    val customerInfo = result.customerInfo
    if (customerInfo.entitlements["pro"]?.isActive == true) {
        navigateToApp()
    }
} catch (e: PurchasesTransactionException) {
    when {
        e.userCancelled -> { /* backed out, do nothing */ }
        e.error.code == PurchasesErrorCode.ProductAlreadyPurchasedError ->
            showMessage("You already have this subscription")
        else -> showError(e.error.message)
    }
}

此代码块的规则:

  • PurchaseResult 是 @Poko。请通过 result.customerInfo 和 result.storeTransaction 访问字段。不要使用 val (transaction, customerInfo) = result 解构。
  • customerInfo.entitlements["<id>"]?.isActive == true 是访问权限判断条件。不要检查 storeTransaction 来决定是否授予访问权限。
  • awaitPurchase 唯一会抛出的异常类型是 PurchasesTransactionException。请捕获该异常,先检查 userCancelled,再检查 e.error.code。
  • 用户取消不应作为错误提示。请忽略该情况。

如果你更喜欢使用回调而非协程,purchaseWith(params, onError, onSuccess) 是等效的入口。

阶段 4:仅在需要时检查 StoreTransaction

result.storeTransaction 可用,但通常不会用到。customerInfo 才是权益的事实来源。如果你需要交易级数据用于日志记录或自有后端:

字段类型说明
orderIdString?恢复的购买为 Null
purchaseTokenString原始 Play 购买令牌
productIdsList<String>交易中的商品 ID
purchaseTimeLongEpoch 毫秒
typeProductTypeSUBS 或 INAPP

阶段 5:重新安装或更换设备后恢复购买

恢复购买会运行 queryPurchasesAsync(),将找到的所有购买发送到 RevenueCat,并返回最新的 CustomerInfo。请像购买完成后一样控制访问权限。

try {
    val customerInfo = Purchases.sharedInstance.awaitRestore()
    if (customerInfo.entitlements["pro"]?.isActive == true) {
        navigateToApp()
    } else {
        showMessage("No active purchases found")
    }
} catch (e: PurchasesException) {
    showError(e.error.message)
}

请注意异常类型。awaitRestore() 会抛出 PurchasesException,而不是 PurchasesTransactionException。由于不会显示计费界面,因此无需检查 userCancelled 标志。

异常类型一览

调用抛出的异常是否包含 userCancelled?
awaitPurchase(params)PurchasesTransactionException是
awaitRestore()PurchasesException否

参考资料

评论

支持 Markdown