Android in app purchase failed

Android in-app purchases, часть 4: коды ошибок от Billing Library и как не облажаться с тестированием

Привет, я Влад, core разработчик Adapty SDK для Android. Продолжаю серию статей про то, как внедрять внутренние покупки в приложение Google Play. Остальные посты можно найти по ссылкам:

Android in-app purchases, часть 4: коды ошибок от Billing Library и как не облажаться с тестированием. — Вы тут.

Сегодня мы поговорим о кодах ошибок, которые мы можем получить от Billing Library в методе getResponseCode().

Пример того, как мы передавали ошибки в свои колбэки, можно посмотреть в этой статье. С одной ошибкой мы уже знакомы по предыдущим статьям — это USER_CANCELED, когда пользователь закрывает диалог покупки, ничего не купив. Давайте познакомимся с остальными.

Коды ошибок

Начнем с самых простых ошибок – с говорящим названием ERROR (responseCode 6) и чуть более говорящим названием DEVELOPER_ERROR (responseCode 5). Для первого случая гугл пишет в документации «Fatal error during the API action», для второго – «Invalid arguments provided to the API». Например, я смог получить DEVELOPER_ERROR, когда для запроса querySkuDetailsAsync() в билдер в setType() передал пустую строку.

Но не всё так просто. Я пошел дальше и в методе launchBillingFlow() использовал измененный SkuDetails (вытащил json из SkuDetails реального продукта, поменял в нем productId и передал в конструктор новому SkuDetails). По сути это invalid argument, и я ожидал получить DEVELOPER_ERROR, но… получил ERROR.

Отдельного упоминания заслуживает текст, который показывается в диалоге в этом кейсе — сравните английский и русский вариант:

Это, конечно, был искусственный пример. Гораздо ближе к реальности кейс, когда гугл отклонил оплату. Если при тестировании покупок с тестовой карты, о чем мы расскажем в конце статьи, в диалоге покупки выбрать «test card, always declined», вернется также ошибка ERROR, но уже с адекватным текстом.

В третьей статье, где описывалась смена подписки, мы для одного из proration mode увеличили цену годовой подписки почти в 3 раза, но не сказали, какая там должна была быть ошибка, если бы мы этого не сделали. Исправляемся.

Так как там, получается, указан неправильный proration mode, по логике мы должны получить всё ту же DEVELOPER_ERROR. Но нет, мы получаем SERVICE_UNAVAILABLE (responseCode 2). Ее же мы получаем и если указать любое левое число в качестве proration mode (это int, а не enum, нас никто не остановит), и если указать неправильный purchaseToken. Смотрим в документацию про SERVICE_UNAVAILABLE – «Network connection is down». Так, стоп…

При этом еще мы видим интересный диалог.

Что еще любопытно – в кейсе с ERROR при закрытии диалога НЕ через кнопку «ОК» (то есть, теми способами, которые интерпретируются как возврат назад) в onPurchasesUpdated() пришло, собственно, ERROR, а в случае с SERVICE_UNAVAILABLE в аналогичном кейсе приходит USER_CANCELED (но если нажать «ОК» в диалоге, то мы, как и ожидали, получим SERVICE_UNAVAILABLE).

Ну и в случае с отсутствием интернета SERVICE_UNAVAILABLE тоже приходит, тут не соврали.

Вот остальные коды ошибок с небольшими комментариями, так сказать, honorable mentions.

BILLING_UNAVAILABLE (responseCode 3). Гугл поясняет, что «Billing API version is not supported for the type requested». Я смог воспроизвести эту ошибку, разлогинившись из Google-аккаунта, а также на Хуавее без Google Play Services. Возможно, она также воспроизведется на старых телефонах, где не обновляли Google Play.

SERVICE_DISCONNECTED (responseCode -1). Приложение иногда дисконнектится от сервиса Google Play. Это может произойти, если Play Store вдруг решит обновиться. Поэтому лучше перестраховаться и коннектиться перед каждым вызовом методов Billing Library, как в предыдущих статьях. А еще мы с гуглом советуем добавить какую-нибудь retry policy, если эта ошибка всё же придет в ответе.

Читайте также:  Что андроид взял у ios

SERVICE_TIMEOUT (responseCode -3). Название говорит само за себя — мы слишком долго ждали ответ от Google Play.

