Integrowanie Biblioteki płatności w Google Play z aplikacją

Z tego dokumentu dowiesz się, jak zintegrować Bibliotekę płatności w Google Play z aplikacją, aby zacząć sprzedawać produkty.

Cykl życia zakupu

Oto typowy proces zakupu w przypadku zakupu jednorazowego lub subskrypcji.

  1. Pokaż użytkownikowi, co może kupić.
  2. Uruchom proces zakupu, aby użytkownik mógł zaakceptować zakup.
  3. Potwierdź zakup na swoim serwerze.
  4. Przekazać użytkownikowi treści.
  5. Potwierdź dostarczenie treści. W przypadku produktów konsumpcyjnych zużyj zakup, aby użytkownik mógł kupić produkt ponownie.

Subskrypcje są automatycznie odnawiane do momentu anulowania. Subskrypcja może przechodzić przez te stany:

  • Aktywna: użytkownik ma dostęp do subskrypcji.
  • Anulowano: użytkownik anulował subskrypcję, ale nadal ma dostęp do treści do daty wygaśnięcia.
  • W okresie prolongaty: użytkownik napotkał problem z płatnością, ale nadal ma dostęp do usługi, ponieważ Google próbuje ponownie obciążyć formę płatności.
  • Wstrzymane: użytkownik napotkał problem z płatnością i nie ma już dostępu, ponieważ Google próbuje ponownie użyć formy płatności.
  • Wstrzymana: użytkownik wstrzymał dostęp i nie ma do niego dostępu, dopóki nie wznowi dostępu.
  • Wygasła: użytkownik anulował subskrypcję i utracił do niej dostęp. Po upływie terminu ważności użytkownik jest uważany za utraconego.

Inicjowanie połączenia z Google Play

Pierwszym krokiem do integracji z systemem rozliczeniowym Google Play jest dodanie do aplikacji biblioteki Płatności w Google Play i inicjalizacja połączenia.

Dodawanie zależności Biblioteki płatności w Google Play

Dodaj zależność Biblioteki płatności w Google Play do pliku build.gradle aplikacji w ten sposób:

Groovy

dependencies {
    def billing_version = "8.0.0"

    implementation "com.android.billingclient:billing:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "8.0.0"

    implementation("com.android.billingclient:billing:$billing_version")
}

Jeśli używasz Kotlina, moduł KTX Biblioteki płatności w Google Play zawiera rozszerzenia Kotlina i obsługę coroutine, które umożliwiają tworzenie kodu w Kotlinie zgodnego z językiem. Aby uwzględnić te rozszerzenia w projekcie, dodaj do pliku build.gradle aplikacji tę zależność:

Groovy

dependencies {
    def billing_version = "8.0.0"

    implementation "com.android.billingclient:billing-ktx:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "8.0.0"

    implementation("com.android.billingclient:billing-ktx:$billing_version")
}

Inicjalizacja BillingClient

Po dodaniu zależności od Biblioteki płatności w Google Play musisz zainicjować wystąpienie BillingClient. BillingClient to główny interfejs do komunikacji między Biblioteką płatności w Google Play a resztą aplikacji. BillingClient udostępnia wygodne metody, zarówno synchroniczne, jak i asynchroniczne, do wielu typowych operacji związanych z płatnościami. Pamiętaj o tych kwestiach:

  • Zalecamy, aby naraz mieć otwarte tylko 1 aktywne połączenie BillingClient, aby uniknąć wielokrotnego wywołania funkcji PurchasesUpdatedListener w przypadku jednego zdarzenia.
  • Zalecamy inicjowanie połączenia dla BillingClient, gdy aplikacja jest uruchamiana lub przenoszona na pierwszy plan, aby mieć pewność, że aplikacja będzie odpowiednio szybko przetwarzać zakupy. Można to osiągnąć, używając ActivityLifecycleCallbacks zarejestrowanego przez registerActivityLifecycleCallbacks i nasłuchując na zdarzenie onActivityResumed, aby zainicjować połączenie, gdy po raz pierwszy wykryjesz wznowienie aktywności. Więcej informacji o tym, dlaczego warto stosować tę sprawdzoną metodę, znajdziesz w sekcji przetwarzanie zakupów. Pamiętaj też, aby zakończyć połączenie po zamknięciu aplikacji.

Aby utworzyć BillingClient, użyj newBuilder. Do funkcji newBuilder() możesz przekazać dowolny kontekst, a funkcja BillingClient użyje go do uzyskania kontekstu aplikacji. Oznacza to, że nie musisz się martwić o wyciek pamięci. Aby otrzymywać informacje o zakupach, musisz też zadzwonić pod numer setListener, podając numer referencyjny PurchasesUpdatedListener. Ten odbiorca otrzymuje informacje o wszystkich zakupach w aplikacji.

Kotlin

private val purchasesUpdatedListener =
   PurchasesUpdatedListener { billingResult, purchases ->
       // To be implemented in a later section.
   }

private var billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   // Configure other settings.
   .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // To be implemented in a later section.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    // Configure other settings.
    .build();

Połącz z Google Play

