google内购以及拉起报错,充值拉不起来总结

发布时间:2024年01月11日

1.<uses-permission android:name="com.android.vending.BILLING" />

2.implementation("com.android.billingclient:billing:5.0.0")

3.谷歌内购代码

 //google内购//
    private BillingClient billingClient;

    private static final long RECONNECT_TIMER_START_MILLISECONDS = 1L * 1000L;
    private static final long RECONNECT_TIMER_MAX_TIME_MILLISECONDS = 1000L * 60L * 15L; // 15 mins
    private long reconnectMilliseconds = RECONNECT_TIMER_START_MILLISECONDS;
    private boolean billingSetupComplete = false;
    private static final Handler handler = new Handler(Looper.getMainLooper());
    protected static Handler uiHandler = new Handler(Looper.getMainLooper());
    private static Map<String, SkuDetails> skuDetailsLiveDataMap = new HashMap<>();
    private String[] cacheRequestList;
    private String buyProductId;


    public interface Action {
        public void Invoke();
    }

    //----------------------1.谷歌连接服务器-------------------------------
    protected void BillingClientInit() {
        System.out.print("-------1.连接服务器-----" + "\n");
        billingClient = BillingClient.newBuilder(this).setListener(this).enablePendingPurchases().build();
        billingClient.startConnection(this);
    }

    @Override
    public void onBillingServiceDisconnected() {
        // PrintLog("onBillingServiceDisconnected");
        billingSetupComplete = false;
        retryBillingServiceConnectionWithExponentialBackoff();
    }


    //----------------------1.谷歌连接服务器,状态-------------------------------
    @Override
    public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
        int responseCode = billingResult.getResponseCode();
        String debugMessage = billingResult.getDebugMessage();

        System.out.print("-------1.连接服务器成功:onBillingSetupFinished " + debugMessage + "(" + GetResponseText(responseCode) + ")" + "\n");

        switch (responseCode) {
            case BillingClient.BillingResponseCode.OK:
                // The billing client is ready. You can query purchases here.
                // This doesn't mean that your app is set up correctly in the console -- it just
                // means that you have a connection to the Billing service.
                reconnectMilliseconds = RECONNECT_TIMER_START_MILLISECONDS;
                billingSetupComplete = true;
                System.out.print("-------1.连接服务器成功 onBillingSetupFinished " + debugMessage + "(" + GetResponseText(responseCode) + ")" + "\n");
                break;
            case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE:
            case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE:
                System.out.print("-------1.连接服务器失败onBillingSetupFinished " + debugMessage + "(" + GetResponseText(responseCode) + ")" + "\n");
                break;
            default:
                retryBillingServiceConnectionWithExponentialBackoff();
                break;
        }
    }

    private void retryBillingServiceConnectionWithExponentialBackoff() {
        handler.postDelayed(() ->
                        billingClient.startConnection(this),
                reconnectMilliseconds);
        reconnectMilliseconds = Math.min(reconnectMilliseconds * 2,
                RECONNECT_TIMER_MAX_TIME_MILLISECONDS);
    }


    //----------------------------------------------------2.开始购买----------------------------------------------------------------------------
    public static void OnBuyProduct(String productId, String isConsumable1) {
        System.out.print("-------2.开始购买111  OnBuyProduct------  productId:" + productId + ",isConsumable:" + isConsumable1 + "\n");
        uiHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    activity.OnBuyProduct1(productId, true);
                } catch (Exception e) {
                    System.out.print("-------2.开始购买111  BuyProduct数据传输错误:" + e.getMessage() + "\n");
                }
            }
        });
    }

    public void OnBuyProduct1(String productId, boolean isConsumable) {
        System.out.print("-------2.开始购买222  OnBuyProduct1------  productId:" + productId + ",isConsumable:" + isConsumable + "\n");
        SkuDetails skuDetails = skuDetailsLiveDataMap.get(productId);
        if (skuDetails == null) {
            System.out.print("-------2.开始购买333  OnBuyProduct1------(skuDetails == null) productId:" + productId + ",isConsumable:" + isConsumable + "\n");
            RequstProducts(new String[]{productId}, new Action() {
                @Override
                public void Invoke() {
                    SkuDetails skuDetails = skuDetailsLiveDataMap.get(productId);
                    System.out.print("-------6.查詢商品id -成功-返回商品信息  开始购买  Invoke   RequstProducts:" + productId + ",isConsumable:" + isConsumable + "\n");
                    Purchase(productId, isConsumable, skuDetails);
                }
            });
        } else {
            System.out.print("-------2.开始购买333  OnBuyProduct1------  productId:" + productId + ",isConsumable:" + isConsumable + "\n");
            Purchase(productId, isConsumable, skuDetails);
        }
    }

    //3.查詢商品id
    private void RequstProducts(String[] productId, Action callBack) {
        System.out.print("-------3.查詢商品id111  RequstProducts------productId:" + productId + "\n");
        List<String> skuList = new ArrayList<>();
        skuList.addAll(Arrays.asList(productId));
        cacheRequestList = productId;
        SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
        params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);

        billingClient.querySkuDetailsAsync(params.build(),
                (billingResult, skuDetailsList) -> {
                    int responseCode = billingResult.getResponseCode();
                    System.out.print("------3.查詢商品id222 RequstProducts  查询商品列表:responseCode:" + responseCode + ",skuDetailsList.size()=" + skuDetailsList.size() + "\n");
                    switch (responseCode) {
                        case BillingClient.BillingResponseCode.OK:
                            System.out.print("------3.查詢商品id222 RequstProducts  成功  responseCode:" + responseCode + "\n");
                            RecieveProducts(skuDetailsList);
                            break;
                        default:
                            System.out.print("------3.查詢商品id222 RequstProducts  失败:" + billingResult.getDebugMessage() + "\n");
                            RequestProductsFail("Failed to query inventory: " + billingResult.getDebugMessage());
                            break;
                    }

                    if (callBack != null) {
                        System.out.print("------3.查詢商品id333  RequstProducts  callBack:callBack" + "\n");
                        callBack.Invoke();
                    }
                });
    }

    //4.查詢商品id -成功
    private void RecieveProducts(List<SkuDetails> skuDetailsList) {
        System.out.print("------4.查詢商品id-成功111   RecieveProducts  skuDetailsList.size():" + skuDetailsList.size() + "\n");
        ArrayList<SkuItem> skuItems = new ArrayList<SkuItem>();
        ArrayList<String> invaildIds = new ArrayList<String>();

        int length = cacheRequestList != null ? cacheRequestList.length : 0;
        if (length > 0) {
            for (int i = 0; i < length; i++) {
                String productId = cacheRequestList[i];
                if (!TextUtils.isEmpty(productId)) {
                    SkuDetails detail = null;
                    for (SkuDetails skuDetails : skuDetailsList) {
                        if (skuDetails.getSku().equals(productId)) {
                            detail = skuDetails;
                            break;
                        }
                    }

                    if (detail == null) {
//                        PrintLog("未找到该产品信息:"+productId);
                        invaildIds.add(productId);
                        continue;
                    }
                    skuDetailsLiveDataMap.put(productId, detail);

                    String price = detail.getPrice();
                    String formatPrice = price;

                    SkuItem skuItem = new SkuItem();
                    skuItem.productId = productId;
                    skuItem.title = detail.getTitle();
                    skuItem.desc = detail.getDescription();
                    skuItem.price = price;
                    skuItem.formatPrice = formatPrice;
                    skuItem.priceCurrencyCode = detail.getPriceCurrencyCode();
                    skuItem.skuType = detail.getType();

                    skuItems.add(skuItem);
                }
            }
        }
        RecieveProductInfo(skuItems, invaildIds);
    }

    //5.查詢商品id -成功-返回商品信息
    protected void RecieveProductInfo(ArrayList<SkuItem> skuItems, ArrayList<String> invalidProductIds) {
        JSONObject jsonObject = new JSONObject();
        try {
            JSONArray skuArray = new JSONArray();
            JSONObject tmpObj = null;
            for (int i = 0; i < skuItems.size(); i++) {
                SkuItem skuItem = skuItems.get(i);
                tmpObj = new JSONObject();
                tmpObj.put("productId", skuItem.productId);
                tmpObj.put("title", skuItem.title);
                tmpObj.put("desc", skuItem.desc);
                tmpObj.put("price", skuItem.price);
                tmpObj.put("formatPrice", skuItem.formatPrice);
                tmpObj.put("priceCurrencyCode", skuItem.priceCurrencyCode);
                tmpObj.put("skuType", skuItem.skuType);
                skuArray.put(tmpObj);
            }

            JSONArray invalidArray = new JSONArray();
            for (int i = 0; i < invalidProductIds.size(); i++) {
                invalidArray.put(invalidProductIds.get(i));
            }
            jsonObject.put("skuItems", skuArray);
            jsonObject.put("invalidIds", invalidArray);
        } catch (JSONException e) {
            // PrintLog("Json数据错误:"+e.getMessage());
        }
        String info = jsonObject.toString();
        System.out.print("------5.查詢商品id -成功-返回商品信息111  RecieveProducts  info:" + info + "\n");
    }

    private boolean isConsumable;

    //----------------------------------------------------3.开始购买---------------------------------------------------------------------------
    private void Purchase(String productId, boolean isConsumable, SkuDetails skuDetails) {
        System.out.print("-------7.开始购买Purchase productId:" + productId + ",isConsumable:" + isConsumable + "\n");
        if (null != skuDetails) {
            buyProductId = productId;
            this.isConsumable = isConsumable;

            BillingFlowParams purchaseParams =
                    BillingFlowParams.newBuilder()
                            .setSkuDetails(skuDetails)
                            .build();
            System.out.print("-------7.开始购买Purchase   buyProductId:" + buyProductId + "\n");
            billingClient.launchBillingFlow(this, purchaseParams);
        } else {
            System.out.print("-------7.开始购买Purchase  Can not find SkuDetails productId:" + buyProductId + "\n");
            BuyFail(productId, "Can not find SkuDetails:" + productId);
        }
    }

    public String ArrayList2String(ArrayList<String> arrayList) {
        String result = "";
        if (arrayList != null && arrayList.size() > 0) {
            for (String item : arrayList) {
                result += item + ",";
            }
            result = result.substring(0, result.length() - 1);
        }
        return result;
    }

    private void handlePurchase(Purchase purchase1) {
        ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchase1.getPurchaseToken()).build();
        ConsumeResponseListener listener = new ConsumeResponseListener() {
            @Override
            public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    try {

                        String signedData = purchase1.getOriginalJson();
                        String signature = purchase1.getSignature();

                        JSONObject jObject = new JSONObject();
                        jObject.put("signedData", signedData);
                        jObject.put("signature", signature);

                        System.out.print("------8.开始购买-上次购买物品未消耗-ITEM_ALREADY_OWNED  signedData:" + signedData + "\n");
                        System.out.print("------8.开始购买-上次购买物品未消耗-ITEM_ALREADY_OWNED  signature:" + signature + "\n");
                        System.out.print("------8.开始购买-上次购买物品未消耗-ITEM_ALREADY_OWNED  jObject.toString():" + jObject.toString() + "\n");

                        JavaGoJS("ProductBuyComplete", jObject.toString());

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        billingClient.consumeAsync(consumeParams, listener);  //去消耗道具
    }

    //3.开始购买--结果
    @Override
    public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> list) {
        int responseCode = billingResult.getResponseCode();
        System.out.print("-------8.开始购买--onPurchasesUpdated-- BillingResult [" + GetResponseText(responseCode) + "]: " + billingResult.getDebugMessage() + ",responseCode" + responseCode + "\n");
        switch (responseCode) {
            case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:

                System.out.print("-------8.开始购买-上次购买物品未消耗-ITEM_ALREADY_OWNED 00000 " + "\n");
                //上次购买物品未消耗
                if (billingClient != null && billingClient.isReady()) {
                    billingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP, new PurchasesResponseListener() {
                        @Override
                        public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> purchasesList) {
                            if (purchasesList != null) {
                                System.out.print("-------8.开始购买-上次购买物品未消耗-ITEM_ALREADY_OWNED   purchasesList.size():" + purchasesList.size() + "\n");
                                for (int i = 0; i < purchasesList.size(); i++) {
                                    Purchase purchase = purchasesList.get(i);
                                    handlePurchase(purchase);
                                }
                            } else {
                                // LogUtils.i(TAG, "processPurchases: with no purchases");
                            }
                        }
                    });
                }


                break;
            case BillingClient.BillingResponseCode.OK:
                System.out.print("-------8.开始购买--onPurchasesUpdated   成功  responseCode:" + responseCode + "\n");
                FlowFinish(true, null, list);
                break;
            case BillingClient.BillingResponseCode.USER_CANCELED:
                String productId = buyProductId;
                buyProductId = null;
                BuyCancle(productId);
                break;
            default:
                System.out.print("-------8.开始购买--onPurchasesUpdated    失败  responseCode:" + responseCode + "\n");
                FlowFinish(false, billingResult.getDebugMessage(), list);
                break;
        }
    }

    //3.开始购买--结果
    private void FlowFinish(Boolean isSuccess, String message, List<Purchase> purchases) {
        System.out.print("------ 9.FlowFinish  isSuccess:" + isSuccess + ",message:" + message + ",buyProductId:" + buyProductId + ",isConsumable:" + isConsumable + "\n");
        if (isSuccess) {
            if (buyProductId != null) {
                String productId = buyProductId;
                buyProductId = null;
                if (isConsumable) {
                    String purchaseToken = null;
                    String signedData = "";
                    String signature = "";
                    if (purchases != null) {
                        for (Purchase purchase : purchases) {
                            for (String skus : purchase.getSkus()) {
                                //需要校验付款状态
                                if (skus.contains(productId) &&
                                        purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
                                    purchaseToken = purchase.getPurchaseToken();
                                    signedData = purchase.getOriginalJson();
                                    signature = purchase.getSignature();

                                    System.out.print("------9.FlowFinish-purchaseToken" + purchaseToken + ",signedData:" + signedData + ",signature:" + signature + "\n");
                                    break;
                                }
                                if (purchaseToken != null) break;
                            }
                        }
                    }


                    System.out.print("------9.FlowFinish-purchaseToken" + purchaseToken + ",productId:" + productId + ",signature:" + signature + "\n");

                    if (purchaseToken == null) {
                        CallBackBuyFail("unknown purchaseToken:" + productId);
                    } else {

                        //验证购买。确保此purchaseToken的授权尚未被授予。授予用户权限。

                        ConsumeParams consumeParams =
                                ConsumeParams.newBuilder()
                                        .setPurchaseToken(purchaseToken)
                                        .build();

                        String finalSignedData = signedData;
                        String finalSignature = signature;
                        //consumeAsync()是处理消耗性商品
                        billingClient.consumeAsync(consumeParams, (billingResult, token) -> {
                            System.out.print("------9.FlowFinish-billingResult.getResponseCode()" + billingResult.getResponseCode() + ",finalSignedData:" + finalSignedData + ",finalSignature:" + finalSignature + "\n");
                            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                                System.out.print("------9.FlowFinish-OKOKOKOK" + "\n");
                                BuyComplete(productId, finalSignedData, finalSignature);
                            } else {
                                System.out.print("------9.FlowFinish-FailFailFail" + "\n");
                                CallBackBuyFail(billingResult.getDebugMessage());
                            }
                        });

                    }
                } else {
                    BuyComplete(productId, "", "");
                }
            }
        } else {
            if (buyProductId != null) {
                CallBackBuyFail(message);
            }
        }
    }


    //----------------------------------------------------4.开始购买结果--完成---------------------------------------------------------------------------
    protected void BuyComplete(String productId, String signedData, String signature) {
        System.out.print("------10.BuyComplete  productId:" + productId + ",signedData:" + signedData + ",signature:" + signature + "\n");
        try {
            JSONObject jObject = new JSONObject();
            // jObject.put("productId", productId);
            jObject.put("signedData", signedData);
            jObject.put("signature", signature);


            System.out.print("------10.BuyComplete  productId:" + productId + "\n");
            System.out.print("------10.BuyComplete  signedData:" + signedData + "\n");
            System.out.print("------10.BuyComplete  signature:" + signature + "\n");


            //{"signedData":"{\"orderId\":\"GPA.3309-4457-0847-02874\",\"packageName\":\"org.cocos2d.anzhan1\",\"productId\":\"80000\",\"purchaseTime\":1704802700986,\"purchaseState\":0,\"purchaseToken\":\"lcidfngdoakkjmcklgnjbmno.AO-J1OxyCG1tBKRiAtWsDijnTxR_aFwrbmBvPNXDca_xA_bhin10V0KIpzAEfQmhfBJmIrXOUIHo0MqensVlyYjVtYLCMBatGA\",\"quantity\":1,\"acknowledged\":false}","signature":"NHtMrmG0X5h4LTSfqgSQ57\/zQxUSpu9s2aOQ1C8jCDLTfRBS7kA2BtM0VGQSFR6Qf6hMd+k56pbZzzKVrJpL3N9\/fu23exI8\/UlHfmvovWB2m4a5Ukktgya4X1YOIIKGDjMPhxumKrarH+HZElFyvle1BG+BKOsXFLAF+vJ4FR9ONCDPmS2ljM9Sh8lOaPX4sNkYAVuAxsJ7TqBqTA+xJMLGkGIp\/7XKK82NW+Ge0moiGd02b2s0+3xjd28MsKqjLy58CoXCzCxf+uEZVY+6cipDdf049M0XjpV7C+rBlhPWGnr2aZBMXrK6nX+u2z3yMydy6SqNiOOYyJzezNzV\/A=="}
            System.out.print("------10.BuyComplete  jObject.toString():" + jObject.toString() + "\n");

            JavaGoJS("ProductBuyComplete", jObject.toString());

            //System.out.print("------10.BuyComplete  ---ProductBuyCompleteTest---" + "\n");
            //GoogleUtils.getInstance().JavaGoJSfu("ProductBuyCompleteTest", signedData, signature);
            //  SendUnityMessage("ProductBuyComplete", jObject.toString());
        } catch (JSONException e) {
            System.out.print("------10.BuyComplete  BuyComplete数据错误:" + e.getMessage() + "\n");
        }
    }


    protected void RequestProductsFail(String message) {
        System.out.print("------11.RequestProductsFail  message:" + message + "\n");
        JavaGoJS("ProductRequestFail", message);
    }


    protected void BuyCancle(String productId) {
        System.out.print("------11.ProductBuyCancled  productId:" + productId + "\n");
        JavaGoJS("ProductBuyCancled", productId);
    }


    private void CallBackBuyFail(String message) {
        String productId = buyProductId;
        buyProductId = null;
        BuyFail(productId, message);
        //  PrintLog("Error purchasing: " + message);
    }

    protected void BuyFail(String productId, String error) {
        //  PrintLog("购买失败:"+productId+"原因:"+error);
        try {
            JSONObject jObject = new JSONObject();
            jObject.put("productId", productId);
            jObject.put("error", error);

            System.out.print("------11.ProductBuyFailed  jObject.toString():" + jObject.toString() + "\n");
            JavaGoJS("ProductBuyFailed", jObject.toString());

        } catch (JSONException e) {
            // PrintLog("BuyFail数据错误:"+e.getMessage());
        }
    }


    private String GetResponseText(int responseCode) {
        switch (responseCode) {
            case BillingClient.BillingResponseCode.OK:
                return "OK";
            case BillingClient.BillingResponseCode.SERVICE_TIMEOUT:
                return "SERVICE_TIMEOUT";
            case BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED:
                return "FEATURE_NOT_SUPPORTED";
            case BillingClient.BillingResponseCode.USER_CANCELED:
                return "USER_CANCELED";
            case BillingClient.BillingResponseCode.SERVICE_DISCONNECTED:
                return "SERVICE_DISCONNECTED";
            case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE:
                return "SERVICE_UNAVAILABLE";
            case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE:
                return "BILLING_UNAVAILABLE";
            case BillingClient.BillingResponseCode.ITEM_UNAVAILABLE:
                return "ITEM_UNAVAILABLE";
            case BillingClient.BillingResponseCode.DEVELOPER_ERROR:
                return "DEVELOPER_ERROR";
            case BillingClient.BillingResponseCode.ERROR:
                return "ERROR";
            case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:
                return "ITEM_ALREADY_OWNED";
            case BillingClient.BillingResponseCode.ITEM_NOT_OWNED:
                return "ITEM_NOT_OWNED";
            default:
                return "UnKnown";
        }
    }

5.测试总结经验

? ?1.不要从本地studio安装手机包去测试充值,大部分情况是拉不起来充值,会包billingresult.getresponsecode() code 3问题

? ?2.上线内部测试版本就可以测试充值了。但是上传到google商店需要等20分钟左右测试最佳,从谷歌商店下载内部测试版本的时候一定要看版本号,大部分情况是上次的版本号,需要等20分钟左右才改变版本号。

? ?3.查看谷歌商店付费栏目里面有没有产品,如果有产品是可以测试充值的,无产品那就是账号的问题了,被锁区。需要更换账号,不需要更换手机。

文章来源:https://blog.csdn.net/alengan/article/details/135521100
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。