FEATURE NOT SUPPORTED (responseCode -2). В классе BillingClient есть пять констант FeatureType. Их доступность на данном устройстве можно проверять с помощью метода billingClient.isFeatureSupported(BillingClient.FeatureType.НужнаяФича). У меня на телефоне (Xiaomi Mi A2 Lite) FEATURE_NOT_SUPPORTED вернулось только для SUBSCRIPTIONS_ON_VR. При этом для IN_APP_ITEMS_ON_VR, как и для всех остальных фич, вернулось OK.

ITEM_NOT_OWNED (responseCode 8). Возникает при попытке законсьюмить покупку, которой у нас нет. Например, повторно после успешного консьюма.

ITEM_ALREADY_OWNED (responseCode 7). А тут наоборот – при попытке купить продукт, который у нас уже есть. В таком кейсе просто нужно обновить UI и сделать кнопку покупки некликабельной.

Самая популярная ошибка

Последняя и, наверное, самая популярная ошибка в начале пути внедрения in-app purchases — это ITEM_UNAVAILABLE (responseCode 4). Она говорит о том, что продукт недоступен для покупки, но не говорит, почему. А причины могут быть самые разные: от тестирования на неправильном аккаунте или неправильной сборке до покупки неактивированного продукта.

Вот чек-лист, что нужно сделать, чтобы избежать ее при тестировании:

Отправить в ваш test track сборку с Billing Library. Это обязательное условие — при этом вы можете тестировать и на дебажных сборках с таким же applicationId, но важно, чтобы хотя бы один раз сборка с Billing Library была загружена в Play Console.

Добавить в этот test track гугл-аккаунты тестировщиков, что особенно актуально для internal testing или закрытой альфы/беты. Там же будет ссылка в разделе How testers join your test, по которой тестировщики должны будут принять приглашение.

Покупать можно только активированный продукт. После создания продукта в Play Console есть кнопка activate, более детально процесс создания продукта мы описывали в первой статье.

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

applicationId сборки, с которой тестируется покупка, должно полностью совпадать с applicationId из Play Console. Это особенно важно для тех, у кого добавляется суффикс в дебажных сборках.

Добавить email-адреса тестировщиков в раздел Setup → License Testing в левом меню аккаунта (не приложения), чтобы они покупали продукты бесплатно с тестовой карты, а не с реальной. Еще один плюс, что подписки в данном случае будут иметь тестовую длительность. Не связано с этой ошибкой, но тоже полезное знание.

Заключение

Ошибки способны сильно усложнить работу, поэтому всегда важно понимать, как они могут возникнуть. Учитывая, сколько шагов нужно пройти, чтобы получить доступ к продуктам, проще всего словить ITEM_UNAVAILABLE. Поэтому я надеюсь, что мой чек-лист вам поможет.

Про Adapty

Для более простой работы с ошибками советую попробовать Adapty SDK для внедрения внутренних покупок в приложения. Кроме технической части, Adapty даёт много преимуществ:

Встроенная аналитика позволяет быстро понять основные метрики приложения.

Когортный анализ отвечает на вопрос, как быстро сходится экономика.

А/Б тесты увеличивают выручку приложения.

Интеграции с внешними системами позволяют отправлять транзакции в сервисы атрибуции и продуктовой аналитики.

Промо-кампании уменьшают отток аудитории.

Open source SDK позволяет интегрировать подписки в приложение за несколько часов.

Серверная валидация и API для работы с другими платформами.

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

Источник

android in app billing purchase verification failed

i’ having trouble implementing in app billing in my android app. i’m getting a purchase signature verification failed. In a first time i tough it was the base64 key but i checked it many times and i’m still getting the error, then after i took a look at the Security.java file and i found this method which i edited for get some informations about what was wrong:

Читайте также:  Конвертер аудио форматов андроид

And i’m getting «signature is empty». Even after i follow the steps below: -Sign the apk with my release key -upload it as a draft -install it on a device with «adb -d install app.apk»

I’m testing with real purchases. Thanks.

Edit The purchase flow is fine, i get the error when i call queryInventoryAsync

4 Answers 4

You can use the test SKU’s to do testing, as explained here. These are:

  • android.test.purchased
  • android.test.canceled
  • android.test.refunded
  • android.test.item_unavailable

These purchases will be successful (at least the android.test.purchased) even in test and debug scenario’s, without the need to cancel the purchase.

In the verifyPurchase I changed return false to:

but you should be aware to use this only in test scenario’s.

This will return true, if you have a debug build, and the signature data is missing. Since the BuildConfig.DEBUG will be false in a production build this should be OK. But better is to remove this code after everything is debugged.

Replace your verifyPurchase() method with below one. Use old code that given below, google developer are trying to solve this error in the near future but before they updated their code you should prefer below code.

check this link for more information:

