android googleplay 支付接入
今天跟大家一起看下Google的in-app Billing V3支付。
注意:类型根据VPN而定,我用的是L2TP/IPSecPSK,选择此类型时,编辑只需填写名称,服务器地址和IPSec预共享密钥即可,然后连接的时候填写帐号和密码。当打开Google商店能看到付费软件表名VPN已成功连接,如果显示VPN已连接但还看不到付费软件时,进入应用程序管理器分别清除GooglePlay服务和Google Play商店数据之后再打开Google商店即可。
(2).Consuming In-app Products,消耗产品时的通信过程
(1).测试支付官方文档链接http://developer.android.com/google/play/billing/billing_testing.html
(2).Testing with staticresponses,静态测试,即当支付状态为一下四种情况时游戏逻辑是否正确。
- mHelper.launchPurchaseFlow(MainActivity.this,“android.test.purchased”,RC_REQUEST,mPurchaseFinishedListener);
一:受管理商品和不受管理商品
1.IabHelper.OnIabPurchaseFinishedListener 支付完成的回调,如果是受管理的商品在此回调中直接可以将道具给用户
2.IabHelper.OnConsumeFinishedListener 消耗完成的回调,当不受管理的商品被成功消耗进入此回调,此时将不受管理的商品给用户
3.IabHelper.QueryInventoryFinishedListener 查询完成的回调,RestoreOrder的时候用,当有订单成功付款但由于种种原因(突然断网、断电等)没收到Google支付成功的回调时,在这里可以查询到此订单,此时需要对订单进行处理(给用户道具等)。
四:测试用的app一定要跟上传到Google的测试版的包名、版本code、name、签名一致,否则无法进行支付测试。
1.当签名不一致或者版本code、版本name不一致时错误界面如下:
2.当包名不一致时错误界面如下:
接下来跟大家一起看一下代码具体实现:
1.下载in-app-billing-v03,下载地址:http://pan.baidu.com/share/link?shareid=1387554851&uk=473193131将下载后的压缩包解压:
将src目录下两个包及包中的java文件引入工程,例如:
2.添加权限:
- <uses-permissionandroid:nameuses-permissionandroid:name="com.android.vending.BILLING"/>
- String base64EncodedPublicKey ="";此处填写Google控制台添加新应用程序后的appid
- mHelper =new IabHelper(this, base64EncodedPublicKey);
- // enable debuglogging (for a production application, you should set this tofalse).
- mHelper.enableDebugLogging(false);
- // Start setup. This is asynchronous andthe specified listener
- // will be called oncesetup completes.
- Log.d(TAG,"Starting setup.");
- mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener(){
- publicvoid onIabSetupFinished(IabResult result){
- Log.d(TAG,"Setupfinished.");
- if (!result.isSuccess()) {
- // Ohnoes, there was a problem.
- complain("Problemsetting up in-app billing: " + result);
- return;
- }
- iap_is_ok = true;
- //Hooray, IAB is fully set up. Now, let's get an inventory of stuffwe own.
- Log.d(TAG, "Setup successful. Queryinginventory.");
- }
- });
调用支付接口:
- if(iap_is_ok){
- mHelper.launchPurchaseFlow(MainActivity.this,skus[1],RC_REQUEST, mPurchaseFinishedListener);
- }else {
- showMessage("提示", "GooglePlay初始化失败,当前无法进行支付,请确定您所在地区支持Google Play支付或重启游戏再试!");
- }
调用查询接口:
- mHelper.queryInventoryAsync(mGotInventoryListener);
调用获取道具价格接口:(因Google市场是根据不同国家显示不同货币价格,所以显示到游戏道具列表中的价格不是定值,而是动态获取的)
- billingservice =mHelper.getService();
- Bundle querySkus = newBundle();
- querySkus.putStringArrayList("ITEM_ID_LIST", skus);
- try {
- Bundle skuDetails = billingservice.getSkuDetails(3,MainActivity.this.getPackageName(),"inapp", querySkus);
- ArrayList<String> responseList =skuDetails.getStringArrayList("DETAILS_LIST");
- if (null!=responseList) {
- for (String thisResponse :responseList) {
- try {
- SkuDetails d = newSkuDetails(thisResponse);
- for (int i = 0; i <sku_list.size(); i++) {
- if(sku_list.get(i).equals(d.getSku())) {
- price_list.set(i, d.getPrice());
- }
- }
- iapHandler.sendEmptyMessage(0);
- }catch (JSONException e) {
- // TODO Auto-generated catchblock
- e.printStackTrace();
- }
- }
- }
- }catch (RemoteException e) {
- // TODO Auto-generated catchblock
- e.printStackTrace();
- }
三个回调:
- // Callback for when a purchase is finished
- IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener =newIabHelper.OnIabPurchaseFinishedListener() {
- publicvoidonIabPurchaseFinished(IabResult result, Purchase purchase) {
- Log.d(TAG,"Purchase finished: " + result+", purchase: " +purchase);
- if (result.isFailure()) {
- // Oh noes!
- complain("Error purchasing: " + result);
- return;
- }
- Log.d(TAG,"Purchase successful.");
- if(purchase.getSku().equals("coins_100")||purchase.getSku().equals("android.test.purchased")){
- mHelper.consumeAsync(purchase, mConsumeFinishedListener);
- }elseif (purchase.getSku().equals("double_income")) {
- //受管理的商品,开启双倍经验
- showMessage("支付成功","成功购买双倍经验");
- }
- }
- };
- // Called when consumption is complete
- IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =newIabHelper.OnConsumeFinishedListener() {
- publicvoid onConsumeFinished(Purchasepurchase, IabResult result) {
- Log.d(TAG,"Consumption finished. Purchase: "+purchase + ", result: " +result);
- // We know this is the "gas"sku because it's the only onewe consume,
- // so we don't check whichsku was consumed. If you havemore than one
- //sku, you probably shouldcheck...
- if (result.isSuccess()) {
- //successfully consumed, so we apply the effects of the item inour
- //game world's logic, which in our case means filling the gas tank abit
- if(purchase.getSku().equals("coins_100")||purchase.getSku().equals("android.test.purchased")){
- showMessage("支付成功","成功购买100猫币");
- }
- }
- else {
- complain("Error while consuming: " + result);
- }
- }
- };
- // Listener that's called when we finish querying the items weown
- IabHelper.QueryInventoryFinishedListener mGotInventoryListener =newIabHelper.QueryInventoryFinishedListener() {
- publicvoidonQueryInventoryFinished(IabResult result, Inventory inventory){
- Log.d(TAG,"Query inventory finished.");
- if (result.isFailure()) {
- complain("Failed to query inventory: " +result);
- return;
- }
- Log.d(TAG,"Query inventory was successful.");
- if(inventory.hasPurchase("double_income")) {
- //查询到有受管理的商品支付成功需要将道具给用户
- showMessage("成功Restore双倍金币", "查询到有双倍金币需要恢复");
- }elseif(inventory.hasPurchase("cions_100")){
- //查询到不受管理的商品支付成功需要将道具消耗掉
- showMessage("成功Restore100金币","查询到有100金币需要恢复");
- }
- }
- };
处理返回Activity后的数据:
- @Override
- protectedvoid onActivityResult(int requestCode,int resultCode, Intent data) {
- // TODO Auto-generated methodstub
- Log.d(TAG, "onActivityResult("+ requestCode + "," +resultCode +"," + data);
- // Pass on theactivity 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 activityresults not related to in-app
- // billing...
- super.onActivityResult(requestCode,resultCode, data);
- }
- else {
- Log.d(TAG,"onActivityResult handled by IABUtil.");
- }
- }
退出游戏后销毁IabHelper:
- @Override
- protectedvoid onDestroy() {
- // TODO Auto-generated methodstub
- super.onDestroy();
- if (mHelper !=null) mHelper.dispose();
- mHelper =null;
- }
最后附上MainActivity.java完整文件,源码下载地址:http://pan.baidu.com/share/link?shareid=1579953623&uk=473193131:
- packagecn.catcap.together;
- importjava.util.ArrayList;
- importorg.json.JSONException;
- importcom.android.vending.billing.IInAppBillingService;
- importcom.example.android.trivialdrivesample.util.IabHelper;
- importcom.example.android.trivialdrivesample.util.IabResult;
- importcom.example.android.trivialdrivesample.util.Inventory;
- importcom.example.android.trivialdrivesample.util.Purchase;
- importcom.example.android.trivialdrivesample.util.SkuDetails;
- importandroid.os.Bundle;
- importandroid.os.Handler;
- importandroid.os.RemoteException;
- importandroid.app.Activity;
- importandroid.app.AlertDialog;
- importandroid.content.Intent;
- importandroid.util.Log;
- importandroid.view.View;
- importandroid.widget.TextView;
- public class MainActivityextends Activity {
- // The helper object
- IabHelper mHelper;
- // Debugtag, for logging
- static final String TAG = "TrivialDrive";
- //Current amount of gas in tank, in units
- int mTank;
- //(arbitrary) request code for the purchase flow请求码
- static final int RC_REQUEST = 10001;
- private boolean iap_is_ok = false;
- //double_income为受管理商品,coins_100为不受管理商品
- private String[] skus ={"android.test.purchased","double_income","coins_100"};
- privateArrayList<String> sku_list;
- privateArrayList<String> price_list;
- private IInAppBillingService billingservice;
- private TextView tv;
- @Override
- protected voidonCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Stringbase64EncodedPublicKey = "";//此处填写自己的appid
- mHelper =new IabHelper(this, base64EncodedPublicKey);
- // enabledebug logging (for a production application, you should set this tofalse).
- mHelper.enableDebugLogging(false);
- // Start setup. This isasynchronous and the specified listener
- // will becalled once setup completes.
- Log.d(TAG,"Starting setup.");
- mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
- public voidonIabSetupFinished(IabResult result) {
- Log.d(TAG, "Setup finished.");
- if (!result.isSuccess()) {
- // Ohnoes, there was a problem.
- complain("Problem setting up in-app billing: " + result);
- return;
- }
- iap_is_ok = true;
- // Hooray, IAB is fully set up. Now, let's getan inventory of stuff we own.
- Log.d(TAG, "Setup successful. Queryinginventory.");
- }
- });
- //购买双倍金币(受管理商品)
- findViewById(R.id.button1).setOnClickListener(newView.OnClickListener() {
- @Override
- public void onClick(Viewv) {
- // TODO Auto-generatedmethod stub
- iapHandler.sendEmptyMessage(1);
- }
- });
- //购买100猫币(不受管理商品)
- findViewById(R.id.button2).setOnClickListener(newView.OnClickListener() {
- @Override
- public void onClick(Viewv) {
- // TODO Auto-generatedmethod stub
- iapHandler.sendEmptyMessage(2);
- }
- });
- //RestoreOrder
- findViewById(R.id.button3).setOnClickListener(newView.OnClickListener() {
- @Override
- public void onClick(Viewv) {
- // TODO Auto-generatedmethod stub
- if (iap_is_ok) {
- mHelper.queryInventoryAsync(mGotInventoryListener);
- }else {
- showMessage("提示", "GooglePlay初始化失败,当前无法进行支付,请确定您所在地区支持Google Play支付或重启游戏再试!");
- }
- }
- });
- //获取价格
- findViewById(R.id.button4).setOnClickListener(newView.OnClickListener() {
- @Override
- public void onClick(Viewv) {
- // TODO Auto-generatedmethod stub
- sku_list = newArrayList<String>();
- price_list = newArrayList<String>();
- //添加默认值
- sku_list.add("double_income");
- price_list.add("HK$40");
- sku_list.add("coins_100");
- price_list.add("HK$8");
- new Thread(new Runnable(){
- @Override
- public void run() {
- // TODO Auto-generatedmethod stub
- getPrice();
- }
- }).start();
- }
- });
- //测试订单
- findViewById(R.id.button5).setOnClickListener(newView.OnClickListener() {
- @Override
- public void onClick(Viewv) {
- // TODO Auto-generatedmethod stub
- iapHandler.sendEmptyMessage(3);
- }
- });
- //显示价格
- tv =(TextView) findViewById(R.id.text);
- }
- //获取价格
- private voidgetPrice(){
- ArrayList<String> skus = newArrayList<String>();
- skus.add("double_income");
- skus.add("coins_100");
- billingservice =mHelper.getService();
- Bundle querySkus = newBundle();
- querySkus.putStringArrayList("ITEM_ID_LIST",skus);
- try {
- Bundle skuDetails =billingservice.getSkuDetails(3,MainActivity.this.getPackageName(),"inapp", querySkus);
- ArrayList<String> responseList =skuDetails.getStringArrayList("DETAILS_LIST");
- if (null!=responseList){
- for (String thisResponse :responseList) {
- try {
- SkuDetails d = newSkuDetails(thisResponse);
- for (int i = 0; i< sku_list.size(); i++) {
- if(sku_list.get(i).equals(d.getSku())) {
- price_list.set(i,d.getPrice());
- }
- }
- iapHandler.sendEmptyMessage(0);
- } catch (JSONException e){
- // TODO Auto-generatedcatch block
- e.printStackTrace();
- }
- }
- }
- } catch (RemoteExceptione) {
- // TODO Auto-generatedcatch block
- e.printStackTrace();
- }
- }
- Handler iapHandler = newHandler(){
- public voidhandleMessage(android.os.Message msg) {
- switch(msg.what){
- case 0:
- tv.setText(price_list.get(0)+"\n"+price_list.get(1));
- break;
- case 1:
- if (iap_is_ok) {
- mHelper.launchPurchaseFlow(MainActivity.this, skus[1], RC_REQUEST, mPurchaseFinishedListener);
- }else {
- showMessage("提示", "GooglePlay初始化失败,当前无法进行支付,请确定您所在地区支持Google Play支付或重启游戏再试!");
- }
- break;
- case 2:
- if (iap_is_ok) {
- mHelper.launchPurchaseFlow(MainActivity.this, skus[2], RC_REQUEST,mPurchaseFinishedListener);
- }else {
- showMessage("提示", "GooglePlay初始化失败,当前无法进行支付,请确定您所在地区支持Google Play支付或重启游戏再试!");
- }
- break;
- case 3:
- if (iap_is_ok) {
- mHelper.launchPurchaseFlow(MainActivity.this, skus[0], RC_REQUEST,mPurchaseFinishedListener);
- }else {
- showMessage("提示", "GooglePlay初始化失败,当前无法进行支付,请确定您所在地区支持Google Play支付或重启游戏再试!");
- }
- break;
- default:
- break;
- }
- };
- };
- // Callback for when apurchase is finished
- IabHelper.OnIabPurchaseFinishedListenermPurchaseFinishedListener = newIabHelper.OnIabPurchaseFinishedListener() {
- publicvoid onIabPurchaseFinished(IabResult result, Purchase purchase){
- Log.d(TAG, "Purchasefinished: " + result + ", purchase: " + purchase);
- if (result.isFailure()) {
- // Oh noes!
- complain("Error purchasing: " + result);
- return;
- }
- Log.d(TAG, "Purchasesuccessful.");
- if(purchase.getSku().equals("coins_100")||purchase.getSku().equals("android.test.purchased")){
- mHelper.consumeAsync(purchase, mConsumeFinishedListener);
- }else if(purchase.getSku().equals("double_income")) {
- //受管理的商品,开启双倍经验
- showMessage("支付成功","成功购买双倍经验");
- }
- }
- };
- // Called when consumption is complete
- IabHelper.OnConsumeFinishedListenermConsumeFinishedListener = newIabHelper.OnConsumeFinishedListener() {
- publicvoid onConsumeFinished(Purchase purchase, IabResult result) {
- Log.d(TAG, "Consumptionfinished. Purchase: " + purchase + ", result: " + result);
- // We know this is the "gas"sku because it's the only one we consume,
- // so we don't check whichsku was consumed. If you have more than one
- // sku, you probably shouldcheck...
- if (result.isSuccess()) {
- // successfully consumed, so we apply theeffects of the item in our
- // game world's logic, which in our case meansfilling the gas tank a bit
- if(purchase.getSku().equals("coins_100")||purchase.getSku().equals("android.test.purchased")){
- showMessage("支付成功","成功购买100猫币");
- }
- }
- else {
- complain("Error while consuming: " +result);
- }
- }
- };
- // Listener that's called when we finishquerying the items we own
- IabHelper.QueryInventoryFinishedListenermGotInventoryListener = newIabHelper.QueryInventoryFinishedListener() {
- publicvoid onQueryInventoryFinished(IabResult result, Inventoryinventory) {
- Log.d(TAG, "Query inventoryfinished.");
- if (result.isFailure()) {
- complain("Failed to query inventory: " +result);
- return;
- }
- Log.d(TAG, "Query inventorywas successful.");
- if(inventory.hasPurchase("double_income")) {
- //查询到有受管理的商品支付成功需要将道具给用户
- showMessage("成功Restore双倍金币", "查询到有双倍金币需要恢复");
- }elseif(inventory.hasPurchase("cions_100")){
- //查询到不受管理的商品支付成功需要将道具消耗掉
- showMessage("成功Restore100金币","查询到有100金币需要恢复" );
- }
- }
- };
- @Override
- protected voidonActivityResult(int requestCode, int resultCode, Intent data){
- // TODO Auto-generatedmethod stub
- Log.d(TAG,"onActivityResult(" + requestCode + "," + resultCode + "," +data);
- // Pass onthe activity result to the helper for handling
- if(!mHelper.handleActivityResult(requestCode, resultCode, data)){
- // not handled, so handle itourselves (here's where you'd
- // perform any handling ofactivity results not related to in-app
- // billing...
- super.onActivityResult(requestCode, resultCode, data);
- }
- else {
- Log.d(TAG, "onActivityResulthandled by IABUtil.");
- }
- }
- @Override
- protected void onDestroy(){
- // TODO Auto-generatedmethod stub
- super.onDestroy();
- if (mHelper != null)mHelper.dispose();
- mHelper =null;
- }
- void complain(Stringmessage) {
- Log.e(TAG,"**** TrivialDrive Error: " + message);
- alert("Error: " + message);
- }
- void alert(String message){
- AlertDialog.Builder bld = new AlertDialog.Builder(this);
- bld.setMessage(message);
- bld.setNeutralButton("OK", null);
- Log.d(TAG,"Showing alert dialog: " + message);
- bld.create().show();
- }
- private voidshowMessage(String title,String message){
- newAlertDialog.Builder(MainActivity.this).setTitle(title).setMessage(message).setPositiveButton("确定",null).show();
- }
- }
以上就是完整的Google in-appBilling接入过程,接下来会跟大家一起走一遍亚马逊支付,如有疑问请留言。
android googleplay 支付接入相关推荐
- android 微信支付过程,android 微信 支付 接入流程总结
[TOC] 客户端微信支付 登录微信官方开放平台微信,注册账号,在微信开放平台申请应用,输入已上线app的正式的应用包名和签名,微信提供了一个签名工具,一般使用它提供的签名工具生成签名,然后填写到对应 ...
- Android的支付接入(一):支付宝
相信相同过App获取利润的都会需要接入计费SDK,下边就跟大家走一遍完整的支付宝SDK接入,支付系列均通过计费Button触发,计费所有代码均放到一个java文件实现,这样虽然会有点违背java面向对 ...
- Android Payme支付接入
公司新项目需要接入HK的payme支付,一开始说没资料自己网上找,搜了一圈,发现啥都可以参考的案例,就参照后台的来撸了一把,再次记录下.坑多得很... 首先申请密钥啥的都不说了,申请下来即可. 第一步 ...
- 支付宝、微信Android APP支付接入流程
支付类型: 一次性支付 自动续费(支付宝周期扣款.微信委托扣款):1.支付并签约 2.先签约后扣费 注:微信委托扣款中先签约后扣费:自动续费.授权扣款.免密支付 支付宝 支付流程中各端交互逻辑 支付流 ...
- Android支付接入(7):Google In-app-Billing
今天跟大家一起看下Google的in-app Billing V3支付. 如果没有GooglePlay此处附上安装Google Play的一键安装器的链接(需要Root权限):http://www.m ...
- Android支付接入(七):Google In-app-Billing
转载 http://blog.csdn.net/michael_liu_89/article/details/12704461 今天跟大家一起看下Google的in-app Billing V3支付. ...
- Android支付接入:Google In-app-Billing
http://blog.csdn.net/michael_liu_89/article/details/12704461 今天跟大家一起看下Google的in-app Billing V3支付. ...
- Android支付接入(七):Google In-app-Billing
今天跟大家一起看下Google的in-app Billing V3支付. 如果没有GooglePlay此处附上安装Google Play的一键安装器的链接(需要Root权限):http://www ...
- Android支付接入(五):机锋网
前边已经陆续跟大家走了一遍运营商和支付宝付费接入,今天跟大家一起看看机锋网的支付接入.事实上付费接入本身并没有太多须要注意的地方,做的多了以后你会发现套路都是大同小异的.而须要注意的地方在于怎么跟游戏 ...
最新文章
- boost spirit的简单使用
- vim全局搜索并跳转
- linux将bridge当做hub来用
- [C++]怎么样实现一个较快的Hash Table
- 【Tiny4412】使用dnw烧写内核
- python pandas serie简介及基本使用
- 金士顿 8G u盘 红色 量产记录
- 作者:王海洋(1980-),男,中国科学院计算技术研究所网络数据科学与技术重点实验室、烟台中科网络技术研究所工程师。...
- 行业巨头争相布局物联网
- python yield from_简述 yield 和 yield from
- BZOJ2142: 礼物
- Linux如何整数分区,硬盘整数分区怎么计算?NTFS整数分区数值表分享
- RocketMQ报错:service not available now, maybe disk full
- android 运行apk时崩溃,从Android Studio运行时安装APK时应用程序崩溃完美无缺
- 微信小程序开放平台代码部署特约商户
- 计算机导论sql试题,数据库SQL语句练习题
- Word的样式库在 选项卡中_Word|表格的设置
- 嵌入式系统的软件看门狗和硬件看门狗
- 扯点关于经济的淡-贸易顺差都是有利的吗
- GRAINS: Generative Recursive Autoencoders for INdoor Scenes 2019 TOG(家居布局、树结构网络、RvNN)
热门文章
- K-Means聚类分析广告投放效果的改进(数据标准化、最佳K值的确定)
- c语言如何将数组里的数排序输出,c程序输入10个数到一维数组中,按升序排序后输出。...
- 最新前端体系学习路径推荐(内附免费资料)
- 架构师小跟班:SSL证书免费申请及部署,解决页面样式错乱问题完整攻略
- 【技术分享】Android App常见安全问题演练分析系统-DIVA-Part1
- 咖啡粉的粗细如何影响风味?| 啡鸟集
- 深度估计 DenseDepth 笔记
- 杭电oj第1000题—— A + B Problem
- 宇宙代码与磁子计算机,新认识!宇宙产生什么最强磁铁?比人类产生的最强磁场强一亿倍...
- openstack ironic standalone 方式部署