android - 2020 年 5 月 Google 应用内购买集成工作示例
问题描述
这实际上不是一个问题。我花了一些时间在这上面,所以我在这里列出了进行应用内购买所涉及的步骤。
添加依赖项
//billing-client
implementation 'com.android.billingclient:billing:2.2.1'
implementation 'com.android.billingclient:billing-ktx:2.2.1'
在清单中添加了权限
- 在 Play Console 中创建应用程序。
- Play 管理中心 -> 设置 -> 定价模板 :: 添加的定价模板。
- 选择申请表控制台 -> 商店状态 -> 应用内产品 -> 托管产品 -> 创建托管产品。
- 对于测试,首先,您需要发布一个 Alpha 版本(在封闭轨道中注册了一些测试邮件 id。)
- 成功发布后,您可以使用相同的构建(可能需要相同的版本代码和版本号)(调试和发布都可以)来测试购买。
- 确保测试邮件 ID 是 google id (@gmail.com)
以下是我用于计费的代码片段。
implement PurchasesUpdatedListener, on fragment or activity
设置计费客户端
private fun setupBillingClient() {
billingClient = BillingClient.newBuilder(mainActivity)
.enablePendingPurchases()
.setListener(this)
.build()
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
// The BillingClient is setup
log("Setup Billing Done")
loadAllSKUs()
}
}
override fun onBillingServiceDisconnected() {
log("Failed")
}
})
}
加载所有 Skus(您的采购模板的 ID(使用 arraylist))
private fun loadAllSKUs() = if (billingClient.isReady) {
val params = SkuDetailsParams
.newBuilder()
.setSkusList(skuList)
.setType(BillingClient.SkuType.INAPP)
.build()
billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList ->
// Process the result.
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && skuDetailsList.isNotEmpty()) {
for (skuDetails in skuDetailsList) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && skuDetailsList.isNotEmpty()) {
this.skuDetailsList = skuDetailsList
}
}
}
}
} else {
log("Billing Client not ready")
}
使用 Google 付款
private fun invokeGooglePayPayment(skuDetails: SkuDetails) {
val billingFlowParams = BillingFlowParams
.newBuilder()
.setSkuDetails(skuDetails)
.build()
billingClient.launchBillingFlow(mainActivity, billingFlowParams)
}
如果您需要在同一个应用内购买项目上再次购买,您可以使用此代码,
override fun onPurchasesUpdated(
billingResult: BillingResult?,
purchases: MutableList<Purchase>?
) {
//todo remove this function only for token log
if (!purchases.isNullOrEmpty()) {
for (purchase in purchases) {
Log.e("Purchase Token" + purchase.purchaseToken, "OK")
}
}
if (billingResult?.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
for (purchase in purchases) {
acknowledgePurchase(purchase) // do after purchase
}
} else if (billingResult?.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
//todo
} else if (billingResult?.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
val consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken("inapp:${BuildConfig.APPLICATION_ID}:${selectedSkuDetails?.sku}")
.build()
runBlocking {
CoroutineScope(Dispatchers.IO).launch {
billingClient.consumePurchase(consumeParams)
}
MainScope().launch {
invokeGooglePayPayment(selectedSkuDetails!!)
}
}
}
}
解决方案
推荐阅读
- python - 在 pyodbc 中一次插入多行的比 executemany 更快的解决方案
- c# - 物联网中心资源的 Http 端点
- android - 根据样式更改背景色调
- jenkins - 如何在詹金斯作业 DSL groovy 脚本中设置构建监视器视图的列数?
- elasticsearch - 无法在 filebeat 配置中使用自定义索引
- enterprisedb - 使用 EDB*plus 从远程服务器调用 EDB 存储过程(具有输出参数)
- c++ - 通过在 argv[1] 中传递多个文件来读取它们
- ruby-on-rails - gem PgSearch 按名称查找错误的客户端
- python - python numpy - 无法比较2个数组
- vue.js - NUXT (production, extractCSS: true) 不会移除一些 Vue 包的内联样式