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

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

Cykl zakupu

Oto typowy proces zakupu w przypadku produktu kupowanego raz 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. Przekazać użytkownikowi treści.
  5. potwierdzenie dostarczenia treści. W przypadku produktów konsumpcyjnych zużyj zakup, aby użytkownik mógł kupić produkt ponownie.

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

  • Aktywny: użytkownik ma dobrą historię płatności i ma dostęp do subskrypcji.
  • Anulowano: użytkownik anulował subskrypcję, ale nadal ma dostęp do treści do daty wygaśnięcia.
  • W okresie prolongaty:użytkownik napotkał problem z płatnością, ale nadal ma dostęp do konta, gdy Google ponawia próbę użycia formy płatności.
  • Wstrzymane: użytkownik napotkał problem z płatnością i nie ma już dostępu, ponieważ Google próbuje ponownie użyć formy płatności.
  • Wstrzymany: użytkownik wstrzymał swój dostęp i nie ma do niego dostępu, dopóki go nie wznowi.
  • Wygasła: użytkownik anulował subskrypcję i utracił do niej dostęp. Po wygaśnięciu konta użytkownika uznajemy, że użytkownik go zrezygnował.

Inicjowanie połączenia z Google Play

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

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

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

Odlotowe

dependencies {
    def billing_version = "7.0.0"

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

Kotlin

dependencies {
    val billing_version = "7.0.0"

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

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

Odlotowe

dependencies {
    def billing_version = "7.0.0"

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

Kotlin

dependencies {
    val billing_version = "7.0.0"

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

Inicjalizacja BillingClient

Po dodaniu zależności od Biblioteki płatności w Google Play musisz zainicjować wystąpienie BillingClient. BillingClient to główny interfejs komunikacji między Biblioteką płatności w Google Play a pozostałą częścią aplikacji. BillingClient udostępnia wygodne metody, zarówno synchroniczne, jak i asynchroniczne, na potrzeby wielu typowych operacji rozliczeniowych. Zdecydowanie zalecamy, aby naraz mieć otwarte tylko jedno aktywne połączenie BillingClient, aby uniknąć wielokrotnego wywołania funkcji PurchasesUpdatedListener w przypadku pojedynczego zdarzenia.

Aby utworzyć BillingClient, użyj newBuilder(). Do funkcji newBuilder() możesz przekazać dowolny kontekst, a funkcja BillingClient użyje go do uzyskania kontekstu aplikacji. Dzięki temu nie musisz się martwić o wycieki pamięci. Aby otrzymywać informacje o zakupach, musisz też zadzwonić na numer setListener(), podając numer referencyjny PurchasesUpdatedListener. Otrzymuje on 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();
.

Łączenie z Google Play

Po utworzeniu BillingClient musisz połączyć się z Google Play.

Aby połączyć się z Google Play, zadzwoń pod numer startConnection(). Proces połączenia jest asynchroniczny i gdy klient będzie gotowy do wysyłania kolejnych żądań, musisz wdrożyć BillingClientStateListener, aby otrzymać wywołanie zwrotne.

Musisz też zaimplementować logikę ponownych prób, aby obsługiwać utracone połączenia z Google Play. Aby wdrożyć logikę ponownych prób, zastąp metodę wywołania zwrotnego onBillingServiceDisconnected() i upewnij się, że BillingClient wywołuje metodę startConnection(), aby ponownie połączyć się z Google Play, zanim wyślesz kolejne żądania.

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

Kotlin

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

Java

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

wyświetlać produkty dostępne do kupienia;

Po połączeniu z Google Play możesz wysyłać zapytania o dostępne produkty i wyświetlać je użytkownikom.

Wysyłanie zapytań o szczegóły produktów jest ważnym krokiem przed wyświetleniem produktów użytkownikom, ponieważ zwraca ono zlokalizowane informacje o produktach. W przypadku subskrypcji upewnij się, że wyświetlanie produktu przestrzega wszystkich zasad Google Play.

Aby zapytać o szczegóły usługi w aplikacji, zadzwoń pod numer queryProductDetailsAsync().

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

Kotlin

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

billingClient.queryProductDetailsAsync(queryProductDetailsParams) {
    billingResult,
    productDetailsList ->
      // check billingResult
      // process returned productDetailsList
}

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,
                List<ProductDetails> productDetailsList) {
            // check billingResult
            // process returned productDetailsList
        }
    }
)

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

Wysyłanie zapytań za pomocą rozszerzeń Kotlina

Jeśli używasz rozszerzeń Kotlin, możesz wysyłać zapytania o szczegóły produktu w aplikacji, wywołując funkcję rozszerzenia queryProductDetails().

queryProductDetails() wykorzystuje współrzędne Kotlin, więc nie trzeba definiować oddzielnego detektora. Funkcja jest zawieszana do czasu zakończenia wykonywania zapytania, po czym możesz przetworzyć wynik:

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

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

    // Process the result.
}