Po utworzeniu BillingClient musisz nawiązać połączenie z Google Play.

Aby połączyć się z Google Play, zadzwoń pod numer startConnection. Proces połączenia jest asynchroniczny, dlatego musisz zaimplementować BillingClientStateListener, aby otrzymywać połączenia zwrotne po zakończeniu konfiguracji klienta i jego gotowości do wysyłania kolejnych żądań.

Musisz też zaimplementować logikę ponownych prób, aby obsługiwać utracone połączenia z Google Play. Aby zaimplementować logikę ponownego próbowania, zastąpij metodę wywołania onBillingServiceDisconnected() i upewnij się, że metoda BillingClient wywołuje metodę startConnection(), aby nawiązać ponowne połączenie z Google Play, zanim prześle kolejne żądania.

Ten przykład pokazuje, jak utworzyć połączenie i sprawdzić, czy jest ono gotowe do użycia:

Kotlin

billingClient.startConnection(object : BillingClientStateListener {
    override fun onBillingSetupFinished(billingResult: BillingResult) {
        if (billingResult.responseCode ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    override fun onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
})

Java

billingClient.startConnection(new BillingClientStateListener() {
    @Override
    public void onBillingSetupFinished(BillingResult billingResult) {
        if (billingResult.getResponseCode() ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    @Override
    public void onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
});

Automatyczne nawiązywanie połączenia

Dzięki wprowadzeniu metody enableAutoServiceReconnection() w wersji 8.0.0 (BillingClient.Builder) biblioteka Play Billing Library może teraz automatycznie nawiązywać połączenie z usługą, jeśli zostanie wysłane wywołanie interfejsu API, gdy usługa jest rozłączona. Może to spowodować zmniejszenie liczby odpowiedzi SERVICE_DISCONNECTED, ponieważ ponowne połączenie jest obsługiwane wewnętrznie przed wywołaniem interfejsu API.

Jak włączyć automatyczne ponowne łączenie

Podczas tworzenia wystąpienia BillingClient użyj metody enableAutoServiceReconnection()BillingClient.Builder, aby włączyć automatyczne ponowne łączenie.

Kotlin

val billingClient = BillingClient.newBuilder(context)
    .setListener(listener)
    .enablePendingPurchases()
    .enableAutoServiceReconnection() // Add this line to enable reconnection
    .build()

Java

BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(listener)
    .enablePendingPurchases()
    .enableAutoServiceReconnection() // Add this line to enable reconnection
    .build();

wyświetlać produkty dostępne do kupienia;

Po nawiązaniu połączenia z Google Play możesz wysyłać zapytania dotyczące dostępnych produktów i wyświetlać je użytkownikom.

Wysyłanie zapytania o szczegóły produktów jest ważnym krokiem przed wyświetleniem produktów użytkownikom, ponieważ zwraca ono zlokalizowane informacje o produktach. W przypadku subskrypcji sprawdź, czy wyświetlanie produktu jest zgodne ze wszystkimi zasadami Google Play.

Aby zapytać o szczegóły produktu kupowanego raz, wywołaj metodę queryProductDetailsAsync. Ta metoda może zwrócić wiele ofert na podstawie konfiguracji jednorazowego produktu. Więcej informacji znajdziesz w artykule Wiele opcji zakupu i oferty dotyczące produktów kupowanych raz.

Aby obsłużyć wynik operacji asynchronicznej, musisz też określić listenera, który implementuje interfejs ProductDetailsResponseListener. Następnie możesz zastąpić wartość onProductDetailsResponse, która powiadamia listenera o zakończeniu zapytania, jak w tym przykładzie:

Kotlin

val queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build()

billingClient.queryProductDetailsAsync(queryProductDetailsParams) {
    billingResult,
    queryProductDetailsResult ->
      if (billingResult.getResponseCode() == BillingResponseCode.OK) {
               for (ProductDetails productDetails : queryProductDetailsResult.getProductDetailsList()) {
                 // Process successfully retrieved product details here.
               }

               for (UnfetchedProduct unfetchedProduct : queryproductDetailsResult.getUnfetchedProductList()) {
                 // Handle any unfetched products as appropriate.
               }
            }
}

Java

QueryProductDetailsParams queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build();

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
        public void onProductDetailsResponse(BillingResult billingResult,
                QueryProductDetailsResult queryProductDetailsResult) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
               for (ProductDetails productDetails : queryProductDetailsResult().getProductDetailsList()) {
                 // Process success retrieved product details here.
               }

               for (UnfetchedProduct unfetchedProduct : queryproductDetailsResult.getUnfetchedProductList()) {
                 // Handle any unfetched products as appropriate.
               }
            }
        }
    }
)

Gdy wysyłasz zapytanie o szczegóły produktu, prześlij instancję QueryProductDetailsParams, która określa listę ciągów znaków identyfikatorów produktów utworzonych w Konsoli Google Play, wraz z wartością ProductType. ProductType może być równe ProductType.INAPP w przypadku produktów jednorazowych lub ProductType.SUBS w przypadku subskrypcji.

