原文链接:http://www.mobile-open.com/2016/966337.html

因为公司需要接入Google的应用内支付(即Google的in-app Billing V3),接入过程中查阅了很多的文章,也遇到很多的问题。故此想和大家分享及交流一下心得,好了废话不多说了下面我们开始接入google的应用内支付。

第一步:准备工作

首先想要使用google的支付,首先必须要有一部安装了google play服务的测试机,在这里提供了三个方法:

1)如果有小米的测试机最好因为小米的系统完整的保留了google play服务.

2)如果没有可以看下此处附上的连接:http://zhidao.baidu.com/link?url=qDozAoR_-mlZrVAp6oxLdcyR6uscgdDTsN2Z8PWvdLVF1USqKuAEIjw_QI_9eA5tKbZWIfvhMDhVhLEPjd5AEq
安装Google play的服务.

3)如果以上两种方式你都失败了,不要沮丧下面这种方法可能会更好,点击链接:http://www.droid4x.cn/ 下载海马玩模拟器,它可以一步解决问题。

Google play服务安装完成后如下图所示:

其次你还需要一个VPN账号(美国的最好),推荐一下我使用的VPN(如下图)可以随心所欲的选择地点。

     

最后需要下载开发包,打开Android SDK Manager下载Android SDK的extras部分(如下图),其中有我们支付所用到的包,开发用到的说明文档,例子等等。

下载完成后在SDK目录下可以找到这个文件夹android-sdk-windows\extras\google\play_billing

其中samples是google支付接入的demo,可以根据例子进行google支付的接入。同时在SDK目录下可以找到这个文件夹android-sdk-windows\docs\google\play\billing这个是google支付的官方说明文档可以对支付工程及原理有一个了解。

说明文档里讲的很详细,建议把文档完整的看一遍,相信如果你看懂了这几个文档,google支付也就很容易搞定了

第二步:代码接入

准备工作做完了,接下来就是代码接入过程了,首先你需要将之前下载的IInAppBillingService.aidl文件添加到你的工程中,添加方法就是在你的工程里新建一个com.android.vending.billing文件夹,将IInAppBillingService.aidl这个 文件拷贝到其中刷新工程即可(具体的可以参考下载的demo)。

其次把之前下载的google支付库中的demo simple例子中的代码粘贴到你的工程文件中(如下图),可以新建一个包放到里面。

在这里说明一下,如果你是和我一样的初学者,可以打着拿来主义的旗号直接使用,但要注意修改一下类名和变量名,毕竟这个代码是公开的大家都可以看到;如果你是大神觉得这个代码写的太low了,也可以自己修改成你想要的那个范。

1.添加权限

接入之前需要在AndroidManifest.xml 文件中添加支付的权限:

<uses-permission android:name="com.android.vending.BILLING" />2.初始化IabHelper:

// Create the helper, passing it our context and the public key to verify signatures with
Log.d(TAG, "Creating IAB helper.");
mHelper = new IabHelper(this, base64EncodedPublicKey);

// enable debug logging (for a production application, you should set this to false).
mHelper.enableDebugLogging(true);

// Start setup. This is asynchronous and the specified listener
// will be called once setup completes.
Log.d(TAG, "Starting setup.");
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");

if (!result.isSuccess()) {
// Oh noes, there was a problem.
complain("Problem setting up in-app billing: " + result);
return;
}

// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;

// IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});

3.调用支付接口:

是用来购买商品的方法:

mHelper.launchPurchaseFlow(this, SKU_GAS, RC_REQUEST,
mPurchaseFinishedListener, payload);购买方法的回调:

// Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);

// if we were disposed of in the meantime, quit.
if (mHelper == null) return;

if (result.isFailure()) {
complain("Error purchasing: " + result);
setWaitScreen(false);
return;
}
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification failed.");
setWaitScreen(false);
return;
}

Log.d(TAG, "Purchase successful.");