Rzadko niektóre urządzenia nie obsługują funkcji ProductDetails i queryProductDetailsAsync() – zwykle z powodu nieaktualnej wersji Usług Google Play. Aby zapewnić prawidłowe działanie w tym scenariuszu, dowiedz się, jak korzystać z funkcji zgodności wstecznej w przewodniku po migracji do Biblioteki płatności w Play 5.

Przetwarzanie wyniku

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

Zanim zaoferujesz produkt do sprzedaży, sprawdź, czy użytkownik nie jest już jego właścicielem. Jeśli użytkownik ma w bibliotece produktów zużywany produkt, musi go spożyć, zanim będzie mógł ponownie kupić produkt.

Zanim zaoferujesz subskrypcję, sprawdź, czy użytkownik jeszcze jej nie subskrybuje. Pamiętaj też o tym:

  • queryProductDetailsAsync() zwraca szczegóły produktu objętego subskrypcją i maksymalnie 50 ofert na subskrypcję.
  • queryProductDetailsAsync() zwraca tylko oferty, które są dostępne dla użytkownika. Jeśli użytkownik spróbuje kupić ofertę, do której nie kwalifikuje się (np. aplikacja wyświetla nieaktualną listę ofert), Google Play informuje go, że nie kwalifikuje się do skorzystania z oferty, i może zamiast tego kupić abonament podstawowy.
.

Uruchamianie procesu zakupu

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

Kotlin

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

val productDetailsParamsList = listOf(
    BillingFlowParams.ProductDetailsParams.newBuilder()
        // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
        .setProductDetails(productDetails)
        // For One-time product, "setOfferToken" method shouldn't be called.
        // For subscriptions, to get an offer token, 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)
            // For one-time products, "setOfferToken" method shouldn't be called.
            // For subscriptions, to get an offer token, call
            // ProductDetails.subscriptionOfferDetails() for a list of offers
            // that are available to the user.
            .setOfferToken(selectedOfferToken)
            .build()
    );

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

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

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

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

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

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

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

Kotlin

override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
   if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) {
       for (purchase in purchases) {
           handlePurchase(purchase)
       }
   } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
       // Handle an error caused by a user cancelling 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) {
            handlePurchase(purchase);
        }
    } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
        // Handle an error caused by a user cancelling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

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

Ekran potwierdzający zakup w Google Play
Rysunek 2. Ekran potwierdzenia zakupu w Google Play.

Po pomyślnym zakupie generowany jest też token zakupu, czyli unikalny identyfikator reprezentujący użytkownika i identyfikator produktu kupionego w aplikacji. Aplikacje mogą przechowywać token zakupu lokalnie, ale zalecamy przekazanie go na bezpieczny serwer backendu, na którym możesz zweryfikować zakup i zabezpieczyć się przed oszustwem. W następnej sekcji znajdziesz więcej informacji na ten temat.

Użytkownik otrzyma też e-maila z potwierdzeniem transakcji, który będzie zawierał identyfikator zamówienia lub unikalny identyfikator transakcji. Użytkownicy otrzymują e-maila z unikalnym identyfikatorem zamówienia w przypadku każdego jednorazowego zakupu produktu oraz pierwszego zakupu subskrypcji i kolejnych automatycznych odnowień. Za pomocą identyfikatora zamówienia możesz zarządzać zwrotami środków w Konsoli Google Play.

Wskazać cenę indywidualną

