Flutter中如何用package:in_app_purchase实现单IAP对应多个可购道具
解决方案
首先明确核心结论
- 不需要给
in_app_purchase包提Issue,该场景的支持能力已经完备,也不是包的特性缺失:苹果、谷歌原生IAP SDK本身就没有预留专门的自定义业务数据传参入口,现有applicationUsername字段就是官方提供的用来关联业务侧数据的标准实现。
推荐实现方案(业内通用标准方案,完美解决你提到的所有问题)
利用PurchaseParam自带的applicationUsername字段做唯一标识关联,步骤如下:
- [a]位置(发起购买前)
先调用自有业务后端生成预购订单,订单内存储用户ID、待发放道具ID、订单状态(初始为待支付),后端返回全局唯一的订单号。将订单号赋值给PurchaseParam的applicationUsername属性后再发起购买:
final purchaseParam = PurchaseParam( productDetails: product.productDetails, applicationUsername: 后端返回的订单号, // 新增这一行即可 ); await iapConnection.buyConsumable(purchaseParam: purchaseParam);
- [b]位置(处理购买回调时)
回调返回的PurchaseDetails对象会原样带回你之前传入的applicationUsername值,拿这个值去业务后端查询对应的预购订单,就能直接拿到待发放的道具ID,后续走发道具、更新订单状态逻辑即可。
该方案解决你提到的三个痛点的逻辑
- 不需要维护复杂的本地待购队列:所有订单状态存在业务后端,就算App卸载重装、多设备切换,也可以通过后端拉取当前用户待处理的预购订单完成补发货,重试逻辑直接依赖后端订单状态即可,健壮性更高。
- 购买报错时也可精准匹配:即使
PurchaseStatus.error状态下没有purchase ID,也可以通过返回的applicationUsername将对应预购订单标记为失败,不会和其他待处理订单混淆。 - 和回调顺序无关:每笔购买回调都带唯一的订单号标识,不管回调返回顺序和发起顺序是否一致,都可以精准匹配对应道具,不会出现错发的问题。
可选轻量方案(仅适合不想提前调用后端生成订单的场景)
如果不想提前发起后端请求生成预购订单,也可以在本地生成全局唯一的随机字符串作为applicationUsername,同时将「随机字符串-待购道具ID」的映射关系同时存储在本地和业务后端,回调时用拿到的字符串查询映射关系即可,不过安全性和可靠性弱于预购订单方案。
内容的提问来源于stack exchange,提问作者kaboc
相关产品推荐
相关产品推荐