if (purchase.getSku().equals(SKU_GAS)) {
// bought 1/4 tank of gas. So consume it.
Log.d(TAG, "Purchase is gas. Starting gas consumption.");
mHelper.consumeAsync(purchase, mConsumeFinishedListener);
}
else if (purchase.getSku().equals(SKU_PREMIUM)) {
// bought the premium upgrade!
Log.d(TAG, "Purchase is premium upgrade. Congratulating user.");
alert("Thank you for upgrading to premium!");
mIsPremium = true;
updateUi();
setWaitScreen(false);
}
else if (purchase.getSku().equals(SKU_INFINITE_GAS)) {
// bought the infinite gas subscription
Log.d(TAG, "Infinite gas subscription purchased.");
alert("Thank you for subscribing to infinite gas!");
mSubscribedToInfiniteGas = true;
mTank = TANK_MAX;
updateUi();
setWaitScreen(false);
}
}
};

// Called when consumption is complete
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase, IabResult result) {
Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result);

// if we were disposed of in the meantime, quit.
if (mHelper == null) return;

// We know this is the "gas" sku because it's the only one we consume,
// so we don't check which sku was consumed. If you have more than one
// sku, you probably should check...
if (result.isSuccess()) {
// successfully consumed, so we apply the effects of the item in our
// game world's logic, which in our case means filling the gas tank a bit
Log.d(TAG, "Consumption successful. Provisioning.");
mTank = mTank == TANK_MAX ? TANK_MAX : mTank + 1;
saveData();
alert("You filled 1/4 tank. Your tank is now " + String.valueOf(mTank) + "/4 full!");
}
else {
complain("Error while consuming: " + result);
}
updateUi();
setWaitScreen(false);
Log.d(TAG, "End consumption flow.");
}
};

4.调用查询接口:

是用来查询你当前购买的的商品

mHelper.queryInventoryAsync(mGotInventoryListener); 查询方法的回调:

// Listener that's called when we finish querying the items and subscriptions we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(TAG, "Query inventory finished.");

// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;

// Is it a failure?
if (result.isFailure()) {
complain("Failed to query inventory: " + result);
return;
}

Log.d(TAG, "Query inventory was successful.");

/*
* Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See
* verifyDeveloperPayload().
*/

// Do we have the premium upgrade?
Purchase premiumPurchase = inventory.getPurchase(SKU_PREMIUM);
mIsPremium = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase));
Log.d(TAG, "User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM"));

// Do we have the infinite gas plan?
Purchase infiniteGasPurchase = inventory.getPurchase(SKU_INFINITE_GAS);
mSubscribedToInfiniteGas = (infiniteGasPurchase != null &&
verifyDeveloperPayload(infiniteGasPurchase));
Log.d(TAG, "User " + (mSubscribedToInfiniteGas ? "HAS" : "DOES NOT HAVE")
+ " infinite gas subscription.");
if (mSubscribedToInfiniteGas) mTank = TANK_MAX;

// Check for gas delivery -- if we own gas, we should fill up the tank immediately
Purchase gasPurchase = inventory.getPurchase(SKU_GAS);
if (gasPurchase != null && verifyDeveloperPayload(gasPurchase)) {
Log.d(TAG, "We have gas. Consuming it.");
mHelper.consumeAsync(inventory.getPurchase(SKU_GAS), mConsumeFinishedListener);
return;
}

updateUi();
setWaitScreen(false);
Log.d(TAG, "Initial inventory query finished; enabling main UI.");
}
};
5.消耗商品

因为我们的内购商品是可以重复购买的,但是每次购买之后需要消耗商品,注意这个消耗的意思不是要使用已经购买的商品,而是消除google对改购买商品施加的一个标记,以表示本次购买已成功,之后才可以进行下一次的购买以避免发生重复购买而产生的多次扣款而商品数目不一致的问题。

mHelper.consumeAsync(purchase, mConsumeFinishedListener);
消耗商品的回调:

// Called when consumption is complete
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase, IabResult result) {
Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result);

