应用内结算简介
一、概述
使用应用内结算(In-app Billing)时,我们的应用通过相应的API来访问In-app Billing服务。应用不直接与Google Play服务器通信,而是通过进程间通信(IPC)向Google Play发送结算请求并接收Google Play返回的响应。
In-app Billing在使用之前需要注意以下几点:
- 只能用来销售数字内容,不能销售实体商品
- 应用一旦被购买,无法进行退款服务 Google
- Play不提供内容交付,开发者需要自行交付在应用内购买的数字内容
- 一个应用不能购买另一个应用发布的商品
目前使用的In-app Billing是第3版,需要运行在Android2.2或更高版本,而且要求设备安装了最新版本的Google Play商店。第三版支持两种商品:托管的应用内商品(Managed product)和订阅(Subscription)。
托管的应用商品:由Google Play跟踪和管理其所有权信息的商品,托管的商品在被购买后,必须先向Google Play发送消耗请求进行消耗,然后才能供用户再次购买。
订阅:允许开发者通过按月或按年结算的方式在应用内向用户销售内容、服务或功能,订阅无法消耗。
二、Google Play购买流程
购买开始时,应用需要针对相应的应用内商品发送结算请求。然后,Google Play 会处理此次交易的所有结帐详情,包括请求和验证付款方式以及处理财务交易。
当结帐流程完成后,Google Play 会向应用发送购买详情,例如订单号、订单日期和时间以及所付价格。应用不需要处理任何财务交易,这些事宜完全Google Play负责。
具体流程如下所示:
- 应用向Google Play发送isBillingSupported 请求,确定当前使用的应用内结算 API 目标版本是否受支持;
- 启动或用户登录时,向Google Play进行查询,确定用户拥有哪些商品,发送getPurchases 请求;
- 通知用户商品是否可供购买,发送getSkuDetails 请求;
- 提示用户购买,发送getBuyIntent 请求。
三、消耗托管的应用内商品
应用内商品一经售出,就会被视为“被拥有”。处于“被拥有”状态的应用内商品无法再通过 Google Play 购买。必须对“被拥有”的应用内商品发送消耗请求,然后 Google Play 才能再次将其设成可购买状态。消耗应用内商品会将商品切换回“未被拥有”状态并删除之前的购买数据。
通过发送consumePurchase 提出消耗请求。
接入之前的准备
一、在 Google Play Developer Console 创建应用
- 注册一个开发者账号,按提示绑定信用卡并支付25美金;
- 创建一个新的app,填写应用名称;
- 点击上图中的Prepare Store Listing,按照提示填写app的基本信息,信息一定要填写完整,否则无法正常发布应用;
- 在Services & APIs中,找到license key记录下来。
二、添加In-app Billing库文件(以Android Studio为例)
- 在yourSDKpath/extras/google/market_billing/中找到文件IInAppBillingService.aidl,在src/main中创建文件夹aidl,然后创建package‘com.android.vending.billing’ 如图所示
- 点击执行rebuild,在下图所示位置看到IInAppBillingService.java文件,即为导入成功
- 将market_billing/samples/TrivialDrive 中util包整个复制到项目中。
三、声明权限
在AndroidManifest.xml中声明权限:
<uses-permission android:name="com.android.vending.BILLING" />
- 1
四、初始化与Google Play的连接
1、初始化IabHelper
IabHelper mHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
String base64EncodedPublicKey;
// compute your public key and store it in base64EncodedPublicKey
mHelper = new IabHelper(this, base64EncodedPublicKey);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2、调用startSetup方法
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
@Override
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
Log.e(TAG, "Problem setting up In-app Billing: " + result);
}
if (mHelper == null) {
return;
}
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
3、在Activity的onDestory()中解绑
@Override
protected void onDestroy() {
super.onDestroy();
if (mHelper != null) {
mHelper.dispose();
}
mHelper = null;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
创建应用内购买的商品
一、上传APK并发布
进入APK面板,上传一个带有签名的APK文件,文件可以上传到PRODUCTION、BETA TESTING、ALPHA TESTING中任意一个中,三者区别见附录1。下面的流程以BETA测试为例。
- 进入BETA TESTING页面,上传带有签名的APK文件;
- 进入Content Rating页面,填写内容分级调查问卷,填完进行评估,根据结果接受评估或者重新填写;
- 进入Pricing&Distribution页面,选择应用是付费还是免费,之后选择产品要发布的国家和地区;
- 确保如图所示四个内容都显示为绿色对勾,即可发布应用;
- 点击Publish app发布,如果按钮显示为灰色,可以点击按钮上方的Why can’t I publish?查看还需要添加的内容,应用发布之后需要等候几个小时。在任一页面可以查看App的发布状态,如左图所示为正在发布,右图显示已经发布成功。
二、选择测试方法(BETA测试为例)
待APP发布完成之后,选择一个测试方法,测试方法有三种(详见附录),此处以封闭式Beta测试为例。
- 登录Google Play开发者控制台
- 选择相应应用,点击左侧菜单中的APK
- 选择Beta测试,进入“封闭式测试“
- 创建列表或选择已有列表
- 将Opt-in URL中链接发送给测试人员
- 测试人员需要点击测试连接并选择加入测试
注意:测试时可以选择测试账号是否需要真实支付。比如应用在进行大范围测试时,需要用户可以进行真实的付款操作,而内部测试人员可以进行支付测试,但无需真实付款。可以将内部测试的账号配置到Google Play后台。
配置如下:
将账号填入下图
三、创建商品
- 点击左侧菜单中“In-app Products”,选择”Add new Product“
- In-app Billing第3版支持类型为’Managed product’和’Subscription’的商品
- 配置product ID时要保证product ID是唯一的,product ID也叫做SKU,product ID在查询商品和购买商品时需要用到
- 带商品信息填写完成,将其状态置为active
客户端相关内容实现
客户端实现具体内容详见官方Demo,此处只简单举例说明(示例代码不全,参照Demo)。
一、查询商品详情
通过创建商品时添加的product ID,可以在客户端查询商品的详情,调用queryInventoryAsync(boolean, List, QueryInventoryFinishedListener)
- boolean:是否返回商品详情(此处应设置为true)
- List:要查询的product IDs(SKUs)
- QueryInventoryFinishedListener:监听查询结果
如果查询成功,返回结果封装在Inventory 对象中。
代码示例:
List<String> productNameList = new ArrayList<>();
productNameList.add(PRODUCT_ONE);
productNameList.add(PRODUCT_TWO);
mHelper.queryInventoryAsync(true, productNameList, new IabHelper.QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
String price = inventory.getSkuDetails(PRODUCT_ONE).getPrice();
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
二、购买托管的商品
购买商品时也需要product ID,调用launchPurchaseFlow(Activity, String, int, OnIabPurchaseFinishedListener, String)
- Activity:调用launchPurchaseFlow的activity
- String:product ID,确保是ID而不是商品名称
- Int:request code值,可以是任何正整数,Google Play会将该值随购买的回复一起返回给Activity的onActivityResult
- OnIabPurchaseFinishedListener:购买请求完成的监听器
- String:字符串标记,惟一的标示购买请求,可以为空。如果你指定一个字符串值,谷歌将返回此字符串以及购买响应。在实际项目中最好由服务器随机生成一个字符串使用
如果购买成功,返回结果封装在Purchase 对象里。
类型为‘Managed product’的商品可以重复购买,但再次购买之前一定要先向Google Play发送商品消耗的请求,否则无法购买。
代码示例:
mHelper.launchPurchaseFlow(this, productId, REQUEST_CODE, new IabHelper.OnIabPurchaseFinishedListener() {
@Override
public void onIabPurchaseFinished(IabResult result, Purchase info) {
}
}, "XXXXXXX");
- 1
- 2
- 3
- 4
- 5
- 6
三、购买订阅内容
在购买订阅内容时,调用的方法与购买托管的商品不一样,强行调用同一个方法,会在确认购买时接收到Google Play返回的错误信息。
调用launchSubscriptionPurchaseFlow(Activity, String, int,OnIabPurchaseFinishedListener, String), 参数解释参照2中内容。
代码示例:
mHelper.launchSubscriptionPurchaseFlow(this, productId, REQUEST_CODE, new IabHelper.OnIabPurchaseFinishedListener() {
@Override
public void onIabPurchaseFinished(IabResult result, Purchase info) {
}
}, "purchase subscription");
- 1
- 2
- 3
- 4
- 5
- 6
四、查询已购买商品
查询用户已经购买的商品,调用queryInventoryAsync(QueryInventoryFinishedListener)
注意:查询已购买商品时,查询到的是当前登录到Google Play上的用户已购买到的商品。
代码实例:
mHelper.queryInventoryAsync(new IabHelper.QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result, Inventory inv) {
}
});
- 1
- 2
- 3
- 4
- 5
- 6
五、消耗托管的商品
一旦一个商品被购买,它将被认为是“被拥有”状态,处于该状态下的商品无法被同一用户再次购买。因此需要发送根据需求向Google Play发送消耗请求,调用consumeAsync(Purchase, OnConsumeFinishedListener)
- Purchase:要消耗的商品
- OnConsumeFinishedListener:消耗完成之后的监听
代码示例:
mHelper.consumeAsync(purchase, new IabHelper.OnConsumeFinishedListener() {
@Override
public void onConsumeFinished(Purchase purchase, IabResult result) {
}
});
- 1
- 2
- 3
- 4
- 5
- 6
测试注意事项
由于配置比较复杂,在项目测试的时候,如果遇到“应用无法购买”的问题,请检查以下几点是否完成:
- 确保上传了带有签名的APK文件;
- 确保设备上安装了带有签名的APK,而不是调试版;
- 确保在测试中添加了测试人员;
- 确保设备登录的账号属于测试账号;
- 确保测试账号激活了测试链接(最容易忽略);
- 确保设备上的应用版本号和版本名称与Google开发者后台上传的APK一致;
- 确保商品状态为Active。
参考文档:
http://developer.android.com/intl/zh-cn/google/play/billing/index.html
http://developer.android.com/intl/zh-cn/training/in-app-billing/index.html
附录:Alpha/Beta 版测试
Google为开发者提供了Alpha和Beta两个版本进行测试,开发者不必有正式版APK就可以发布Alpha/Beta应用。Alpha/Beta测试不会影响到线上正式发布的应用,因为只有测试组的用户才会收到Alpha/Beta版本的更新。如果没有正式版的应用,那么只有测试组的用户才可以找到并下载应用。
一、Alpha/Beta版本
使用Alpha/Beta测试时,需要保证测试版APK的版本号高于正式版APK的版本号。
注意:
- Alpha版APK需要具有高于Beta 版 APK的版本号才能供Alpha版测试人员使用;
- 如果上传的Beta版APK高于Alpha版,则Alpha版将会自动停用;
- 如果上传的正式版APK高于Alpha/Beta版,则Alpha/Beta版将会自动停用;
- Alpha用户可以测试Alpha、Beta和正式版,Beta用户可以测试Beta和正式版。
二、不同的测试方法(以Beta为例)
1、封闭式Beta版测试
使用封闭式Beta测试,可以按电子邮件创建Beta测试人员列表,测试用户必须拥有Google账号(@gmail.com)或Google Apps账户才能加入测试。
列表创建完成之后,需要将Opt-in URL中链接发送测试人员,待测试人员使用测试账号访问该链接激活测试账号,才可以正常测试。Opt-in URL只有在应用状态为“已发布”时才会显示。
2、开放式Beta版测试
无需指定电子邮件地址或创建 Google网上论坛或 Google+社群。适用于大范围测试。与封闭式测试相同,将发布之后的链接发送给测试人员,待激活之后即可开始测试。
3、使用Google网上论坛或Google+社群执行封闭式Beta版测试
通过添加Google网上论坛电子邮件地址或Google+社群网址进行链接分享。测试人员必须加入添加的Google网上论坛或Google+社群才可以加入Beta测试,测试之前也需要激活测试账号。
关于Alpha/Beta版本测试详情以及分阶段发布,可以参照Google官方文档:
https://support.google.com/googleplay/android-developer/answer/3131213?hl=zh-Hans