Анализируйте отказы от покупки товаров в Play Billing

1. Введение

В этом практическом занятии вы сосредоточитесь на создании разового продукта, интеграции вашего приложения с Play Billing Library (PBL) и анализе причин отказа от покупок.

Примечание : Для успешного выполнения этого практического задания вам необходим доступ к функции « Множественные варианты покупки и предложения для разовых продуктов ». Эта функция находится в программе раннего доступа (EAP). Продукты и функции в рамках EAP доступны «как есть» и могут иметь ограниченную поддержку. Чтобы получить доступ к функции EAP, отправьте запрос, используя форму заявки на участие в программе EAP для разовых продуктов . Однако, если вы хотите понять только, как анализировать отказы от покупок с помощью кодов ответов Play Billing, перейдите непосредственно к разделу «Анализ отказов от покупок» этого практического задания.

Аудитория

Данный практический курс предназначен для разработчиков Android-приложений, использующих библиотеку Play Billing Library (PBL) или желающих использовать PBL для монетизации своих разовых продуктов.

Что вы узнаете...

  • Как создавать разовые продукты в консоли Google Play.
  • Как интегрировать ваше приложение с PBL.
  • Как обрабатывать разовые закупки расходных и нерасходных товаров в PBL.
  • Как анализировать снижение количества покупок.

Что вам понадобится...

  • Доступ к консоли Google Play возможен только с учетной записью разработчика. Если у вас нет учетной записи разработчика, вам необходимо ее создать .
  • Пример приложения для этого практического занятия, который вы можете скачать с GitHub .
  • Android Studio .

2. Создайте демонстрационное приложение.

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

  • Интеграция приложения с PBL
  • Получить разовые товары
  • Запустите процессы покупки для разовых товаров.
  • Сценарии покупок, приводящие к следующим ответам на запросы по выставлению счетов:
    • BILLING_UNAVAILABLE
    • USER_CANCELLED
    • OK
    • ITEM_ALREADY_OWNED

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

Предварительные требования

Перед сборкой и развертыванием тестового приложения выполните следующие действия:

Строить

Цель этого этапа сборки — сгенерировать подписанный файл пакета Android-приложения для демонстрационного примера.

Для создания пакета приложения Android выполните следующие действия:

  1. Загрузите пример приложения с GitHub .
  2. Соберите демонстрационное приложение . Перед сборкой измените имя пакета демонстрационного приложения, а затем выполните сборку. Если в вашей консоли Play есть пакеты других приложений, убедитесь, что имя пакета, которое вы указываете для демонстрационного приложения, уникально.

    Примечание : При сборке тестового приложения создается только APK-файл, который можно использовать для локального тестирования. Однако при запуске приложения товары и цены не загружаются, поскольку они не были настроены в Play Console, что вы сделаете позже в этом практическом занятии.
  3. Сгенерируйте подписанный пакет приложения для Android.
    1. Сгенерируйте ключ для загрузки и хранилище ключей.
    2. Подпишите свое приложение с помощью ключа загрузки.
    3. Настройка подписи приложений Play.

Следующий шаг — загрузка пакета Android-приложения в Google Play Console.

3. Создайте разовый продукт в Play Console.

Для создания разовых продуктов в Google Play Console необходимо иметь приложение в Play Console. Создайте приложение в Play Console, а затем загрузите ранее созданный подписанный пакет приложения.

Создайте приложение

Для создания приложения:

  1. Войдите в консоль Google Play , используя свою учетную запись разработчика.
  2. Нажмите «Создать приложение» . Откроется страница создания приложения .
  3. Введите название приложения, выберите язык по умолчанию и другие сведения о приложении.
  4. Нажмите «Создать приложение» . Это создаст приложение в консоли Google Play.

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

Загрузите подписанный пакет приложения.

  1. Загрузите подписанный пакет приложения во внутренний тестовый трек Google Play Console . Только после загрузки вы сможете настроить функции монетизации в Play Console.
  2. Нажмите «Тестирование и выпуск» > «Тестирование» > «Внутренний выпуск» > «Создать новый выпуск» .
  3. Введите название релиза и загрузите подписанный файл пакета приложения.
  4. Нажмите «Далее» , а затем «Сохранить и опубликовать» .

Теперь вы можете создавать свои разовые продукты.

Создайте разовый продукт

