Домой Android разработкаJava, Kotlin и Android SDK Покупки внутри приложения. Реализация in-app billing v3

Покупки внутри приложения. Реализация in-app billing v3

by dilix
Покупки внутри приложения. Реализация in-app billing v3

Задача: добавить встроенные покупки в Android приложение. Использовать google in-app billing v3 для реализации одноразовых платежей и подписок.

Монетизация через In-app purchases

Бесплатные приложения позволяют получить больше установок, что логично. Но как в таком случае монетизировать программу, не считая рекламу внутри приложения? Android позволяет проводить микротранзакции внутри приложения. Это могут быть как единоразовые платежи, так и подписки.

Единоразовые платежи в Android приложении

Для реализации таких платежей, необходимо в Google play консоли разработчика создать покупку. Это делается в секции «Ограниченный контент» на странице приложения.

Ограниченный контент для продажи в Google play

Внутри раздела вы создаете тот «предмет», который можно будет купить в вашем приложении. Необходимо указать идентификатор, имя, описание и цену. Всю эту информацию пользователь увидит в интерфейсе Google play во всплывающем окне подтверждения оплаты.

Подписки в Android приложении

С подписками примерно тоже самое. За исключением того, что секция «цены» содержит дополнительные поля.

Настройки подписки в Google play developer console

Тут необходимо указать также

  • Расчетный период — раз в какое время будет происходить оплата
  • Бесплатный пробный период — если хотите дать пользователю попробовать функционал в течении нескольких дней
  • Начальная цена — тут можно задать льготную цены для новых подписчиков
  • Льготный период — сколько есть времени у пользователя, чтобы устранить ошибку с оплатой если таковая имеется, перед тем, как подписка автоматически отменится.

Библиотеки для внедрения покупок в приложение

Можно реализовать покупки внутри приложения, используя напрямую инструменты, предоставленные Гуглом.

Я же предпочитаю использовать стороннюю, зарекомендовавшую себя библиотеку https://github.com/anjlab/android-inapp-billing-v3. Она предоставляет субъективно более дружественный интерфейс к API оплаты от Google.

Инициализация BillingProcessor

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

mBillingProcessor = new BillingProcessor(this, GPLAY_LICENSE, this);
boolean isAvailable = BillingProcessor.isIabServiceAvailable(this);
if (!isAvailable) {
    mProgress.setVisibility(View.GONE);
    showMsg(getString(R.string.billing_not_available));
} else {
    mBillingProcessor.initialize();
}

Как только процессор подгрузился можно загрузить купленные продукты.

    @Override
    public void onBillingInitialized() {
        /*
         * Called when BillingProcessor was initialized and it's ready to purchase
         */
        showMsg("onBillingInitialized");
        if (mBillingProcessor.loadOwnedPurchasesFromGoogle()) {
            handleLoadedItems();
        }
    }

Восстановление купленных продуктов

После успешной загрузки, библиотека может выдать список уже приобретенных товаров если он доступен в кэше. Также внутри доступна информация о каждом продукте. Например локальная цена в правильной валюте.

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

    @Override
    public void onPurchaseHistoryRestored() {
        /*
         * Called when purchase history was restored and the list of all owned PRODUCT ID's
         * was loaded from Google Play
         */
        showMsg("onPurchaseHistoryRestored");
        handleLoadedItems();
    }