Use try to replace OLD CODE method verifyPurchase() method in your project. But It should be only happens when you are trying to purchase test products. Let me know for the real products purchase also after using this code.

Edit:

Why it happens because we will not get any signature while we are using dummy product like «android.test.purchased». So in the old code it is working good because we were return true even if signature is not given and for the New code we are returning false.

more information about the signature data null or blank from link1 and link2

So I suggest you just replace old code method verifyPurchase() instead of New Code method.

I think may be New Code will work fine for the real product but not in the dummy product. But yet I have not tested for the real product.

or

use GvS’s answer for the test purchases it also the good solution for the new code.

Источник

Android In-app purchase: While purchasing got network failed popup but purchase has been completed got an email

I am getting a weird issue from the in-app purchase IInAppBillingService version 3 since 1 week ago.

Below are the steps what I had followed:

Note: I followed these steps because few of my users got same network issue but purchase has been completed. But app still showing Buy button for that product. So to replicate the issue I had to follow these steps.

  1. Installed the debuggable signed APK over the play store version.
  2. Clicked on item to buy
  3. Opened the play store popup with Buy button. Clicked on Buy in the purchased popup
  4. I lost the network while purchasing a product. Got a popup with No Internet Connection
  5. Clicked on ok in the No Internet Connection popup. Return to my application.
  6. Again clicked on item to buy.
  7. Now got the Error —> You already owned this item

But the problem is, I didn’t get any purchase result in the app mPurchaseFinishedListener callback . I got Null. Even I got the email from the google and I checked that whether it is purchased or not in the Google Play store —> Menu —> Account —> Order History

My product is Managed Product but user can purchased it multiple times. So for that, whenever opening the product or after finishing the purchase consuming the desired purchase based on the skuId if it is purchased.

Читайте также:  Как подписать apk файл для android

Now I am not able consume the product or even not able to purchase. Why is it so that play store completed the purchase but it didn’t return the purchase details to callback?

As far as I know if an item already purchased for that SKUID it should return the purchase details. But in my case it is not returning the purchase details.

Источник

Signature verification failed — Android in-app purchase

I have implemented in app billing on an Android application and although it works ok with the testing constants, it breaks on real products.

I have uploaded the application as a draft on Google Play, created and published products, installed the exact same application on the device (included the right base64EncodedPublicKey) and used the right test account (the primary account on the device & the one i did set on my developer account)

The flow is that I get on the Google Play Activity where I can see the product and its details, I press buy, introduce the test account password, it gets out of the activity, receive the congratulation message and

Signature verification failed for product(response:-1003:Purchase signature verification failed)

The item is actually purchased (it appears on Google Checkout and on a 2nd buying atempt it says «Item already owned»). Also I have used only the TriviaDrive example code from Google.

Any suggestions are very helpful. Thank you!

5 Answers 5

In the In App Billing documentation there is a section called Initiate your connection to Google Play.

It tells you that you would need a base64 encoded Public Key to instantiate your IabHelper. You can get this code from the Google Play Developer Console. Login into the console, click apps and then go to the «Services and API» tab.

Please consider the security recommendations suggested in the documentation:

Security Recommendation: It is highly recommended that you do not hard-code the exact public license key string value as provided by Google Play. Instead, you can construct the whole public license key string at runtime from substrings, or retrieve it from an encrypted store, before passing it to the constructor. This approach makes it more difficult for malicious third-parties to modify the public license key string in your APK file.

Another reason this error can appear in v3 of IAB is if you purchase a product (say, a subscription) on one device, and the purchase info doesn’t make it fully into the cache of the Play store app on another device.

I had a scary period where after purchasing a subscription on a Kitkat phone, another phone (gingerbread) was getting this -1003 error. I traced it down to the fact that the getpurchases() method was returning ONLY the INAPP_PURCHASE_ITEM_LIST with a (correct) list purchases. The INAPP_PURCHASE_DATA_LIST and INAPP_DATA_SIGNATURE_LIST were returned as null. (This was even though I could see the subscription in the Play app.)

The signature was null, so of course it got a signature verification error. After a lot of head-scratching/panicking about why it wasn’t working, suddenly it worked without me doing anything. I presume Google Services/Play app finally flushed the cache and updated itself.

Given this, I think the solution may be to just silence that error until the full purchase info propagates to Play Services. w/iabhelper it was something like:

This seems like a pretty big bug— the Play store should wait until it knows everything about the purchase before passing it on to an app, I think. I don’t know whether or not this issue manifests itself in other areas of the purchase flow, but there ya go.

Источник

Оцените статью