Google商店的应用被下架,应用内购买必须走Google支付,还要扣去百分之三十的手续费,而且有些国家还会收一定的销售税最高达27%,其实Google支付只是自己集成了Paypal支付和银行卡支付,然后Google收手续费。用户使用Google正常支付退款时间是48小时,退款只会在商家账号通知。

我们来谈一谈集成Google支付吧:

Google上给出了Demo:https://github.com/cafebazaar/TrivialDrive

里面有购买订阅和受管理产品的,大家可以下载运行一下试一试。我刚开始是按照Google开发文档去集成的,可能是我水平有限,并没有成功。最后是按Demo去搞吧,方便。Google给出的API:https://developer.android.com/google/play/billing/billing_integrate.html

要在您的应用中实现应用内购买结算,您需要执行以下操作:

  1. 将应用内购买结算库添加到您的项目中。
  2. 更新您的 AndroidManifest.xml 文件。
  3. 创建 ServiceConnection 并将其绑定到 IInAppBillingService
  4. 从您的应用发送应用内购买结算请求至IInAppBillingService
  5. 处理来自 Google Play 的应用内购买结算请求响应。

将 AIDL 文件添加到您的项目中


IInAppBillingService.aidl 是一种定义应用内购买结算版本 3 服务接口的 Android 接口定义语言 (AIDL) 文件。 您可以使用此接口通过调用 IPC 方法调用来发送结算请求。

要获取 AIDL 文件,请执行以下操作:

  1. 打开 Android SDK 管理器。
  2. 在 SDK 管理器中,展开 Extras 部分。
  3. 选择 Google Play Billing Library
  4. 点击 Install packages 完成下载。

IInAppBillingService.aidl 文件将安装到 /extras/google/play_billing/

要将 AIDL 添加到您的项目,请执行以下操作:

  1. 首先,下载 Google Play Billing Library 到您的 Android 项目:
    1. 选择 Tools > Android > SDK Manager
    2. 在 Appearance & Behavior > System Settings > Android SDK 下面,选择 SDK Tools 标签以选择并下载 Google Play Billing Library
  2. 接下来,复制 IInAppBillingService.aidl 文件到您的项目。
    • 如果您使用的是 Android Studio,请执行以下操作:
      1. 导航至 Project 工具窗口中的 src/main
      2. 选择 File > New > Directory,然后在 New Directory 窗口中输入 aidl,再选择 OK
      3. 选择 File > New > Package,然后在 New Package 窗口中输入 com.android.vending.billing,再选择 OK
      4. 使用您的操作系统文件资源管理器,导航至 /extras/google/play_billing/,复制 IInAppBillingService.aidl 文件,然后将其粘贴到项目中的 com.android.vending.billing 软件包。
    • 如果您在非 Android Studio 环境中开发,请执行以下操作:创建目录 /src/com/android/vending/billing,并将IInAppBillingService.aidl 文件复制到此目录。 将 AIDL 文件添加到您的项目中并使用 Gradle 工具构建项目,从而生成IInAppBillingService.java 文件。
  3. 开发您的应用。您会在项目的 /gen 目录中看到名为 IInAppBillingService.java 的生成文件。

更新您的应用清单


应用内购买结算依赖于 Google Play 应用,后者将处理应用与 Google Play 服务器之间的所有通信。 要使用 Google Play 应用,您的应用必须请求适当的权限。 您可以通过将 com.android.vending.BILLING 权限添加到 AndroidManifest.xml 文件执行此操作。 如果您的应用未声明应用内购买结算权限,但试图发送结算请求,Google Play 将拒绝请求并使用错误响应。

要为您的应用授予必要的权限,请在 AndroidManifest.xml 文件中添加以下代码行:

这个权限是一定得加的。

按照例子,先把所需Google aidl放好,位置一定不能错。

IInAppBillingService.aidl


还有所需的Util,都拷贝到项目中:


然后Clean一下,不让IInAppBillingService不能用。

下面开始代码集成:

先把所需要的常量定义一下:

    //google支付部分:    // 声明属性The helper object    private IabHelper mHelper;    private String TAG = "MyLog1";    /**     * Google是否初始化成功:     */    boolean iap_is_ok = false;    /**     * Google支付需要的     * 购买产品的id     */    static String purchaseId = "";    // (arbitrary) request code for the purchase flow    //购买请求回调requestcode    static final int RC_REQUEST = 1001;    //base64EncodedPublicKey是在Google开发者后台复制过来的:要集成的应用——>服务和API——>此应用的许可密钥(自己去复制)    String base64EncodedPublicKey = "MIIBIjANBgkqh******************************DAQAB";   

在onCreate中初始化:

