Android支付接入(七):Google In-app-Billing 四:测试用的app一定要跟上传到Google的测试版的包名、版本code、name、签名一致,否则无法进行支付测试。 以上就是完整的Google in-appBilling接入过程,接下来会跟大家一起走一遍亚马逊支付,如有疑问请留言。 




注意:类型根据VPN而定,我用的是L2TP/IPSecPSK,选择此类型时,编辑只需填写名称,服务器地址和IPSec预共享密钥即可,然后连接的时候填写帐号和密码。当打开Google商店能看到付费软件表名VPN已成功连接,如果显示VPN已连接但还看不到付费软件时,进入应用程序管理器分别清除GooglePlay服务和Google Play商店数据之后再打开Google商店即可。
文档下载链接为:
一:接入流程:




支付接入过程中涉及到的接口及名词:
一:受管理商品和不受管理商品 

1.下载in-app-billing-v03,下载地址:http://pan.baidu.com/share/link?shareid=1387554851&uk=473193131将下载后的压缩包解压:
将src目录下两个包及包中的java文件引入工程,例如:
2.添加权限: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; @Overrideprotected 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() { @Overridepublic void onClick(Viewv) {// TODO Auto-generatedmethod stubiapHandler.sendEmptyMessage(1);}}); //购买100猫币(不受管理商品) findViewById(R.id.button2).setOnClickListener(newView.OnClickListener() { @Overridepublic void onClick(Viewv) {// TODO Auto-generatedmethod stubiapHandler.sendEmptyMessage(2);}}); //RestoreOrder findViewById(R.id.button3).setOnClickListener(newView.OnClickListener() { @Overridepublic void onClick(Viewv) {// TODO Auto-generatedmethod stubif (iap_is_ok) {mHelper.queryInventoryAsync(mGotInventoryListener);}else {showMessage("提示", "GooglePlay初始化失败,当前无法进行支付,请确定您所在地区支持Google Play支付或重启游戏再试!");} }}); //获取价格 findViewById(R.id.button4).setOnClickListener(newView.OnClickListener() { @Overridepublic void onClick(Viewv) {// TODO Auto-generatedmethod stubsku_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(){ @Overridepublic void run() {// TODO Auto-generatedmethod stubgetPrice();}}).start();}}); //测试订单 findViewById(R.id.button5).setOnClickListener(newView.OnClickListener() { @Overridepublic void onClick(Viewv) {// TODO Auto-generatedmethod stubiapHandler.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 blocke.printStackTrace();} }}} catch (RemoteExceptione) {// TODO Auto-generatedcatch blocke.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金币需要恢复" );} } }; @Overrideprotected voidonActivityResult(int requestCode, int resultCode, Intent data){// TODO Auto-generatedmethod stubLog.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."); }} @Overrideprotected void onDestroy(){// TODO Auto-generatedmethod stubsuper.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();}}