Zapytania z użyciem rozszerzeń Kotlina

Jeśli używasz funkcji rozszerzeń Kotlina, możesz wysłać zapytanie o szczegóły jednorazowego produktu, wywołując funkcję rozszerzenia queryProductDetails().

queryProductDetails() korzysta z korobon Kotlina, dzięki czemu nie musisz definiować osobnego listenera. Funkcja jest zawieszana do czasu zakończenia wykonywania zapytania, po czym możesz przetworzyć wynik:

suspend fun processPurchases() {
    val productList = listOf(
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId("product_id_example")
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    )
    val params = QueryProductDetailsParams.newBuilder()
    params.setProductList(productList)

    // leverage queryProductDetails Kotlin extension function
    val productDetailsResult = withContext(Dispatchers.IO) {
        billingClient.queryProductDetails(params.build())
    }

    // Process the result.
}

W niektórych przypadkach niektóre urządzenia nie obsługują funkcji ProductDetailsqueryProductDetailsAsync(), zwykle z powodu przestarzałych wersji Usług Google Play. Aby zapewnić odpowiednią pomoc w takim przypadku, zapoznaj się z funkcjami zgodności wstecznej w przewodniku po migracji do Biblioteki płatności w Google Play 7.

Przetwarzanie wyniku

Biblioteka płatności w Google Play przechowuje wyniki zapytania w obiekcie QueryProductDetailsResult. QueryProductDetailsResult zawiera List obiektów ProductDetails. Następnie możesz wywoływać różne metody na każdym obiekcie ProductDetails na liście, aby wyświetlić odpowiednie informacje o pobieranym produkcie jednorazowym, takie jak cena czy opis. Aby wyświetlić dostępne informacje o szczegółach produktu, zapoznaj się z listą metod w klasie ProductDetails.

Obiekt QueryProductDetailsResult zawiera też obiekt List obiektów UnfetchedProduct. Następnie możesz wysłać zapytanie do każdego elementu UnfetchedProduct, aby uzyskać kod stanu odpowiadający przyczynie niepowodzenia pobierania. Aby wyświetlić dostępne informacje o produktach, które nie zostały pobrane, zapoznaj się z listą metod w klasie UnfetchedProduct.

Zanim zaoferujesz produkt do sprzedaży, sprawdź, czy użytkownik nie jest już jego właścicielem. Jeśli użytkownik ma produkt jednorazowy, który nadal znajduje się w bibliotece, musi go wykorzystać, zanim będzie mógł go ponownie kupić.

Zanim zaoferujesz subskrypcję, sprawdź, czy użytkownik nie ma już subskrypcji. Zwróć też uwagę na te kwestie:

  • W przypadku subskrypcji metoda queryProductDetailsAsync() zwraca szczegóły subskrypcji i maksymalnie 50 kwalifikujących się ofert na użytkownika na subskrypcję. Jeśli użytkownik spróbuje kupić ofertę, która nie kwalifikuje się do zakupu (np. jeśli aplikacja wyświetla nieaktualną listę kwalifikujących się ofert), Google Play informuje go, że nie kwalifikuje się do skorzystania z oferty, i może zamiast tego kupić abonament podstawowy.

  • W przypadku produktów kupowanych raz metoda queryProductDetailsAsync() zwraca tylko oferty dostępne dla użytkownika. Jeśli użytkownik spróbuje kupić ofertę, do której nie kwalifikuje się (np. osiągnął limit ilości), Google Play poinformuje go, że nie kwalifikuje się, a użytkownik może zamiast tego kupić ofertę opcji zakupu.

.

Uruchamianie procesu zakupu

Aby rozpocząć żądanie zakupu z aplikacji, wywołaj metodę launchBillingFlow() w głównym wątku aplikacji. Ta metoda przyjmuje odwołanie do obiektu BillingFlowParams, który zawiera odpowiedni obiekt ProductDetails uzyskany przez wywołanie metody queryProductDetailsAsync. Aby utworzyć obiekt BillingFlowParams, użyj klasy BillingFlowParams.Builder.

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...;

val productDetailsParamsList = listOf(
    BillingFlowParams.ProductDetailsParams.newBuilder()
        // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
        .setProductDetails(productDetails)
        // Get the offer token:
        // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList()
        // for a list of offers that are available to the user.
        // b. For subscriptions, call ProductDetails.subscriptionOfferDetails()
        // for a list of offers that are available to the user.
        .setOfferToken(selectedOfferToken)
        .build()
)

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build()

// Launch the billing flow
val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Java

// An activity reference from which the billing flow will be launched.
Activity activity = ...;

