Z tego dokumentu dowiesz się, jak zintegrować Bibliotekę płatności w Google Play z aplikacją, aby rozpocząć sprzedaż produktów.
Cykl życia zakupu
Oto typowy proces zakupu w przypadku zakupu jednorazowego lub subskrypcji.
- Pokaż użytkownikowi, co może kupić.
- Uruchom proces zakupu, aby użytkownik mógł go zaakceptować.
- Zweryfikuj zakup na serwerze.
- przekazywać treści użytkownikowi;
- Potwierdź dostarczenie treści. W przypadku produktów konsumpcyjnych zużyj zakup, aby użytkownik mógł ponownie kupić produkt.
Subskrypcje odnawiają się automatycznie do momentu anulowania. Subskrypcja może przechodzić przez te stany:
- Aktywna: użytkownik jest w dobrej kondycji i ma dostęp do subskrypcji.
- Anulowano: użytkownik anulował subskrypcję, ale nadal ma dostęp do usługi do momentu wygaśnięcia.
- W okresie prolongaty: wystąpił problem z płatnością, ale użytkownik nadal ma dostęp, podczas gdy Google ponawia próbę obciążenia formy płatności.
- Wstrzymane: użytkownik napotkał problem z płatnością i nie ma już dostępu, a Google ponawia próbę obciążenia formy płatności.
- Wstrzymany: użytkownik wstrzymał dostęp i nie ma do niego dostępu, dopóki go nie wznowi.
- Wygasła: użytkownik anulował subskrypcję i stracił do niej dostęp. Użytkownik jest uznawany za rezygnującego po wygaśnięciu subskrypcji.
Inicjowanie połączenia z Google Play
Pierwszym krokiem integracji z systemem rozliczeniowym Google Play jest dodanie do aplikacji biblioteki Płatności w Google Play i zainicjowanie 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 języka Kotlin, moduł Biblioteki płatności w Google Play KTX zawiera rozszerzenia Kotlin i obsługę korutyn, które umożliwiają pisanie idiomatycznego kodu Kotlin podczas korzystania z Biblioteki płatności w Google Play. 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") }
Inicjowanie obiektu BillingClient
Po dodaniu zależności od Biblioteki płatności w Google Play musisz zainicjować instancję BillingClient
. BillingClient
to główny interfejs komunikacji między Biblioteką płatności w Google Play a pozostałą częścią aplikacji. BillingClient
udostępnia wygodne metody synchroniczne i asynchroniczne do wielu typowych operacji rozliczeniowych. Zwróć uwagę na te kwestie:
- Zalecamy, aby w danym momencie było otwarte tylko 1 aktywne połączenie
BillingClient
, aby uniknąć wielu wywołań zwrotnychPurchasesUpdatedListener
w przypadku jednego zdarzenia. - Zalecamy zainicjowanie połączenia z BillingClient, gdy aplikacja zostanie uruchomiona lub przeniesiona na pierwszy plan, aby zapewnić terminowe przetwarzanie zakupów. Możesz to zrobić, używając
ActivityLifecycleCallbacks
zarejestrowanego przezregisterActivityLifecycleCallbacks
i nasłuchując 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 dotyczącej przetwarzania 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 BillingClient
użyje go do uzyskania kontekstu aplikacji. Oznacza to, że nie musisz się martwić wyciekami pamięci. Aby otrzymywać informacje o zakupach, musisz też wywołać funkcję setListener
, przekazując odwołanie do PurchasesUpdatedListener
. Ten odbiorca otrzymuje aktualizacje dotyczące wszystkich zakupów w Twojej 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 łączenia jest asynchroniczny i musisz zaimplementować BillingClientStateListener
, aby otrzymać wywołanie zwrotne po zakończeniu konfiguracji klienta i gdy będzie on gotowy do wysyłania kolejnych żądań.
Musisz też wdrożyć logikę ponawiania, aby obsługiwać utracone połączenia z Google Play.
Aby zaimplementować logikę ponawiania, zastąp metodę wywołania zwrotnego onBillingServiceDisconnected()
i upewnij się, że BillingClient
wywołuje metodę startConnection()
, aby ponownie połączyć się z Google Play przed wysłaniem kolejnych żądań.
Poniższy przykład pokazuje, jak nawiązać połączenie i sprawdzić, czy jest 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 ponowne nawiązywanie połączenia
Wraz z wprowadzeniem metody enableAutoServiceReconnection()
w BillingClient.Builder
w wersji 8.0.0 biblioteka płatności w Play może teraz automatycznie przywracać połączenie z usługą, jeśli wywołanie API zostanie wykonane, gdy usługa jest odłączona. Może to spowodować zmniejszenie liczby odpowiedzi SERVICE_DISCONNECTED
, ponieważ ponowne połączenie jest obsługiwane wewnętrznie przed wykonaniem wywołania interfejsu API.
Jak włączyć automatyczne ponowne łączenie
Podczas tworzenia instancji BillingClient
użyj metody enableAutoServiceReconnection()
w 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świetlanie produktów dostępnych do kupienia
Po nawiązaniu połączenia z Google Play możesz wysyłać zapytania o dostępne produkty i wyświetlać je użytkownikom.
Wysyłanie zapytań o szczegóły produktu to ważny krok przed wyświetleniem produktów użytkownikom, ponieważ zwraca on zlokalizowane informacje o produkcie. W przypadku subskrypcji sprawdź, czy wyświetlanie produktu jest zgodne ze wszystkimi zasadami Google Play.
Aby wysłać zapytanie o szczegóły produktu kupowanego raz, wywołaj metodę queryProductDetailsAsync
. Ta metoda może zwracać wiele ofert na podstawie konfiguracji produktu kupowanego raz. Więcej informacji znajdziesz w sekcji Wiele opcji zakupu i ofert dla produktów kupowanych raz.
Aby obsłużyć wynik operacji asynchronicznej, musisz też określić odbiorcę, który implementuje interfejs ProductDetailsResponseListener
.
Możesz wtedy zastąpić onProductDetailsResponse
, które powiadamia odbiorcę o zakończeniu zapytania, jak pokazano 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. } } } } )
Podczas wysyłania zapytania o szczegóły produktu przekaż instancję QueryProductDetailsParams
, która określa listę ciągów identyfikatorów produktów utworzonych w Konsoli Google Play, oraz ProductType
. Wartość ProductType
może być równa ProductType.INAPP
w przypadku produktów kupowanych raz lub ProductType.SUBS
w przypadku subskrypcji.
Zapytanie z rozszerzeniami Kotlin
Jeśli używasz rozszerzeń Kotlin, możesz wysyłać zapytania o szczegóły produktów kupowanych raz, wywołując funkcję rozszerzenia queryProductDetails()
.
queryProductDetails()
korzysta z korutyn Kotlin, więc nie musisz definiować osobnego odbiorcy. Zamiast tego funkcja zawiesza działanie do momentu zakończenia 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.
}
Niektóre urządzenia rzadko nie obsługują ProductDetails
i queryProductDetailsAsync()
, zwykle z powodu nieaktualnych wersji Usług Google Play. Aby zapewnić prawidłową obsługę tego scenariusza, dowiedz się, jak korzystać z funkcji zgodności wstecznej w przewodniku po migracji do Biblioteki płatności w Play w wersji 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łać różne metody na każdym obiekcie ProductDetails
na liście, aby wyświetlić odpowiednie informacje o pomyślnie pobranym produkcie jednorazowym, takie jak jego cena czy opis. Aby wyświetlić dostępne informacje o szczegółach produktu, zapoznaj się z listą metod w klasie ProductDetails
.
QueryProductDetailsResult
zawiera też List
obiektów UnfetchedProduct
. Następnie możesz wysłać zapytanie do każdego obiektu UnfetchedProduct, aby uzyskać kod stanu odpowiadający przyczynie niepowodzenia pobierania.
Aby wyświetlić dostępne informacje o produkcie, które nie zostały jeszcze pobrane, zapoznaj się z listą metod w klasie UnfetchedProduct
.
Zanim zaoferujesz produkt na sprzedaż, sprawdź, czy użytkownik nie jest już jego właścicielem. Jeśli użytkownik ma produkt jednorazowy, który nadal znajduje się w jego bibliotece, musi go wykorzystać, zanim będzie mógł kupić go ponownie.
Zanim zaoferujesz subskrypcję, sprawdź, czy użytkownik nie ma już subskrypcji. Pamiętaj też o tych kwestiach:
W przypadku subskrypcji metoda
queryProductDetailsAsync()
zwraca szczegóły produktu subskrypcji i maksymalnie 50 ofert dla użytkowników na subskrypcję. Jeśli użytkownik spróbuje kupić niekwalifikującą się ofertę (np. jeśli aplikacja wyświetla nieaktualną listę kwalifikujących się ofert), Google Play poinformuje go, że nie kwalifikuje się do skorzystania z niej, i użytkownik 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 ma uprawnień (np. osiągnął limit zakupu), Play poinformuje go, że nie może skorzystać z tej oferty, i użytkownik będzie mógł zamiast tego kupić ofertę opcji zakupu.
Uruchamianie procesu zakupu
Aby rozpocząć żądanie zakupu z poziomu 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 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 proces zakupu został uruchomiony bez błędów. BillingResponseCode
OK
oznacza udane wprowadzenie.
Po prawidłowym wywołaniu funkcji launchBillingFlow()
system wyświetli ekran zakupu w Google Play. Ilustracja 1 przedstawia ekran zakupu subskrypcji:

