最近因为项目需要加入googleplay的内购功能~所以网上找了很多资料,这里做个记号~
官方的内购支付接入文档:https://developer.android.com/training/in-app-billing/index.html
网上别人的资料:http://zengrong.net/post/1801.htm
下面用到的所有代码都来自Google官方给的Demo,大概路径是:<android_sdk>/extras/google/play_billing/
Google Play开发者后台需要的配置
1.测试时需要把app正式签名后上传到googlepay的后台
2.网上说测试需要把账号添加到后台而且得用信用卡来测试(这个本人没测过)
3.需要在google play后台给对应的apk添加产品
关于产品的说明:
a.产品分为不受管理的商品(消耗品,比如游戏中的金币)和受管理的商品(一次性购买即属于本账号,比如某些游戏需要玩家付费后才可以使用完整版本)
b.受管理类产品需要考虑如果玩家用同一个支付账号到别的设备完同一款游戏,这时需要考虑把那个设备也设置成已支付
c.产品的id是唯一的字符串定义,比如com.engine.produce01
d.后台添加产品后需要激活
代码部分(使用的是version3 api)
IabHelper类
初始化方法
mHelper=new IabHelper(this, base64EncodedPublicKey);
这里的base64EncodedPublicKey是googleplay后台的发布产品的时候生成提供的
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; } // Hooray, 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); } });
startSetup 的操作是检查是否有权限和连接到Google Billing service是否成功;这里回调的操作是如果成功,调用queryInventoryAsync查看产品id是否可以使用;
查询完成后会调用IabHelper.QueryInventoryFinishedListener 这个回调接口进行通知,在这个接口中可以获取商品的详细信息SkuDetails和Purchase信息。
点击购买按钮,需要调用的支付方法
String payload = ""; mHelper.launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode, OnIabPurchaseFinishedListener listener, String payload);
boolean verifyDeveloperPayload(Purchase p) { String payload = p.getDeveloperPayload(); /* * TODO: verify that the developer payload of the purchase is correct. It will be * the same one that you sent when initiating the purchase. * * WARNING: Locally generating a random string when starting a purchase and * verifying it here might seem like a good approach, but this will fail in the * case where the user purchases an item on one device and then uses your app on * a different device, because on the other device you will not have access to the * random string you originally generated. * * So a good developer payload has these characteristics: * * 1. If two different users purchase an item, the payload is different between them, * so that one user's purchase can't be replayed to another user. * * 2. The payload must be such that you can verify it even when the app wasn't the * one who initiated the purchase flow (so that items purchased by the user on * one device work on other devices owned by the user). * * Using your own server to store and verify developer payloads across app * installations is recommended. */ return true; }
verifyDeveloperPayload这个方法是在支付完成的时候在回调里头去验证用的,关于payload的生产,看上面官方给的demo的注释,大概理解了下:
1.不同的玩家所生成的payload需要不一样
2.即使玩家在不同设备上初始化payload,也要可以通过~
大概是这个意思(如果翻译有问题~砸砖吧~)
下面是支付方法回调的监听:
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { public void onIabPurchaseFinished(IabResult result, Purchase purchase) { Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase); 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); } } };上面有中文注释的地方调用了 mHelper.consumeAsync这个方法,这里应该是只有非管理类的产品才需要调用的方法;相当于在购买成功后调用消耗(可以理解为消耗一个道具)
在IabHelper.OnConsumeFinishedListener的回调用于处理成功调用成功支付的逻辑(这里可能还需要一步去调用远程服务器验证)