You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何通过in_app_purchases检测用户已拥有的商品

问题结论

你需要实现的历史会话已购商品识别能力,确实属于恢复购买(Restore Purchases)的覆盖范畴,但官方示例只覆盖了实时购买的主流程,没有说明不同商品类型对应的已购校验逻辑,才会导致你找不到对应实现参考。
明确说:绝对不要在每次应用冷启动时无条件执行全量恢复购买操作,不管是App Store还是Google Play都对恢复购买接口有调用频率限制,高频触发会被限流拦截,且iOS端调用恢复购买会弹出系统级的Apple ID密码验证框,启动就弹窗会严重破坏用户体验。

分场景已购检测方案

根据你接入的内购商品类型不同,检测逻辑要分开处理:

  • 非消耗型商品、永久权限类商品
    这类商品用户一次购买终身有效,可通过两层逻辑校验已购状态:
    1. 触发全量恢复的时机仅保留三个:用户重装应用后首次启动、用户主动点击页面上的「恢复购买」按钮、用户切换应用内绑定的账号。此时调用restorePurchases()拉取全量历史有效交易,和本地权益做对齐,校验通过后为用户下发对应权限,同时将已购状态通过加密方式存在本地(不要用明文普通存储,避免被篡改绕过付费)。
    2. 日常应用启动、进入付费相关页面时,不需要调用全量恢复接口,直接读取本地缓存的已购状态即可;如果担心本地缓存被清理或状态异常,可以调用商店提供的轻量查询接口拉取当前有效交易:Android端调用queryPastPurchases(),iOS端先读取当前交易队列中未完成的有效交易即可,这类接口不会触发账号密码弹窗,也不会被限流,性能开销远低于全量恢复。
  • 消耗型商品、自动续期订阅类商品
    这类商品完全不能依赖客户端恢复购买接口判定权益状态:
    1. 消耗型商品在支付完成、权益发放后就会被标记为已核销,后续不会出现在恢复购买的返回列表里,必须在用户支付成功的第一时间将购买记录同步到自有服务端存储,本地仅做临时缓存。
    2. 自动续期订阅的状态是动态变化的(续费成功、用户取消订阅、订阅过期、订单退款),客户端恢复接口无法拿到实时的订阅状态,必须对接商店的服务端实时通知回调来同步订阅状态,客户端启动时直接拉取自有服务端的用户权益接口即可,不需要直接调用商店端的恢复接口。
实现注意事项
  • 所有从商店接口拿到的购买凭证(不管是实时购买还是恢复拉取的历史订单),都不要直接在客户端判定有效后就发放权益,最好把凭证传到自有服务端做二次校验,避免被伪造凭证绕过付费。
  • Android端的历史购买查询接口,默认仅返回未核销的非消耗型商品、处于有效期内的订阅,已过期的订阅、已核销的消耗品不会出现在返回结果中,不要依赖这个接口拉取全量历史订单。
  • 恢复购买流程处理完所有返回的交易记录后,必须要调用交易完成接口,否则对应交易会一直留在交易队列里,每次启动都会重复触发购买监听回调。

内容的提问来源于stack exchange,提问作者under

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:45:43