ImmutableList<ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // Get the offer token:
            // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList()
            // for a list of offers that are available to the user.
            // b. For subscriptions, call ProductDetails.subscriptionOfferDetails()
            // for a list of offers that are available to the user.
            .setOfferToken(selectedOfferToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

Metoda launchBillingFlow() zwraca jeden z kilku kodów odpowiedzi wymienionych w BillingClient.BillingResponseCode. Sprawdź ten wynik, aby upewnić się, że podczas uruchamiania procesu zakupu nie wystąpiły żadne błędy. Wartość BillingResponseCodeOK oznacza, że uruchomienie było udane.

Po pomyślnym wywołaniu interfejsu launchBillingFlow() system wyświetli ekran zakupu w Google Play. Rysunek 1 przedstawia ekran zakupu subskrypcji:

Ekran zakupu w Google Play zawiera subskrypcję, którą można kupić
Rysunek 1. Na ekranie zakupów w Google Play wyświetla się subskrypcja, którą można kupić.

Google Play wywołuje funkcję onPurchasesUpdated(), aby przekazać wynik operacji zakupu do detektorów, które implementują interfejs PurchasesUpdatedListener. Słuchacz jest określany za pomocą metody setListener() podczas inicjowania klienta.

Aby obsłużyć możliwe kody odpowiedzi, musisz zaimplementować onPurchasesUpdated(). Poniższy przykład pokazuje, jak zastąpić onPurchasesUpdated():

Kotlin

override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
   if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) {
       for (purchase in purchases) {
           // Process the purchase as described in the next section.
       }
   } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
       // Handle an error caused by a user canceling the purchase flow.
   } else {
       // Handle any other error codes.
   }
}

Java

@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
    if (billingResult.getResponseCode() == BillingResponseCode.OK
        && purchases != null) {
        for (Purchase purchase : purchases) {
            // Process the purchase as described in the next section.
        }
    } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
        // Handle an error caused by a user canceling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

Po pomyślnym zakupie wyświetla się ekran potwierdzenia zakupu w Google Play podobny do tego na rysunku 2.

Ekran potwierdzenia zakupu w Google Play
Rysunek 2. Ekran potwierdzenia zakupu w Google Play.

Po pomyślnym zakupie generowany jest również token zakupu, czyli unikalny identyfikator reprezentujący użytkownika i identyfikator produktu, który został kupiony raz. Aplikacje mogą przechowywać token zakupu lokalnie, ale zdecydowanie zalecamy przekazanie go na bezpieczny serwer backendu, na którym możesz zweryfikować zakup i zabezpieczyć się przed oszustwem. Ten proces jest szczegółowo opisany w artykule Wykrywanie i przetwarzanie zakupów.

Użytkownik otrzymuje też e-maila z potwierdzeniem transakcji zawierającym identyfikator zamówienia lub unikalny identyfikator transakcji. Użytkownicy otrzymują e-maila z unikalnym identyfikatorem zamówienia w przypadku każdego jednorazowego zakupu produktu, a także w przypadku początkowego zakupu subskrypcji i kolejnych automatycznych odnowień. Za pomocą identyfikatora zamówienia możesz zarządzać zwrotami środków w Konsoli Google Play.

Wskazać cenę indywidualną

Jeśli Twoja aplikacja może być rozpowszechniana w Europie, podczas wywoływania metody launchBillingFlow użyj metody setIsOfferPersonalized(), aby poinformować użytkowników, że cena produktu została spersonalizowana za pomocą automatycznego podejmowania decyzji.

Ekran zakupu w Google Play wskazujący, że cena została dostosowana do użytkownika.
Rysunek 3. Ekran zakupu w Google Play wskazujący, że cena została dostosowana do użytkownika.

Musisz zapoznać się z art. 6 (1) (ea) dyrektywy w sprawie praw konsumentów (2011/83/UE), aby określić, czy cena oferowana użytkownikom jest spersonalizowana.

setIsOfferPersonalized() przyjmuje dane wejściowe typu logicznego. Gdy true, interfejs Google Play zawiera informacje. Jeśli false, interfejs pomija informacje. Wartością domyślną jest false.

Więcej informacji znajdziesz w Centrum pomocy dla konsumentów.

Dołączanie identyfikatorów użytkowników

Gdy rozpoczniesz proces zakupu, Twoja aplikacja może dołączyć dowolne identyfikatory użytkownika, które masz dla kupującego, za pomocą obfuscatedAccountId lub obfuscatedProfileId. Przykładem identyfikatora może być zaciemniona wersja loginu użytkownika w Twoim systemie. Ustawienie tych parametrów może pomóc Google wykrywać oszustwa. Dodatkowo możesz mieć pewność, że zakupy są przypisywane do właściwego użytkownika, zgodnie z informacjami zawartymi w artykule Przekażanie uprawnień użytkownikom.

Wykrywanie i przetwarzanie zakupów

Wykrywanie i przetwarzanie zakupu opisane w tej sekcji dotyczy wszystkich rodzajów zakupów, w tym zakupów poza aplikacją, np. realizacji promocji.

Aplikacja wykrywa nowe zakupy i ukończone zakupy oczekujące na realizację w jeden z tych sposobów:

  1. Gdy funkcja onPurchasesUpdated jest wywoływana w wyniku wywołania funkcji launchBillingFlow przez Twoją aplikację (jak opisano w poprzedniej sekcji) lub gdy aplikacja jest uruchomiona z aktywnym połączeniem z biblioteką płatności, a dochodzi do zakupu poza aplikacją lub do ukończenia oczekującego zakupu. Na przykład członek rodziny zatwierdza oczekujący zakup na innym urządzeniu.
  2. Gdy aplikacja wywołuje metodę queryPurchasesAsync, aby zapytać o zakupy użytkownika.

