Почему API биллинга Google, установленный в их документации, постоянно возвращает код 5?

Я начинающий разработчик Android, который никогда не использовал биллинг внутри приложения. Поэтому я выполнил шаги, описанные в собственной документации Google по адресу http://developer.android.com/google/play/billing/billing_integrate.html.

Я добавил файл IInAppBillingService.aidl в main/aidl/com.android.vending.billing, и моя структура соответствует бесчисленным скриншотам, которые я видел в Интернете.

Я добавил код, очень похожий на пример кода, в часть моего приложения, которая взаимодействует с моим онлайн-магазином. Упрощенная версия этого кода с удалением посторонних вещей:

    imports...
    import android.content.ServiceConnection;

    import com.android.vending.billing.IInAppBillingService;


    public class intMarket extends Activity {
        IInAppBillingService mService;
        public static final String SHARED_PREFS_NAME="myAppSettings";
        public static String purchaseToken = "";

        ServiceConnection mServiceConn = new ServiceConnection() {
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mService = null;
            }

            @Override
            public void onServiceConnected(ComponentName name,
                                           IBinder service) {
                mService = IInAppBillingService.Stub.asInterface(service);
            }
        };

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.intbrowser);

            Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
            serviceIntent.setPackage("com.android.vending");
            bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);

            WebView myWebView = (WebView) findViewById(R.id.webview);
            myWebView.setWebViewClient(new WebViewClient());
            WebSettings webSettings = myWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);
            myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");

            String tUrl = getString(R.string.urlMarket);
            SharedPreferences settings = getSharedPreferences(SHARED_PREFS_NAME, 0);
            myWebView.loadUrl(tUrl);
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            if (mService != null) {
                unbindService(mServiceConn);
            }
        }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == 1001) {
                int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
                String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
                String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");

                if (resultCode == RESULT_OK) {
                    try {
                        JSONObject jo = new JSONObject(purchaseData);
                        String sku = jo.getString("productId");
                        purchaseToken = jo.getString("purchaseToken");
                    }
                    catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        public class  WebAppInterface {
            Context mContext;

            /** Instantiate the interface and set the context */
            WebAppInterface(Context c) {
                mContext = c;
            }

            /** Show a toast from the web page */
            @JavascriptInterface
            public void showToast(String toast) {
                Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
            }

             @JavascriptInterface
            public void purchaseItem(Integer itemID, String itemName, BigDecimal itemPrice) {
                // Credit Purchase
                 ArrayList<String> skuList = new ArrayList<String> ();
                 Bundle querySkus = new Bundle();
                 querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
                 String purchaseCreditsResponse = "Success";
                 try {
                     Bundle skuDetails = mService.(3, getPackageName(), "inapp", querySkus);
                     Log.d("WPS", skuDetails.toString());

                     int response = skuDetails.getInt("RESPONSE_CODE");
                     Log.d("WPS", Integer.toString(response));

                     if (response == 0) {
                         ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
                         String thisItemID = "0";

                         for (String thisResponse : responseList) {
                             JSONObject object = new JSONObject(thisResponse);
                             String itemPrice = object.getString("price");
                             if (itemPrice.equals(itemPrice.toString()))
                                 thisItemID = object.getString("productId");
                         }

                         if (Integer.parseInt(thisItemID) > 0) {
                             Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), thisItemID, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
                             if (buyIntentBundle.getInt("RESPONSE_CODE") == 0) {
                                 PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
                                 //startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
                                 // purchaseToken
                                 purchaseCreditsResponse = "Failure";
                                 Toast.makeText(mContext, "Buying: " + itemName, Toast.LENGTH_LONG).show();
                             }
                         } else {
                             purchaseCreditsResponse = "Failure";
                             Toast.makeText(mContext, "Sorry, but there was a problem with your purchase.  Please try again.  If the problem persists, contact support.  Error Code: 001.", Toast.LENGTH_LONG).show();
                         }
                     } else {
                         purchaseCreditsResponse = "Failure";
                         Toast.makeText(mContext, "Sorry, but there was a problem with your purchase.  Please try again.  If the problem persists, contact support.  Error Code: 002.", Toast.LENGTH_LONG).show();
                     }
                 } catch (RemoteException e) {
                     purchaseCreditsResponse = "Failure";
                     Toast.makeText(mContext, "Sorry, but there was a problem with your purchase.  Please try again.  If the problem persists, contact support.  Error Code: 003.", Toast.LENGTH_LONG).show();
                 } catch (JSONException e) {
                     purchaseCreditsResponse = "Failure";
                     Toast.makeText(mContext, "Sorry, but there was a problem with your purchase.  Please try again.  If the problem persists, contact support.  Error Code: 004.", Toast.LENGTH_LONG).show();
                 }// catch (IntentSender.SendIntentException e) {
                 //    purchaseCreditsResponse = "Failure";
                 //    Toast.makeText(mContext, "Sorry, but there was a problem with your purchase.  Please try again.  If the problem persists, contact support.  Error Code: 005.", Toast.LENGTH_LONG).show();
                 //}



                // Purchase Report
                // Report purchase and get response into purchaseResponse
                // Todo


                // Credit Consumption
                // Todo
            }
        }
    }

Затем я скомпилировал эту версию, загрузил APK в Google Play в качестве альфа-теста и опубликовал его. Я делаю обновления и использую ADB для установки новых скомпилированных APK на свой телефон, но я постоянно получаю следующее из этого кода в LogCat:

    03-23 15:07:55.325    2958-3009/? D/WPS﹕ Bundle[mParcelledData.dataSize=48]
    03-23 15:07:55.325    2958-3009/? D/WPS﹕ 5

Что, конечно, указывает: BILLING_RESPONSE_RESULT_DEVELOPER_ERROR

Я прочитал в другом посте SO, что вы не можете проверить выставление счетов на устройстве, основная учетная запись которого совпадает с учетной записью разработчика. Поэтому вчера я потратил несколько часов на то, чтобы найти другой телефон и настроить его с помощью совершенно отдельной учетной записи (и единственной учетной записи на устройстве). Я загрузил новую сборку в Google Play в качестве альфа-теста и опубликовал ее. Я подождал, пока другой телефон получит новую версию, и снова попытался протестировать биллинг. Телефон сообщил об этом сообщении об ошибке, которое я встроил:

 Sorry, but there was a problem with your purchase.  Please try again.  If the problem persists, contact support.  Error Code: 002.

Что указывает на ту же ошибку, с которой я столкнулся раньше. Это подразумевает, что есть проблема с моим кодом, которая не удивит меня.

Я ничего не сделал с большим гигантским лицензионным кодом, который появляется на панели разработчиков Google Play, потому что в вышеупомянутой документации ничего не сказано о том, что он требуется. Но так ли это? Если нет, то как насчет моего кода вызывает эту проблему?

2 ответа

Люди комментируют, что это ошибка в биллинговом API Google (может быть, Google считает это функцией?). Похоже, вы должны потреблять токен покупки, так же, как парень здесь:

String purchaseToken = o.optString("token", o.optString("purchaseToken"));
// Consume purchaseToken, handling any errors
mService.consumePurchase(3, getPackageName(), purchaseToken);

Подтвердите это com.android.vending.BILLING добавлен в ваши разрешения манифеста.

Также убедитесь, что ваше приложение подписано вашим рабочим ключом, и версия в Google Play должна совпадать с версией, с которой вы тестируете.

Также взгляните на эту легкую, простую библиотеку, которую вы можете использовать на Github ниже: https://github.com/anjlab/android-inapp-billing-v3

Другие вопросы по тегам