// if we were disposed of in the meantime, quit.
if (mHelper == null) return;

// We know this is the "gas" sku because it's the only one we consume,
// so we don't check which sku was consumed. If you have more than one
// sku, you probably should check...
if (result.isSuccess()) {
// successfully consumed, so we apply the effects of the item in our
// game world's logic, which in our case means filling the gas tank a bit
Log.d(TAG, "Consumption successful. Provisioning.");
mTank = mTank == TANK_MAX ? TANK_MAX : mTank + 1;
saveData();
alert("You filled 1/4 tank. Your tank is now " + String.valueOf(mTank) + "/4 full!");
}
else {
complain("Error while consuming: " + result);
}
updateUi();
setWaitScreen(false);
Log.d(TAG, "End consumption flow.");
}
};
6.返回数据方法:

在购买时不要忘记添加下面这个方法,它是用来出来返回的数据。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
if (mHelper == null) return;

// Pass on the activity result to the helper for handling
if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
// not handled, so handle it ourselves (here's where you'd
// perform any handling of activity results not related to in-app
// billing...
super.onActivityResult(requestCode, resultCode, data);
}
else {
Log.d(TAG, "onActivityResult handled by IABUtil.");
}
}7.退出后销毁IabHelper:

在退出时需要销毁IabHelper:

// We're being destroyed. It's important to dispose of the helper here!
@Override
public void onDestroy() {
super.onDestroy();

// very important:
Log.d(TAG, "Destroying helper.");
if (mHelper != null) {
mHelper.dispose();
mHelper = null;
}
}第三步:打包上传

首先你需要有一个google开发者账号,登录到google开发者后台添加一个应用,同时添加商品的相关部分。

其次google的支付可不是写完代码编译下就可以支付的,所以完成代码的部分后就需要将工程打包上传到google开发者后台,打包的过程相信不需要我多说什么了吧,不会的可以看下这个连接:http://jingyan.baidu.com/article/7908e85c8dea30af491ad24f.html,上传到Bate版或者ALPHA版,如果是公司开发那应该会有妹子或者汉子帮你完成这个步骤,如果是自己的话那就。。。呵呵。

google的审核过程还是很快的大约半个小时就出炉了,这个时候还需要添加测试账号在这个文档中详细介绍了如何添加测试账号,当然添加测试账号并不意味着你就可以测试了,在审核结束时在google开发者后台的apk界面有一个测试连接,打开后输入测试的账号成为测试人员,这个时候就可以进行google支付的测试了

第四步:测试中的问题

首先测试账号需要有一个绑定的信用卡而且是VISA信用卡账户,点击支付按钮,如果你已经成为测试人员,但是google提示“需要验证身份,需要登录Google账号”这个问题的话很可能是你的商品id有问题,你可以检查下商品id是否正确后重新测试。

关于如何添加商品id google支付的说明文档中会有详细的说明。

如果测试中遇到“无法购买你想要买的商品”这个提示,那可能是你还未成为测试人员或者你用开发者账号进行测试的原因。

1.当前应用程序不支持购买此商品:确定你手机上装的程序包名和签名和后台上传的一致。p.s.上传后台后APK需要等一段时间才能生效。

2.购买的商品不存在 :确保你代码里的商品名字和后台的一致,如果一致,则可能需要等一两个小时再测试,Google后台的问题。

3.loading了很长时间,最后给你提示未知错误:这个不管它,Google后台的问题,等会再测。

最后国内开发者确保是在vpn下进行测试,有什么疑惑的地方可以和我私聊!!!!

源码下载:https://github.com/guojunhua/GooglePay.git

