Встраиваем In-App purchase в своё приложение

в 14:45, , рубрики: android, in-app purchases, Разработка под android

image Во второй части статьи про свою новогоднюю игрушку я расскажу про внутри игровые покупки. Я совсем не люблю рекламу в приложениях, по этому вопрос встраивания рекламы в своё приложение, для меня отпал сразу. Мой опыт выкладывания в Gooogle Play платных игр говорит о том, что резко падает количество желающих эту игру скачать, по этому вариант продажи игры, тоже отпал. И так как я не стремлюсь заработать на игре состояние, а делаю это больше в своё удовольствие, то решил что пусть пользователи сами решают, платить что-нибудь или нет.

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

Для работы со встраиваемыми покупками я остановился на очень простой, на мой взгляд, но вполне функциональной библиотеке Anjlab (ссылка на GitHub).

В Google play существуют два типа товаров:
— Продукт — приобретается разово, до реализации, не имеет срока действия
— Подписка — может приобретаться регулярно, имеет срок действия

Покупка товаров работает асинхронно, то есть сначала делаете запрос на покупку, потом получаете ответ об успешной покупке или коде ошибки.

Для подключения библиотеки в наше приложение необходимо в файле build.gradle (Module: app)
image

Добавить строку compile 'com.anjlab.android.iab.v3:library:1.0.44' в раздел dependencies (Не забываем после внесения изменений, нажать Sync Now в верхнем правом углу окна.)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "ru.crazyprojects.android.newyeartree"
        minSdkVersion 14
        targetSdkVersion 26
        versionCode 8
        versionName '1.8'
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:0.5'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
    compile 'com.anjlab.android.iab.v3:library:1.0.44'
}

Добавляем в файл с Activity две библиотеки:

import com.anjlab.android.iab.v3.BillingProcessor;
import com.anjlab.android.iab.v3.TransactionDetails;

Снабжаем нашу Activity функционалом BillingProcessor.IBillingHandler:

public class NewYearTree extends AppCompatActivity implements BillingProcessor.IBillingHandler { ... }

Для работы с покупками создаём объект класса BillingProcessor и добавляем требуемые методы:

public class NewYearTree extends AppCompatActivity implements BillingProcessor.IBillingHandler {

    BillingProcessor bp;

    ...........

    @Override
    public void onBillingInitialized() {
    /*
    * Вызывается, когда объект инициализирован и можно совершать покупки
    */
    }


    @Override
    public void onProductPurchased(String productId, TransactionDetails details) {
    /*
    * Вызывается когда покупка совершена
    */    
    }

    @Override
    public void onBillingError(int errorCode, Throwable error) {
    /*
    * Вызывается при возникновении каких-либо ошибок при совершении покупки
    */
    }

    @Override
    public void onPurchaseHistoryRestored() {
    /*
    * Вызывается один раз при первом запуске после установки или переустановки приложения. 
    * Служит для получения приобретённых ранее покупок, например, на другом устройстве
    */ 
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Тут не совсем разобрался, если кто подскажет, буду благодарен
        if (!bp.handleActivityResult(requestCode, resultCode, data)) {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }
}

В методе onCreate инициализируем переменную:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ........

        if(!BillingProcessor.isIabServiceAvailable(this)) {
            Toast.makeText(this, "In-app billing service is unavailable.", Toast.LENGTH_LONG).show();
        }

        bp = new BillingProcessor(this, "ЛИЦЕНЗИОННЫЙ КЛЮЧ ИЗ Google Play", this); // где взять этот ключ расскажу чуть ниже.
        bp.initialize();
    }

Заполняем кодом переопределённые методы:

@Override
    public void onBillingInitialized() {
        Log.d("LOG", "On Billing Initialaized"); // Просто пишем в лог
    }


    @Override
    public void onProductPurchased(String productId, TransactionDetails details) {
        Toast.makeText(this, "Thanks for Your donate. "+productId, Toast.LENGTH_LONG).show(); // Благодарим за пожертвование
        bp.consumePurchase(productId); // И сразу после успешного завершения покупки сразу реализуем приобретённый товар, чтобы его можно было купить снова.
    }

    @Override
    public void onBillingError(int errorCode, Throwable error) {
        Log.d("LOG", "On Billing Error"+Integer.toString(errorCode)); // Пишем ошибку в лог
    }

    @Override
    public void onPurchaseHistoryRestored() {
        // Так как информация о ранее приобретённых товарах в моём приложении не нужна, то данный метод оставляю пустым.
        // при необходимости, тут должен быть код для получения ранее купленных товаров и сохранения их в приложении на устройстве
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //Toast.makeText(this, "On Activity Result", Toast.LENGTH_LONG).show();
        Log.d("LOG", "On Activity Result");
        if (!bp.handleActivityResult(requestCode, resultCode, data)) {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    // Добавляю дополнительный метод, который буду вызывать для инициации процесса покупки
    public void donate(String ProductID) {
        bp.purchase(this, ProductID);  // Отправляем запрос на покупку товара
    }

Со стороны приложения всё сделали, теперь надо выполнить ряд действий в консоли Google Play.
Сначала необходимо получить «ЛИЦЕНЗИОННЫЙ КЛЮЧ ИЗ Google Play». Этот ключ уникальный для каждого приложения, по этому, чтобы его получить, приложение необходимо опубликовать, например, как бета-версию.
После того как приложение будет опубликовано, заходим в раздел управления приложением (просто щёлкнув на него в списке приложений), затем в левом меню раскрываем раздел «Инструменты разработки» и переходим в подраздел «Службы и API», там в панели «Лицензирование и продажа контента» и есть необходимый ключ, который имеет вид «MIIBIjANBgkqhkiG9w0BAQEFAAOCA......................................................................................»
Этот ключ используется при вызове метода:

      bp = new BillingProcessor(this, "MIIBIjANBgkqhkiG9w0BAQEFAAOCA......................................................................................", this);

Теперь нам необходимо создать контент, который будем продавать. Для этого в левом меню переходим в раздел «Настройки страницы приложения» и подраздел «Контент для продажи».
Далее нам необходимо определить какой тип контента нам нужен — продукт или подписка, определившись с типом, переходим на соответствующую вкладку и создаём необходимый контент, заполняя требуемые поля. В приложении может быть как продукты, так и подписки одновременно.

Стоит обратить внимание на именование идентификатора продукта, именно он будет использоваться в нашем приложении.
Например, создаём продукт с идентификатором one_dollar_donate, и для покупки в приложении будем использовать следующий вызов функции:

      bp.purchase(this, "one_dollar_donate");

С Наступающим Новым Годом! и пусть он будет интереснее предыдущих!

Автор: Роман Совалов

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js