W przypadku 1 funkcja onPurchasesUpdated będzie wywoływana automatycznie w przypadku nowych lub ukończonych zakupów, o ile aplikacja jest uruchomiona i ma aktywne połączenie z biblioteką Google Play Billing. Jeśli aplikacja nie jest uruchomiona lub nie ma aktywnego połączenia z Biblioteką płatności Google Play, funkcja onPurchasesUpdated nie zostanie wywołana. Pamiętaj, że zalecamy utrzymywanie aktywnego połączenia przez cały czas, gdy aplikacja jest na pierwszym planie, aby mogła otrzymywać aktualne informacje o zakupach.

W przypadku 2 musisz wywołać metodę BillingClient.queryPurchasesAsync(), aby aplikacja przetwarzała wszystkie zakupy. Zalecamy wykonanie tego, gdy aplikacja nawiąże połączenie z Biblioteką płatności w Google Play (co powinno nastąpić, gdy aplikacja zostanie uruchomiona lub przejdzie na pierwszy plan, jak opisano w sekcji inicjalizacja BillingClient). Można to zrobić, wywołując metodę queryPurchasesAsync po otrzymaniu pomyślnego wyniku z metody onServiceConnected. Przestrzeganie tej rekomendacji jest kluczowe do obsługi zdarzeń i sytuacji takich jak:

  • Problemy z siecią podczas zakupu: użytkownik może dokonać zakupu i otrzymać potwierdzenie od Google, ale jego urządzenie traci połączenie z siecią, zanim urządzenie i aplikacja otrzymają powiadomienie o zakupie za pomocą PurchasesUpdatedListener.
  • Wiele urządzeń: użytkownik może kupić produkt na jednym urządzeniu, a potem oczekiwać, że będzie on widoczny po przełączeniu urządzenia.
  • Obsługa zakupów dokonywanych poza aplikacją: niektóre zakupy, np. wykorzystanie promocji, mogą być dokonywane poza aplikacją.
  • Obsługa przejść stanu zakupu: użytkownik może dokonać płatności za zakup w stanie ODDATKOWYM, gdy aplikacja nie jest uruchomiona, i oczekywać potwierdzenia zakupu po jej otwarciu.

Gdy aplikacja wykryje nowy lub zakończony zakup, powinna:

  • Potwierdź zakup.
  • przyznać użytkownikowi treści za dokonane zakupy;
  • Powiadomienie użytkownika.
  • Poinformuj Google, że Twoja aplikacja przetworzyła zakupy.

W następnych sekcjach znajdziesz szczegółowe instrukcje, a na końcu znajdziesz podsumowanie wszystkich czynności.

Weryfikacja zakupu

Zanim przyznasz użytkownikowi korzyści, aplikacja powinna zawsze weryfikować wiarygodność zakupów. Aby to zrobić, postępuj zgodnie z wytycznymi opisanymi w artykule Weryfikowanie zakupów przed przyznawaniem uprawnień. Dopiero po zweryfikowaniu zakupu aplikacja powinna przetworzyć zakup i przyznawać uprawnienia użytkownikowi. Więcej informacji znajdziesz w następnej sekcji.

Przyznawanie uprawnień użytkownikowi

Gdy aplikacja potwierdzi zakup, może przyznać użytkownikowi uprawnienia i poinformować go o tym. Zanim przyznasz uprawnienia, sprawdź, czy Twoja aplikacja sprawdza stan zakupu (PURCHASED). Jeśli zakup jest w stanie OCZEKIWANIE, aplikacja powinna poinformować użytkownika, że musi on jeszcze wykonać czynności, aby dokończyć zakup, zanim zostaną przyznane uprawnienia. Przyznaj uprawnienia tylko wtedy, gdy stan zakupu zmieni się z OCZEKIWANIE na POWIODŁ. Więcej informacji znajdziesz w artykule Zarządzanie transakcjami oczekującymi.

Jeśli do zakupu zostały dołączone identyfikatory użytkowników zgodnie z opisem w sekcji Dołączanie identyfikatorów użytkowników, możesz pobrać te identyfikatory i przypisać je do odpowiedniego użytkownika w Twoim systemie. Ta metoda jest przydatna podczas uzgadniania zakupów, gdy aplikacja utraciła kontekst dotyczący tego, dla którego użytkownika dokonano zakupu. Pamiętaj, że w przypadku zakupów dokonywanych poza aplikacją te identyfikatory nie są ustawiane. W takim przypadku aplikacja może przyznać uprawnienia zalogowanemu użytkownikowi lub poprosić go o wybranie preferowanego konta.

W przypadku zamówienia w przedsprzedaży zakup jest w stanie ODDAŃ DO ROZWAŻENIA przed osiągnięciem daty premiery. Zamówienie w ramach przedsprzedaży zostanie zrealizowane w dacie premiery i stan zmieni się na KUPIONO bez konieczności podejmowania dodatkowych działań.

