Android集成Google Play支付,从配置到测试通过

 文档地址:google play 的结算服务

首先说明这不是google pay,而是google play自己的结算服务,上架google play后可直接调起支付;第一次上海外,刚开始也准备接入google pay,不接害怕google play审核不通过,但流程太过麻烦,还需要注册第三方的账号,偶然发现google play自带了结算服务,接入也比较简单,也不需要注册其他平台的账号,就选择了这个;还有一点要注意:以下每一步都很重要,全部都要做。都是我走过不少坑总结出来的。

前提准备:

  1. 需要手机配置google服务
  2. 把应用上传到google play平台,未上架的可以传到测试渠道
  3. 设置定价模板,为应用内商品使用

          Android集成Google Play支付,从配置到测试通过_第1张图片

       4. 选中应用,创建应用内商品

           Android集成Google Play支付,从配置到测试通过_第2张图片

        5. 设置付款资料,其中的商家ID后续在代码中会用到

           Android集成Google Play支付,从配置到测试通过_第3张图片

         6. 设置商家账号并与付款资料关联

客户端开发流程:

  • 添加库  当前最新的为4.0.0
    //google play 结算
    implementation "com.android.billingclient:billing:${project.ext.billingVersion}"
  •  初始化
    /**
     * 初始化
     */
    public void init() {
        mBillingClient = BillingClient.newBuilder(mActivityRef.get())
                .setListener(mPurchasesUpdatedListener)
                .enablePendingPurchases()
                .build();
        if (!mBillingClient.isReady()) {
            mBillingClient.startConnection(new BillingClientStateListener() {
                @Override
                public void onBillingSetupFinished(BillingResult billingResult) {
                    if (billingResult != null) {
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            getOrderID();//从后台获取订单id
                        } else {
                            ToastUtil.showToast(ReaderApplication.getInstance()
                                    .getResources().getString(R.string.recharge_no_service));
                        }
                    }
                }

                @Override
                public void onBillingServiceDisconnected() {
                    ToastUtil.showToast(ReaderApplication.getInstance()
                            .getResources().getString(R.string.recharge_no_service));
                }
            });
        } else {
            getOrderID();
        }
    }
  • 获取订单id
    /**
     * 获取订单ID
     */
    private void getOrderID() {
        HashMap params = new HashMap<>(16);
        params.put("productId", productId);
        new NetModel().doPost(NetApi.ANDROID_URL_PAY_ORDER_GOOGLE, params, new INetCallBack() {
            @Override
            public void onSuccess(JSONObject result) {
                boolean success = JsonUtil.getBoolean(result, "success");
                String message = JsonUtil.getString(result, "message");
                JSONObject data = JsonUtil.getJSONObject(result, "data");
                if (success) {
                    mOrderID = JsonUtil.getString(data, "topUpId");
                    recharge();
                } else {
                    mListener.onState(mActivityRef.get(),
                            RechargeResult.failOf(message));
                }
            }
            @Override
            public void onFail(String msg) {
                ToastUtil.showToast(msg);
            }
        });
    }
  • 购买
    /**
     * 购买 mUserID:就是上面提到的商家id
     */
    private void recharge() {
        if (mBillingClient.isReady()) {
            List skuList = new ArrayList<>();
            skuList.add(mSku);
            SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
            params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
            mBillingClient.querySkuDetailsAsync(params.build(),
                    (billingResult, skuDetailsList) -> {
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
                                && skuDetailsList != null) {
                            for (SkuDetails skuDetails : skuDetailsList) {
                                String sku = skuDetails.getSku();
                                if (mSku.equals(sku)) {
                                    BillingFlowParams purchaseParams =
                                            BillingFlowParams.newBuilder()
                                                    .setSkuDetails(skuDetails)
                                                    .setObfuscatedAccountId(mUserID)
                                                    .setObfuscatedProfileId(mOrderID)
                                                    .build();
                                    mBillingClient.launchBillingFlow(mActivityRef.get(), purchaseParams);
                                }
                            }
                        } else {
                            ToastUtil.showToast(ReaderApplication.getInstance()
                                    .getResources().getString(R.string.recharge_no_service));
                        }
                    });
        }
    }
   /**
     * 购买回调
     */
    private PurchasesUpdatedListener mPurchasesUpdatedListener = new PurchasesUpdatedListener() {
        @Override
        public void onPurchasesUpdated(BillingResult billingResult, List list) {
            String debugMessage = billingResult.getDebugMessage();
            Log.e(TAG, debugMessage);
            if (list != null && list.size() > 0) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    for (Purchase purchase : list) {
                        mConsume = "2";
                        uploadToServer(purchase.getPurchaseToken(), mOrderID);
                    }
                } else {
                    ToastUtil.showToast(billingResult.getDebugMessage());
                }
            } else {
                switch (billingResult.getResponseCode()) {
                    case BillingClient.BillingResponseCode.SERVICE_TIMEOUT: {//服务连接超时"-3"
//                        mListener.onState(mActivityRef.get(), RechargeResult.failOf("-3"));
                        mListener.onState(mActivityRef.get(), "服务连接超时");
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED: {//-2
//                        mListener.onState(mActivityRef.get(), RechargeResult.failOf("-2"));
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.SERVICE_DISCONNECTED: {//服务未连接-1
                        mListener.onState(mActivityRef.get(), "服务未连接");
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.USER_CANCELED: {//取消1
                        mListener.onState(mActivityRef.get(), "支付取消");
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE: {//服务不可用2
                        mListener.onState(mActivityRef.get(), "服务不可用");
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE: {//购买不可用3
                        mListener.onState(mActivityRef.get(), "购买不可用");
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.ITEM_UNAVAILABLE: {//商品不存在4
                        mListener.onState(mActivityRef.get(), "商品不存在");
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.DEVELOPER_ERROR: {//提供给 API 的无效参数5
                        mListener.onState(mActivityRef.get(), "提供给 API 的无效参数");
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.ERROR: {//错误6
                        mListener.onState(mActivityRef.get(), "错误");
                        mActivityRef.get().finish();
                        break;
                    }
                    case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED: {//未消耗掉
                        mConsume = "1";
                        queryHistory();
                        break;
                    }
                    case BillingClient.BillingResponseCode.ITEM_NOT_OWNED: {//不可购买8
                        mListener.onState(mActivityRef.get(), "不可购买");
                        mActivityRef.get().finish();
                        break;
                    }
                    default:
                        break;
                }
            }
        }
    };
  •  上传到服务器验证
    /**
     * 上传到服务器验证接口
     */
    private void uploadToServer(final String purchaseToken, String mOrderID) {
        HashMap params = new HashMap<>(16);
        Log.i(TAG, "uploadToServer: purchaseToken=" + purchaseToken + "    topUpId=" + mOrderID);
        params.put("purchaseToken", purchaseToken);
        params.put("topUpId", mOrderID);
        new NetModel().doPost(NetApi.ANDROID_URL_PAY_CALL_GOOGLE, params, new INetCallBack() {
            @Override
            public void onSuccess(JSONObject result) {
                boolean success = JsonUtil.getBoolean(result, "success");
                String message = JsonUtil.getString(result, "message");
                if (success) {
                    ToastUtil.showToast("充值成功");
                    AppsFlyerPoint.purchaseSuccess(amount, bookId, chapterId);
                    consume(purchaseToken);
                } else {
                    mListener.onState(mActivityRef.get(),
                            RechargeResult.failOf(message));
                }

            }

            @Override
            public void onFail(String msg) {
                ToastUtil.showToast(msg);
            }
        });
    }
    /**
     * 消耗
     */
    private void consume(String purchaseToken) {
        if (mBillingClient.isReady()) {
            ConsumeParams consumeParams = ConsumeParams.newBuilder()
                    .setPurchaseToken(purchaseToken)
                    .build();
            mBillingClient.consumeAsync(consumeParams, (billingResult, s) -> {

            });
        } else {
            mBillingClient.startConnection(new BillingClientStateListener() {
                @Override
                public void onBillingSetupFinished(BillingResult billingResult) {
                    if (billingResult != null) {
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            ConsumeParams consumeParams = ConsumeParams.newBuilder()
                                    .setPurchaseToken(purchaseToken)
                                    .build();
                            mBillingClient.consumeAsync(consumeParams, (billingResult1, s) -> {

                            });
                        } else {
                            ToastUtil.showToast(ReaderApplication.getInstance()
                                    .getResources().getString(R.string.recharge_no_service));
                        }
                    }
                }

                @Override
                public void onBillingServiceDisconnected() {
                }
            });
        }

    }

测试

还有流程和国内差别最大的一点,测试

  • 必须设置 许可测试  ,在google play 的应用管理中心,设置-许可测试,添加测试人员,并把许可相应设为:LICENSED;没设置之前调起一直显示商品无法购买;

       Android集成Google Play支付,从配置到测试通过_第4张图片

  •  选中应用,添加测试用户,此处需要复制链接后,让测试人员登录google浏览器,打开此链接,接受邀请,测试账号设置过许可测试后,不需要非要从该链接下载应用测试,直接运行到手机的debug版也可以测试支付功能,而且不会真实扣费,也不需要绑定信用卡等;

         Android集成Google Play支付,从配置到测试通过_第5张图片

你可能感兴趣的:(第三方,android,android,studio,gradle)