您当前的位置:首页 > 互联网百科 > 百科

简单 3 步配置 Google Play Billing

时间:2020-09-03 15:59:21  来源:  作者:
 

 

作者 / Caren Chang, Android Engineer

google Play Billing 系列内容是专门为中文开发者开辟的系列分享,着重讲解中国开发者对 Play Billing 最容易感到疑惑的地方。如果您有任何问题,也欢迎在留言区提出,我们会收集大家的反馈并在后续文章中做出解答。

 

销售数字内容是许多 Android 应用的主要营收渠道。具体形式包括销售应用内的特定商品 (如游戏金币) 以及订阅计划 (比如允许用户在限定时间内访问高级功能)。Google Play Billing 作为一个数字内容销售的工具和服务的集合,可以帮助开发者在 Android 应用中销售线上商品。

 

本文将从基础知识开始,带大家逐步深入,详细了解 Google Play Billing 3,及其用例和最佳实践。

 

首先,我们来熟悉一下 Google Play Billing 的一些关键组件。

  • Google Play 管理中心 (Google Play Console) - Google Play 管理中心既是 Android 应用发布平台,也可以用于设置应用中销售的各种内容。在 Play 管理中心可以配置待出售的商品,包括价格点,以及针对每个产品进行高级配置,如提供订阅的免费试用期;
  • Google Play Billing Library - 这是您集成到 Android 应用中的开发库。使用此库连接 Google Play 就可以执行各种与销售相关的任务,例如在用户购买商品时处理购买流程;
  • Google Play Developer API - 一组 REST API,可用于与 Google Play 通信。使用这些 API 可以查询和管理应用销售的商品。这些 API 还可以验证用户的购买中是否存在欺诈行为,或者检查订阅是否仍处于有效状态。
Google Play 管理中心
https://developer.android.google.cn/distribute/console
Google Play Billing Library
https://developer.android.google.cn/google/play/billing/billing_library_overview
Google Play Developer API
https://developers.google.cn/android-publisher

 

了解了 Google Play Billing 的关键组件之后,我们将从头介绍如何设置环境并开始在 Android 应用中销售商品。

1. 设置 Android 应用使用 Google Play Billing 开发库

第一步,也是最重要的一步,是设置 Android 应用以使用 Google Play Billing 开发库。

App/build.gradle 文件中添加以下依赖关系,在应用中实现 Google Play Billing:

implementation ‘com.android.billingclient:billing:3.0.0’

添加库依赖关系后,为应用构建一个发布版 APK,并将其上传到 Google Play 管理中心。

 

2. 添加应用内产品

 

上传 APK 后,可以使用 Google Play 管理中心开始添加要在应用中销售的应用内产品。在 "商店发布 (Store Presence)" 下,有一个设置应用内产品的部分。在这里可以设置两种类型的商品:

  • 托管产品 (或一次性购买)
  • 订阅

创建新的托管产品和订阅时,需要输入商品的产品 ID (Product ID) 或 SKU。这个产品 ID 后续将在应用代码中使用,我们稍后会讲到。在创建托管产品之前,应慎重规划产品 ID。产品 ID 在应用中必须唯一,并且在创建后无法更改或重复使用。

简单 3 步配置 Google Play Billing

 

为了使测试更快、更简单,您可以将您的 Google 帐号添加到 Google Play 开发者帐号的 "许可测试 (License Testing)" 中。这样,只要软件包名称与 Play Store 中的 APK 匹配,就可以使用调试版本和调试签名进行测试。

将 Google 帐号添加到 Google Play 开发者帐号的 "许可测试 (License Testing)"  中
https://developer.android.google.cn/google/play/billing/billing_testing#testing-purchases

 

3. 检查设置是否成功

在 Play 管理中心中设置好产品后,您可以在应用中查询产品的详细信息来检查设置是否成功。

 

lateinit private var billingClient: BillingClient
override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   // Set up the billing client
   billingClient = BillingClient
      .newBuilder(this)
      .enablePendingPurchases()
      .setListener(this)
      .build()
   billingClient.startConnection(object : BillingClientStateListener {
      override fun onBillingSetupFinished(billingResult: BillingResult) {
         if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
            Log.i(TAG, "Billing client successfully set up")
            queryOneTimeProducts()
         }
      }
      
      override fun onBillingServiceDisconnected() {
         Log.i(TAG, "Billing service disconnected")
      }
   })
}
private fun queryOneTimeProducts() {
   val skuListToQuery = ArrayList<String>()
   skuListToQuery.add("coins_5")
   // ‘coins_5’ is the product ID that was set in the Play Console.
   // Here is where we can add more product IDs to query for based on
   // what was set up in the Play Console.
   val params = SkuDetailsParams.newBuilder()
   params
      .setSkusList(skuListToQuery)
      .setType(BillingClient.SkuType.INAPP)
   // SkuType.INAPP refers to 'managed products' or one time purchases.
   // To query for subscription products, you would use SkuType.SUBS.
   billingClient.querySkuDetailsAsync(
      params.build(),
      object : SkuDetailsResponseListener {
         override fun onSkuDetailsResponse(
            result: BillingResult?,
            skuDetails: MutableList<SkuDetails>?
         ) {
            Log.i(TAG, "onSkuDetailsResponse ${result?.responseCode}")
            if (skuDetails != null) {
               for (skuDetail in skuDetails) {
                  Log.i(TAG, skuDetail.toString())
               }
            } else {
               Log.i(TAG, "No skus found from query")
            }
         }
      })
}

 

如果一切顺利,您将会看到刚刚添加进 Play 管理中心的产品的详细信息!

 

4. 接入 Google Play Billing 开发库

下一步,便是如何在您的 Android 应用中接入 Google Play Billing 开发库。

本文将以一次性购买的生命周期为例,即在应用中销售数字商品及授予用户的过程。如果您在应用中提供了订阅功能,您也可以阅读往期文章《订阅取消后的那些事儿——恢复订阅和重新订阅》了解更复杂生命周期的订阅流程。

 

一次性产品可以是消耗品,也可以是非消耗品。消耗品意味着用户可以再次购买。例如,如果您的游戏允许用户购买金币,您可以将金币做成消耗品,让用户可以多次购买。非消耗品意味着用户只能购买一次,典型示例是包含额外应用内功能的升级包。

 

在 Google Play 管理中心配置应用内产品后,其销售过程如下:

简单 3 步配置 Google Play Billing

 

让我们逐步分析这一过程。

1. 设置 BillingClient - BillingClient 类让您的应用可以与 Play Billing Library 进行通信。您的应用需要做的第一件事是调用 startConnection() 与 Google Play 建立连接。

startConnection()
https://developer.android.google.cn/reference/com/android/billingclient/api/BillingClient#startconnection


在实际环境中连接是有可能中断的,所以您的应用还必须重写 onBillingServiceDisconnected() 回调来处理重新连接,确保应用在发出任何进一步请求之前已与 Google Play 连接。

onBillingServiceDisconnected()
https://developer.android.google.cn/reference/com/android/billingclient/api/BillingClientStateListener#onBillingServiceDisconnected()

 

onBillingServiceDisconnected()
https://developer.android.google.cn/reference/com/android/billingclient/api/BillingClientStateListener#onBillingServiceDisconnected()

 

2. 获取用户的既有购买记录 - 成功设置 BillingClient 后,您的应用现在可以调用queryPurchases() 来查询用户先前的购买记录。

/**
 * Query Google Play Billing for existing purchases.
 *
 * New purchases will be provided to PurchasesUpdatedListener.
 */
fun queryPurchases() {
    if (!billingClient.isReady) {
        Log.e(TAG, "queryPurchases: BillingClient is not ready")
    }    // Query for existing in app products that have been purchased. This does NOT include subscriptions.
    val result = billingClient.queryPurchases(BillingClient.SkuType.INAPP)
    if (result.purchasesList == null) {
        Log.i(TAG, "No existing in app purchases found.")
    } else {
        Log.i(TAG, "Existing purchases: ${result.purchasesList}")
    }
}

 

3. 呈现待售产品 - 在本文的前半部分我们谈到了如何在 Google Play 管理中心中设置产品以及如何在应用中查询这些产品。在调用 querySkuDetailsAsync() 获取每个产品的 SkuDetails 后,即可使用这些信息设置对应的界面。

private fun queryOneTimeProducts() {
    val skuListToQuery = ArrayList<String>()
    // sku refers to the product ID that was set in the Play Console
    skuListToQuery.add("small_pineapple_seed")
    val params = SkuDetailsParams.newBuilder()
    params
        .setSkusList(skuListToQuery)
        .setType(BillingClient.SkuType.INAPP)
    // SkuType.INAPP refers to 'managed products' or one time purchases
    // To query for subscription products, you would use SkuType.SUBS
    billingClient.querySkuDetailsAsync(
        params.build(),
        object : SkuDetailsResponseListener {
            override fun onSkuDetailsResponse(
                result: BillingResult,
                skuDetails: MutableList<SkuDetails>?
            ) {
                if (skuDetails != null) {
                    // Store sku and skuDetail to be used later
                } else {
                    Log.i(TAG, "No sku found from query")
                }
            }
        })
}

 

querySkuDetailsAsync()
https://developer.android.google.cn/reference/com/android/billingclient/api/BillingClient#queryskudetailsasync
SkuDetails
https://developer.android.google.cn/reference/com/android/billingclient/api/SkuDetails

 

4. 启动购买流程 - 当用户点击产品进行购买时,您的应用需要带上产品 SkuDetails 来调用launchBillingFlow(),从而向用户展示 Google Play 购买界面 (如下图所示)。

简单 3 步配置 Google Play Billing

 

fun launchPurchaseFlow(skuDetails: SkuDetails) {
    val flowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)        .build()    val responseCode = billingClient.launchBillingFlow(this, flowParams)
    Log.i(TAG, "launchPurchaseFlow result ${responseCode}")
}
launchBillingFlow()
https://developer.android.google.cn/reference/com/android/billingclient/api/BillingClient#launchbillingflow

 

5. 处理购买结果 - 在用户退出 Google Play 购买界面时 (点击 "购买" 按钮完成购买,或者点击 "返回" 按钮取消购买),onPurchaseUpdated() 回调会将购买流程的结果发送回您的应用。然后,根据 BillingResult.responseCode 即可确定用户是否成功购买产品。如果 responseCode == OK,则表示购买已成功完成。

 

  • onPurchaseUpdated()
https://developer.android.google.cn/reference/com/android/billingclient/api/PurchasesUpdatedListener#onPurchasesUpdated(com.android.billingclient.api.BillingResult,%20JAVA.util.List%3Ccom.android.billingclient.api.Purchase%3E)
  • BillingResult.responseCode
https://developer.android.google.cn/reference/com/android/billingclient/api/BillingClient.BillingResponseCode

 

onPurchaseUpdated() 会传回一个 Purchase 对象列表,其中包括用户通过应用进行的所有购买。每个 Purchase 对象都包含 sku、purchaseToken 和 isAcknowledged 以及其他很多字段。使用这些字段,您可以确定每个 Purchase 对象是需要处理的新购买还是不需要进一步处理的既有购买。

// Google Play calls this method to propogate the result of the purchase flow
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase?>?) {    if (billingResult.responseCode == OK && purchases != null) {
        for (purchase in purchases) {
            handlePurchase(purchase)        }    } else if (billingResult.responseCode == USER_CANCELED) {
        Log.i(TAG, "User cancelled purchase flow.")
    } else {
        Log.i(TAG, "onPurchaseUpdated error: ${billingResult?.responseCode}")
    }}

 

  • Purchase
https://developer.android.google.cn/reference/com/android/billingclient/api/Purchase

 

6. 验证和确认购买 - 使用 Play Billing Library 3.0 时,您的应用需要确认购买成功才能完成购买流程。如果您的应用未在 72 小时内确认购买,则用户会自动收到退款,并且 Google Play 会撤消该购买交易

 

如果您的应用包含验证服务器组件,您应在验证成功后再确认购买。我们强烈推荐开发者对所有的应用内购买进行验证。请查看本指南了解有关打击欺诈性购买的更多信息。

 

指南: 打击欺诈和滥用行为
https://developer.android.google.cn/google/play/billing/security#verify

 

在对购买进行验证之后,您还需要对其进行确认。

  • 非消耗品必须通过调用 acknowledgePurchase() 进行确认;
  • 消耗品必须通过调用 consumeAsync() 来标记为 "已消耗 (consumed)",使得用户可以再次购买。调用 consumeAsync() 还会将购买设置为已确认,因此只要调用了consumeAsync(),就无需再对消耗品调用 acknowledgePurchase()。
fun handlePurchase(purchase: Purchase) {
    // If your app has a server component, first verify the purchase by checking that the
    // purchaseToken hasn't already been used.
    // If purchase was a consumable product (a product you want the user to be able to buy again)
    handleConsumableProduct(purchase)
    // If purchase was non-consumable product
    handleNonConsumableProduct(purchase)
}
fun handleConsumableProduct(purchase: Purchase) {
    val consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build()
    billingClient.consumeAsync(consumeParams, { billingResult, purchaseToken ->
        if (billingResult.responseCode == BillingResponse.OK) {
            // Handle the success of the consume operation.
        }
    })
}
fun handleNonConsumableProduct(purchase: Purchase) {
    if (purchase.purchaseState == PURCHASED) {
        if (!purchase.isAcknowledged) {
            val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                .setPurchaseToken(purchase.purchaseToken)
            billingClient.acknowledgePurchase(acknowledgePurchaseParams.build())
        }
    }
}

 

acknowledgePurchase()
https://developer.android.google.cn/reference/com/android/billingclient/api/BillingClient#acknowledgepurchase
consumeAsync()
https://developer.android.google.cn/reference/com/android/billingclient/api/BillingClient#consumeasync

 

7. 授予用户产品 - 完成上述步骤后,您的应用就可以向用户授予他们购买的应用内产品了!

如果您想查看 Google Play Billing 开发库的资源,可以在此处访问官方文档。我们还提供了一些示例,演示了实现 Billing 库的最佳实践。本文中的代码示例可以在 GitHub 上获取。

 