Powiadomienie użytkownika

Po przyznaniu uprawnień użytkownikowi aplikacja powinna wyświetlić powiadomienie potwierdzające zakup. Dzięki temu użytkownik nie będzie miał wątpliwości, czy zakup został prawidłowo zrealizowany, co mogłoby spowodować, że przestanie korzystać z aplikacji, skontaktuje się z zespołem pomocy lub złoży skargę w mediach społecznościowych. Pamiętaj, że Twoja aplikacja może wykrywać aktualizacje zakupów w dowolnym momencie jej cyklu życia. Na przykład rodzic zatwierdza oczekujący zakup na innym urządzeniu. W takim przypadku Twoja aplikacja może opóźnić wysyłanie powiadomienia do użytkownika do odpowiedniego momentu. Oto kilka przykładów sytuacji, w których opóźnienie jest uzasadnione:

  • Podczas dynamicznych części gry lub przerywników wyświetlanie wiadomości może rozpraszać użytkownika. W takim przypadku musisz powiadomić użytkownika po zakończeniu części dotyczącej działania.
  • podczas początkowego samouczka i konfiguracji użytkownika. Użytkownik może na przykład dokonać zakupu poza aplikacją przed jej zainstalowaniem. Zalecamy, aby powiadomić nowych użytkowników o nagrodach od razu po uruchomieniu gry lub podczas początkowej konfiguracji konta. Jeśli Twoja aplikacja wymaga od użytkownika utworzenia konta lub zalogowania się, zanim przyzna mu uprawnienia, zalecamy poinformowanie go, jakie kroki musi wykonać, aby zrealizować zakup. Jest to bardzo ważne, ponieważ po 3 dniach od zakupu środki są zwracane, jeśli aplikacja nie przetworzyła zakupu.

W Google Play zalecamy stosowanie następujących mechanizmów powiadamiania użytkownika o zakupie:

  • wyświetlić okno dialogowe w aplikacji.
  • Przesyłanie wiadomości do okna wiadomości w aplikacji i jasne wskazanie, że w oknie wiadomości w aplikacji jest nowa wiadomość.
  • Użyj komunikatu z powiadomienia systemu operacyjnego.

Powiadomienie powinno informować użytkownika o korzyściach, które otrzymał. Na przykład: „Kupiono 100 złotych monet”. Jeśli zakup został dokonany w ramach programu, takiego jak Play Pass, aplikacja informuje o tym użytkownika. Na przykład „Otrzymane produkty Udało Ci się zdobyć 100 klejnotów dzięki Play Pass. Kontynuuj”. Każdy program może zawierać wskazówki dotyczące zalecanego tekstu, który ma być wyświetlany użytkownikom w celu przedstawienia korzyści.

Powiadomienie Google o przetworzeniu zakupu

Gdy aplikacja przyzna użytkownikowi uprawnienia i powiadomi go o udanej transakcji, musi powiadomić Google o pomyślnym przetworzeniu zakupu. Aby to zrobić, musisz potwierdzić zakup w ciągu 3 dni, aby nie doszło do automatycznego zwrotu środków i unieważnienia uprawnień. Proces potwierdzania różnych typów zakupów opisaliśmy w następnych sekcjach.

Produkty konsumpcyjne

Jeśli Twoja aplikacja ma bezpieczne zaplecze, zalecamy użycie Purchases.products:consume, aby zapewnić niezawodne wykorzystanie zakupów. Sprawdź, czy zakup nie został już wykorzystany, sprawdzając wartość consumptionState z wyniku wywołania funkcji Purchases.products:get. Jeśli Twoja aplikacja jest aplikacją tylko po stronie klienta i nie ma zaplecza, użyj consumeAsync() z Biblioteki płatności w Google Play. Obie metody spełniają wymagania dotyczące potwierdzenia i wskazują, że aplikacja przyznała użytkownikowi uprawnienia. Te metody umożliwiają też aplikacji udostępnienie produktu jednorazowego odpowiadającego tokenowi zakupu wejściowego do ponownego zakupu. W przypadku funkcji consumeAsync() musisz też przekazać obiekt, który implementuje interfejs ConsumeResponseListener. Ten obiekt obsługuje wynik operacji konsumpcji. Możesz zastąpić metodę onConsumeResponse(), którą Biblioteka płatności w Google Play wywołuje po zakończeniu operacji.

Poniższy przykład pokazuje wykorzystanie produktu za pomocą biblioteki Google Play Billing przy użyciu powiązanego tokena zakupu:

Kotlin

    val consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build()
    val consumeResult = withContext(Dispatchers.IO) {
        client.consumePurchase(consumeParams)
    }

Java

    ConsumeParams consumeParams =
            ConsumeParams.newBuilder()
                .setPurchaseToken(purchase.getPurchaseToken())
                .build();

    ConsumeResponseListener listener = new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Handle the success of the consume operation.
            }
        }
    };

    billingClient.consumeAsync(consumeParams, listener);

Produkty niekonsumpcyjne