Android支付接入之Google In-app-Billing的更多相关文章

  1. Android支付接入(七):Google In-app-Billing

    前段时间有事请耽搁了,今天跟大家一起看下Google的in-app Billing V3支付.    如果没有Google Play此处附上安装Google Play的一键安装器的链接(需要Root权 ...

  2. Android支付接入(7):Google In-app-Billing

    今天跟大家一起看下Google的in-app Billing V3支付.    如果没有GooglePlay此处附上安装Google Play的一键安装器的链接(需要Root权限):http://ww ...

  3. Android支付接入(五):机锋网

    原地址:http://blog.csdn.net/simdanfeg/article/details/9012083 前边已经陆续跟大家走了一遍运营商和支付宝付费接入,今天跟大家一起看看机锋网的支付接 ...

  4. Android支付接入(四):联通VAC计费

    原地址:http://blog.csdn.net/simdanfeg/article/details/9012031 注意事项: 1.联通支付是不需要自己标识软硬计费点的,当平台申请计费点的时候会提交 ...

  5. Android支付接入(三):电信爱游戏支付

    原地址:http://blog.csdn.net/simdanfeg/article/details/9011977 注意事项: 1.电信要求必须先启动电信的闪屏界面 2.非网络游戏不允许有Inter ...

  6. Android支付接入(二):移动游戏基地

    原地址:http://blog.csdn.net/simdanfeg/article/details/9011863 上篇博文跟大家一起走了一遍支付宝支付,今天我们来看看移动支付.众所周知目前付费通道 ...

  7. Android支付接入(一):支付宝

    原地址:http://blog.csdn.net/simdanfeg/article/details/9011603 转载之前我想深深地感谢屌丝哥 相信相同过App获取利润的都会需要接入计费SDK,下 ...

  8. Android支付接入(八):Amazon亚马逊支付

    下面跟大家一起走一遍Amazon亚马逊的支付,亚马逊目前刚把业务拓展到大陆市场,但这并不代表Amazon支付不成熟,恰恰相反,Amazon的支付流程,支付结果获取及测试另人称赞,支付流程.测试流程简洁 ...

  9. Android Q 接入 MQTT

    Android Q 接入 MQTT 首先在APP 下引入mqtt的库 implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1 ...

随机推荐

  1. jquery li a 样式

    jQuery(".CwebtopNavContainer").find("li:last a").css("color","red ...

  2. bzoj1452 最大流

    很明显最大流.. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #defi ...

  3. Java 基础总结大全

    Java 基础总结大全 一.基础知识 1.JVM.JRE和JDK的区别 JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性. java语言是跨平台,jv ...

  4. 【C#】线程问题

    多线程编程对很多程序员来说并不容易,在启动访问相同数据的多个线程时,会间歇性地遇到难以发现的问题.如果使用任务.并行LINQ或Parallel类,也会遇到这些问题.为了避免这一系列问题,开发程序中必须 ...

  5. 【C#】日期格式转换

    C#里内置的DateTime基本上都可以实现这些功能,巧用DateTime会使你处理这些事来变轻松多了今天DateTime.Now.Date.ToShortDateString();昨天,就是今天的日 ...

  6. ES6-Set 和 Map 数据结构

    ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set 数据结构. const s = new Set(); [2, 3 ...

  7. ref:phpstorm配置远程调试(xdebug)(docker中)

    ref:https://www.cnblogs.com/yjken/p/6555438.html readme:本文设置远程调试ubuntu中的php代码. 在docker中也可以,经过测试phpin ...

  8. asp.net core结合Gitlab-CI实现自动化部署

    0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 一.前言 在之前的文章中写过k8s+Jenkins+GitLab-自动化部署asp.net core项目 的topic,这次讲解一 ...

  9. 八步详解Hibernate的搭建及使用

    本文通过了八个步骤以及一些实例添加用户来介绍Hibernate的搭建和使用,真切的介绍了hibernate的基本用法,其中好多优点等待我们自己去发现,比如hibernate中的缓存机制,映射方案. 1 ...

  10. Xamarin Android权限请求

    Xamarin Android权限请求   Android权限规定了App是否可以访问特定的资源,如网络.电话和短信.在原有API 6.0之前,App在安全的时候,会请求一次权限.一旦安装后,App就 ...