Google Play Billingv 3.0
План
Изучение API Открываем счет в банке) Регистрируем карточку
Создаем продукты
Качаем и настраиваем
исходники
Тестируем Обеспечиваем безопасность
Выводы
Работа с APIСхематическое представление
● Версия 2.0 ● Версия 3.0
● Проверка наличия подписки или покупки
Работа с APIПокупка + Подписка
Bundle buyIntentBundle = mService.getBuyIntent(3, packageName, "sku", "inapp|subs", "developerPayload");
PendingIntent pendingIntent = buyIntentBundle.getParcelable ("BUY_INTENT");
startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), Integer.valueOf(0),
Integer.valueOf(0), Integer.valueOf(0));
где developerPayload - используется для контроля покупки (String).
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) {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
}
}
}
Работа с APIПокупка + Подписка
Ответ
BuyProduct: {
"orderId":"12999763169054705758.137107940638715",
"packageName":"com.example.app",
"productId":"exampleSku",
"purchaseTime":1345678900000,
"purchaseState":0,
"developerPayload":"DeveloperPayload",
"purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
}
Signature: E8it1W0vaxaqldd6H6w0hrbFw1BNZrhSQYLfn0g7ErWu6mxOb4WI7brXWQggEHoU9r4.......uqlgEkA==
Работа с APIПотребление + отписка
● Версия 2.0
Потребление — только версия 3.0
Отмена подписки — аналогично версии 3.0
● Версия 3.0
Потребление
int response = mService.consumePurchase(3, packageName, token);
Предупреждение: Не вызывайте consumePurchase метод в основном потоке.
Отмена подписки
● Текущая версия Billing API не предоставляет поддержку программной отмены подписки.
● После отмены подписки пользователь все равно имеет доступ к подписке до конца срока (Месяц, Год).
● Возврат средств за уже купленную подписку может вернуть только разработчик.
● После удаления приложения, все подписки остаются
● Подписка не является потребляемым продуктом.
● Есть возможность открыть нужную страницу Google Play:
Intent intent = new Intent(Intent.ACTION_VIEW);
String url = "market://details?id=" + packageName;
intent.setData(Uri.parse(url));
startActivity(intent);
Работа с APIПолучение деталей продуктов
Предупреждение: Не вызывайте getSkuDetails метод в основном потоке.
int response = skuDetails.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList responseList = skuDetails.getStringArrayList("DETAILS_LIST");
for (String thisResponse : responseList) {
ProductDetails productDetail = new ProductDetails(itemType, thisResponse);
}
}
ArrayList skuList = new ArrayList();
skuList.add("premiumUpgrade");
Bundle querySkus = new Bundle();
querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
Bundle skuDetails = mService.getSkuDetails(3, packageName, "inapp|subs", querySkus);
Работа с APIПолучение деталей продуктов
Ответ
ProductDetail: {
"title":"Subscription 1 (Billing 3.0)",
"price":"8,14 ₴",
"type":"subs",
"description":"Description of subscriptions ",
"productId":"subscription_1"
}
Работа с APIПолучение списка купленных продуктов
Bundle items = mService.getPurchases(3, packageName, "inapp|subs", null);
//Возвращает не более 700 покупок за раз.
int response = items.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList<String> ownedSkus = items.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList = items.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String> signatureList = items.getStringArrayList("INAPP_DATA_SIGNATURE");
String continuationToken = items.getString("INAPP_CONTINUATION_TOKEN");
//Если продуктов меньше 700 то continuationToken вернется пустым.
for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i);
String signature = signatureList.get(i);
String sku = ownedSkus.get(i);
}
}
Работа с APIПолучение списка купленных продуктов
Ответ
OwnedSku: controlled_1
PurchaseData: {
"orderId":"12999763169054705758.1366607722131921",
"packageName":"com.ua.makeev.billingexample",
"productId":"controlled_1",
"purchaseTime":1365369158000,
"purchaseState":0,
"purchaseToken":"koybwcalcuninxrvzzocieaz.AO.........o6jcIjXTCN-7Yrt3tIoUzEDJuxabfpI2H1J5U2"}
}
Signature: E8it1W0vaxaqldd6H6w0hrbFw1BNZrhSQYLfn0g7ErWu6mxOb4WI7brXWQggEHoU9r4.......uqlgEkA==
Подготовка
Страны, разработчики из которых могут быть продавцами
Аргентина, Австралия, Австрия, Бельгия, Бразилия, Канада, Чехия, Дания, Финляндия, Франция, Германия, Гонконг, Индия, Ирландия, Израиль, Италия, Япония, Мексика, Нидерланды, Новая Зеландия, Норвегия, Польша, Португалия, Россия, Сингапур, Испания, Южная Корея, Швеция, Швейцария, Тайвань, Великобритания, США
ПодготовкаОткрываем счет в иностранном банке)
1) Регистируемся http://www.payoneer.com/cardholdersIntro.aspx
При наличии загран паспорта используем его. Доставка карты 1 месяц
2) Подаем заявку на подключение к услуге US Payment Service.
3) Цены (цена зависит от партнёрской программы):
$29.95 - ежегодное содержание карты
$12.95 - замена карты
$3.15 - снятие наличных денег.
+ 3 % - при снятии не в долларах
$1.00 - отказ в выдаче средств
$1.00 - Проверка баланса
Создание продуктов в developer консоли
● Контролируемые - продукты, информацию о которых, можно в любой момент получить с Google Play. Используется в версиях 2.0 и 3.0.
● Не контролируемые - может покупаться много раз. Информация о транзакциях не храниться в Google Play. Доступен только для версии 2.0. При использовании версии 3.0 эти продукты воспринимаются как контролируемые.
● Подписка - возможна ежемесячная и годовая подписка. Используется в версиях 2.0 и 3.0.
Настройка консоли разработчика
Настройка консоли разработчика
Настройка консоли разработчика
Настройка приложения
Настройка манифеста● Версия 2.0
<uses-permission android:name="com.android.vending.BILLING" />
<service android:name=".billing.BillingService" />
<receiver android:name=".billing.BillingReceiver" >
<intent-filter>
<action android:name="com.android.vending.billing.IN_APP_NOTIFY" />
<action android:name="com.android.vending.billing.RESPONSE_CODE" />
<action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" />
</intent-filter>
</receiver>
● Версия 3.0
<uses-permission android:name="com.android.vending.BILLING" />
● Открываем Android SDK Manager.● Устанавливаем Google Play Billing Library.Исходники лежат в <sdk>/extras/google/play_billing/.
Качаем исходники
ТестированиеТестовые продукты
● Зарезервированные идентификаторы продуктов
android.test.purchased — ответ, как будто вы успешно купили товар.
android.test.canceled — покупка отменена.
android.test.refunded — возврат средств.
android.test.item_unavailable — продукт не найден в списке продуктов.
Приложение было опубликовано?
Приложение только загружено?
Кто запускает приложение
Ответ
No No Any Unsigned
No No Developer Signed
Yes No Any Unsigned
Yes No Developer Signed
Yes No Test account Signed
Yes Yes Any Signed
Тестирование● Требования для тестирования:
1) Продукт должен быть активирован.
2) Версии приложения в маркете и на устройстве должны совпадать
3) Приложение должно быть подписано Production ключом.
4) Использовать тестовый аккаунт и он должен быть главным на устройстве. Нельзя покупать у самого себя.
5) Только Google аккаунт
Примечание: для установки другой учетной записи как основной нужно сбрасывать настройки до заводских
Собственные продукты
Безопасность● Проверка покупки на стороне сервера;
● Иметь возможность отменить покупку со стороны сервера (при его наличии);
● Динамическая генерация developerPayload;
● Обфускация кода реализующего логику покупки;
При использовании Proguard, в файл конфигурации добавить:
-keep class com.android.vending.billing.**;
● Не сохранять Public Key как статическую строку;
Выводы
● Преимущества 3 версии:
1) Появилась возможность смотреть детали продуктов доступных для продажи (цена, тип, название, описание);
2) Информация о покупке доступна сразу после ее завершения;
3) Все продукты стали контролируемыми;
4) Более простая реализация.
● Преимущества 2 версии:
1) Не нужно использовать onActivityResult слушатель.
Есть вопросы?
Спасибо за внимание!
dmitriy_makeev
dmitriy.makeev1
id=190485666
dmitrij.makeev