Aby potwierdzać zakupy niekonsumpcyjnych, jeśli aplikacja ma bezpieczny backend, zalecamy użycie interfejsu Purchases.products:acknowledge, aby niezawodnie potwierdzać zakupy. Sprawdź, czy zakup nie został wcześniej potwierdzony, sprawdzając wartość acknowledgementState w wyniku wywołania funkcji Purchases.products:get.

Jeśli Twoja aplikacja jest tylko dla klienta, użyj w niej metody BillingClient.acknowledgePurchase() z Biblioteki płatności w Google Play. Przed potwierdzeniem zakupu aplikacja powinna sprawdzić, czy został on już potwierdzony, korzystając z metody isAcknowledged() w Bibliotece płatności w Google Play.

Poniższy przykład pokazuje, jak potwierdzić zakup za pomocą Biblioteki płatności w Google Play:

Kotlin

val client: BillingClient = ...
val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ...

val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
    .setPurchaseToken(purchase.purchaseToken)
val ackPurchaseResult = withContext(Dispatchers.IO) {
     client.acknowledgePurchase(acknowledgePurchaseParams.build())
}

Java

BillingClient client = ...
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...

AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
 client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);

Subskrypcje

Subskrypcje są traktowane podobnie jak niekonsumowalne. Jeśli to możliwe, użyj interfejsu Purchases.subscriptions.acknowledge z interfejsu Play Developer API, aby niezawodnie potwierdzić zakup z bezpiecznego backendu. Sprawdź, czy zakup nie został wcześniej potwierdzony, sprawdzając wartość atrybutu acknowledgementState w zasobie zakupu z Purchases.subscriptions:get. W przeciwnym razie możesz potwierdzić subskrypcję za pomocą BillingClient.acknowledgePurchase() z biblioteki Płatności w Google Play po sprawdzeniu isAcknowledged(). Wszystkie wstępne zakupy subskrypcji muszą zostać potwierdzone. Odnowienia subskrypcji nie wymagają potwierdzenia. Więcej informacji o tym, kiedy należy potwierdzić subskrypcję, znajdziesz w artykule Sprzedaż subskrypcji.

W skrócie

Poniższy fragment kodu zawiera podsumowanie tych czynności.

Kotlin

