内购(IAP)
FRVR.iap 在 Google Play、Facebook Instant、Apple iAP 等渠道计费后端之上做抽象。你描述一份目录,各渠道会把你的产品 ID 映射到自家商店。
声明商品目录
Section titled “声明商品目录”- 键(
COINS_100)是你自己代码里用的。 storeId是当前渠道商店里这个商品的名字。label是 UI 上展示用的人类可读名(没有现成的就用它)。
FRVR.init() 之后、第一次引导 tick 之后,目录就绪:
价格/币种来自底层商店。请用它们 —— 不要硬编码价格。
错误类型:
| 错误 | 含义 |
|---|---|
IAPPurchaseErrorCancelledByUser | 用户关掉了支付窗口。这不是要弹给用户看的错误。 |
IAPPurchaseErrorAlreadyOwned | 该账号已拥有该耐用品。 |
IAPPurchaseErrorUnknownProduct | 产品 ID 错误。 |
IAPPurchaseErrorInProgress | 另一笔购买还在进行中。 |
IAPPurchaseErrorPopupBlocked | 浏览器拦截了结账窗口。没有扣款。 |
IAPPurchaseErrorPending | 玩家已付款,但支付尚未确认。不要发货。 |
IAPPurchaseErrorHeldByEconomy | 由 consumePurchase 抛出:FRVR 的 economy 仍在结算这笔购买。不要发货。 |
IAPError | 兜底通用错误。看 .code。 |
这些错误都继承自 IAPError,所以通用的 catch 照常可用。每个错误的 err.name 也等于它的类名;当错误可能来自另一个 bundle 时,用它判断更稳妥。
Web 上的购买
Section titled “Web 上的购买”web 渠道通过 FRVR 的 Web 支付 provider 销售:Google Pay、Apple Pay 和银行卡结账。有多个可用时,SDK 会让玩家选择。和商店购买相比有几点不同:
- **在点击或触摸的回调里直接调用
purchase()。**游戏运行在其他网站的 iframe 里时,结账会在新窗口打开;浏览器拦截它时会以IAPPurchaseErrorPopupBlockedreject。请玩家再试一次。 - **结账关闭时支付可能还未确认。**这时
purchase()以IAPPurchaseErrorPendingreject(err.pending === true)。告诉玩家商品稍后到账。确认之后,这笔购买会从getUnconsumedPurchases()返回:在那里发货并消耗。 - **玩家可能需要先登录。**SDK 会自己打开登录界面,然后继续购买。
- 银行卡结账的价格含税。
getProductById()返回的这些商品带有taxIncluded: true,玩家实付金额就是显示的价格。
要自己绘制支付按钮,先读取可选项,再把玩家选的那个传进去:
消耗品 vs. 耐用品
Section titled “消耗品 vs. 耐用品”消耗品(金币、宝石)可以反复购买。发完物品后,要消耗这笔购买,商店才会放开让用户再次购买:
耐用品(去广告、角色皮肤)永远不消耗。在新设备上重新发放:
从崩溃中恢复
Section titled “从崩溃中恢复”如果你的 App 在购买与发货之间崩了,商店会把收据保留为待处理状态。每次启动时:
哪怕用户在购买中途强杀了 App,这一步也能把闭环兜回来。
如果 consumePurchase() 以 IAPPurchaseErrorHeldByEconomy reject,跳过这笔购买,不要发货。FRVR 的 economy 服务正在结算它,会在之后的启动中完成。
onReady 可能触发不止一次。玩家在会话中途登录了另一个账号时,SDK 会再调用它一次,让游戏恢复该账号的购买:
确保这个回调执行两次也没问题。
dev 渠道自带一份模拟目录和一条假的购买流程。可以试一下买 → 消耗 → 恢复。
IAP:目录、购买、消耗、恢复
loading SDK…
API 摘要
Section titled “API 摘要”| 方法 | 作用 |
|---|---|
isReady() / onReady(cb) | provider 是否就绪。账号变化后 onReady 会再次触发。 |
getCatalog() | 按你定义的 ID 列出所有商品。 |
getProductById(id) | 单个商品,含商店价格。 |
purchase(id, meta?, options?) | 发起结账。resolve 出收据。options.provider 可跳过支付方式选择。 |
getPurchaseOptions() | 玩家可选的支付方式。 |
consumePurchase(purchase) | 把消耗品标记为已发放。 |
restorePurchases() | 重新派发用户拥有的耐用品。 |
getUnconsumedPurchases() | 未完成的消耗品 —— 启动时调用以恢复。 |
errors.* | 用 instanceof 判定的错误类。 |