Так или иначе мы получаем список ранее купленных вещей в нашем Android приложении. Давайте его обработаем и покажем в UI.

    private void handleLoadedItems() {
        mProgress.setVisibility(View.GONE);

        boolean isOneTimePurchaseSupported = mBillingProcessor.isOneTimePurchaseSupported();
        if (isOneTimePurchaseSupported) {
            mSingleTimePaymentButton.setVisibility(View.VISIBLE);
            mConsumabelButton.setVisibility(View.VISIBLE);
        } else {
            showMsg(getString(R.string.one_time_payment_not_supported));
        }

        boolean isSubsUpdateSupported = mBillingProcessor.isSubscriptionUpdateSupported();
        if (isSubsUpdateSupported) {
            mSubscriptionButton.setVisibility(View.VISIBLE);
        } else {
            showMsg(getString(R.string.subscription_not_supported));
        }

        setupConsumableButtons(mBillingProcessor.listOwnedProducts().contains(ONE_TIME_PAYMENT));
        setupSubscription(mBillingProcessor.listOwnedSubscriptions().contains(SUBSCRIPTION));
    }

    private void setupConsumableButtons(boolean isPurchased) {
        mConsumabelButton.setEnabled(isPurchased);
        mSingleTimePaymentButton.setEnabled(!isPurchased);
        if (isPurchased) {
            mSingleTimePaymentButton.setText(R.string.already_bought);
            mConsumabelButton.setText(R.string.consume_one_time);
        } else {
            SkuDetails details = mBillingProcessor.getPurchaseListingDetails(ONE_TIME_PAYMENT);
            mSingleTimePaymentButton.setText(getString(R.string.one_time_payment_value, details.priceText));
            mConsumabelButton.setText(R.string.not_bought_yet);
        }
    }

    private void setupSubscription(boolean isPurchased) {
        mSubscriptionButton.setEnabled(!isPurchased);
        if (isPurchased) {
            mSubscriptionButton.setText(R.string.already_subscribed);
        } else {
            SkuDetails details = mBillingProcessor.getSubscriptionListingDetails(SUBSCRIPTION);
            mSubscriptionButton.setText(getString(R.string.subscription_value, details.priceText));
        }
    }

Обработка успешной покупки внутри приложения

Результат о совершенной покупки приходит асинхронно. Нам остается только его обработать и «выдать» цифровой товар пользователю.

Важно: существуют способы обмануть серверы google что покупка успешно состоялась, но на самом деле никакой оплаты не было. Например, есть программы, которые выступают прослойкой и эмулируют успешный ответ. Правильный способ этого избежать — проверять покупки на своем доверенном сервере. Общение server-server намного сложнее подделать, потому что у злоумышленника нет доступа к вашему ресурсу. Как реализовать такую проверку рассказывали на stackoverflow. Также есть уже готовые библиотеки. Например вот одна из них.

В данном примере мы опустим проверку и будем предполагать, что покупка корректная.

    @Override
    public void onProductPurchased(String productId, TransactionDetails details) {
        /*
         * Called when requested PRODUCT ID was successfully purchased
         */
        showMsg("onProductPurchased");
        if (checkIfPurchaseIsValid(details.purchaseInfo)) {
            showMsg("purchase: " + productId + " COMPLETED");
            switch (productId) {
                case ONE_TIME_PAYMENT:
                    setupConsumableButtons(true);
                    break;
                case SUBSCRIPTION:
                    setupSubscription(true);
                    break;
            }
        } else {
            showMsg("fakePayment");
        }
    }

Тестирование внутренних покупок в Android приложении

Есть 2 способа, с помощью которых можно тестировать встроенные покупки.

Тестирование покупок с помощью статических ответов

Еще до публикации приложения можно использовать тестовые ID покупок, чтобы получать те или иные ответы.

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

Тестирование покупок с реальными даннымиэ

Куда удобнее проверить, что именно ваши конкретные товары работают правильно. Что ID корректно прописаны, данные корректно приходят. Для этого необходимо опубликовать ваше приложение хотя бы в канале для внутреннего тестирования.

Когда вы сами у себя тестировщик и скачиваете приложение через Google play — все ваши внутренние покупки будут корректно приходить. При этом ничего платить не надо. Гугл предоставляет «тестовые карточки» прямо в своем интерфейсе. Вы сможете проверить как отрабатывает ваше приложение при успешном ответе или отказе.

Реализованный пример покупок внутри приложения с in-app billing v3

Исходники примера на GitHub

Пример покупок в Android приложении

 

Пример можно скачать и посмотреть в Google play

Примеры, обучения и практика в приложении на Google play

Wesplit - учет совместных расходов, написан на Kotlin и Compose multiplatform
Хочешь обсудить Android разработку?
Заходи к нам Вконтакте, на Facebook и в Телеграм!

Добавить комментарий

Может быть интересно

Этот сайт использует Cookie файлы для улучшения вашего пользовательского взаимодействия. Используя данный сайт вы соглашается с этим. Принять Читать

Политика конфиденциальности и Cookies