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 czasu wygaśnięcia subskrypcji.
- W okresie prolongaty: wystąpił problem z płatnością, ale użytkownik nadal ma dostęp do usługi, podczas gdy Google ponawia próbę obciążenia formy płatności.
- Wstrzymane: wystąpił problem z płatnością i użytkownik 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.gradleaplikacji w ten sposób:
Groovy
dependencies { def billing_version = "8.1.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "8.1.0" implementation("com.android.billingclient:billing:$billing_version") }
Jeśli używasz języka Kotlin, moduł KTX Biblioteki płatności w Google Play zawiera rozszerzenia Kotlin i obsługę współprogramów, 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.1.0" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Kotlin
dependencies { val billing_version = "8.1.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ń zwrotnychPurchasesUpdatedListenerw 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
ActivityLifecycleCallbackszarejestrowanego przezregisterActivityLifecycleCallbacksi 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ń.
Ten 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 prowadzić do zmniejszenia 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 artykule Wiele opcji zakupu i ofert dla produktów kupowanych raz.
Aby obsłużyć wynik operacji asynchronicznej, musisz też określić odbiornik, który implementuje interfejs ProductDetailsResponseListener.
Możesz wtedy zastąpić funkcję onProductDetailsResponse, która 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 zawiera listę ciągów identyfikatorów produktów utworzonych w Konsoli Google Play, oraz ProductType. ProductType może być ProductType.INAPP w przypadku produktów kupowanych raz lub ProductType.SUBS w przypadku subskrypcji.
Wykonywanie zapytań za pomocą rozszerzeń 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 w Kotlinie, 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.
}
Rzadko zdarza się, że niektóre urządzenia nie obsługują ProductDetails i queryProductDetailsAsync(), zwykle z powodu nieaktualnych wersji Usług Google Play. Aby zapewnić odpowiednią obsługę tego scenariusza, dowiedz się, jak korzystać z funkcji zgodności wstecznej w przewodniku po przejściu na Bibliotekę 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 produktach, 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. jeśli osiągnął limit liczby zakupów), Play poinformuje go, że nie może skorzystać z tej oferty, a użytkownik może zamiast tego kupić ofertę opcji zakupu.
Uruchamianie procesu zakupu
Aby rozpocząć żądanie zakupu z aplikacji, wywołaj metodę launchBillingFlow() z głównego 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
of 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. 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 udanym zakupie wyświetli się ekran potwierdzenia zakupu w Google Play podobny do tego na rysunku 2.
Pomyślny zakup generuje też token zakupu, czyli unikalny 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 automatycznego podejmowania decyzji.
Musisz zapoznać się z art. 6 (1) (ea) dyrektywy w sprawie praw konsumentów 2011/83/EU.
setIsOfferPersonalized() przyjmuje dane wejściowe w postaci wartości logicznej. Gdy true, interfejs Google Play zawiera informację. Gdy false, interfejs użytkownika 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 artykule Przyznawanie użytkownikom uprawnień.
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
onPurchasesUpdatedjest 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 w momencie zakupu dokonanego poza aplikacją lub gdy oczekujący zakup zostanie sfinalizowany. Na przykład członek rodziny zatwierdza oczekujący zakup na innym urządzeniu. - Gdy aplikacja wywołuje funkcję queryPurchasesAsync, aby sprawdzić zakupy użytkownika.
W przypadku #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, gdy aplikacja jest uruchamiana lub przechodzi 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.
- Zawieszone subskrypcje: subskrypcja może zostać zawieszona w trakcie cyklu życia subskrypcji. BillingClient.queryPurchasesAsync() zwraca zawieszone subskrypcje tylko wtedy, gdy parametr
includeSuspendedSubscriptionsjest ustawiony naQueryPurchasesParams.Builder. Zawieszone subskrypcje nie są zwracane wPurchasesUpdatedListener.
Gdy aplikacja wykryje nowy lub zrealizowany zakup, powinna:
- Zweryfikuj zakup.
- Przyznawanie użytkownikowi treści za dokonane zakupy.
- Powiadom użytkownika.
- Powiadom Google, że Twoja aplikacja przetworzyła zakończone zakupy.
Szczegółowo omawiamy te kroki w kolejnych sekcjach, a następnie podsumowujemy je w osobnej sekcji.
Weryfikacja zakupu
Zanim przyznasz użytkownikowi korzyści, aplikacja powinna zawsze sprawdzać, czy zakupy są zgodne z prawem. 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 OCZEKUJĄCYM, aplikacja powinna powiadomić użytkownika, że musi on wykonać dodatkowe działania, aby dokończyć zakup i uzyskać dostęp do treści.
Przyznawaj uprawnienia tylko wtedy, gdy stan zakupu zmieni się z PENDING na SUCCESS.
Więcej informacji znajdziesz w sekcji 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 dokonanych 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 czas premiery. Zakup w przedsprzedaży zostanie sfinalizowany w momencie premiery i zmieni stan na ZAKUPIONO 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 scenkach przerywnikowych 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ż po 3 dniach zwracamy środki za zakupy, jeśli aplikacja nie przetworzy płatności.
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 otrzymanej korzyści. Na przykład: „Zakupiono 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ślnej 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 unieważnienie uprawnień. Proces potwierdzania różnych typów zakupów opisujemy w sekcjach poniżej.
Produkty konsumpcyjne
W przypadku produktów jednorazowych, jeśli Twoja aplikacja ma bezpieczny backend, zalecamy używanie funkcji Purchases.products:consume do niezawodnego wykorzystywania zakupów. 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 Twoja aplikacja przyznała użytkownikowi uprawnienia.
Te metody umożliwiają też aplikacji udostępnienie produktu kupowanego raz odpowiadającego tokenowi zakupu wejściowego do ponownego 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, które się nie zużywają
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 tylko klientem, 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 niepodlegające konsumpcji. Jeśli to możliwe, używaj metody
Purchases.subscriptions.acknowledge z interfejsu Google Play Developer API, aby niezawodnie potwierdzać zakup z bezpiecznego backendu. Sprawdź, czy zakup nie został wcześniej zatwierdzony, sprawdzając wartość 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 wykonuje te czynności, zapoznaj się z przewodnikiem 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 to PURCHASED.
Jeśli aplikacja jest uruchomiona i masz aktywne połączenie z Biblioteką Płatności Google Play, gdy użytkownik dokona zakupu, funkcja PurchasesUpdatedListener zostanie ponownie wywołana, a wartość PurchaseState będzie teraz wynosić 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 uwzględniać zakupy wielu sztuk, logika udostępniania w 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.quantityz 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 wysyłać zapytania 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 Google Play Gry (domyślnie włączone)
W przypadku deweloperów gier, którzy zarabiają na produktach jednorazowych, 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 Gry Play w Sklepie Google Play.
Ta funkcja jest domyślnie włączona, aby ułatwić użytkownikom kontynuowanie od miejsca, w którym skończyli, 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: