实现应用内购买结算

官方连接

Google Play 上的应用内购买结算提供了一个直接、简单的界面,让您可以使用 Google Play 发送应用内购买结算请求和管理应用内购买结算交易。 下面的信息涵盖了如何使用 API 版本 3 从您的应用调用应用内购买结算服务的基本知识。

:要查看完整实现并了解如何测试您的应用,请参阅出售应用内商品培训课程。 培训课程提供了一个完整的示例应用内购买结算应用,包括多种工具类,便于处理关键任务(例如设置您的连接、发送购买结算请求和处理来自 Google Play 的响应以及管理后台线程),这样您就可以从主 Activity 调用应用内购买结算。

开始前,请务必阅读应用内购买结算概览,以便熟悉一些概念,使您能够轻松实现应用内购买结算。

要在您的应用中实现应用内购买结算,您需要执行以下操作:

  1. 将应用内购买结算库添加到您的项目中。
  2. 更新您的 AndroidManifest.xml 文件。
  3. 创建 ServiceConnection 并将其绑定到 IInAppBillingService
  4. 从您的应用发送应用内购买结算请求至IInAppBillingService
  5. 处理来自 Google Play 的应用内购买结算请求响应。

将 AIDL 文件添加到您的项目中


IInAppBillingService.aidl 是一种定义应用内购买结算版本 3 服务接口的 Android 接口定义语言 (AIDL) 文件。 您可以使用此接口通过调用 IPC 方法调用来发送结算请求。

要获取 AIDL 文件,请执行以下操作:

  1. 打开 Android SDK 管理器。
  2. 在 SDK 管理器中,展开 Extras 部分。
  3. 选择 Google Play Billing Library
  4. 点击 Install packages 完成下载。

IInAppBillingService.aidl 文件将安装到 <sdk>/extras/google/play_billing/

要将 AIDL 添加到您的项目,请执行以下操作:

  1. 首先,下载 Google Play Billing Library 到您的 Android 项目:

    1. 选择 Tools > Android > SDK Manager
    2. 在 Appearance & Behavior > System Settings > Android SDK 下面,选择 SDK Tools 标签以选择并下载 Google Play Billing Library
  2. 接下来,复制 IInAppBillingService.aidl 文件到您的项目。
    • 如果您使用的是 Android Studio,请执行以下操作:

      1. 导航至 Project 工具窗口中的 src/main
      2. 选择 File > New > Directory,然后在 New Directory 窗口中输入 aidl,再选择 OK
      3. 选择 File > New > Package,然后在 New Package 窗口中输入 com.android.vending.billing,再选择 OK
      4. 使用您的操作系统文件资源管理器,导航至 <sdk>/extras/google/play_billing/,复制 IInAppBillingService.aidl 文件,然后将其粘贴到项目中的 com.android.vending.billing 软件包。
    • 如果您在非 Android Studio 环境中开发,请执行以下操作:创建目录 /src/com/android/vending/billing,并将 IInAppBillingService.aidl 文件复制到此目录。 将 AIDL 文件添加到您的项目中并使用 Gradle 工具构建项目,从而生成 IInAppBillingService.java 文件。
  3. 开发您的应用。您会在项目的 /gen 目录中看到名为 IInAppBillingService.java 的生成文件。

更新您的应用清单


应用内购买结算依赖于 Google Play 应用,后者将处理应用与 Google Play 服务器之间的所有通信。 要使用 Google Play 应用,您的应用必须请求适当的权限。 您可以通过将 com.android.vending.BILLING 权限添加到 AndroidManifest.xml 文件执行此操作。 如果您的应用未声明应用内购买结算权限,但试图发送结算请求,Google Play 将拒绝请求并使用错误响应。

要为您的应用授予必要的权限,请在 AndroidManifest.xml 文件中添加以下代码行:

<uses-permission android:name="com.android.vending.BILLING" />

创建 ServiceConnection


您的应用必须拥有 ServiceConnection 才能实现应用与 Google Play 之间的通信。 您的应用至少需要执行以下操作:

  • 绑定到 IInAppBillingService
  • 发送结算请求(作为 IPC 方法调用)至 Google Play 应用。
  • 处理每个结算请求返回的同步响应消息。

绑定到 InAppBillingService

要在 Google Play 上与应用内购买结算服务建立连接,请实现 ServiceConnection,以便将您的 Activity 绑定到 IInAppBillingService。 建立连接后,重写 onServiceDisconnected 和 onServiceConnected 方法以获取 IInAppBillingService 实例的引用。

IInAppBillingService mService;ServiceConnection mServiceConn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {mService = null;}@Overridepublic void onServiceConnected(ComponentName name,IBinder service) {mService = IInAppBillingService.Stub.asInterface(service);}
};

在您 Activity 的 onCreate 方法中,通过调用 bindService 方法执行绑定。 向方法传递引用应用内购买结算服务的 Intent 和您创建的一个ServiceConnection 实例,并明确地将 Intent 的目标软件包名称设置为 com.android.vending — Google Play 应用的软件包名称。

注意:要保护结算交易的安全性,请始终确保使用下面示例中所示的 setPackage() 明确地将 Intent 的目标软件包名称设置为 com.android.vending。 明确地设置软件包名称能够确保只有 Google Play 应用可以处理来自您的应用的结算请求,从而防止其他应用拦截这些请求。

@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent serviceIntent =new Intent("com.android.vending.billing.InAppBillingService.BIND");serviceIntent.setPackage("com.android.vending");bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
}

现在,您可以使用 mService 引用来与 Google Play 服务通信。

重要说明:完成您的 Activity 后,请务必与应用内购买结算服务解除绑定。 如果不解除绑定,开启的服务连接会导致您的设备性能下降。 此示例说明了如何通过重写 Activity 的 onDestroy 方法对到应用内购买结算的服务连接 mServiceConn 执行解除绑定操作。

@Override
public void onDestroy() {super.onDestroy();if (mService != null) {unbindService(mServiceConn);}
}

如需了解绑定到 IInAppBillingService 的服务连接的完整实现,请参阅出售应用内商品培训课程和相关示例。

发起应用内购买结算请求


将应用连接到 Google Play 后,您可以对应用内商品发送购买请求。 Google Play 为用户进入他们的付款方式提供了一个结账界面,这样您的应用就无需直接处理付款交易。 在商品被用户购买后,Google Play 会识别用户拥有此商品,并在此商品被消耗前阻止用户购买具有相同商品 ID 的另一商品。 您可以控制如何在应用中消耗商品,并通知 Google Play 该商品可供再次购买。 您也可以查询 Google Play,以便快速地检索用户的购买列表。 这样十分有用,例如,非常适合您希望在用户启动应用时恢复用户购买的情况。

查询可供购买的商品

在您的应用中,可以使用 In-app Billing Version 3 API 从 Google Play 查询商品详情。 要将请求传递至应用内购买结算服务,首先需要创建一个包含商品 ID 字符串 ArrayList 的 Bundle,该字符串带有键“ITEM_ID_LIST”,每个字符串是可购买商品的商品 ID。

ArrayList<String> skuList = new ArrayList<String> ();
skuList.add("premiumUpgrade");
skuList.add("gas");
Bundle querySkus = new Bundle();
querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);

要从 Google Play 检索此信息,请在 In-app Billing Version 3 API 上调用 getSkuDetails 方法,然后将 In-app Billing API 版本(“3”)、发起调用的应用的软件包名称、商品类型(“应用内”)以及您创建的 Bundle 传递给方法。

Bundle skuDetails = mService.getSkuDetails(3,getPackageName(), "inapp", querySkus);

如果请求成功,返回的 Bundle 将包含响应代码 BILLING_RESPONSE_RESULT_OK (0)。

警告:请不要在主线程上调用 getSkuDetails 方法。 调用此方法会触发网络请求,进而阻塞主线程。 请创建单独的线程并从该线程内部调用getSkuDetails 方法。

要从 Google Play 查看所有可能的响应代码,请参阅应用内购买结算参考。

查询结果将保存在带有键 DETAILS_LIST 的字符串 ArrayList 中。购买信息存储在 JSON 格式的字符串中。 要查看返回的商品类型详细信息,请参阅应用内购买结算参考。

在此示例中,您将从之前代码段返回的 skuDetails Bundle 中检索您的应用内商品的价格。

int response = skuDetails.getInt("RESPONSE_CODE");
if (response == 0) {ArrayList<String> responseList= skuDetails.getStringArrayList("DETAILS_LIST");for (String thisResponse : responseList) {JSONObject object = new JSONObject(thisResponse);String sku = object.getString("productId");String price = object.getString("price");if (sku.equals("premiumUpgrade")) mPremiumUpgradePrice = price;else if (sku.equals("gas")) mGasPrice = price;}
}

购买商品

要从您的应用发起购买请求,请在应用内购买结算服务上调用 getBuyIntent 方法。 将 In-app Billing API 版本(“3”)、发起调用的应用的软件包名称、要购买商品的商品 ID、商品类型(“应用内”或“订阅”)以及 developerPayload 字符串传递给方法。 developerPayload 字符串用于指定您想要 Google Play 随购买信息一同发送的任何其他参数。

Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),sku, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");

如果请求成功,返回的 Bundle 将包含响应代码 BILLING_RESPONSE_RESULT_OK (0) 和您可以用于开始购买流程的 PendingIntent。 要从 Google Play 查看所有可能的响应代码,请参阅应用内购买结算参考。 接下来,请使用键 BUY_INTENT 从响应 Bundle 中提取 PendingIntent

PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");

要完成购买交易,请调用 startIntentSenderForResult 方法并使用您创建的 PendingIntent。 在此示例中,您将任意值 1001 用于请求代码。

startIntentSenderForResult(pendingIntent.getIntentSender(),1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0),Integer.valueOf(0));

Google Play 会将对您 PendingIntent 的响应发送至应用的 onActivityResult 方法。 onActivityResult 方法将获得结果代码 Activity.RESULT_OK (1) 或Activity.RESULT_CANCELED (0)。要查看响应 Intent 中返回的订单类型信息,请参阅应用内购买结算参考。

订单的购买数据是 JSON 格式的字符串,将映射到响应 Intent 中的 INAPP_PURCHASE_DATA 键,例如:

'{"orderId":"GPA.1234-5678-9012-34567","packageName":"com.example.app","productId":"exampleSku","purchaseTime":1345678900000,"purchaseState":0,"developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ","purchaseToken":"opaque-token-up-to-1000-characters"}'

:Google Play 会为购买生成令牌。此令牌是不透明的字符序列,最长可为 1,000 字符。 将整个令牌传递至其他方法(例如在您消耗购买时,如消耗购买中所述)。 不要省略或者截断此令牌,您必须保存并返回整个令牌。

继续前面的示例,您将从响应 Intent 获得响应代码、购买数据和签名。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == 1001) {int responseCode = data.getIntExtra("RESPONSE_CODE", 0);String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");if (resultCode == RESULT_OK) {try {JSONObject jo = new JSONObject(purchaseData);String sku = jo.getString("productId");alert("You have bought the " + sku + ". Excellent choice,adventurer!");}catch (JSONException e) {alert("Failed to parse purchase data.");e.printStackTrace();}}}
}

安全性建议:在您发送购买请求时,请创建一个可以对此购买请求进行唯一标识的字符串令牌并在 developerPayload 中包含此令牌。您可以将随机生成的字符串作为令牌。 从 Google Play 接收到购买响应时,请确保检查返回的数据签名、orderId 和 developerPayload 字符串。 为了增强安全性,您应在自己安全的服务器上执行检查。 请确保验证 orderId 为您之前未处理的唯一值,且 developerPayload 字符串与您之前通过购买请求发送的令牌相匹配。

查询已购买商品

要从您的应用检索用户所发起购买的相关信息,请在应用内购买结算版本 3 服务上调用 getPurchases 方法。 将 In-app Billing API 版本(“3”)、发起调用的应用的软件包名称以及商品类型(“应用内”或“订阅”)传递给方法。

Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);

Google Play 服务仅会返回由当前登录设备的用户帐户发起的购买。 如果请求成功,返回的 Bundle 将包含响应代码 0。响应 Bundle 也会包含商品 ID 列表、每个购买的订单详情列表以及每个购买的签名。

为了提升性能,第一次调用 getPurchase 时,应用内购买结算服务仅会返回由用户拥有的最多 700 个商品。 如果用户拥有大量商品,Google Play 会在响应 Bundle 中包含映射到键 INAPP_CONTINUATION_TOKEN 的字符串令牌,以表明可以检索更多的商品。 然后,您的应用可以进行后续 getPurchases 调用,并将此令牌作为参数传递。 Google Play 会继续在响应 Bundle 中返回继续令牌,直到用户拥有的所有商品都发送到您的应用。

如需了解有关由 getPurchases 返回的数据的详细信息,请参阅应用内购买结算参考。 下面的示例说明了如何从响应中检索此数据。

int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {ArrayList<String> ownedSkus =ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");ArrayList<String>  purchaseDataList =ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");ArrayList<String>  signatureList =ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");String continuationToken =ownedItems.getString("INAPP_CONTINUATION_TOKEN");for (int i = 0; i < purchaseDataList.size(); ++i) {String purchaseData = purchaseDataList.get(i);String signature = signatureList.get(i);String sku = ownedSkus.get(i);// do something with this purchase information// e.g. display the updated list of products owned by user}// if continuationToken != null, call getPurchases again// and pass in the token to retrieve more items
}

消耗购买

您可以使用 In-app Billing Version 3 API 跟踪在 Google Play 中购买的应用内商品的所有权。 应用内商品一经购买,就会被视为“被拥有”且无法从 Google Play 购买。 您必须对应用内商品发送消耗请求,然后 Google Play 才能允许再次购买。

重要说明:可以消耗托管的应用内商品,但不能消耗订阅。

如何在应用中使用消耗机制取决于您。通常情况下,您可以对用户想要购买多次、能够提供短期效益的应用内商品实现消耗(例如,游戏中使用的货币或设备)。 您通常不必对仅供购买一次和具有永久效应的应用内商品实现消耗(例如,高级版升级)。

要记录购买消耗,请将 consumePurchase 方法发送到应用内购买结算服务并在标识要移除购买的 purchaseToken 字符串值中传递。 purchaseToken 是由购买请求成功后 Google Play 服务在 INAPP_PURCHASE_DATA 字符串中所返回数据的一部分。 在此示例中,您会将使用 purchaseToken 标识的商品的消耗记录在 token 变量中。

int response = mService.consumePurchase(3, getPackageName(), token);

警告:请不要在主线程上调用 consumePurchase 方法。 调用此方法会触发网络请求,进而阻塞主线程。 请创建单独的线程并从该线程内部调用consumePurchase 方法。

您负责控制和跟踪如何向用户配置应用内商品。 例如,如果用户购买了游戏内货币,您应使用购买的货币金额更新玩家的库存。

安全性建议:您必须首先发送消耗请求,才能向用户配置可消耗的应用内购买商品。 确保已从 Google Play 接收到成功的消耗请求,然后再配置商品。

实现订阅

启动订阅的购买流程与启动商品的购买流程相似,不同之处是商品类型必须设置为“订阅”。 购买结果会传送至您 Activity 的onActivityResult 方法,与应用内商品的情况完全一样。

Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",MY_SKU, "subs", developerPayload);PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT);
if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {// Start purchase flow (this brings up the Google Play UI).// Result will be delivered through onActivityResult().startIntentSenderForResult(pendingIntent, RC_BUY, new Intent(),Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
}

要查询有效订阅,请使用 getPurchases 方法,并将商品类型参数设置为“订阅”。

Bundle activeSubs = mService.getPurchases(3, "com.example.myapp","subs", continueToken);

调用会返回 Bundle,其包含由用户拥有的所有有效订阅。 如果订阅到期且不续订,将不会出现在返回的 Bundle 中。

保证您的应用安全


为了确保发送到您应用的交易信息的完整性,Google Play 会签署包含购买订单响应数据的 JSON 字符串。 Google Play 会使用 Developer Console 中与您的应用关联的私钥来创建此签名。 Developer Console 会为每个应用生成一个 RSA 密钥对。

:要找到此密钥对的公钥部分,请在 Developer Console 中打开应用的详细信息,然后点击 Services & APIs,并查看命名为 Your License Key for This Application 的字段。

由 Google Play 生成的以 Base64 编码的 RSA 公钥为二进制编码,格式为 X.509 subjectPublicKeyInfo DER SEQUENCE。 它与 Google Play 许可使用的公钥相同。

当您的应用接收到带签名的响应后,您可以使用 RSA 密钥对的公钥部分验证签名。通过执行签名验证,您可以检测到被篡改或假冒的响应。 您可以在应用中执行此签名验证步骤;不过,如果您的应用是连接到安全的远程服务器,我们建议您在该服务器上执行签名验证。

Google Play_SDK(官方API)相关推荐

  1. Google离线地图API概要解析

    Google离线地图API概要解析 发布时间:2018-01-17 版权: 1.说明 离线地图发布有多种方式均可以实现,可以利用ArcGis Server.GeoServer等构建地图Web服务器,还 ...

  2. google chrome 官方下载安装的方法和离线包官方下载

    Google浏览器官方已经不能访问了,第三方的软件很多都是经过别人修改后,有的甚至有木马程序,前几天我从abobe推广下载的Google浏览器,都卡的不能上网,其他第三方的可见一斑,或许得看手气吧,但 ...

  3. Google Static Maps API

    Google Static Maps API概述 Google Maps提供了强大的地图调用函数.对于普通用户来说,须要了解一定的JavaScript语法,才可以完全使用Google Maps所提供的 ...

  4. Google中国地图API应用

    <script type="text/javascript"></script> <script src="http://pagead2.g ...

  5. Google Guava官方教程(中文版)gu

    Google Guava官方教程(中文版) 原文链接  译文链接 译者: 沈义扬,罗立树,何一昕,武祖  校对:方腾飞 引言 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库, ...

  6. Google Web 字体 API 访谈

    对很多纠结于字体的 Web 设计与开发者而言,昨天有关 Google Font API 的新 闻 着实让他们高兴了一回,这个非常简单实用的 API 包含了一套字体库 和预览工具 ,结合 Google ...

  7. 使用Youtube官方API获取频道及视频数据

    2020-06-04更新 下面附上笔者提供的源码(已经验证过功能.后续会在同一个工程中更新Facebook和Insgram的相关爬虫代码). https://github.com/zhangjz777 ...

  8. Google Maps Android API v2官网例子使用说明

    2019独角兽企业重金招聘Python工程师标准>>> 1.安装Google Play services SDK Google Maps SDK已经作为Google Play ser ...

  9. Google Maps Android API V2的使用及问题解决

    Google Maps Android API V2的使用及问题解决 参考文章: (1)Google Maps Android API V2的使用及问题解决 (2)https://www.cnblog ...

  10. Google Maps Android API V2使用及问题解决

    这一段时间因为毕设题目是:android版的google地图,所以目前在公司忙里偷闲,弄弄毕设,学习学习google android地图的使用 1. 目前google已经不再提供Google Maps ...

最新文章

  1. 香港居民换领新智能身份证 市民对办理过程表满意
  2. c语言循环结构程序设计视频,第13讲:循环结构程序设计1
  3. 八十五、store数据,actionCreators 与 constants 的拆分和redux-immutable的使用
  4. abp模块生命周期设计思路剖析
  5. [剑指offer][JAVA]面试题第[12]题[矩阵的路径][DFS][剪枝]
  6. 金税盘怎么安装在电脑上_金税盘处于锁死期不能开票怎么办?
  7. 迷恋猫爆红,彰显区块链 NFT 巨大魔力!
  8. GOF业务场景的设计模式-----责任链模式
  9. 【Google Play】Google Play 签名维护 ( 签名机制 | Google Play 签名机制选择 | 签名更新 )
  10. 八、PyQt5绘图技术
  11. Linux下 QT中 log4cplus 最基本配置及使用
  12. 安装tensorflow报错
  13. c语言循环上机题,c语言循环结构上机习题
  14. 036-2018-1028 线程 效率对比 数据共享 同步锁死锁递归锁 守护线程 信号量
  15. 【Web技术】959- JavaScript 如何在线解压 ZIP 文件?
  16. 1D/2D/3D卷积详解
  17. 开源操作系统读《移动互联网白皮书》有感
  18. 模拟退火算法实现寻找函数最值
  19. 计算机主机电源键,怎么才能让电脑按关机键不关机?让电脑主机上关机键失效的方法...
  20. Web服务技术与应用

热门文章

  1. 微信公众号 手机充值 html,怎么实现通过微信公众号给会员卡充值?
  2. go 代理加速配置详解
  3. creo管道设计教程_Pro/E Pro/PIPING 管道设计教程|就上UG网
  4. js输入关键词生成标签代码
  5. 全球互联网排名_全球互联网的梦想已死
  6. Web3.0究竟是什么?
  7. echarts盒须图颜色填充
  8. sentencepiece原理与实践
  9. Android TabLayout基本使用及完美调整指示器位置的技巧
  10. 第979期机器学习日报(2017-05-24)