mHelper = new IabHelper(this, base64EncodedPublicKey);        // enable debug logging (for a production application, you should set this to false).        mHelper.enableDebugLogging(true);        mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {            public void onIabSetupFinished(IabResult result) {                MyLog.i(TAG, "初始化完成.");                if (!result.isSuccess()) {                    // Oh noes, there was a problem.                    complain("Problem setting up in-app billing:初始化失败 " + result);                    return;                }                iap_is_ok = true;                if (mHelper == null) return;                MyLog.i(TAG, "Google初始化成功.");                if (iap_is_ok) {                    try {                        mHelper.queryInventoryAsync(mGotInventoryListener);                    } catch (IabHelper.IabAsyncInProgressException e) {                        e.printStackTrace();                    }                }else {                    MyLog.i(TAG, "Google Play初始化失败,当前无法进行支付,请确定您所在地区支持Google Play支付或重启游戏再试!");//                    toast("Google Play初始化失败,当前无法进行支付,请确定您所在地区支持Google Play支付或重启游戏再试!");                }            }        });
初始化的时候会去查询一下Google 后台自己所建立的产品,查询监听:

// Listener that's called when we finish querying the items and subscriptions we own  查询所有的产品    IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {        public void onQueryInventoryFinished(IabResult result, Inventory inventory) {            MyLog.i(TAG, "查询库存完成.");            // Have we been disposed of in the meantime? If so, quit.            if (mHelper == null) return;            // Is it a failure?            if (result.isFailure()) {                complain("查询库存失败: " + result);                return;            }            MyLog.i(TAG, "查询库存成功.");            /*             * Check for items we own. Notice that for each purchase, we check             * the developer payload to see if it's correct! See             * verifyDeveloperPayload().             */                       // Check for gas delivery -- if we own gas, we should fill up the tank immediately    //查询你的产品是否存在没有消耗的,要是没有消耗,先去消耗,再购买        Purchase gasPurchase = inventory.getPurchase(purchaseId);         if (gasPurchase != null && verifyDeveloperPayload(gasPurchase))         {             try {                 mHelper.consumeAsync(inventory.getPurchase(purchaseId), mConsumeFinishedListener);             } catch (IabHelper.IabAsyncInProgressException e) {                 complain("Error consuming gas. Another async operation in progress.");             }             return;         }         MyLog.i(TAG, "初始库存查询完成;启用主用户界面.");                     }             };

 然后是购买产品的点击事件中添加购买事件:   

    /**     * 去购买Google产品     * purchaseId  Google产品id     *     * 点击购买的时候,才去初始化产品,看看是否有这个产品,是否消耗     *     */    private void toBuyGooglepay(){        // launch the gas purchase UI flow.        // We will be notified of completion via mPurchaseFinishedListener        MyLog.i(TAG, "开始购买");        /* TODO: for security, generate your payload here for verification. See the comments on         *        verifyDeveloperPayload() for more info. Since this is a SAMPLE, we just use         *        an empty string, but on a production app you should carefully generate this. */        //这个payload是要给Google发送的备注信息,自定义参数,购买完成之后的订单中也有该字段        String payload = Contants.userID;        try {            mHelper.launchPurchaseFlow(TypeActivity.this, purchaseId, RC_REQUEST,mPurchaseFinishedListener, payload);        } catch (Exception e) {            Toast.makeText(TypeActivity.this,"无法完成谷歌支付",Toast.LENGTH_SHORT).show();        }    }
下面是几个所需的购买过程中事件监听:

1:购买完成的回调事件监听:

// Callback for when a purchase is finished购买完成的回调    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {            MyLog.i(TAG, "Purchase finished: " + result + ", purchase: " + purchase);            // if we were disposed of in the meantime, quit.            if (mHelper == null) return;            if (result.isFailure()) {                complain("Error purchasing: " + result);                return;            }            if (!verifyDeveloperPayload(purchase)) {                complain("Error purchasing. Authenticity verification failed.");                return;            }            MyLog.i("MyLog1", "购买完成.");            //购买完成时候就能获取到订单的详细信息:purchase.getOriginalJson(),要是想要什么就去purchase中get            //根据获取到产品的Id去判断是哪一项产品            if (purchase.getSku().equals(purchaseId)) {                MyLog.i(TAG, "购买的是"+purchase.getSku());                try {                    //购买完成之后去消耗产品                    mHelper.consumeAsync(purchase, mConsumeFinishedListener);                } catch (IabHelper.IabAsyncInProgressException e) {                    complain("Error consuming gas. Another async operation in progress.");                    return;                }            }        }    };

购买完成事件中有产品消耗事件监听,也就是说,购买完成时候,一定要去消耗一下产品,不然不能进行下次购买。

Google给出的声明:应用内商品一经购买,就会被视为“被拥有”且无法从 Google Play 购买。 您必须对应用内商品发送消耗请求,然后 Google Play 才能允许再次购买。可以消耗托管的应用内商品,但不能消耗订阅。下面是消耗监听:

// Called when consumption is complete 消耗产品的回调    IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {        public void onConsumeFinished(Purchase purchase, IabResult result) {            MyLog.i(TAG, "消耗完。购买(Purchase): " + purchase + ", result: " + result);            // if we were disposed of in the meantime, quit.            if (mHelper == 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                MyLog.i(TAG, "消费成功。Provisioning.");            }else {                complain("Error while consuming: " + result);            }        }    };

下面是几个用到的辅助类:

 /** Verifies the developer payload of a purchase. */    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;    }    void complain(String message) {        MyLog.i(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);        MyLog.i(TAG, "Showing alert dialog: " + message);        bld.create().show();    }