Для создания разового продукта:

  1. В консоли Google Play в левом навигационном меню перейдите в раздел «Монетизация через Play» > «Продукты» > «Разовые продукты» .
  2. Нажмите «Создать разовый продукт» .
  3. Введите следующие данные о товаре:
    • Идентификатор товара: Введите уникальный идентификатор товара. Введите one_time_product_01 .
    • (Необязательно) Теги: Добавьте соответствующие теги.
    • Название: Введите название товара. Например, Product name .
    • Описание: Введите описание товара. Например, Product description .
    • (Необязательно) Добавьте изображение значка: Загрузите значок, представляющий ваш продукт.
    Примечание: В рамках данного практического занятия вы можете пропустить настройку раздела «Налоги, соответствие требованиям и программы» .
  4. Нажмите «Далее» .
  5. Добавьте вариант покупки и настройте его региональную доступность. Для разового продукта необходим как минимум один вариант покупки, который определяет способ предоставления права пользования, его цену и региональную доступность. В этом практическом задании мы добавим стандартный вариант покупки для продукта. В разделе « Варианты покупки» введите следующие данные:
    • Идентификатор варианта покупки: Введите идентификатор варианта покупки. Например, buy .
    • Тип покупки: Выберите «Купить» .
    • (Необязательно) Теги: Добавьте теги, относящиеся к данному варианту покупки.
    • (Необязательно) Нажмите «Дополнительные параметры» , чтобы настроить дополнительные параметры. В рамках данного практического занятия вы можете пропустить настройку дополнительных параметров.
  6. В разделе «Доступность и цены» нажмите «Установить цены» > «Массовое редактирование цен» .
  7. Выберите пункт «Страна/регион» . Это выберет все регионы.
  8. Нажмите «Продолжить» . Откроется диалоговое окно для ввода цены. Введите 10 долларов США и нажмите «Применить» .
  9. Нажмите «Сохранить» , а затем « Активировать» . Это создаст и активирует опцию покупки.

Для целей данного практического занятия создайте 3 дополнительных разовых продукта со следующими идентификаторами:

  • расходный_продукт_01
  • расходный_продукт_02
  • расходный_продукт_03

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

Откройте демонстрационное приложение в Google Play Console и перейдите в раздел «Монетизация через Play» > «Продукты» > «Разовые продукты» . Затем нажмите «Создать разовый продукт» и повторите шаги с 3 по 9.

Видео о создании одноразового продукта

В приведенном ниже видеоролике показаны этапы создания одноразового продукта, описанные ранее.

4. Интеграция с проблемно-ориентированным обучением.

Теперь мы рассмотрим, как интегрировать ваше приложение с библиотекой Play Billing (PBL) . В этом разделе описаны основные шаги интеграции и приведены фрагменты кода для каждого из них. Вы можете использовать эти фрагменты в качестве руководства для реализации вашей фактической интеграции.

Для интеграции вашего приложения с PBL выполните следующие шаги:

  1. Добавьте зависимость Play Billing Library в пример приложения.
    dependencies {
    val billing_version = "8.0.0"
    
    implementation("com.android.billingclient:billing-ktx:$billing_version")
    }
    
  2. Инициализируйте BillingClient . BillingClient — это клиентский SDK, который находится в вашем приложении и взаимодействует с библиотекой Play Billing. Следующий фрагмент кода показывает, как инициализировать клиент для выставления счетов.
    protected BillingClient createBillingClient() {
    return BillingClient.newBuilder(activity)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
        .enableAutoServiceReconnection()
        .build();
    }
    
  3. Подключение к Google Play. Следующий фрагмент кода показывает, как подключиться к Google Play.
    public void startBillingConnection(ImmutableList<Product> productList) {
    Log.i(TAG, "Product list sent: " + productList);
    Log.i(TAG, "Starting connection");
    billingClient.startConnection(
        new BillingClientStateListener() {
          @Override
          public void onBillingSetupFinished(BillingResult billingResult) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
              // Query product details to get the product details list.
              queryProductDetails(productList);
            } else {
              // BillingClient.enableAutoServiceReconnection() will retry the connection on
              // transient errors automatically.
              // We don't need to retry on terminal errors (e.g., BILLING_UNAVAILABLE,
              // DEVELOPER_ERROR).
              Log.e(TAG, "Billing connection failed: " + billingResult.getDebugMessage());
              Log.e(TAG, "Billing response code: " + billingResult.getResponseCode());
            }
          }
    
          @Override
          public void onBillingServiceDisconnected() {
            Log.e(TAG, "Billing Service connection lost.");
          }
        });
    }
    
  4. Получите информацию о разовом товаре. После интеграции вашего приложения с PBL вам необходимо получить информацию о разовом товаре в вашем приложении. Следующий фрагмент кода показывает, как получить информацию о разовом товаре в вашем приложении.
    private void queryProductDetails(ImmutableList<Product> productList) {
    Log.i(TAG, "Querying products for: " + productList);
    QueryProductDetailsParams queryProductDetailsParams =
        QueryProductDetailsParams.newBuilder().setProductList(productList).build();
    billingClient.queryProductDetailsAsync(
        queryProductDetailsParams,
        new ProductDetailsResponseListener() {
          @Override
          public void onProductDetailsResponse(
              BillingResult billingResult, QueryProductDetailsResult productDetailsResponse) {
            // check billingResult
            Log.i(TAG, "Billing result after querying: " + billingResult.getResponseCode());
            // process returned productDetailsList
            Log.i(
                TAG,
                "Print unfetched products: " + productDetailsResponse.getUnfetchedProductList());
            setupProductDetailsMap(productDetailsResponse.getProductDetailsList());
            billingServiceClientListener.onProductDetailsFetched(productDetailsMap);
          }
        });
    }
    
    При получении ProductDetails ) вы получите ответ, похожий на следующий:
    {
        "productId": "consumable_product_01",
        "type": "inapp",
        "title": "Shadow Coat (Yolo's Realm | Play Samples)",
        "name": "Shadow Coat",
        "description": "A sleek, obsidian coat for stealth and ambushes",
        "skuDetailsToken": "<---skuDetailsToken--->",
        "oneTimePurchaseOfferDetails": {},
        "oneTimePurchaseOfferDetailsList": [
            {
                "priceAmountMicros": 1990000,
                "priceCurrencyCode": "USD",
                "formattedPrice": "$1.99",
                "offerIdToken": "<--offerIdToken-->",
                "purchaseOptionId": "buy",
                "offerTags": []
            }
        ]
    },
    {
        "productId": "consumable_product_02",
        "type": "inapp",
        "title": "Emperor Den (Yolo's Realm | Play Samples)",
        "name": "Emperor Den",
        "description": "A fair lair glowing with molten rock and embers",
        "skuDetailsToken": "<---skuDetailsToken--->",
        "oneTimePurchaseOfferDetails": {},
        "oneTimePurchaseOfferDetailsList": [
            {
                "priceAmountMicros": 2990000,
                "priceCurrencyCode": "USD",
                "formattedPrice": "$2.99",
                "offerIdToken": "<--offerIdToken-->",
                "purchaseOptionId": "buy",
                "offerTags": []
            }
        ]
    }
    
  5. Запустите процесс выставления счетов.
    public void launchBillingFlow(String productId) {
    ProductDetails productDetails = productDetailsMap.get(productId);
    if (productDetails == null) {
      Log.e(
          TAG, "Cannot launch billing flow: ProductDetails not found for productId: " + productId);
      billingServiceClientListener.onBillingResponse(
          BillingResponseCode.ITEM_UNAVAILABLE,
          BillingResult.newBuilder().setResponseCode(BillingResponseCode.ITEM_UNAVAILABLE).build());
      return;
    }
    ImmutableList<ProductDetailsParams> productDetailsParamsList =
        ImmutableList.of(
            ProductDetailsParams.newBuilder().setProductDetails(productDetails).build());
    
    BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(productDetailsParamsList)
            .build();
    
    billingClient.launchBillingFlow(activity, billingFlowParams);
    }
    
  6. Выявление и обработка покупок. На этом этапе вам необходимо:
    1. Подтвердите покупку
    2. Предоставить пользователю право на использование сервиса.
    3. Уведомить пользователя
    4. Уведомить Google о процессе покупки
    Из перечисленных шагов a, b и c следует выполнить на бэкэнде, поэтому они выходят за рамки данного практического занятия. Следующий фрагмент кода показывает, как уведомить Google о расходуемом разовом продукте:
    private void handlePurchase(Purchase purchase) {
    // Step 1: Send the purchase to your secure backend to verify the purchase following
    // https://developer.android.com/google/play/billing/security#verify
    
    // Step 2: Update your entitlement storage with the purchase. If purchase is
    // in PENDING state then ensure the entitlement is marked as pending and the
    // user does not receive benefits yet. It is recommended that this step is
    // done on your secure backend and can combine in the API call to your
    // backend in step 1.
    
    // Step 3: Notify the user using appropriate messaging.
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
      for (String product : purchase.getProducts()) {
        Log.d(TAG, product + " purchased successfully! ");
      }
    }
    
    // Step 4: Notify Google the purchase was processed.
    // For one-time products, acknowledge the purchase.
    // This sample app (client-only) uses billingClient.acknowledgePurchase().
    // For consumable one-time products, consume the purchase
    // This sample app (client-only) uses billingClient.consumeAsync()
    // If you have a secure backend, you must acknowledge purchases on your server using the
    // server-side API.
    // See https://developer.android.com/google/play/billing/security#acknowledge
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED && !purchase.isAcknowledged()) {
    
      if (shouldConsume(purchase)) {
        ConsumeParams consumeParams =
            ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();
        billingClient.consumeAsync(consumeParams, consumeResponseListener);
    
      } else {
        AcknowledgePurchaseParams acknowledgePurchaseParams =
            AcknowledgePurchaseParams.newBuilder()
                .setPurchaseToken(purchase.getPurchaseToken())
                .build();
        billingClient.acknowledgePurchase(
            acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
      }
     }
    }
    