fun handlePurchase(Purchase purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your
    // onPurchasesUpdated.
    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 (delaying
    // notification if needed as discussed above).

    // Step 4: Notify Google the purchase was processed using the steps
    // discussed in the processing purchases section.
}

Java

void handlePurchase(Purchase purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your
    // onPurchasesUpdated.
    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 (delaying
    // notification if needed as discussed above).

    // Step 4: Notify Google the purchase was processed using the steps
    // discussed in the processing purchases section.
}

Aby sprawdzić, czy aplikacja poprawnie wdrożyła te kroki, możesz skorzystać z tego przewodnika po testowaniu.

Obsługa oczekujących transakcji

Google Play obsługuje transakcje oczekujące, czyli transakcje, które wymagają co najmniej 1 dodatkowego kroku między rozpoczęciem zakupu przez użytkownika a przetworzeniem formy płatności. Twoja aplikacja nie powinna przyznawać uprawnień do tych rodzajów zakupów, dopóki Google nie powiadomi Cię o tym, że obciążono formę płatności użytkownika.

Użytkownik może na przykład rozpocząć transakcję, wybierając sklep stacjonarny, w którym zapłaci gotówką. Użytkownik otrzyma kod zarówno w powiadomieniu, jak i e-mailu. Gdy użytkownik przyjdzie do sklepu stacjonarnego, może zrealizować kod u kasjera i zapłacić gotówką. Google powiadomi Ciebie i użytkownika o otrzymaniu płatności. Twoja aplikacja może wtedy przyznać użytkownikowi uprawnienia.

W ramach inicjowania BillingClient wywołaj funkcję enablePendingPurchases(), aby umożliwić oczekujące transakcje w aplikacji. Aplikacja musi umożliwiać i obsługiwać oczekujące transakcje w przypadku produktów kupowanych raz. Zanim dodasz wsparcie, zapoznaj się z cyklem życia zakupu w przypadku oczekujących transakcji.

Gdy Twoja aplikacja otrzyma nowy zakup, czy to za pomocą interfejsu PurchasesUpdatedListener, czy też w wyniku wywołania interfejsu queryPurchasesAsync, użyj metody getPurchaseState(), aby określić, czy stan zakupu to PURCHASED czy PENDING. Upoważnienie należy przyznać tylko, gdy stan jest PURCHASED.

Jeśli aplikacja jest uruchomiona i ma aktywne połączenie z biblioteką płatności Google Play, gdy użytkownik dokona zakupu, ponownie zostanie wywołana funkcja PurchasesUpdatedListener, a wartość PurchaseState zmieni się na PURCHASED. W tym momencie Twoja aplikacja może przetworzyć zakup za pomocą standardowej metody wykrywania i przetwarzania zakupów. Aplikacja powinna też wywoływać metodę queryPurchasesAsync() w metodie onResume(), aby obsługiwać zakupy, które przeszły do stanu PURCHASED, gdy aplikacja była wyłączona.

Gdy zakup przechodzi z PENDING na PURCHASED, klient real_time_developer_notifications otrzymuje powiadomienie ONE_TIME_PRODUCT_PURCHASED lub SUBSCRIPTION_PURCHASED. Jeśli zakup zostanie anulowany, otrzymasz powiadomienie ONE_TIME_PRODUCT_CANCELED lub SUBSCRIPTION_PENDING_PURCHASE_CANCELED. Może się tak zdarzyć, jeśli klient nie dokona płatności w wymaganym terminie. Pamiętaj, że możesz zawsze użyć interfejsu Google Play Developer API, aby sprawdzić bieżący stan zakupu.

Obsługa zakupów o różnej ilości

Biblioteka Google Play Billing Library w wersjach 4.0 i wyższych umożliwia klientom zakup więcej niż 1 taki sam produkt w ramach jednej transakcji przez określenie ilości w koszyku zakupów. Aplikacja powinna obsługiwać zakupy w wielokrotnościach i przyznawać uprawnienia na podstawie określonej liczby zakupów.

Aby umożliwić zakupy w większej ilości, logika obsługi aplikacji musi sprawdzać ilość produktu. Do pola quantity możesz uzyskać dostęp za pomocą jednego z tych interfejsów API:

Po dodaniu logiki do obsługi zakupów w wielokrotnościach musisz włączyć funkcję zakupów w wielokrotnościach w przypadku odpowiedniego produktu na stronie zarządzania produktami jednorazowymi w Konsoli Play.

Wysyłanie zapytania o konfigurację płatności użytkownika

getBillingConfigAsync() określa kraj, którego użytkownik używa w Google Play.

Konfigurację płatności użytkownika możesz sprawdzić po utworzeniu BillingClient. Ten fragment kodu pokazuje, jak wywołać funkcję getBillingConfigAsync(). Obsługa odpowiedzi przez wdrożenie BillingConfigResponseListener. Ten odbiorca otrzymuje informacje o wszystkich zapytaniach dotyczących konfiguracji rozliczeń, które zostały zainicjowane w Twojej aplikacji.

Jeśli zwrócony obiekt BillingResult nie zawiera błędów, możesz sprawdzić pole countryCode w obiekcie BillingConfig, aby uzyskać kraj użytkownika w Google Play.

Kotlin

// Use the default GetBillingConfigParams.
val getBillingConfigParams = GetBillingConfigParams.newBuilder().build()
billingClient.getBillingConfigAsync(getBillingConfigParams,
    object : BillingConfigResponseListener {
        override fun onBillingConfigResponse(
            billingResult: BillingResult,
            billingConfig: BillingConfig?
        ) {
            if (billingResult.responseCode == BillingResponseCode.OK
                && billingConfig != null) {
                val countryCode = billingConfig.countryCode
                ...
            } else {
                // TODO: Handle errors
            }
        }
    })

Java

// Use the default GetBillingConfigParams.
GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(getBillingConfigParams,
    new BillingConfigResponseListener() {
      public void onBillingConfigResponse(
          BillingResult billingResult, BillingConfig billingConfig) {
        if (billingResult.getResponseCode() == BillingResponseCode.OK
            && billingConfig != null) {
            String countryCode = billingConfig.getCountryCode();
            ...
         } else {
            // TODO: Handle errors
        }
      }
    });

przypomnienia o porzuceniu koszyka na stronie głównej Gier Google Play (włączone domyślnie);

Deweloperzy gier, którzy zarabiają na produktach jednorazowych, mogą sprzedawać produkty w Konsoli Google Play poza aplikacją, korzystając z funkcji przypomnienia o porzuceniu koszyka, która zachęca użytkowników do dokończenia wcześniej przerwanych zakupów podczas przeglądania Sklepu Google Play. Te zakupy są dokonywane poza aplikacją, w Grze Google Play w Sklepie Google Play.

Ta funkcja jest domyślnie włączona, aby pomóc użytkownikom wrócić do miejsca, w którym przerwali, oraz pomóc deweloperom zmaksymalizować sprzedaż. Możesz jednak zrezygnować z tej funkcji w swojej aplikacji, przesyłając formularz rezygnacji z funkcji przypomnienia o porzuceniu koszyka. Sprawdzone metody zarządzania kodami SKU w Konsoli Google Play znajdziesz w artykule Tworzenie produktu w aplikacji.

Poniższe obrazy pokazują przypomnienie o porzuconym koszyku wyświetlane w Sklepie Google Play:

na ekranie Sklepu Google Play pojawia się prośba o dokonanie zakupu wcześniej porzuconego zakupu
Rysunek 2. Na ekranie Sklepu Google Play wyświetla się prośba o dokonanie zakupu w przypadku wcześniej porzuconego zakupu.

na ekranie Sklepu Google Play pojawia się prośba o dokonanie zakupu wcześniej porzuconego zakupu
Rysunek 3. Na ekranie Sklepu Google Play wyświetla się prośba o dokonanie zakupu w przypadku wcześniej porzuconego zakupu.