在onActivityResult中添加:

    @Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);            if (mHelper == null) return;            // Pass on the activity result to the helper for handling            try {                if (!mHelper.handleActivityResult(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...                    super.onActivityResult(requestCode, resultCode, data);                }else {                    MyLog.i("MyLog1", "onActivityResult handled by IABUtil.");                }            } catch (Exception e) {                e.printStackTrace();            }            if (requestCode == 1001) {                int responseCode = data.getIntExtra("RESPONSE_CODE", 0);//订单信息                String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");                String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");                MyLog.i("MyLog1", "responseCode:: " + responseCode );                MyLog.i("MyLog1", "purchaseData:: " + purchaseData );                MyLog.i("MyLog1", "dataSignature:: " + dataSignature );                if (resultCode == RESULT_OK) {                    try {                        JSONObject jo = new JSONObject(purchaseData);//订单Id                        String sku = jo.getString("productId");                        System.out.println("You have bought the " + sku + ". Excellent choice,adventurer!");                    }                    catch (JSONException e) {                        MyLog.i("MyLog1","Failed to parse purchase data.");                        System.out.println("Failed to parse purchase data.");                        e.printStackTrace();                    }                }            }        }}

完成购买之后一定要解除应用内购买服务,在onDestroy中添加

 @Override    protected void onDestroy() {        super.onDestroy();        if (mHelper != null) {            try {                mHelper.dispose();            } catch (Exception e) {                e.printStackTrace();            }        }        mHelper = null;    }

注:国内部分手机由于不能启动Google play service ,所以在解绑的时候可能会出错,(调用mHelper.dispose();方法时报错),解决办法:

在IabHelp.java中的300行左右把:

mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);


修改为:

新建一个绑定的判断:

public  boolean isBound;isBound = mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);


然后在dispose();方法中修改:

public void dispose() throws IabAsyncInProgressException {        synchronized (mAsyncInProgressLock) {            if (mAsyncInProgress) {                throw new IabAsyncInProgressException("Can't dispose because an async operation " +                    "(" + mAsyncOperation + ") is in progress.");            }        }        logDebug("Disposing.");        mSetupDone = false;        if (mServiceConn != null) {            logDebug("Unbinding from service.");            if (mContext != null && isBound){                mContext.unbindService(mServiceConn);                isBound = false;            }        }        mDisposed = true;        mContext = null;        mServiceConn = null;        mService = null;        mPurchaseListener = null;    }


代码集成到此结束,下面是测试:

首先你得有一个能安装Google play的手机,还要有个Gmail邮箱(不能和Google开发者的Gmail邮箱一样),测试支付不产生订单id,要是需要查看订单id就得真实支付(需要支持双币的信用卡或者paypal账号)。测试用的app一定要跟上传到Google的测试版的包名、版本code、name、签名一致,否则无法进行支付测试。

在Google开发后台:设置-->信息-->设置测试许可中添加你的测试Gmail邮箱(重要,不然会真实扣费)。在应用中的APK选项中,上传一版Bata版,发布,在测试人员中设置你的测试Gmail,和测试许可中的一致


另附Google play billing下载地址:https://github.com/googlesamples/android-play-billing/tree/master/TrivialDrive/app/src/main


更多相关文章

  1. 关于Android(安卓)WebView不支持location.href打开的解决方法 小
  2. NFC钥匙扣对于iPhone和Android设备从中国RFID
  3. Android支付宝支付
  4. Android(安卓)Pay,能冲破第三方支付围堵吗?
  5. Android(安卓)针对个人开发者的bmob支付
  6. 微信支付宝支付调用SDK
  7. android 支付宝
  8. android App集成支付宝
  9. Android中集成支付宝

随机推荐

  1. [置顶] android 长按和点击监听事件 谁先
  2. Android消息处理机制、Hanlder机制(Handle
  3. Android 检测键盘显示或隐藏键盘的实现代
  4. Android(安卓)开发遇到的问题
  5. Android的文件监控系统不可靠
  6. android屏幕触摸事件机制
  7. Android Binder 面试知识小结
  8. Android 更新UI的两种方法——handler和r
  9. android的软盘影响背景问题
  10. 如何解决android studio 运行时中文乱码