Jeśli Twoja aplikacja może być rozpowszechniana w Unii Europejskiej, użyj metody setIsOfferPersonalized(), aby poinformować użytkowników, że cena produktu została spersonalizowana za pomocą zautomatyzowanego podejmowania decyzji.

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

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

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

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

Przetwarzanie zakupów

Gdy użytkownik dokona zakupu, aplikacja musi go przetworzyć. W większości przypadków aplikacja jest powiadamiana o zakupach przez PurchasesUpdatedListener. Jednak w niektórych przypadkach Twoja aplikacja będzie powiadamiana o zakupach przez wywołanie funkcji BillingClient.queryPurchasesAsync(), jak opisano w sekcji Pobieranie zakupów.

Jeśli na swoim bezpiecznym serwerze masz klienta Powiadomień w czasie rzeczywistym dla deweloperów, możesz rejestrować nowe zakupy, otrzymując subscriptionNotification lub oneTimeProductNotification z informacją o nowym zakupie. Po otrzymaniu tych powiadomień wywołaj interfejs API dla deweloperów Google Play, aby uzyskać pełny stan i zaktualizować stan własnego backendu.

Aplikacja powinna przetwarzać zakupy w ten sposób:

  1. Potwierdź zakup.
  2. Przekazać użytkownikowi treści i potwierdzić ich dostarczenie. Opcjonalnie oznacz produkt jako wykorzystany, aby użytkownik mógł go kupić ponownie.

Aby potwierdzić zakup, najpierw sprawdź, czy stan zakupu to PURCHASED. Jeśli zakup jest PENDING, przetwórz go zgodnie z opisem w artykule Przetwarzanie oczekujących transakcji. W przypadku zakupów otrzymanych z onPurchasesUpdated() lub queryPurchasesAsync() należy dodatkowo zweryfikować zakup, aby upewnić się, że jest on prawidłowy, zanim aplikacja przyzna uprawnienia. Aby dowiedzieć się, jak prawidłowo weryfikować zakupy, przeczytaj artykuł Weryfikacja zakupów przed przyznaniem uprawnień.

Po zweryfikowaniu zakupu aplikacja jest gotowa do przyznania uprawnień użytkownikowi. Konto użytkownika powiązane z zakupem można zidentyfikować za pomocą parametru ProductPurchase.obfuscatedExternalAccountId zwracanego przez funkcję Purchases.products:get w przypadku zakupów produktów w aplikacji oraz parametru SubscriptionPurchase.obfuscatedExternalAccountId zwracanego przez funkcję Purchases.subscriptions:get w przypadku subskrypcji po stronie serwera lub parametru obfuscatedAccountId zwracanego przez funkcję Purchase.getAccountIdentifiers() po stronie klienta, jeśli został on ustawiony za pomocą funkcji setObfuscatedAccountId w momencie dokonania zakupu.

Gdy przyznasz aplikacji uprawnienia, musi ona potwierdzić zakup. To potwierdzenie informuje Google Play o tym, że użytkownik ma uprawnienia do zakupionych treści.

Proces przyznawania uprawnień i potwierdzania zakupu zależy od tego, czy zakupione treści są treściami zużywalnymi, niezużywalnymi czy subskrypcją.

Produkty konsumpcyjne

W przypadku materiałów eksploatacyjnych, jeśli aplikacja ma bezpieczny backend, zalecamy korzystanie z Purchases.products:consume, aby móc niezawodnie korzystać z zakupów. Upewnij się, że zakup nie został już wykorzystany, sprawdzając wartość consumptionState z wyniku wywołania funkcji Purchases.products:get. Jeśli aplikacja jest przeznaczona tylko dla klienta i nie ma backendu, użyj opcji consumeAsync() z Biblioteki płatności w Google Play. Obie metody spełniają wymóg potwierdzenia i wskazują, że aplikacja przyznała użytkownikowi odpowiednie uprawnienia. Te metody umożliwiają też aplikacji udostępnienie produktu jednorazowego odpowiadającego tokenowi zakupu wejściowego do ponownego zakupu. W przypadku funkcji consumeAsync() musisz też przekazać obiekt, który implementuje interfejs ConsumeResponseListener. Ten obiekt obsługuje wynik operacji konsumpcji. Możesz zastąpić metodę onConsumeResponse(), którą Biblioteka płatności w Google Play wywołuje po zakończeniu operacji.

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

Kotlin

suspend fun handlePurchase(purchase: Purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
    val purchase : Purchase = ...;

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

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

Java

void handlePurchase(Purchase purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
    Purchase purchase = ...;

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

    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

Jeśli chcesz potwierdzić zakupy, których nie można wykorzystać, jeśli Twoja aplikacja ma bezpieczny backend, zalecamy używanie Purchases.products:acknowledge do potwierdzania zakupów. Sprawdź, czy zakup nie został wcześniej potwierdzony, zaznaczając acknowledgementState w wyniku wywołania Purchases.products:get.

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

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

Kotlin

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

suspend fun handlePurchase() {
    if (purchase.purchaseState === PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged) {
            val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.purchaseToken)
            val ackPurchaseResult = withContext(Dispatchers.IO) {
               client.acknowledgePurchase(acknowledgePurchaseParams.build())
            }
        }
     }
}

Java

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

void handlePurchase(Purchase purchase) {
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged()) {
            AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
            client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
        }
    }
}

Subskrypcje

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

Pobieranie zakupów

Odsłuchiwanie aktualizacji zakupów za pomocą PurchasesUpdatedListener nie wystarczy, aby mieć pewność, że Twoja aplikacja przetwarza wszystkie zakupy. Możliwe, że Twoja aplikacja nie wie o wszystkich zakupach dokonanych przez użytkownika. Oto kilka sytuacji, w których aplikacja może utracić informacje o zakupach lub nie być świadoma ich dokonania:

  • Problemy z siecią podczas zakupu: użytkownik dokonuje zakupu i otrzymuje potwierdzenie od Google, ale urządzenie traci połączenie z siecią, zanim otrzyma powiadomienie o zakupie (w systemie PurchasesUpdatedListener).
  • Wiele urządzeń: użytkownik kupuje produkt na jednym urządzeniu, a potem oczekuje, że będzie on widoczny po przełączeniu urządzenia.
  • Zarządzanie zakupami dokonywanymi poza aplikacją: niektóre zakupy, np. wykorzystanie promocji, można dokonać poza aplikacją.

Aby obsłużyć te sytuacje, w metodzie onResume() w aplikacji wywołuj funkcję BillingClient.queryPurchasesAsync(), aby mieć pewność, że wszystkie zakupy są przetwarzane zgodnie z opisem w sekcji przetwarzanie zakupów.

Poniższy przykład pokazuje, jak pobrać informacje o zakupach subskrypcji użytkownika. Pamiętaj, że queryPurchasesAsync() zwraca tylko aktywne subskrypcje i niewykorzystane jednorazowe zakupy.

Kotlin

val params = QueryPurchasesParams.newBuilder()
               .setProductType(ProductType.SUBS)

// uses queryPurchasesAsync Kotlin extension function
val purchasesResult = billingClient.queryPurchasesAsync(params.build())

// check purchasesResult.billingResult
// process returned purchasesResult.purchasesList, e.g. display the plans user owns

Java

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
      .setProductType(ProductType.SUBS)
      .build(),
    new PurchasesResponseListener() {
      public void onQueryPurchasesResponse(BillingResult billingResult, List<Purchase> purchases) {
        // check billingResult
        // process returned purchase list, e.g. display the plans user owns

      }
    }
);

Obsługa zakupów dokonywanych poza aplikacją

Niektóre zakupy mogą być dokonywane poza aplikacją, np. w ramach promocji lub przypomnień o porzuconym koszyku w Google Play Games. Gdy użytkownik dokonuje zakupu poza aplikacją, oczekuje, że aplikacja wyświetli wiadomość lub użyje jakiegoś mechanizmu powiadomień, aby poinformować go, że zakup został prawidłowo odebrany i przetworzony. Dopuszczalne mechanizmy to m.in.:

  • wyświetlać wyskakujące okienko w aplikacji.
  • Wyślij wiadomość do okienka wiadomości w aplikacji i wyraźnie zaznacz, że w okienku jest nowa wiadomość.
  • Użyj powiadomienia z systemu operacyjnego.

Pamiętaj, że aplikacja może znajdować się w dowolnym stanie, w którym rozpozna zakup. Może się nawet zdarzyć, że aplikacja nie zostanie zainstalowana nawet po zakupie. Użytkownicy oczekują, że zakupione treści będą dostępne, gdy wznowią korzystanie z aplikacji, niezależnie od jej stanu.

Zakupy musisz wykrywać niezależnie od stanu aplikacji w momencie ich dokonania. Są jednak pewne wyjątki, w których przypadku nie jest konieczne natychmiastowe powiadomienie użytkownika o otrzymaniu produktu. Na przykład:

  • Podczas wykonywania czynności, w której wyświetlenie komunikatu może rozpraszać użytkownika. W takim przypadku musisz powiadomić użytkownika po zakończeniu części z działaniem.
  • podczas przerywników, ponieważ wyświetlanie wiadomości może rozpraszać użytkownika. W takim przypadku musisz powiadomić użytkownika po zakończeniu przerywnika.
  • W trakcie początkowego samouczka i konfiguracji użytkownika w grze. Zalecamy poinformowanie nowych użytkowników o nagrodach zaraz po uruchomieniu gry lub podczas początkowej konfiguracji konta. Możesz jednak poczekać, aż główna sekwencja gry będzie dostępna, aby powiadomić użytkownika.

Decydując, kiedy i jak informować użytkowników o zakupach dokonanych poza aplikacją, zawsze miej na uwadze użytkownika. Jeśli użytkownik nie otrzyma natychmiast powiadomienia, może się pogubić, przestać korzystać z aplikacji, skontaktować się z zespołem pomocy lub złożyć skargę w mediach społecznościowych.

.

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

W przypadku deweloperów gier, którzy zarabiają na zakupach w aplikacji, jednym ze sposobów sprzedaży aktywnych w Konsoli Google Play jednostek magazynowych poza aplikacją jest funkcja Przypomnienie o porzuceniu koszyka, która zachęca użytkowników do dokończenia wcześniej porzuconych zakupów podczas przeglądania Sklepu Google Play. Te zakupy są dokonywane poza aplikacją, w Grze Google Play w Sklepie Google Play.

Ta funkcja jest domyślnie włączona, aby pomóc użytkownikom w powrocie do miejsca, w którym przerwali, oraz 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.

Te obrazy pokazują przypomnienie o porzuceniu koszyka, które wyświetla się w Sklepie Google Play:

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

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

Obsługa oczekujących transakcji

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

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

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

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

Jeśli aplikacja jest uruchomiona, gdy użytkownik dokona zakupu, funkcja PurchasesUpdatedListener zostanie wywołana ponownie, a wartość PurchaseState zmieni się na PURCHASED. W tym momencie Twoja aplikacja może przetworzyć zakup, korzystając ze standardowej metody przetwarzania zakupów. Aplikacja powinna też wywoływać metodę queryPurchasesAsync() w metodie onResume(), aby obsługiwać zakupy, które przeszły w stanie PURCHASED, gdy aplikacja była wyłączona.

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

Obsługa zakupów wielu sztuk

Biblioteka Google Play umożliwia klientom zakup więcej niż 1 sztukę tego samego produktu w aplikacji w ramach jednej transakcji. Aby to zrobić, należy określić liczbę w koszyku zakupów. Funkcja jest obsługiwana w wersjach 4.0 i wyższych biblioteki Google Play Billing Library. Aplikacja powinna obsługiwać zakupy naraz i przyznawać uprawnienia na podstawie określonej liczby zakupów.

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

Gdy dodasz już zasady obsługi zakupów wielu sztuk tego samego produktu, musisz włączyć tę funkcję dla odpowiedniego produktu na stronie zarządzania produktami w aplikacji w Konsoli programisty Google Play.

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

getBillingConfigAsync() to kraj, który użytkownik podaje w Google Play.

Po utworzeniu zapytania BillingClient możesz wysłać zapytanie o konfigurację płatności użytkownika. Poniższy fragment kodu pokazuje, jak wywołać funkcję getBillingConfigAsync(). Aby przetworzyć odpowiedź, zaimplementuj tag BillingConfigResponseListener. Ten odbiornik otrzymuje aktualizacje dotyczące wszystkich zapytań dotyczących konfiguracji płatności inicjowanych z 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
        }
      }
    });