官方文档: Google Play Billing 服务概览https://developer.android.google.cn/google/play/billing/billing_overview
Play Billing 开发库示例
https://github.com/android/play-billing-samples
本文中的代码示例
http://github.com/calren

 

如果您的应用目前尚未使用 Play Billing Library 3,务必查看我们的迁移指南,将您的应用迁移到最新的 Play Billing Library。

从 AIDL 迁移到 Google Play Billing 开发库的迁移指南
https://developer.android.google.cn/google/play/billing/migrate

 

简单 3 步配置 Google Play Billing

 

 

文章转载自:谷歌开发者公众号原创文章



Tags:Google Play Billing   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
销售数字内容是许多 Android 应用的主要营收渠道。具体形式包括销售应用内的特定商品 (如游戏金币) 以及订阅计划 (比如允许用户在限定时间内访问高级功能)。Google Play Billing 作为一个数字内容销售的工具和服务的...【详细内容】
2020-09-03  Tags: Google Play Billing  点击:(67)  评论:(0)  加入收藏
▌简易百科推荐
在互联网的江湖里头,每天都有新鲜事。我们昨天还在聊元宇宙,还没有了解元宇宙是个啥,今天又开始了web3.0,站在时代的浪潮之巅,哪怕我们只是一滴最普通的水,也会随着巨浪此起彼伏,直...【详细内容】
2021-12-24  程序员老王聊科技    Tags:Web3.0   点击:(6)  评论:(0)  加入收藏
社交媒体营销的好处: 我们可以使用社交媒体来定义企业的品牌标识以及提供的产品或服务。 社交媒体可以和不了解我们产品和服务的人群建立关系。 社交媒体可以和用户完成互动...【详细内容】
2021-12-22  搜索引擎和短视频推广    Tags:社交媒体   点击:(12)  评论:(0)  加入收藏
之前我们讲到说,有些网站在复制的时候会提示一个弹窗,我们可以去掉网站的copy事件监听就可以了,但是我们经常用到的一个网站,百度文库,网站不是这样设计的。 可以随便打开一个百...【详细内容】
2021-12-03  追风Office    Tags:百度文库   点击:(9)  评论:(0)  加入收藏
都说现在的年轻人网上冲浪有三大痛点:听歌被版权拒之门外,看剧被超前点播劝退,网盘下载文件被无情限速。不巧,这些痛点我刚好都经历过,手机里光是这些类型的APP都有好几个,这不是...【详细内容】
2021-11-11  黑科技工具圈    Tags:网盘   点击:(46)  评论:(0)  加入收藏
今天跟大家分享9个珍藏已久的网站,满满的黑科技,保证看完会让你感觉发现了新大陆,下面一起来看看吧。1.国际空间站模拟器这个网站满满的科技感,它在线真实模拟了宇宙飞船对接国...【详细内容】
2021-11-01  职场办公技能    Tags:网站   点击:(32)  评论:(0)  加入收藏
好用的网站能够受益一生,一些优质的网站用起来的确可以这样说。今天分享6个资源丰富的网站,质量杠杠的。 1.【字由网】推荐理由:免费商用字体、字体库 当工作中需要制作海报或...【详细内容】
2021-10-27  小杰好厉害呀    Tags:资源网站   点击:(18)  评论:(0)  加入收藏
终于准备离开网络了吗?如果您正在阅读本文,则您的个人信息很可能会向公众公开。我所说的“公共”是指任何地方的每个人。那么,如何将自己从互联网上删除以阻止公司获取您的信...【详细内容】
2021-10-27  编程老妖    Tags:互联网   点击:(24)  评论:(0)  加入收藏
经过上次会议的"洗礼",郝自信对于职场"黑话"已经有了一定的了解和学习,这次会议他表现如何呢? 播放视频看来,黑话作为职场通用语,不仅能让经验丰富的职场人彼此心照不宣,也能让一...【详细内容】
2021-10-26    计算机世界  Tags:互联网   点击:(26)  评论:(0)  加入收藏
从开始分享软件工具到现在,询问百度网盘名不限速下载的问题就没有间断过,看来大家也是苦百度网盘已久,本文咱们就分享一下百度网盘不限速下载的方法。 文章比较长,实际上操作...【详细内容】
2021-10-25  网创智慧库    Tags:百度网盘   点击:(525)  评论:(0)  加入收藏
我们使用电脑查询或寻找素材时,会去浏览器搜索,搜索结果五花八门,要花时间去筛选。但如果去对应的网站搜索,那就方便多了,今天分享6个资源超多的网站,个个都是精品。 【办公资源网...【详细内容】
2021-10-21  小杰好厉害呀    Tags:网站   点击:(28)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条