GooglePlay内购In-app Billing 总结
GooglePlay支付的接入可以参考SDKgoogleapi的例子(sdk/google/play_billing/samples/TrivialDrive)
商品的说明:
Google Play 没有可重复购买商品这个概念,所有的“商品/充值档”用户成功购买过一次之后就不允许再次购买了。所以为了实现像应用内支付充值这种可重复购买的“商品/充值档”,Google Play 提供了一个“消耗”借口(ConsumingIn-app Products)。用户购买完商品后,调一下“消耗”接口,这样用户下次就可以继续购买了。
1. 产品分为不受管理的商品(消耗品,比如游戏中的金币)和受管理的商品(一次性购买即属于本账号,比如某些游戏需要玩家付费后才可以使用完整版本)
2. 受管理类产品需要考虑如果玩家用同一个支付账号到别的设备完同一款游戏,这时需要考虑把那个设备也设置成已支付
GoolePlay说明:
1.手机连接Gooleplay,需要连接VPN,VPN最好是美国或日本的;
2.在打开GooglePlay商店之前,首先清理应用缓存,否则Google会认为是大陆地区,导致支付失败。然后打开GooglePlay商店,如果可以看到付费应用,则说明没有问题,可以正常进行支付;
3.要想付费成功,你使用的 Google Play 帐号必须绑定有海外支付能力的信用卡或者有海外支付能力的 Paypal 账户
三个回调:
1. IabHelper.OnIabPurchaseFinishedListener 支付完成的回调,如果是受管理的商品在此回调中直接可以将道具给用户;
2. IabHelper.OnConsumeFinishedListener 消耗完成的回调,当不受管理的商品被成功消耗进入此回调,此时将不受管理的商品给用户;
3. IabHelper.QueryInventoryFinishedListener 查询完成的回调,Restore Order的时候用,当有订单成功付款但由于种种原因(突然断网、断电等)没收到Google支付成功的回调时,在这里可以查询到此订单,此时需要对订单进行处理(给用户道具等)。
测试用的app一定要跟上传到Google的测试版的包名、版本code、name、签名一致,否则无法进行支付测试。
代码具体实现:
初始化IapHelper:
private static final String BASE64_PUBLIC_KEY=””;
mHelper = new IabHelper(this, BASE64_PUBLIC_KEY);
// enable debuglogging (for a production application, you should set
// this to false).
mHelper.enableDebugLogging(true);
// Start setup.This is asynchronous and the specified listener
// will be calledonce setup completes.
Log.d(TAG,"Starting setup.");
mHelper.startSetup(newIabHelper.OnIabSetupFinishedListener() {
public voidonIabSetupFinished(IabResult result) {
Log.d(TAG,"Setup finished.");
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. Querying inventory.");
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
调用查询接口:
mHelper.queryInventoryAsync(mGotInventoryListener);
调用支付接口:
mHelper.launchPurchaseFlow(TexasPoker.this, productId,
RC_REQUEST,mPurchaseFinishedListener, orderId);
调用消耗接口:
mHelper.consumeAsync(mCurrentPurchase,mConsumeFinishedListener);
三个支付回调:
// Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListenermPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public voidonIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG,"Purchase finished: " + result + ", purchase: "
+purchase);
if(result.isFailure()) {
// Oh noes
complain("Errorpurchasing: " + result);
return;
}
mCurrentPurchase= purchase;
SysUtil.OnIabPurchaseFinished(0,purchase);
Log.d(TAG,"Purchase successful.");
}
};
// Called whenconsumption is complete
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =new IabHelper.OnConsumeFinishedListener() {
public voidonConsumeFinished(Purchase purchase, IabResult result) {
Log.d(TAG,"Consumption finished. Purchase: " + purchase
+", result: " + result);
// We knowthis is the "gas" sku because it's the only one we
// consume,
// so we don'tcheck which sku was consumed. If you have more than
// one
// sku, youprobably should check...
if(result.isSuccess()) {
//successfully consumed, so we apply the effects of the item in
// our
// gameworld's logic, which in our case means filling the gas
// tank abit
Log.d(TAG,"Consumption finished. Success!");
//showMessage("支付成功","成功购买" + nPurchaseNum + "万能豆!");
// SysUtil.OnIabConsumeFinished(0,nPurchaseNum);
SysUtil.OnPayCallback(tradeNo);
mCurrentPurchase= null;
nPurchaseNum= 0;
tradeNo ="";
} else {
complain("Errorwhile consuming: " + result);
}
}
};
// Listener that's called when we finish querying the items weown
IabHelper.QueryInventoryFinishedListener mGotInventoryListener =new IabHelper.QueryInventoryFinishedListener() {
public voidonQueryInventoryFinished(IabResult result,
Inventoryinventory) {
Log.d(TAG,"Query inventory finished.");
if(result.isFailure()) {
complain("Failedto query inventory: " + result);
return;
}
Log.d(TAG,"Query inventory was successful.");
List<Purchase>listPurchase = inventory.getAllPurchases();
// 如果有多个未消耗的商品,每次消耗第一个
if(listPurchase.size() > 0) {
Purchasepurchase = listPurchase.get(0);
mCurrentPurchase= purchase;
SysUtil.OnIabPurchaseFinished(0,purchase);
}
}
};