Google Play wywołuje onPurchasesUpdated()
, aby przekazać wynik operacji zakupu do odbiorcy, który implementuje interfejs PurchasesUpdatedListener
. Słuchacz jest określany za pomocą metody setListener()
podczas inicjowania klienta.
Musisz wdrożyć onPurchasesUpdated()
, aby obsługiwać możliwe kody odpowiedzi. W poniższym przykładzie pokazujemy, 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 udanym zakupie pojawi się ekran potwierdzenia zakupu w Google Play podobny do tego na rysunku 2.

Pomyślny zakup generuje też token zakupu, czyli niepowtarzalny identyfikator reprezentujący użytkownika i identyfikator produktu kupowanego raz. Aplikacje mogą przechowywać token zakupu lokalnie, ale zdecydowanie zalecamy przekazywanie go na bezpieczny serwer backendu, gdzie możesz zweryfikować zakup i chronić się przed oszustwami. 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 niepowtarzalnym identyfikatorem zamówienia w przypadku każdego jednorazowego zakupu produktu, a także w przypadku zakupu początkowej subskrypcji i kolejnych automatycznych odnowień. Identyfikator zamówienia możesz wykorzystać do zarządzania zwrotami środków w Konsoli Google Play.
Wskazywanie ceny spersonalizowanej
Jeśli Twoja aplikacja może być rozpowszechniana wśród użytkowników w Unii Europejskiej, podczas wywoływania funkcji launchBillingFlow
używaj metody setIsOfferPersonalized()
, aby informować użytkowników, że cena produktu została spersonalizowana przy użyciu zautomatyzowanego podejmowania decyzji.

