Defold 提供了方便的 iOS Appstore “in-app purchases” 和 Google Play 及 Amazon “in-app billing” 系统接口. Facebook Canvas 的 “game payments” 用于 Facebook Canvas 游戏. 这些服务能让你销售:
目前 Defold 接口可以与 Apple 的 Storekit 完整交互. 对于 Google Play 和 Facebook Canvas, 接口是一致的, 这有助于代码跨平台. 但是不同平台需要的流程有所不同. 而且注意目前没有针对 macOS 系统上 Mac Appstore 的支付接口.
关于 Apple, Google, Amazon 和 Facebook 的详细文档参考:
首先要在 game.project 文件中加入内支付扩展依赖. 最新稳定版本地址如下:
https://github.com/defold/extension-iap/archive/master.zip
推荐使用 正式发布版 的zip连接作为依赖引用.
其 API 文档详见 扩展项目首页.
Android 建议使用 Google Play 的静态报告来实现 IAP. 这样在正式发布之前就可以确保内支付工作正常. 测试用静态报告包括4个ID:
android.test.purchased
android.test.canceled
android.test.refunded
android.test.item_unavailable
iOS 和 Android 内支付的准备流程差不多:
为应用商店进行测试配置:
对于 Google Play, 你需要 上传并发布 测试版 .apk 文件. 对于 iTunes Connect, 直到应用审批之前你 不用上传 应用文件给 iTunes Connect. 加入上传了未完成的应用文件给 iTunes Connect, Apple 会拒绝该应用.
设置应用内消费品.
Facebook 内支付准备流程:
内支付 API 是异步的, 也就是说应用发送信息给服务器, 然后能继续运行. 等到从服务器传回的信息时, 一个 回调 函数会被调用, 从中可以根据回调数据进行各种处理工作.
获得消费品列表:
local COINS_ID = "com.defold.examples.coins"
local LOGO_ID = "com.defold.examples.logo"
local function product_list(self, products, error)
if error == nil then
for i,p in pairs(products) do
print(p.ident)
print(p.title)
print(p.description)
print(p.currency_code)
print(p.price_string)
end
else
print(error.error)
end
end
function init(self)
-- 初始化消费品列表 (对于 Google Play 来说一次能获取 20 个)
iap.list({ COINS_ID, LOGO_ID }, product_list)
end
对于正式交易, 首先要注册交易结果监听器, 然后在玩家购买时调用内支付函数:
local function iap_listener(self, transaction, error)
if error == nil then
if transaction.state == iap.TRANS_STATE_PURCHASING then
print("Purchasing...")
elseif transaction.state == iap.TRANS_STATE_PURCHASED then
print("Purchased!")
elseif transaction.state == iap.TRANS_STATE_UNVERIFIED then
print("Unverified!")
elseif transaction.state == iap.TRANS_STATE_FAILED then
print("Failed!")
elseif transaction.state == iap.TRANS_STATE_RESTORED then
print("Restored")
end
else
print(error.error)
end
end
function on_message(self, message_id, message, sender)
...
-- 注册内支付结果监听器.
iap.set_listener(iap_listener)
-- 买一个金币...
iap.buy(COINS_ID)
...
end
操作系统会自动弹出支付界面. 要是处于测试/沙盒环境下, 界面中会明确标明.
大多数付款系统都是实时的. 支付完成时应用会收到一个消息, TRANS_STATE_PURCHASED. 这是交易的最终状态, 表明对于这笔交易不会再有其他消息了.
有的付款系统需要非实时的支持. 也就是说你的应用只在付款开始时收到一个消息. 为了验证付款完成与否, 需要你的服务器 (或者客户端) 与付款系统进行更多的交流. 这种情况下支付完成时应用会收到一个 TRANS_STATE_UNVERIFIED 消息 (而不是 TRANS_STATE_PURCHASED). 这也是交易的最终状态, 表明对于这笔交易不会再有其他消息了.
玩家购买消费品之后, 应用有义务告知玩家支付已完成 (比如服务器验证支付成功之后).
内支付支持 auto-completion, 也就是自动产生支付完成的消息 (默认设置). 也可以在项目配置里关闭 auto-completion. 支付完成时手动调用 iap.finish()
, 来产生完成消息.
Google Play 应用商店只支持消耗品. 必须使用非消耗品的话就关闭 auto-completion 并且不要调用完成函数. 这样在 iap.set_listener()
被调用时, 消费品购买总是保持着购买中的状态.
Apple App Store 支持非消耗品, 也就是说购买完成时才向玩家提供消费品交付. 这种情况下 auto-completion 可以开启也可以关闭 (比如你需要自己验证支付成功) 之后调用 iap.finish()
.
收据是一堆加密数据, 可以把它发送给 App Store 来验证付款是否真正完成. 这是用开发者服务器验证付款必须使用的东西.
iap.list()
返回 “failed to fetch product”iap.list()
只返回 20 个消费品iap.list()
然后合并返回结果以实现20个以上的消费品列表.iap.list()
返回空值检查 “Member Center” 上的应用ID是否开启了 in-app purchases (检查 “Member Center” 里 “Certificates, Identifiers & Profiles” 的 “Enabled Services:” 项) 并且该应用 (或者调试版应用) 已用供应商档案进行了签名而且签名没过期.
内支付消费品信息传到沙盒环境需要几小时时间, 请耐心等待.
iap.list()
产生错误日志 “Unexpected callback set”iap.list()
调用不可以嵌套. 从 iap.list()
调用 iap.list()
就会产生这个错误日志.iap.list()
返回的数据使用 不间断空白 (\u00a0
) 分割价格和货币符号并填充 “price_string” 变量. 使用 GUI 组件渲染的话, 需要在字体 extra_characters 属性里设置所需字符. 在 macOS 上按 Option + SPACE 就是不间断空白. 详情请见 http://en.wikipedia.org/wiki/Non-breaking_space.Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB