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 jednorazowego lub subskrypcji.

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

Subskrypcje odnawiają się automatycznie, dopóki nie zostaną anulowane. Subskrypcja może mieć te stany:

  • Aktywny: 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 subskrypcji.
  • W okresie prolongaty: u użytkownika wystąpił problem z płatnością, ale nadal ma on dostęp do treści, 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 do usługi, a Google ponawia próbę obciążenia formy płatności.
  • Wstrzymany: użytkownik wstrzymał dostęp i nie będzie go miał, dopóki go nie wznowi.
  • Wygasła: użytkownik anulował subskrypcję i stracił do niej dostęp. Po wygaśnięciu subskrypcji użytkownik jest uznawany 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 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:

Dynamiczny

dependencies {
    def billing_version = "9.1.0"

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

Kotlin

dependencies {
    val billing_version = "9.1.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ę współprogramów, które umożliwiają pisanie idiomatycznego kodu Kotlina 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ść:

Dynamiczny

dependencies {
    def billing_version = "9.1.0"

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

Kotlin

dependencies {
    val billing_version = "9.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 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 rozliczeniowych. Zwróć uwagę na te kwestie:

  • Zalecamy, aby w danym momencie było otwarte tylko 1 aktywne połączenie BillingClient. Pozwoli to uniknąć wielu wywołań zwrotnych PurchasesUpdatedListener w przypadku pojedynczego zdarzenia.
  • Zalecamy zainicjowanie połączenia z BillingClient, gdy aplikacja zostanie uruchomiona lub przejdzie na pierwszy plan, aby zapewnić terminowe przetwarzanie zakupów. Można to zrobić, używając interfejsu ActivityLifecycleCallbacks zarejestrowanego przez registerActivityLifecycleCallbacks i nasłuchując onActivityResumed, aby zainicjować połączenie po pierwszym wykryciu wznowienia 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. Możesz przekazać dowolny kontekst do newBuilder(), a BillingClient użyje go do uzyskania kontekstu aplikacji. Oznacza to, że nie musisz się martwić o wycieki pamięci. Aby otrzymywać aktualizacje dotyczące zakupów, musisz też wywołać funkcję setListener, przekazując odwołanie do PurchasesUpdatedListener. Ten detektor otrzymuje aktualizacje dotyczące wszystkich zakupów 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();

Łączenie 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 i musisz zaimplementować interfejs BillingClientStateListener, aby otrzymać wywołanie zwrotne po zakończeniu konfiguracji klienta i gdy będzie on gotowy do wysyłania kolejnych żądań.

Jeśli nie masz włączonego automatycznego ponownego łączenia z usługą, musisz też zaimplementować logikę ponawiania prób, aby obsługiwać utracone połączenia z Google Play. Aby wdrożyć 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ń. Jeśli masz włączone automatyczne ponowne łączenie z usługą, możesz zaimplementować tę metodę jako operację bez efektu.

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() {
        // If automatic service reconnection is enabled, this can be left empty (no-op)
        // because the library handles retries. You can still use this for non-retry
        // tasks like logging or updating the UI to reflect a disconnected state.
        // Otherwise, 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.
                    // It's a good practice to query products after the connection is established.
                    queryProductDetails();
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
                // This is automatically handled by the library when you call a method that requires a connection.
            }
        });

.

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 interfejsu API nastąpi, 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 wywołaniem 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(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
    .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 zapytania o szczegóły produktu to ważny krok przed wyświetleniem produktów użytkownikom, ponieważ zwraca ono 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 produktów kupowanych raz.

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

Kotlin

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

billingClient.queryProductDetailsAsync(queryProductDetailsParams) {
        billingResult,
        queryProductDetailsResult ->
    if (billingResult.responseCode == BillingResponseCode.OK) {
        for (productDetails in queryProductDetailsResult.productDetailsList) {
            // Process successfully retrieved product details here.
        }

        for (unfetchedProduct in queryProductDetailsResult.unfetchedProductList) {
            // 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 successfully 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, wraz z ProductType. Wartość ProductType może wynosić 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ń Kotlina, możesz wysłać zapytanie o szczegóły produktu kupowanego raz, wywołując funkcję rozszerzenia queryProductDetails().

queryProductDetails() wykorzystuje współprogramy Kotlin, dzięki czemu nie musisz definiować osobnego detektora. 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.
}

W rzadkich przypadkach niektóre urządzenia nie obsługują aplikacji 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 migracji na Bibliotekę płatności w 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łać różne metody na każdym obiekcie ProductDetails na liście, aby wyświetlić odpowiednie informacje o pomyślnie pobranym produkcie kupowanym raz, np. jego cenę lub 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 niepobrane informacje o produkcie, 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 w bibliotece produktów produkt konsumpcyjny, musi go wykorzystać, zanim będzie mógł go kupić 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 objętego subskrypcją i maksymalnie 50 ofert dla użytkowników na subskrypcję. Jeśli użytkownik spróbuje kupić ofertę, do której się nie kwalifikuje (np. jeśli aplikacja wyświetla nieaktualną listę ofert, do których użytkownik się kwalifikuje), Google Play poinformuje go o tym, że nie może skorzystać z oferty, i zaproponuje zakup abonamentu podstawowego.

  • 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 się nie kwalifikuje (np. jeśli osiągnął limit liczby zakupów), Google Play poinformuje go o tym, że nie może skorzystać z tej oferty, i będzie mógł zamiast tego kupić ofertę z opcją zakupu.

.

Uruchamianie procesu zakupu

Aby rozpocząć prośbę o zakup z poziomu 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.getSubscriptionOfferDetails()
        // 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<BillingFlowParams.ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        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.getSubscriptionOfferDetails()
            // 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. Pamiętaj, aby sprawdzić ten wynik i upewnić się, że podczas uruchamiania procesu zakupu nie wystąpiły błędy. BillingResponseCode o wartości OK oznacza udane uruchomienie.

Po udanym wywołaniu metody launchBillingFlow() system wyświetla ekran zakupu w Google Play. Rysunek 1 przedstawia ekran zakupu subskrypcji:

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

Google Play wywołuje onPurchasesUpdated(), aby przekazać wynik operacji zakupu do odbiorcy, który implementuje interfejs PurchasesUpdatedListener. Detektor jest określany za pomocą metody setListener() podczas inicjowania klienta.

Aby obsługiwać 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 udanym zakupie wyświetli się ekran potwierdzający zakup w Google Play podobny do tego na rysunku 2.

ekran udanego zakupu w Google Play
Rysunek 2. Ekran udanego zakupu w Google Play.

Udany zakup generuje też token zakupu, który jest unikalnym identyfikatorem reprezentującym użytkownika i identyfikator produktu kupowanego raz. Aplikacje mogą przechowywać token zakupu lokalnie, ale zdecydowanie zalecamy przekazywanie go na bezpieczny serwer backendu, na którym możesz zweryfikować zakup i chronić się przed oszustwami. Ten proces jest dokładniej opisany w artykule Wykrywanie i przetwarzanie zakupów.

Użytkownik otrzyma też e-mailem potwierdzenie transakcji zawierające identyfikator zamówienia lub unikalny identyfikator transakcji. Użytkownicy otrzymują e-maila z unikalnym identyfikatorem zamówienia w przypadku każdego zakupu produktu kupowanego raz, a także w przypadku pierwszego zakupu subskrypcji i kolejnych cyklicznych automatycznych odnowień. Możesz użyć identyfikatora zamówienia, aby zarządzać zwrotami środków w Konsoli Google Play.

Wskazywanie spersonalizowanej ceny

Jeśli Twoja aplikacja może być rozpowszechniana wśród użytkowników w Unii Europejskiej, podczas wywoływania metody launchBillingFlow użyj metody setIsOfferPersonalized(), aby poinformować użytkowników, że cena produktu została spersonalizowana przy użyciu automatycznego podejmowania decyzji.

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

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

setIsOfferPersonalized() przyjmuje dane wejściowe w postaci wartości logicznej. Gdy true, interfejs Google Play zawiera informacje o wykorzystaniu AI. Gdy false, interfejs użytkownika pomija informację. Wartością domyślną jest false.

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

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

Gdy uruchomisz proces zakupu, Twoja aplikacja może dołączyć dowolne identyfikatory użytkownika, które masz dla użytkownika dokonującego zakupu, za pomocą obfuscatedAccountId lub obfuscatedProfileId. Przykładowym identyfikatorem może być zaciemniona 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 zapewnieniu, że zakupy są przypisywane do właściwego użytkownika, jak opisano w sekcji Przyznawanie uprawnień użytkownikom.

Wykrywanie i przetwarzanie zakupów

Wykrywanie i przetwarzanie zakupu opisane w tej sekcji dotyczy wszystkich typów zakupów, w tym zakupów poza aplikacją, takich jak wykorzystanie promocji.

Aplikacja może wykrywać nowe zakupy i zakończone oczekujące zakupy w jeden z tych sposobów:

  1. Gdy funkcja onPurchasesUpdated jest wywoływana w wyniku wywołania przez aplikację funkcji launchBillingFlow (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 grupy rodzinnej zatwierdza oczekujący zakup na innym urządzeniu.
  2. gdy aplikacja wywołuje metodę queryPurchasesAsync, aby sprawdzić zakupy użytkownika;

W przypadku 1 metoda onPurchasesUpdated będzie automatycznie wywoływana w odniesieniu do 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 działa 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 próbowała utrzymać aktywne połączenie, dopóki jest na pierwszym planie, aby otrzymywać aktualne informacje o zakupach.

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 w momencie uruchomienia aplikacji lub przejścia na pierwszy plan, jak opisano w sekcji Inicjowanie BillingClient). Możesz to zrobić, wywołując funkcję queryPurchasesAsync po otrzymaniu wyniku onServiceConnected. Zastosowanie się do tej rekomendacji jest kluczowe w przypadku takich zdarzeń i sytuacji jak:

  • Problemy z siecią podczas zakupu: użytkownik może dokonać zakupu i otrzymać potwierdzenie od Google, ale jego urządzenie traci połączenie sieciowe, 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 na innym urządzeniu.
  • Obsługa zakupów dokonywanych poza aplikacją: niektóre zakupy, np. wykorzystanie promocji, mogą być dokonywane poza aplikacją.
  • Obsługa zmian stanu zakupu: użytkownik może dokonać płatności za OCZEKUJĄCY zakup, 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. Metoda BillingClient.queryPurchasesAsync() zwróci zawieszone subskrypcje tylko wtedy, gdy parametr includeSuspendedSubscriptions jest ustawiony na QueryPurchasesParams.Builder. Zawieszone subskrypcje nie są zwracane w PurchasesUpdatedListener.

Gdy aplikacja wykryje nowy lub sfinalizowany zakup, powinna:

  • Zweryfikuj zakup.
  • Przyznaj użytkownikowi dostęp do treści po dokonaniu zakupu.
  • Powiadom użytkownika.
  • powiadomić Google, że aplikacja przetworzyła zrealizowane zakupy;

Te kroki zostały szczegółowo omówione w kolejnych sekcjach, a na końcu znajduje się sekcja podsumowująca wszystkie kroki.

Weryfikacja zakupu

Zanim przyznasz użytkownikowi korzyści, Twoja aplikacja powinna zawsze zweryfikować, czy zakupy są autentyczne. Możesz to zrobić, postępując zgodnie ze wskazówkami opisanymi w artykule Weryfikowanie zakupów przed przyznaniem uprawnień. Dopiero po zweryfikowaniu zakupu aplikacja powinna kontynuować jego przetwarzanie i przyznać uprawnienia użytkownikowi, co omówimy w następnej sekcji. Jeśli zakup nie przejdzie weryfikacji, sprawdzania kryteriów kwalifikacji lub kontroli nadużyć, zapoznaj się z artykułem Postępowanie w przypadku odrzuconych lub niezrealizowanych zakupów.

Przyznawanie uprawnień użytkownikowi

Gdy aplikacja zweryfikuje zakup, może nadal przyznawać uprawnienia użytkownikowi i powiadamiać go o tym. Zanim przyznasz uprawnienia, upewnij się, że aplikacja sprawdza, czy stan zakupu to PURCHASED. Jeśli zakup ma stan OCZEKUJĄCY, aplikacja powinna powiadomić użytkownika, że musi on jeszcze wykonać działania, aby sfinalizować zakup, zanim otrzyma uprawnienia. Przyznawaj uprawnienia tylko wtedy, gdy zakup zmieni stan z OCZEKUJĄCY na ZAKUPIONY. Więcej informacji znajdziesz w artykule Obsługa oczekujących transakcji.

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 je pobrać i użyć do przypisania zakupu do właściwego 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. Aby chronić się przed nadużyciami, Google Play zaleca zweryfikowanie tych identyfikatorów w bezpiecznym backendzie przed przyznaniem uprawnień. Więcej informacji znajdziesz w artykule Weryfikowanie zakupów przed przyznaniem uprawnień. Pamiętaj, że zakupy dokonane poza aplikacją nie będą miały ustawionych tych identyfikatorów. 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 OCZEKUJE, dopóki nie nadejdzie czas premiery. Zakup w przedsprzedaży zostanie sfinalizowany w momencie premiery i zmieni stan na ZAKUPIONO bez dodatkowych działań.

Powiadamianie użytkownika

Po przyznaniu uprawnień użytkownikowi aplikacja powinna wyświetlić powiadomienie potwierdzające zakup. Dzięki powiadomieniu użytkownik nie ma wątpliwości, czy zakup został sfinalizowany. W przeciwnym razie mógłby przestać korzystać z aplikacji, skontaktować się z zespołem pomocy lub poskarżyć się w mediach społecznościowych. Pamiętaj, że aplikacja może wykryć aktualizacje zakupów 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. Oto kilka przykładów sytuacji, w których opóźnienie może być odpowiednie:

  • Podczas akcji w grze lub scenek przerywnikowych wyświetlanie wiadomości może rozpraszać użytkownika. W takim przypadku musisz powiadomić użytkownika po zakończeniu działania.
  • podczas początkowego samouczka i konfigurowania gry przez użytkownika; Użytkownik mógł na przykład dokonać zakupu poza aplikacją przed jej zainstalowaniem. Zalecamy powiadomienie nowych użytkowników o nagrodzie natychmiast 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 o czynnościach, które 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.

W przypadku powiadamiania użytkownika o zakupie Google Play zaleca te mechanizmy:

  • wyświetlić okno w aplikacji,
  • Dostarczyć wiadomość do skrzynki odbiorczej w aplikacji i wyraźnie poinformować, że w skrzynce odbiorczej w aplikacji jest nowa wiadomość.
  • Użyj powiadomienia systemowego.

Powiadomienie powinno informować użytkownika o otrzymanej korzyści. Na przykład: „Kupiono 100 złotych monet”. Dodatkowo, jeśli zakup został dokonany w ramach korzyści z programu takiego jak Play Pass, aplikacja informuje o tym użytkownika. Na przykład „Odebrano produkty! Właśnie otrzymałeś(-aś) 100 klejnotów dzięki Play Pass. Kontynuuj”. Każdy program może zawierać wskazówki dotyczące zalecanego tekstu, który należy wyświetlać użytkownikom, aby poinformować 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 należy potwierdzić zakup. Musisz to zrobić w ciągu 3 dni, aby środki nie zostały automatycznie zwrócone, a uprawnienia cofnięte. 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 wykorzystywać zakupy. Sprawdź, czy zakup nie został już wykorzystany, sprawdzając wartość 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 produktu kupowanego raz, który odpowiada wejściowemu tokenowi zakupu, 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 i 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 =
        (billingResult, purchaseToken) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Handle the success of the consume operation.
            }
        };

billingClient.consumeAsync(consumeParams, listener);

Produkty, które się nie zużywają

Jeśli Twoja aplikacja ma bezpieczny backend, do potwierdzania zakupów produktów niekonsumpcyjnych zalecamy używanie metody Purchases.products:acknowledge. Sprawdź, czy zakup nie został wcześniej potwierdzony, sprawdzając acknowledgementState w wyniku wywołania funkcji Purchases.products:get.

Jeśli Twoja aplikacja działa tylko po stronie klienta, użyj metody BillingClient.acknowledgePurchase() z Biblioteki płatności w Google Play. Przed potwierdzeniem zakupu 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 = billingClient
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
    .setPurchaseToken(purchase.purchaseToken)
val ackPurchaseResult = withContext(Dispatchers.IO) {
    client.acknowledgePurchase(acknowledgePurchaseParams.build())
}

Java

if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
    if (!purchase.isAcknowledged()) {
        AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                        .setPurchaseToken(purchase.getPurchaseToken())
                        .build();
        billingClient.acknowledgePurchase(acknowledgePurchaseParams, (billingResult) -> {
            // Acknowledgment handled.
        });
    }
}

Subskrypcje

Subskrypcje są obsługiwane podobnie jak produkty niekonsumpcyjne. 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 potwierdzony, sprawdzając acknowledgementState w zasobie zakupu z Purchases.subscriptions:get. Możesz też potwierdzić subskrypcję za pomocą metody BillingClient.acknowledgePurchase() z Biblioteki płatności w Google Play po sprawdzeniu isAcknowledged(). Wszystkie pierwsze zakupy subskrypcji muszą zostać potwierdzone. Odnowienia subskrypcji nie wymagają potwierdzenia. Więcej informacji o tym, kiedy należy potwierdzać subskrypcje, znajdziesz w temacie Sprzedaż subskrypcji.

Odrzucone lub niezrealizowane zakupy

Jeśli zakup nie przejdzie weryfikacji backendu, kontroli uprawnień użytkownika, kontroli pod kątem oszustw i nadużyć lub jeśli Twój system nie może zrealizować uprawnienia, nie przyznawaj uprawnienia i nie potwierdzaj ani nie wykorzystuj zakupu.

Niepotwierdzone zakupy są automatycznie zwracane i anulowane po upływie okresu potwierdzenia, co ma na celu ochronę konsumentów. Nie polegaj jednak na tym okresie, aby odrzucać zakupy. Jeśli okno potwierdzenia wygaśnie, zamówienie pozostanie w stanie niepotwierdzonym i będzie niejednoznaczne dla Google Play, które nie będzie w stanie odróżnić celowego odrzucenia przez dewelopera od przekroczenia limitu czasu przetwarzania backendu.

Zamiast tego natychmiast unieważnij odrzucone zakupy i zwróć środki z poziomu backendu za pomocą interfejsu Google Play Developer API:

  • Subskrypcje: wywołaj purchases.subscriptionsv2.revoke z "fullRefund": {} w revocationContext. Spowoduje to natychmiastowe zakończenie subskrypcji, odebranie dostępu i rozpoczęcie procesu pełnego zwrotu środków.
  • Produkty kupowane raz: wywołaj metodę orders.refund z parametrem revoke ustawionym na true, aby natychmiast zwrócić środki za zamówienie i unieważnić uprawnienia. Podczas wywoływania tej metody musisz przekazać identyfikator zamówienia, który można pobrać za pomocą Purchase.getOrderId() lub purchases.productsv2.getproductpurchasev2. Nie wysyłaj nigdy wywołań consumeAsync(), acknowledgePurchase(), Purchases.products:consume ani Purchases.products:acknowledge w przypadku odrzuconych zakupów.
  • Działanie powiadomień w czasie rzeczywistym dla deweloperów i Voided Purchases API: odwołania i zwroty środków zainicjowane przez dewelopera (purchases.subscriptionsv2.revoke i orders.refund z parametrem revoke ustawionym na true) wywołują powiadomienia w czasie rzeczywistym dla deweloperów i są rejestrowane w Voided Purchases API (purchases.voidedpurchases.list z polem odpowiedzi voidedSource ustawionym na 1 dla dewelopera):
    • Subskrypcje: wysyła powiadomienie SUBSCRIPTION_REVOKED i VoidedPurchaseNotification.
    • Produkty kupowane raz: wysyła powiadomienie VoidedPurchaseNotification (oraz powiadomienie ONE_TIME_PRODUCT_CANCELED, jeśli w Konsoli Play skonfigurujesz aplikację tak, aby otrzymywała wszystkie powiadomienia o produktach kupowanych raz).
    • Wywołanie orders.refund bez ustawienia revoke na true powoduje zwrot środków za zamówienie bez unieważnienia uprawnień i nie wywołuje powiadomienia o unieważnieniu ani o anulowaniu zakupu. Więcej informacji znajdziesz w artykule Zarządzanie subskrypcjami i jednorazowymi zakupami.

Podsumowanie

Poniżej znajdziesz podsumowanie tych kroków.

  1. Wyślij zakup do bezpiecznego backendu, aby zweryfikować zakupy przed przyznaniem uprawnień.

  2. Zaktualizuj pamięć uprawnień o zakup. Jeśli zakup jest w stanie OCZEKUJĄCY, upewnij się, że uprawnienie jest oznaczone jako oczekujące, a użytkownik nie otrzymuje jeszcze korzyści. Zalecamy wykonanie tego kroku w bezpiecznym backendzie. Możesz go połączyć z wywołaniem interfejsu API w backendzie w kroku 1.

  3. Powiadom użytkownika za pomocą odpowiedniej wiadomości (w razie potrzeby opóźnij powiadomienie, jak opisano wcześniej).

  4. Powiadom Google, że zakup został przetworzony, wykonując czynności opisane w sekcji dotyczącej przetwarzania zakupów.

Aby sprawdzić, czy aplikacja prawidłowo wykonuje te czynności, możesz skorzystać z przewodnika po testowaniu.

Obsługa oczekujących transakcji

Google Play obsługuje oczekujące transakcje, czyli transakcje, które wymagają wykonania co najmniej 1 dodatkowej czynności między rozpoczęciem zakupu przez użytkownika a przetworzeniem formy płatności za ten zakup. Aplikacja nie powinna przyznawać uprawnień do tego typu zakupów, dopóki Google nie powiadomi Cię, że forma płatności użytkownika została obciążona.

Użytkownik może na przykład 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 podać kod kasjerowi i zapłacić gotówką. Następnie Google powiadamia Ciebie i użytkownika o otrzymaniu płatności. Aplikacja może wtedy przyznać użytkownikowi uprawnienia.

Wywołaj enablePendingPurchases() w ramach inicjowania BillingClient, aby włączyć oczekujące transakcje w aplikacji. Aplikacja musi włączać i 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 nowy zakup, czy to przez 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 w Play, gdy użytkownik dokona zakupu, metoda PurchasesUpdatedListener zostanie wywołana ponownie, a PurchaseState będzie mieć wartość PURCHASED. W tym momencie aplikacja może przetworzyć zakup, korzystając ze 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ń w czasie rzeczywistym dla deweloperów 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 terminie. Pamiętaj, że zawsze możesz użyć interfejsu Google Play Developer API, aby sprawdzić bieżący stan zakupu.

Obsługa zakupów wielokrotnych

Google Play umożliwia klientom kupowanie więcej niż 1 sztuki tego samego produktu kupowanego raz w ramach jednej transakcji. Wystarczy, że w koszyku podadzą odpowiednią liczbę. Ta funkcja jest obsługiwana w wersjach 4.0 i nowszych Biblioteki płatności w Google Play. Aplikacja powinna obsługiwać zakupy wielu sztuk i przyznawać uprawnienia na podstawie określonej liczby zakupionych produktów.

Aby uwzględniać zakupy wielu sztuk, logika udostępniania aplikacji musi sprawdzać liczbę produktów. Dostęp do pola quantity możesz uzyskać za pomocą jednego z tych interfejsów 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 detektor otrzymuje aktualizacje dotyczące wszystkich zapytań o konfigurację rozliczeń zainicjowanych z poziomu aplikacji.

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

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 {
                // Handle errors
            }
        }
    }
)

Java

GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(
        getBillingConfigParams,
        (billingResult, billingConfig) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK && billingConfig != null) {
                String countryCode = billingConfig.getCountryCode();
            } else {
                // TODO: Handle errors
            }
        });