revenuecat-purchase-flow
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineserevenuecat-purchase-flow: buy a package and restore purchases
revenuecat-purchase-flow:购买套餐与恢复购买记录
Use this skill when the user wants to complete the purchase side of RevenueCat: fetch offerings, call , deal with cancellation and errors, and expose a "Restore" action. It does not cover rendering a paywall UI (that lives in ) or gating features (that lives in ).
purchaserevenuecat-paywallrevenuecat-entitlements-gate当用户需要完成RevenueCat的购买相关操作时使用此技能:获取产品服务、调用方法、处理取消操作与错误,并提供“恢复”功能。此技能不包含付费墙UI的渲染(该功能在中)或功能权限控制(该功能在中)。
purchaserevenuecat-paywallrevenuecat-entitlements-gate1. Detect the platform
1. 检测平台
Inspect the working directory and pick the first match, from top to bottom:
- React Native: has a
package.jsonentry, orreact-native-purchasesas a dependency → readreact-native. Ifplatforms/react-native.mdis also a dependency, note it as an Expo project.expo - Flutter: exists at the project root → read
pubspec.yaml.platforms/flutter.md - Kotlin Multiplatform: contains a
build.gradle.ktsmultiplatform source sets block, or depends onkotlin { … }→ readcom.revenuecat.purchases:purchases-kmp*.platforms/kmp.md - Android (native): applies
build.gradle(.kts)(and is not KMP) → readcom.android.application.platforms/android.md - iOS (native): ,
Package.swift,*.xcodeproj, or*.xcworkspaceat the project root → readPodfile.platforms/ios.md
If several match (e.g. an folder inside a Flutter project), pick the outermost project, the one that owns the build. If still ambiguous, ask the user which platform they want to configure.
ios/检查工作目录,从上到下选择第一个匹配项:
- React Native:中包含
package.json条目,或依赖react-native-purchases→ 查看react-native。如果同时依赖platforms/react-native.md,则标记为Expo项目。expo - Flutter:项目根目录存在→ 查看
pubspec.yaml。platforms/flutter.md - Kotlin Multiplatform:包含
build.gradle.kts多平台源码集块,或依赖kotlin { … }→ 查看com.revenuecat.purchases:purchases-kmp*。platforms/kmp.md - Android(原生):应用了
build.gradle(.kts)(且非KMP项目)→ 查看com.android.application。platforms/android.md - iOS(原生):项目根目录存在、
Package.swift、*.xcodeproj或*.xcworkspace→ 查看Podfile。platforms/ios.md
如果存在多个匹配项(例如Flutter项目内包含文件夹),请选择最外层的项目,即拥有构建权限的项目。若仍存在歧义,请询问用户需要配置哪个平台。
ios/2. Shared concepts (all platforms)
2. 通用概念(全平台)
- Flow. Call , pick a
getOfferings()from the current offering, callPackage. When it completes successfully, the returnedpurchase(package)already reflects the purchase. ReadcustomerInfoto confirm access.customerInfo.entitlements.active["<id>"] - User cancellation is not an application error. Each SDK surfaces it differently: iOS throws a code, Android throws a
purchaseCancelledErrorwithPurchasesException, Flutter surfaces aPurchasesErrorCode.PurchaseCancelledErrorwith that same code, React Native setsPlatformException. Return silently in this case. Do not show an alert.e.userCancelled === true - Errors worth messaging. Payment declined, network errors, store unavailable, receipt already in use. Everything else should be logged and let the user try again. Never silently succeed when the purchase actually failed.
- Do not unlock content inside the purchase callback. Refresh customer info and let your entitlements listener (see ) flip the gated UI. This keeps one source of truth for access and avoids drift between the purchase path and the restore path.
revenuecat-entitlements-gate - is a user action, not an automatic step. It asks the store for the current receipt and syncs it to RevenueCat. Expose it from a visible "Restore purchases" button on the paywall and/or settings screen. Legal requirements on iOS mandate such a button.
restorePurchases() - One purchase at a time. Disable the paywall buy buttons while a purchase is in flight to prevent double charges.
- 流程:调用,从当前产品服务中选择一个
getOfferings(),调用Package。操作成功完成后,返回的purchase(package)已反映购买情况。读取customerInfo确认访问权限。customerInfo.entitlements.active["<id>"] - 用户取消不属于应用错误:各SDK的表现形式不同:iOS抛出错误码,Android抛出带有
purchaseCancelledError的PurchasesErrorCode.PurchaseCancelledError,Flutter返回带有相同错误码的PurchasesException,React Native设置PlatformException。这种情况下应静默返回,不要显示提示框。e.userCancelled === true - 需要提示用户的错误:支付拒绝、网络错误、商店不可用、收据已被使用。其他所有错误应仅记录日志并允许用户重试。购买实际失败时绝不能静默标记为成功。
- 不要在购买回调中解锁内容:刷新客户信息,让权限监听器(参考)切换受权限控制的UI。这样可以保持访问权限的单一数据源,避免购买路径与恢复路径之间出现数据不一致。
revenuecat-entitlements-gate - 是用户主动操作,而非自动步骤:它会向商店请求当前收据并同步到RevenueCat。在付费墙和/或设置页面上提供一个可见的“恢复购买记录”按钮。iOS的法律要求强制提供此类按钮。
restorePurchases() - 同一时间仅处理一次购买:购买进行中时禁用付费墙的购买按钮,防止重复扣费。
3. Implementation
3. 实现
Read the platform file that matches detection:
platforms/ios.mdplatforms/android.mdplatforms/kmp.mdplatforms/flutter.mdplatforms/react-native.md
Each platform file contains a complete purchase function and a restore function.
查看与检测结果匹配的平台文件:
platforms/ios.mdplatforms/android.mdplatforms/kmp.mdplatforms/flutter.mdplatforms/react-native.md
每个平台文件都包含完整的购买函数和恢复函数。
4. Verify
4. 验证
Do not claim the flow works until:
- A sandbox purchase of the current offering's package succeeds end to end, and the user's entitlement flips to active.
- Cancelling the store sheet does not show an error alert and does not leave the UI in a loading state.
- A second purchase attempt for the same active subscription is handled cleanly (StoreKit / Play Billing will surface a /
productAlreadyPurchasedpath; the flow should not crash).receiptAlreadyInUse - The restore button, on a fresh install signed in to the same store account, restores the entitlement and updates the UI.
满足以下条件后才能确认流程可用:
- 当前产品服务套餐的沙箱购买能够端到端成功,且用户权限切换为激活状态。
- 取消商店界面不会显示错误提示框,也不会让UI停留在加载状态。
- 针对同一激活订阅的第二次购买尝试能够被正常处理(StoreKit/Play Billing会返回/
productAlreadyPurchased状态;流程不应崩溃)。receiptAlreadyInUse - 在全新安装的设备上登录同一商店账号,点击恢复按钮后能够恢复权限并更新UI。