Musisz zapoznać się z art. 6 (1) (ea) dyrektywy w sprawie praw konsumentów 2011/83/EU, aby określić, czy cena oferowana użytkownikom jest spersonalizowana.
setIsOfferPersonalized()
przyjmuje dane wejściowe w postaci wartości logicznej. Gdy true
, interfejs Google Play zawiera informację. Gdy false
, interfejs pomija informację. Wartością domyślną jest false
.
Więcej informacji znajdziesz w Centrum pomocy dla konsumentów.
Dołączanie identyfikatorów użytkowników
Podczas uruchamiania procesu zakupu aplikacja może dołączyć dowolne identyfikatory użytkownika, które masz w przypadku użytkownika dokonującego zakupu, za pomocą parametrów obfuscatedAccountId lub obfuscatedProfileId. Przykładowym identyfikatorem może być zamaskowana wersja loginu użytkownika w Twoim systemie. Ustawienie tych parametrów może pomóc Google w wykrywaniu oszustw. Może też pomóc w przypisywaniu zakupów do odpowiednich użytkowników, o czym piszemy w sekcji przyznawanie 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ą, takich jak wykorzystanie promocji.
Aplikacja może wykrywać nowe zakupy i zakończone zakupy oczekujące w jeden z tych sposobów:
- Gdy funkcja
onPurchasesUpdated
jest wywoływana w wyniku wywołania przez aplikację funkcjilaunchBillingFlow
(jak opisano w poprzedniej sekcji) lub gdy aplikacja działa z aktywnym połączeniem z biblioteką płatności, a zakup został dokonany poza aplikacją lub oczekujący zakup został sfinalizowany. Na przykład członek rodziny zatwierdza oczekujący zakup na innym urządzeniu. - Gdy aplikacja wywołuje funkcję queryPurchasesAsync, aby wysłać zapytanie o zakupy użytkownika.
W przypadku zdarzenia 1 funkcja onPurchasesUpdated
będzie automatycznie wywoływana w przypadku nowych lub zrealizowanych zakupów, o ile aplikacja jest uruchomiona i ma aktywne połączenie z biblioteką Płatności w Google Play. Jeśli aplikacja nie jest uruchomiona lub nie ma aktywnego połączenia z Biblioteką płatności w Google Play, funkcja onPurchasesUpdated
nie zostanie wywołana. Pamiętaj, że zalecamy, aby aplikacja utrzymywała aktywne połączenie, dopóki jest na pierwszym planie, aby otrzymywać aktualizacje dotyczące zakupów na czas.
W przypadku punktu 2 musisz wywołać funkcję BillingClient.queryPurchasesAsync(), aby mieć pewność, że aplikacja przetworzy wszystkie zakupy. Zalecamy, aby to zrobić, gdy aplikacja nawiąże połączenie z Biblioteką płatności w Google Play (zalecane jest to po uruchomieniu aplikacji lub przejściu jej na pierwszy plan, jak opisano w sekcji Inicjowanie BillingClient). Możesz to zrobić, wywołując funkcję queryPurchasesAsync po otrzymaniu prawidłowego wyniku funkcji onServiceConnected. Postępowanie zgodnie z tą rekomendacją ma kluczowe znaczenie w przypadku 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 utraci połączenie z siecią, zanim urządzenie i aplikacja otrzymają powiadomienie o zakupie za pomocą interfejsu
PurchasesUpdatedListener
. - Wiele urządzeń: użytkownik może kupić produkt na jednym urządzeniu, a potem oczekiwać, że zobaczy go po przełączeniu się na inne urządzenie.
- Obsługa zakupów dokonywanych poza aplikacją: niektóre zakupy, np. wykorzystanie promocji, można dokonać poza aplikacją.
- Obsługa przejść stanu zakupu: użytkownik może dokonać płatności za zakup w stanie PENDING, gdy aplikacja nie jest uruchomiona, i oczekiwać potwierdzenia dokonania zakupu po otwarciu aplikacji.
Gdy aplikacja wykryje nowy lub zrealizowany zakup, powinna:
- Zweryfikuj zakup.
- Przyznawanie użytkownikowi treści za dokonane zakupy.
- Powiadom użytkownika.
- Powiadamiaj Google, że Twoja aplikacja przetworzyła zakończone zakupy.
Szczegółowo omawiamy je w kolejnych sekcjach, a następnie podsumowujemy wszystkie kroki.
Weryfikacja zakupu
Zanim przyznasz użytkownikowi korzyści, aplikacja powinna zawsze sprawdzać, czy zakupy są legalne. Możesz to zrobić, postępując zgodnie z wytycznymi opisanymi w artykule Weryfikowanie zakupów przed przyznaniem uprawnień. Dopiero po zweryfikowaniu zakupu aplikacja powinna kontynuować jego przetwarzanie i przyznawać użytkownikowi uprawnienia, co zostało omówione w następnej sekcji.
Przyznawanie uprawnień użytkownikowi
Po zweryfikowaniu zakupu aplikacja może przyznać użytkownikowi uprawnienia i powiadomić go o tym. Zanim przyznasz uprawnienia, sprawdź, czy aplikacja sprawdza, czy stan zakupu to PURCHASED
. Jeśli zakup jest w stanie OCZEKUJE, aplikacja powinna powiadomić użytkownika, że musi on wykonać jeszcze pewne działania, aby dokończyć zakup i uzyskać uprawnienia.
Przyznawaj uprawnienia tylko wtedy, gdy stan zakupu zmieni się z PENDING na SUCCESS.
Więcej informacji znajdziesz w artykule Obsługa transakcji oczekujących.
Jeśli do zakupu zostały dołączone identyfikatory użytkowników, jak opisano w sekcji Dołączanie identyfikatorów użytkowników, możesz je pobrać i użyć do przypisania zakupu do odpowiedniego użytkownika w swoim systemie. Ta technika jest przydatna podczas uzgadniania zakupów, w przypadku których aplikacja mogła utracić kontekst dotyczący tego, którego użytkownika dotyczy zakup. Pamiętaj, że w przypadku zakupów dokonywanych poza aplikacją te identyfikatory nie będą ustawione. W takim przypadku aplikacja może przyznać uprawnienia zalogowanemu użytkownikowi lub poprosić go o wybranie preferowanego konta.
W przypadku zamówień w przedsprzedaży zakup jest w stanie OCZEKUJĄCY, dopóki nie nadejdzie data premiery. Zakup w przedsprzedaży zostanie sfinalizowany w momencie premiery i zmieni stan na KUPIONO bez dodatkowych działań.
Powiadomienie użytkownika
Po przyznaniu użytkownikowi uprawnień aplikacja powinna wyświetlić powiadomienie potwierdzające zakup. Dzięki temu powiadomieniu użytkownik nie będzie miał wątpliwości, czy zakup został zrealizowany, co mogłoby spowodować, że przestanie korzystać z Twojej aplikacji, skontaktuje się z zespołem pomocy lub złoży skargę w mediach społecznościowych. Pamiętaj, że aplikacja może wykrywać aktualizacje zakupu w dowolnym momencie cyklu życia aplikacji. Na przykład rodzic zatwierdza oczekujący zakup na innym urządzeniu. W takim przypadku aplikacja może opóźnić powiadomienie użytkownika do odpowiedniego momentu. Przykłady sytuacji, w których opóźnienie może być odpowiednie:
- Podczas części gry, w której toczy się akcja, lub w trakcie przerywników wyświetlanie wiadomości może rozpraszać użytkownika. W takim przypadku musisz powiadomić użytkownika po zakończeniu części działania.
- Podczas początkowego samouczka i konfiguracji użytkownika w grze. Na przykład użytkownik mógł dokonać zakupu poza aplikacją przed jej zainstalowaniem. Zalecamy powiadamianie nowych użytkowników o nagrodzie od razu po otwarciu gry lub podczas początkowej konfiguracji. Jeśli Twoja aplikacja wymaga od użytkownika utworzenia konta lub zalogowania się przed przyznaniem mu uprawnień, zalecamy poinformowanie go, jakie kroki musi wykonać, aby odebrać zakup. Jest to bardzo ważne, ponieważ zakupy są zwracane po 3 dniach, jeśli aplikacja nie przetworzy zakupu.
Podczas powiadamiania użytkownika o zakupie Google Play zaleca stosowanie tych mechanizmów:
- Wyświetl okno w aplikacji.
- dostarczać wiadomość do skrzynki wiadomości w aplikacji i wyraźnie informować, że w tej skrzynce znajduje się nowa wiadomość;
- Użyj komunikatu powiadomienia systemu operacyjnego.
Powiadomienie powinno informować użytkownika o korzyściach, które otrzymał. Na przykład: „Kupiono 100 złotych monet”. Dodatkowo, jeśli zakup został dokonany w ramach korzyści z programu takiego jak Play Pass, Twoja aplikacja informuje o tym użytkownika. Na przykład „Odebrano produkty! Otrzymujesz 100 klejnotów w ramach Play Pass. Kontynuuj”. Każdy program może zawierać wskazówki dotyczące zalecanego tekstu, który należy wyświetlać użytkownikom, aby informować ich o korzyściach.
Powiadamianie Google o przetworzeniu zakupu
Gdy aplikacja przyzna użytkownikowi uprawnienia i powiadomi go o pomyślnym zakończeniu transakcji, musi powiadomić Google, że zakup został przetworzony. W tym celu musisz potwierdzić zakup w ciągu 3 dni, aby nie nastąpił automatyczny zwrot środków i nie cofnięto uprawnień. Proces potwierdzania różnych typów zakupów opisujemy w sekcjach poniżej.
Produkty do wykorzystania
W przypadku produktów jednorazowych, jeśli Twoja aplikacja ma bezpieczny backend, zalecamy używanie funkcji Purchases.products:consume
, aby niezawodnie przetwarzać zakupy. Sprawdź, czy zakup nie został już wykorzystany, sprawdzając consumptionState
w wyniku wywołania funkcji Purchases.products:get
. Jeśli Twoja aplikacja jest tylko klientem bez backendu, 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 do ponownego zakupu produktu kupowanego raz odpowiadającego tokenowi zakupu. W przypadku consumeAsync()
musisz też przekazać obiekt, który implementuje interfejs ConsumeResponseListener
. Ten obiekt obsługuje wynik operacji wykorzystania. 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, jak wykorzystać produkt za pomocą Biblioteki Płatności w Google Play 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 produktów jednorazowych, jeśli Twoja aplikacja ma bezpieczny backend, zalecamy używanie metody Purchases.products:acknowledge
, która umożliwia niezawodne potwierdzanie zakupów. Sprawdź, czy zakup nie został wcześniej zatwierdzony, sprawdzając wartość acknowledgementState
w wyniku wywołania funkcji Purchases.products:get
.
Jeśli Twoja aplikacja jest przeznaczona tylko dla klientów, użyj w niej metody BillingClient.acknowledgePurchase()
z Biblioteki płatności w Google Play. Zanim potwierdzisz zakup, aplikacja powinna sprawdzić, czy został on już potwierdzony, używając metody isAcknowledged()
z Biblioteki 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ą obsługiwane podobnie jak produkty niekonsumpcyjne. Jeśli to możliwe, użyj metody
Purchases.subscriptions.acknowledge
z interfejsu Google Play Developer API, aby niezawodnie potwierdzić zakup z bezpiecznego backendu. Sprawdź, czy zakup nie został wcześniej zatwierdzony, sprawdzając acknowledgementState
w zasobie zakupu z Purchases.subscriptions:get
. W innych przypadkach możesz potwierdzić subskrypcję za pomocą metody BillingClient.acknowledgePurchase()
z Biblioteki Płatności w Google Play po sprawdzeniu metody isAcknowledged()
. Wszystkie pierwsze zakupy subskrypcji muszą zostać potwierdzone. Odnowienia subskrypcji nie wymagają potwierdzenia. Więcej informacji o tym, kiedy należy potwierdzić subskrypcje, znajdziesz w artykule Sprzedawanie subskrypcji.
W skrócie
Poniższy fragment kodu zawiera podsumowanie tych kroków.
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 prawidłowo zaimplementowała te kroki, możesz skorzystać z przewodnika po testowaniu.
Obsługa transakcji oczekujących
Google Play obsługuje transakcje oczekujące, czyli transakcje, które wymagają wykonania co najmniej 1 dodatkowego kroku między momentem rozpoczęcia zakupu przez użytkownika a momentem przetworzenia formy płatności za zakup. Aplikacja nie powinna przyznawać uprawnień do tych typów zakupów, dopóki Google nie powiadomi Cię, że forma płatności użytkownika została obciążona.
Na przykład użytkownik może rozpocząć transakcję, wybierając sklep stacjonarny, w którym zapłaci później gotówką. Użytkownik otrzyma kod zarówno w powiadomieniu, jak i w e-mailu. Gdy użytkownik dotrze do sklepu stacjonarnego, może zrealizować kod u kasjera i zapłacić gotówką. Następnie Google powiadomi Ciebie i użytkownika o otrzymaniu płatności. Aplikacja może wtedy przyznać użytkownikowi uprawnienia.
Wywołaj funkcję enablePendingPurchases()
w ramach inicjowania funkcji BillingClient
, aby włączyć oczekujące transakcje w aplikacji. Aplikacja musi obsługiwać oczekujące transakcje w przypadku produktów kupowanych raz. Zanim dodasz obsługę, zapoznaj się z cyklem życia zakupu w przypadku transakcji oczekujących.
Gdy Twoja aplikacja otrzyma informację o nowym zakupie, czy to za pomocą PurchasesUpdatedListener
, czy w wyniku wywołania queryPurchasesAsync
, użyj metody getPurchaseState()
, aby określić, czy stan zakupu to PURCHASED
czy PENDING
. Uprawnienia należy przyznawać tylko wtedy, gdy stan ma wartość PURCHASED
.
Jeśli aplikacja jest uruchomiona i masz aktywne połączenie z biblioteką płatności w Google Play, gdy użytkownik dokona zakupu, funkcja PurchasesUpdatedListener
zostanie ponownie wywołana, a wartość PurchaseState
zmieni się na PURCHASED
. W tym momencie aplikacja może przetworzyć zakup za pomocą standardowej metody wykrywania i przetwarzania zakupów. Aplikacja powinna też wywoływać funkcję queryPurchasesAsync()
w metodzie onResume()
, aby obsługiwać zakupy, które przeszły do stanu PURCHASED
, gdy aplikacja nie była uruchomiona.
Gdy zakup zmieni stan z PENDING
na PURCHASED
, klient powiadomień dewelopera w czasie rzeczywistym otrzyma 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 czasie. Pamiętaj, że zawsze możesz użyć interfejsu Google Play Developer API, aby sprawdzić bieżący stan zakupu.
Obsługa zakupów wielu produktów
Google Play umożliwia klientom kupowanie więcej niż 1 sztuki tego samego produktu kupowanego raz w ramach 1 transakcji. Wystarczy, że określą liczbę w koszyku. Ta funkcja jest obsługiwana w Bibliotece płatności w Google Play w wersji 4.0 i nowszych. Aplikacja powinna obsługiwać zakupy wielu produktów i przyznawać uprawnienia na podstawie określonej liczby zakupionych produktów.
Aby obsługiwać zakupy wielu produktów, logika udostępniania aplikacji musi sprawdzać ilość produktu. Dostęp do pola quantity
możesz uzyskać za pomocą jednego z tych interfejsów API:
getQuantity()
z Biblioteki płatności w Google Play.Purchases.products.quantity
– z interfejsu Google Play Developer API.
Po dodaniu logiki obsługującej zakupy wielu sztuk musisz włączyć funkcję zakupu wielu sztuk dla odpowiedniego produktu na stronie zarządzania produktami kupowanymi raz w Konsoli Google Play.
Sprawdzanie konfiguracji płatności użytkownika
getBillingConfigAsync()
podaje kraj, w którym użytkownik korzysta z Google Play.
Po utworzeniu
BillingClient
możesz wysłać zapytanie o konfigurację płatności użytkownika. Poniższy fragment kodu pokazuje, jak wywołać funkcję getBillingConfigAsync()
. Obsłuż odpowiedź, implementując BillingConfigResponseListener
. Ten odbiorca otrzymuje aktualizacje dotyczące wszystkich zapytań o konfigurację rozliczeń zainicjowanych 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 (domyślnie włączone)
W przypadku deweloperów gier, którzy zarabiają na produktach kupowanych jednorazowo, jednym ze sposobów sprzedaży kodów SKU aktywnych w Konsoli Google Play poza aplikacją jest funkcja 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. Zakupy te są dokonywane poza aplikacją, na stronie głównej Google Play Gry w Sklepie Google Play.
Ta funkcja jest domyślnie włączona, aby ułatwić użytkownikom kontynuowanie przerwanej aktywności i pomóc deweloperom w maksymalizacji sprzedaży. 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 porzuceniu koszyka w Sklepie Google Play:

