Flutter内购:如何获取稳定唯一标识,防止多账户滥用权限
解决Flutter非消耗型内购多账号滥用问题的方案
针对你遇到的in_app_purchase包中PurchaseID不稳定、导致多账号可通过恢复购买滥用付费权限的问题,给你几个不用RevenueCat的可行方案:
方案1:提取原生内购API的稳定交易标识
不同平台的内购API本身提供了稳定的交易标识,不需要依赖第三方服务:
- iOS端:非消耗型内购恢复购买时,原生
SKPaymentTransaction对象的originalTransaction字段会保留首次购买的交易记录,它的transactionIdentifier是固定不变的。你可以通过PurchaseDetails的skPaymentTransaction属性拿到这个原生对象,提取originalTransaction?.transactionIdentifier作为稳定标识存到Firestore。 - Android端:非消耗型内购的
Purchase对象里,purchaseToken是唯一且永久稳定的——不管用户恢复多少次购买,这个token都不会变。从PurchaseDetails的androidPurchase属性里就能拿到这个token,直接存下来就行。
用这个稳定标识替代PurchaseID,就能保证同一个用户的购买状态在不同设备、不同恢复操作下都能被正确识别。
方案2:绑定应用商店用户ID与Firebase账号
核心思路是让一个应用商店账号只能对应一个Firebase付费账号,从根源上防止滥用:
- iOS:如果用户用Apple ID登录,直接用
ASAuthorizationAppleIDProvider获取userIdentifier(这个ID是永久绑定用户Apple账号的);如果是其他登录方式,用SKCloudServiceController请求用户的CloudKit令牌(需要配置开发者token),拿到唯一的应用商店用户标识。 - Android:通过Google Play Services API获取当前登录的Google账号ID(比如
GoogleSignIn.getLastSignedInAccount(context)?.id),或者从BillingClient的回调里提取用户的Play Store账号标识。
在Firestore建一个app_store_user_bindings集合,存储{app_store_user_id: string, firebase_uid: string}的映射。用户购买或恢复购买时,先查这个集合:如果该应用商店用户ID已经绑定了其他Firebase UID,就拒绝标记当前账号为付费;如果没绑定,就把当前Firebase UID和它绑定,并标记付费状态。
方案3:后端验证购买凭证(最安全)
放弃直接存交易ID,改为每次购买/恢复后,把购买凭证发到后端(比如Firebase Functions)验证,验证通过再标记付费:
- iOS:从
SKPaymentQueue.default().appStoreReceiptURL读取收据文件,转成base64字符串后发送到Apple的官方验证接口,验证结果里会包含原始交易ID和用户的唯一标识。 - Android:把
purchaseToken和商品ID发送到Google Play的验证接口,接口会返回该购买的合法性以及对应的用户信息。
后端验证通过后,在Firestore里给对应的Firebase UID标记付费状态,同时记录该凭证对应的应用商店用户ID。这种方式既能确保购买是真实有效的,又能通过后端逻辑严格控制一个应用商店账号只能绑定一个Firebase账号,彻底杜绝滥用。
内容的提问来源于stack exchange,提问作者barbrady
相关产品推荐
相关产品推荐