5. Анализ снижения количества покупок.

До сих пор в ходе практического занятия ответы Play Billing были сосредоточены на ограниченном количестве сценариев, таких как USER_CANCELLED , BILLING_UNAVAILABLE , OK и ITEM_ALREADY_OWNED . Однако Play Billing может возвращать 13 различных кодов ответов , которые могут быть вызваны различными реальными факторами.

В этом разделе подробно рассматриваются причины возникновения ошибок USER_CANCELLED и BILLING_UNAVAILABLE и предлагаются возможные меры по их устранению.

Код ошибки ответа USER_CANCELED

Этот код ответа указывает на то, что пользователь прервал процесс оформления покупки, не завершив её.

Вероятные причины

Какие действия вы можете предпринять?

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

Код ошибки ответа BILLING_UNAVAILABLE

Этот код ошибки означает, что покупка не может быть завершена из-за проблемы с платежным провайдером пользователя или выбранным им способом оплаты. Например, срок действия кредитной карты пользователя истек или пользователь находится в стране, где не поддерживается эта система. Этот код не указывает на ошибку в самой системе Play Billing.

Вероятные причины

Какие действия вы можете предпринять?

  • Приложение Play Store на устройстве пользователя устарело.
  • Пользователь находится в стране, где Play не поддерживается.
  • Пользователь является корпоративным пользователем, и администратор предприятия отключил возможность совершения покупок для других пользователей.
  • Google Play не может списать средства с платежного метода пользователя. Например, срок действия кредитной карты пользователя мог истечь.
  • Отслеживайте тенденции возникновения системных проблем и в отдельных регионах.
  • Рассмотрите возможность перехода на PBL 8, поскольку он поддерживает более детализированный код ответа PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS . Если вы получаете этот код ответа, рассмотрите возможность уведомления пользователей о сбое или предложения альтернативных способов оплаты.
  • Этот код ответа предназначен для повторных попыток, позволяя вам реализовать подходящие стратегии повторного подключения.
    Автоматические повторные попытки в данном случае вряд ли помогут. Однако ручная повторная попытка может помочь, если пользователь устранит причину проблемы. Например, если пользователь обновит версию Play Store до поддерживаемой версии, то ручная повторная попытка выполнения первоначальной операции может сработать.

    Если вы получаете этот код ответа, когда пользователь не находится в сессии, повторная попытка может быть нецелесообразной. Если в результате процесса покупки вы получаете ответ `BILLING_UNAVAILABLE`, весьма вероятно, что пользователь получил обратную связь от Google Play во время покупки и, возможно, знает, что пошло не так. В этом случае вы можете показать сообщение об ошибке, указывающее на возникшую проблему, и предложить кнопку «Попробовать снова», чтобы дать пользователю возможность повторить попытку вручную после устранения неполадки.

Повторные попытки для кодов ошибок ответа

Эффективные стратегии повторных попыток для устранения ошибок, связанных с Play Billing Library (PBL), различаются в зависимости от контекста, например, при взаимодействии пользователя в рамках сессии (например, во время покупки) или при фоновых операциях (например, при запросе информации о покупках после возобновления работы приложения). Важно внедрять эти стратегии, поскольку некоторые значения BillingResponseCode указывают на временные проблемы, которые можно решить повторной попыткой, в то время как другие являются постоянными и не требуют повторных попыток.

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

Подробную информацию о конкретных кодах ответов и соответствующих рекомендуемых стратегиях повторной попытки см. в разделе «Обработка кодов ответов BillingResult» .

6. Дальнейшие шаги

Справочная документация

7. Поздравляем!

Поздравляем! Вы успешно создали новый разовый продукт в консоли Google Play, протестировали коды ответов платежных систем и проанализировали отказы от покупок.

Опрос

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