In-app billing 接入流程和坑点

准备工作

1,在Google play console 注册开发者账号,新建你的项目

2.下载这google play service和billing library, billing v3以上版本,现在好像已经出到v5了

Paste_Image.png

3.下载好之后,在下图这个sdk路径下,samples是官方提供的demo, 我们需要的是IInAppBillingService.aidl这个文件,这个应该是google支付的通信文件

Paste_Image.png

4.将IInAppBillingService.aidl拷贝到com.android.vending.billing这个路径下

Paste_Image.png

5.将官方samples里的这些类全部拷贝到你的代码里,这些都是些google支付的辅助工具类,核心的支付代码后面我会贴出来, 另外记得加入支付权限:com.android.vending.BILLING

Paste_Image.png

6.接下来在你的 google play console 里的应用内商品上传你的apk, 注意点:(1) 确保你的apk是签名后的 (2)确保你的apk已经加入了支付权限 (3)如果你的商品已经上线了应用商店的话,此版本你最好是提交beta版或者alpha版 (4) 测试版的话最好添加测试人员,封闭式测试,如何添加测试人员和封闭式测试后面会讲。设置商家账号的话大概是设置一些绑定的支付等信息,按着里面对应设置就行

Paste_Image.png

7.添加完应用内商品后,这一栏会编程下图的样子,这个是添加你的商品的,你可以添加很多很多的商品,可以设置商品的id,名称,简介,价格等,注意这个商品的id设置后就不能再改动的,其他都可以改,商品id就是后面支付代码里要用到的sku。还有就是选择受管理商品,因为这个才是应用内购物。

Paste_Image.png

8.添加测试人员:创建列表,然后点击进入你的列表页,如果你一次添加多个账号,那个账号之间要用逗号隔开。请注意,开发者账号是不能作为测试人员的,开发者账号也就是登陆这个play console 平台的账号。

Paste_Image.png

Paste_Image.png

9.在你在应用版本发布beta版或者alpha版的时候, 你就可以悬着测试方法,我选择的是封闭式测试,至于这几种测试方式有何不同,可以去开发者文档里看看。然后就是选择你的测试全体, 最下面有一条链接,这个链接你可以发送给其他要测试的人员,他们打开点击里面的要成为测试人员后就会成为你的测试人员了,如果说没有成为测试人员资格之类的话,请在第10点那张图里添加那个测试人员的账号,然后再点击就可以了

Paste_Image.png

10.注意点,这里没说要逗号隔开,但是如果添加多个账号的话,账号之间也是要用逗号隔开的

Paste_Image.png

11.支付是需要用到publickey的,这个publickey在你的服务与API里可以找到,这个publickey在调用时候最好从后台服务器中获取,安全性会好点

Paste_Image.png

12.购买流程
(1) 初始化IabHelper 并查询是否有可消耗的商品

/**
     * 初始化IabHelper
     */
    private void setupIabHelper(String base64EncodedPublicKey) {
        showLog("base64EncodedPublicKey--------" + base64EncodedPublicKey);
        iabHelper = new IabHelper(this, base64EncodedPublicKey);
        iabHelper.enableDebugLogging(true);
        iabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
            @Override
            public void onIabSetupFinished(IabResult result) {

                showLog("Setup finished----------");

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

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

                // IAB is fully set up. Now, let's get an inventory of stuff we own.
                showLog("Setup successful. Querying inventory");
                List<String> additionalSkuList = new ArrayList();
                additionalSkuList.add(SKU_80);
                additionalSkuList.add(SKU_500);
                additionalSkuList.add(SKU_1200);
                additionalSkuList.add(SKU_2500);
                additionalSkuList.add(SKU_6500);
                additionalSkuList.add(SKU_14000);
                iabHelper.queryInventoryAsync(true, additionalSkuList, queryInventoryFinishedListener);
            }
        });
    }

    /**
     * 查询用户所拥有的商品信息
     */
    IabHelper.QueryInventoryFinishedListener queryInventoryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
        @Override
        public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
            showLog("查询商品----" + "Query inventory finished");

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

            // Is it a failure?
            if (result.isFailure()) {
                alert("Failed to query inventory: " + result);
                return;
            }
            showLog("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().
             */

            if (inventory.getPurchase(SKU_80) != null && verifyDeveloperPayload(inventory.getPurchase(SKU_80))) {
                showLog("need consume sku_80.");
                iabHelper.consumeAsync(inventory.getPurchase(SKU_80), consumeFinishedListener);
            }
            if (inventory.getPurchase(SKU_500) != null && verifyDeveloperPayload(inventory.getPurchase(SKU_500))) {
                showLog("need consume sku_500.");
                iabHelper.consumeAsync(inventory.getPurchase(SKU_500), consumeFinishedListener);
            }
            if (inventory.getPurchase(SKU_1200) != null && verifyDeveloperPayload(inventory.getPurchase(SKU_1200))) {
                showLog("need consume sku_1200.");
                iabHelper.consumeAsync(inventory.getPurchase(SKU_1200), consumeFinishedListener);
            }
            if (inventory.getPurchase(SKU_2500) != null && verifyDeveloperPayload(inventory.getPurchase(SKU_2500))) {
                showLog("need consume sku_2500.");
                iabHelper.consumeAsync(inventory.getPurchase(SKU_2500), consumeFinishedListener);
            }
            if (inventory.getPurchase(SKU_6500) != null && verifyDeveloperPayload(inventory.getPurchase(SKU_6500))) {
                showLog("need consume sku_6500.");
                iabHelper.consumeAsync(inventory.getPurchase(SKU_6500), consumeFinishedListener);
            }
            if (inventory.getPurchase(SKU_14000) != null && verifyDeveloperPayload(inventory.getPurchase(SKU_14000))) {
                showLog("need consume sku_14000.");
                iabHelper.consumeAsync(inventory.getPurchase(SKU_14000), consumeFinishedListener);
            }

        }
    };

(2)发起购买

 /**
     * 发起购买
     */
    private void launchPurchaseFlow(String sku) {
        if (checkPlayServices())
            iabHelper.launchPurchaseFlow(this, sku, IabHelper.ITEM_TYPE_INAPP, REQUEST_CODE, purchaseFinishedListener, new Date().toString() + sku);
    }
 /**
     * 购买商品
     */
    IabHelper.OnIabPurchaseFinishedListener purchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
        @Override
        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
            if (null != purchase)
                showLog("购买商品------" + "Purchase finished: " + result + "purchase-" + purchase + ", OriginalJson: " + purchase.getOriginalJson() + "signture----" + purchase.getSignature());
            // if we were disposed of in the meantime, quit.
            if (iabHelper == null) return;

            if (result.isFailure()) {
//                alert("Error purchasing: " + result);  // TODO 用户取消或其他情况
                return;
            }
            if (!verifyDeveloperPayload(purchase)) {
                alert("Error purchasing. Authenticity verification failed.");
                return;
            }
            iabHelper.consumeAsync(purchase, consumeFinishedListener);  // 消耗商品
            if (!TextUtils.isEmpty(money) && wealth != 0 && null != purchase && null != purchase.getOriginalJson() && null != purchase.getSignature() && null != purchase.getOrderId()) {
                showLog("购买商品成功========" + "money-----" + money + "----wealth-----" + wealth + "\npurchaseDta::::" + purchase.getOriginalJson() + "\ndataSignature::::" + purchase.getSignature());
                getP().doBillingRecord(PreferenceUtil.getString(Conf.PF_USER_ID_KEY), PreferenceUtil.getString(Conf.PF_TOKEN_KEY),
                        money, wealth, purchase.getOriginalJson(), purchase.getSignature(), purchase.getOrderId());
            }
        }
    };

(3)消耗商品(消耗了才能再次购买)

 /**
     * 消耗商品
     * (如果商品是可以重复购买的情况下,
     * 在查询结束对需要消耗的商品进行消耗掉,
     * 或者购买完商品对商品进行消耗)
     */
    IabHelper.OnConsumeFinishedListener consumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
        @Override
        public void onConsumeFinished(Purchase purchase, IabResult result) {
            showLog("消耗商品---------" + "Consumption finished. Purchase: " + purchase + ", result: " + result);
            // if we were disposed of in the meantime, quit.
            if (iabHelper == 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
                showLog("消耗商品成功" + "orderId---" + purchase.getOrderId() + "---PurchaseTime----" + purchase.getPurchaseTime() + "----sku-----" + purchase.getSku());
            } else {
                alert("Error while consuming: " + result);
            }
        }
    };

(4) 回调与destroy

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (null != data)
            showLog("回调信息-----------" + requestCode + "," + resultCode + "," + "purchaseData:" + data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA) + "--dataSignature---" + data.getStringExtra(RESPONSE_INAPP_SIGNATURE));
        if (iabHelper == null) return;
        // Pass on the activity result to the helper for handling
        if (!iabHelper.handleActivityResult(requestCode, resultCode, data)) {
            super.onActivityResult(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...
            showLog("handleActivityResult---------------");
        } else {
            showLog("onActivityResult handled by IABUtil-------------.");
        }
    }
 // We're being destroyed. It's important to dispose of the helper here!
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // very important:
        showLog("destroy helper.");
        if (iabHelper != null) {
            iabHelper.dispose();
            iabHelper = null;
        }
    }

在发起购买前最好判断下手机当前是否支持google play service, 判断如下

/**
     * Check the device to make sure it has the Google Play Services APK.If
     * it doesn't, display a dialog that allows users to download the APK from
     * the Google Play Store or enable it in the device's system settings
     */
    private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, this, 101).show();
            } else {
                alert("This device is not supported, Please install google play services");
                finish();
            }
            return false;
        }
        return true;
    }

最后,就剩下测试了,关于测试的账号要注意的:
1.测试账号必须要绑定visa卡或者paypal账号,而且不能是开发者账号
2.由于国内种种原因(你懂得),必须开vpn, 蓝灯挺好用的,而且最好是链接到美国的
3.控制台里将开发账号绑定好结算等等信息
4.你的google商店要登陆你的测试账号从商店上下载应用并测试,我开始是这样测试的,可以支付,但是跑项目测试不行,后来放了一晚后,就可以了,具体原因我也不知道,但是建议用多几款机型测试,国内手机可以安装谷歌安装器来安装谷歌服务(跑本地的项目测试的话记得包名、签名、版本号等信息都要与线上测试的版本一致)

接入前,建议看看开发者文档,会对整个接入流程更加清晰,由于英文不好,这里我就附上中文版的:https://developer.android.com/google/play/billing/versions.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值