BlogRight arrowTutorialRight ArrowZakupy w aplikacji na Androida, część 5: walidacja zakupów po stronie serwera
BlogRight arrowTutorialRight ArrowZakupy w aplikacji na Androida, część 5: walidacja zakupów po stronie serwera

Zakupy w aplikacji na Androida, część 5: walidacja zakupów po stronie serwera

Zakupy w aplikacji na Androida, część 5: walidacja zakupów po stronie serwera
Listen to the episode
Zakupy w aplikacji na Androida, część 5: walidacja zakupów po stronie serwera

Walidacja po stronie serwera (server-side validation) może pomóc w weryfikacji autentyczności zakupu. Urządzenie wyśle żądanie do serwerów Google, aby dowiedzieć się, czy zakup rzeczywiście miał miejsce i czy jest poprawny.

W tym przewodniku omówimy, jak skonfigurować walidację po stronie serwera dla aplikacji na Androida. 

Dlaczego warto dokonywać walidacji zakupów

Należy zauważyć, że walidacja po stronie serwera nie jest obowiązkowa i zakupy w aplikacji będą działać także bez niej. Istnieją jednak pewne znaczące jej korzyści:

  1. Zaawansowana analityka płatności, która jest szczególnie ważna w przypadku subskrypcji, ponieważ wszystko, co dzieje się po aktywacji, nie jest przetwarzane przez urządzenie. Bez przetwarzania zakupu po stronie serwera nie będzie można odzyskać bieżącego statusu subskrypcji i dowiedzieć się, czy użytkownik odnowił lub anulował subskrypcję, czy występują problemy z płatnością, i tak dalej.
  2. Możliwość weryfikacji autentyczności zakupu. Będziesz mieć pewność, że transakcja nie jest oszustwem, a użytkownik faktycznie zapłacił za twój produkt.
  3. Subskrypcje między platformami. Jeśli możesz sprawdzić status subskrypcji użytkownika w czasie rzeczywistym, możesz zsynchronizować ją z innymi platformami. Na przykład użytkownik, który kupił subskrypcję z urządzenia z systemem iOS, będzie mógł z niej korzystać na Androidzie, na stronie internetowej i na innych platformach. 
  4. Możliwość kontrolowania dostępu do treści od strony serwera, który chroni przed użytkownikami próbującymi uzyskać dostęp do danych bez subskrypcji, po prostu wykonując żądania do serwera. 

Mówiąc z naszego doświadczenia, pierwsza zaleta wystarczy, aby skonfigurować przetwarzanie zakupów po stronie serwera.

⭐️ Download our guide on in-app techniques which will make in-app purchases in your app perfect

Walidacja płatności

Możemy podsumować walidację płatności Androida za pomocą tego schematu:

Uwierzytelnianie dla żądań Google Play Developer API

Aby pracować z Google Play Developer API, musisz najpierw wygenerować klucz do podpisania żądań. Najpierw musisz połączyć swoje konto konsoli Google Play (gdzie zarządzasz aplikacją) z kontem Google Cloud (gdzie wygenerujesz klucz do podpisywania żądań). Po skonfigurowaniu wszystkiego konieczne będzie przyznanie użytkownikowi prawa do zarządzania zakupami. Potrzebny byłby dedykowany artykuł, aby opisać ten proces. Na szczęście omówiliśmy to już w przewodniku "krok po kroku", który znajduje się w dokumentacji Adapty

Zauważ, że zwykle musisz poczekać 24 godziny lub więcej po wygenerowaniu klucza, aby zaczął działać. Aby tego uniknąć, po prostu zaktualizuj opis dowolnego produktu w aplikacji lub subskrypcji, która natychmiast aktywuje klucz. 

Korzystamy z oficjalnej biblioteki google-api-python-client do współpracy z Google Play Developer API. Ta biblioteka jest dostępna dla większości popularnych języków i polecam jej używanie, ponieważ obsługuje wszystkie metody, jakich tylko możesz potrzebować.

Walidacja transakcji subskrypcyjnych

W przeciwieństwie do walidacji po stronie serwera iOS, w Androidzie zarówno subskrypcja, jak i inne walidacje produktu są realizowane przy użyciu różnych metod. Dlatego podczas zatwierdzania transakcji musisz wiedzieć, czy masz do czynienia z produktem, czy subskrypcją. W praktyce oznacza to, że musisz przesłać te dane z aplikacji mobilnej, a także zachować oznaczenie w bazie danych na wypadek, gdyby konieczna była ponowna walidacja tokenu.

Drugą ważną różnicą jest to, że podczas gdy każda transakcja ma swój własny token w systemie Android, wszystkie transakcje na iOS używają współdzielonego sekretu, specyficznego dla aplikacji do przechowywania całej historii transakcji. Oznacza to, że jeśli chcesz być w stanie przywrócić zakupy użytkownika w dowolnym momencie, konieczne jest przechowywanie wszystkich token zakupu, w przeciwieństwie do arbitralnego wybierania jednego z nich.

Aby zweryfikować subskrypcję, musisz wywołać metodę purchases.subscriptions.get.  Zasadniczo jest to wywołanie żądania GET:

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}

Wszystkie parametry są wymagane:

  • packageName: identyfikator aplikacji, np. com.adapty.sample_app.
  • subscriptionId: identyfikator subskrypcji dla subskrypcji, która powinna zostać walidowana, np. com.adapty.sample_app.weekly_sub.
  • token: unikalny token transakcji. Pojawia się po przetworzeniu zakupu po stronie aplikacji mobilnej.

Najpierw przyjrzyjmy się komunikatom o błędach, które należy usunąć, aby upewnić się, że wszystko działa tak, jak powinno:

  • 400, Invalid grant: account not found: ten komunikat o błędzie oznacza, że klucz uwierzytelniania żądania został wygenerowany nieprawidłowo. Upewnij się, że Twoje konta są połączone, używasz właściwego, który ma wystarczające uprawnienia oraz że wszystkie wymagane interfejsy API są aktywowane. Zobacz sekcję poniżej, aby dowiedzieć się, jak wszystko skonfigurować. Zwróć uwagę na wskazówkę dotyczącą aktualizacji opisu produktu.
  • 400, The purchase token does not match the package name: ten komunikat o błędzie jest zwykle spotykany w przypadku nieuczciwych transakcji. Jeśli zobaczysz go podczas testowania, upewnij się, że nie używasz tokena zakupu aplikacji należącego do innej aplikacji.
  • 403, Quota exceeded for quota metric 'Queries' and limit 'Queries per day' of service 'androidpublisher.googleapis.com': oznacza to, że dzienny limit żądań API Google został przekroczony. Domyślnie można wykonać do 200 000 żądań na dzień. Ten limit może zostać zwiększony, ale powinien wystarczyć dla większości aplikacji. Jeśli napotkasz ten limit, prawdopodobnie powinieneś dokładnie sprawdzić logikę aplikacji i upewnić się, że wszystko jest w porządku.
  • 410, The subscription purchase is no longer available for query because it has been expired for too long: ten komunikat o błędzie pojawia się w transakcjach, w których subskrypcja wygasła ponad 60 dni temu. Nie jest to rzeczywisty komunikat o błędzie i nie powinien być przetwarzany jako taki.
Start for free

You don't need to write server code yourself,

because we did it for you. Try Adapty SDK!

Start for free

Transakcja subskrypcji 

Jeśli walidacja przebiegła pomyślnie, otrzymasz dane transakcji jako odpowiedź.

Dane transakcji (dla subskrypcji):

{
    "expiryTimeMillis": "1631116261362",
    "paymentState": 1,
    "acknowledgementState": 1,
    "kind": "androidpublisher#subscriptionPurchase",
    "orderId": "GPA.3382-9215-9042-70164",
    "startTimeMillis": "1630504367892",
    "autoRenewing": true,
    "priceCurrencyCode": "USD",
    "priceAmountMicros": "1990000",
    "countryCode": "US",
    "developerPayload": ""
}

Aby dowiedzieć się, czy użytkownik ma dostęp do opcji premium oferowanych przez aplikację (tj. czy posiada aktywną subskrypcję), konieczne jest:

  1. Sprawdź parametry startTimeMillis oraz expiryTimeMillis. Aktualny czas powinien być między nimi.
  2. Co więcej, musisz upewnić się, że parametr paymentState nie posiada wartości '0'. Oznaczałoby to, że zakup subskrypcji jest nadal w toku, dlatego nie ma jeszcze potrzeby przyznawania użytkownikowi dostępu do funkcji premium. 
  3. Jeśli transakcja posiada wartość autoResumeTimeMillis , w takim wypadku abonament zostaje wstrzymany. Oznacza to, że użytkownik nie powinien otrzymać dostępu do funkcji premium przed określoną datą.

Zobaczmy kluczowe wartości transakcji subskrypcji:

  • kind: rodzaj transakcji. W przypadku subskrypcji zawsze posiada wartość androidpublisher#subscriptionPurchase. Dzięki temu parametrowi możesz zrozumieć, czy masz do czynienia z subskrypcją, czy produktem, i odpowiednio wybrać logikę przetwarzania.
  • paymentState: status płatności. Ta wartość nie jest obecna dla wygasłych transakcji. Możliwe wartości to:
    0: Ten zakup nie został jeszcze przetworzony. W niektórych krajach użytkownik może zapłacić za subskrypcję na oddzielnym urządzeniu. Oznacza to, że użytkownik inicjuje zakup subskrypcji ze swojego urządzenia, a płaci za nią w pobliskim terminalu. Ogólnie rzecz biorąc, jest to dość rzadki przypadek, ale nadal należy o nim pamiętać.
    1: Zakupiono abonament.
    2: Subskrypcja jest w okresie próbnym.
    3: Subskrypcja zostanie podwyższona lub obniżona w następnym okresie. Oznacza to, że plan subskrypcji będzie ulegał zmianie.
  • acknowledgementState: status potwierdzenia zakupu. Jest to ważny parametr, który potwierdza, czy użytkownik otrzymał dostęp do tego, za co zapłacił. Wartość "0" oznacza, że nie posiada dostępu, a "1" oznacza, że go ma. Deweloper jest odpowiedzialny za zdefiniowanie tego statusu, co można zrobić zarówno po stronie aplikacji mobilnej, jak i serwera. Jeśli nie potwierdzisz zakupu w ciągu 3 dni od jego dokonania, zostanie on automatycznie zwrócony. Polecam wdrożenie tej logiki: po otrzymaniu transakcji zawierającej acknowledgementState=0, parametr zostanie zmieniony przez serwer. Opowiem, jak to zrobić poniżej. 
  • orderId: unikalny identyfikator transakcji. Każdy zakup lub odnowienie subskrypcji (subscription renewal) będzie posiadało swój własny identyfikator, który można wykorzystać, aby dowiedzieć się, czy ta transakcja została już przetworzona wcześniej. Każdy identyfikator odnowienia będzie posiadać stałą pierwszą połowę, do której dołączane są dwie kropki i liczba odnowień subskrypcji (zaczynająca się od 0). Jeśli subskrypcja podczas aktywacji posiadała identyfikator GPA.3382-9215-9042-70164, wówczas pierwsze odnowienie zostanie zidentyfikowane jako GPA.3382-9215-9042-70164..0, drugie GPA.3382-9215-9042-70164..1, itd. W ten sposób możesz tworzyć łańcuchy transakcji i śledzić liczbę odnowień.
  • startTimeMillis: data rozpoczęcia subskrypcji.
  • expiryTimeMillis: data wygaśnięcia subskrypcji.
  • autoRenewing: znacznik wskazujący, czy subskrypcja ma zostać przedłużona na kolejny okres.
  • priceCurrencyCode: waluta zakupu w formacie trzyliterowym, np. USD.
  • priceAmountMicros: cena zakupu. Aby uzyskać normalną wartość ceny, podziel tę wartość przez 1000000. Oznacza to, że 1990000 w rzeczywistości oznacza 1,99. 
  • countryCode: kraj zakupu w formacie dwuliterowym, np. US
  • purchaseType: rodzaj zakupu. Ten klucz nie będzie obecny w większości przypadków. Jest nadal ważne, aby wziąć go pod uwagę, ponieważ pomaga on zrozumieć, czy zakup został dokonany w środowisku Sandbox. Możliwe wartości to:
    0: zakup został dokonany w środowisku Sandbox, dlatego nie powinien być uwzględniany w danych analitycznych.
    1: zakup został dokonany przy użyciu kodu promocyjnego. 
  • autoResumeTimeMillis: data odnowienia subskrypcji. Jest on obecny tylko dla subskrypcji, które zostały wcześniej wstrzymane. Jeśli ten parametr jest obecny, nie musisz przyznawać użytkownikowi dostępu do funkcji premium przed podaną datą.
  • cancelReason: Powód, dla którego subskrypcja nie zostanie odnowiona. Możliwe wartości to:
    0: użytkownik anulował automatyczne odnawianie subskrypcji.
    1: subskrypcja została anulowana przez system. Jest to najczęściej spowodowane przez problemy z rozliczeniami.
    2: użytkownik przeszedł na inny plan subskrypcji.
    3: deweloper anulował subskrypcję.
  • userCancellationTimeMillis: dane dotyczące anulowania odnowienia subskrypcji. Występuje tylko wtedy, gdy cancelReason wynosi 0. Subskrypcja może być nadal aktywna-aby się upewnić, sprawdź wartość parametru expiryTimeMillis .
  • cancelSurveyResult: Obiekt który przechowuje powód anulowania subskrypcji, który będzie obecny, jeśli użytkownik pozostawił jakiekolwiek opinie w tej sprawie.
  • introductoryPriceInfo: Obiekt który przechowuje wstępne dane cenowe. Na przykład może to być specjalna oferta na 1 miesiąc z 50% zniżką.
  • promotionType: Kod promocyjny, który został użyty do aktywacji subskrypcji. Możliwe wartości to:
    0: jednorazowy kod promocyjny.
    1: Masowy kod promocyjny, który może zostać zastosowany przez wielu klientów. Takie kody są zwykle używane przy współpracy z blogerami. 
  • promotionCode: masowy kod promocyjny, który został użyty do aktywacji subskrypcji. Ten parametr nie jest obecny dla jednorazowych kodów promocyjnych. 
  • priceChange: Obiekt, który przechowuje dane dotyczące przyszłych zmian cen, a także czy użytkownik wyraził na to zgodę.

Potwierdzenie subskrypcji

Jak już wspomniano powyżej, jeśli subskrypcja nie zostanie potwierdzona w ciągu 3 dni od dokonania zakupu, zostanie automatycznie anulowana i zwrócona. Szczerze mówiąc, nie bardzo rozumiem logikę, która się kryje w tym systemie, i nigdy nie spotkałem się z nim w innych systemach przetwarzania płatności, w tym iOS. Mimo to, jeśli otrzymasz transakcję zawierającą acknowledgementState=0, musisz potwierdzić subskrypcję.

Aby to zrobić, musisz wywołać metodę purchases.subscriptions.acknowledge. Ta metoda wykonuje żądanie POST

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}:acknowledge

Parametry są takie same jak w przypadku walidacji żądania. Jeśli żądanie zostanie pomyślnie zrealizowane, subskrypcja zostanie potwierdzona, co oznacza, że nie stracisz pieniędzy. 

Jeśli subskrypcja nie została jeszcze w pełni zakupiona, nie ma potrzeby potwierdzania jej. 

Anulowanie, odwołanie, zwrot i odroczenie odnowienia subskrypcji

Oprócz weryfikacji i potwierdzenia subskrypcji, Google Play Developer API może być również używane do innych operacji, związanych z subskrypcjami. Należy zauważyć, że są one dość rzadkie i, z wyjątkiem odnowienia, są obsługiwane przez konsolę Google Play. Mimo tego wymienię je, aby dać ci ogólne zrozumienie zakresu rozwiązań API. Wszystkie te żądania mają te same parametry wymagane jak wyżej wymienione metody, a mianowicie, packageName, subscriptionId, oraz token.

  • Anulowanie odnowienia (renewal cancellation). Metoda purchases.subscriptions.cancel. Anuluje automatyczne odnawianie wybranej subskrypcji. Subskrypcja będzie jednak nadal dostępna przez cały bieżący okres rozliczeniowy.
  • Zwrot opłaty za subskrypcję (subscription refund). Metoda purchases.subscriptions.refund. Dokonuje ona zwrotu opłaty za subskrypcję. Jednak użytkownik nadal zachowa dostęp do subskrypcji i zostanie ona automatycznie odnowiona w następnym okresie. W większości przypadków powinieneś również odwołać subskrypcję przy dokonywaniu zwrotu pieniędzy.
  • Odwołanie subskrypcji (subscription revocation). Metoda purchases.subscriptions.revoke. Natychmiast anuluje subskrypcję, co oznacza, że użytkownik nie będzie mógł uzyskać dostępu do funkcji premium. Subskrypcja nie zostanie odnowiona. Metoda ta jest zwykle wywoływana wraz z dokonaniem zwrotu środków.
  • Odroczenie zakupu subskrypcji (subscription purchase deferral). Metoda purchases.subscriptions.defer. Przedłuża subskrypcję do określonej daty. W żądaniu określ datę wygaśnięcia subskrypcji, a także datę, na którą chcesz ją zastąpić. To ostatnie musi skutkować dłuższym okresem subskrypcji niż poprzedni.

Walidacja produktu (nie subskrypcji)

Walidacja produktu jest podobna do walidacji subskrypcji. Musisz powołać się na metodę purchases.products.get do wykonania żądania GET.

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}

Wszystkie te parametry znamy już z powyższych przykładów.

Dane transakcji (dla produktu):

{
  "purchaseTimeMillis": "1630529397125",
  "purchaseState": 0,
  "consumptionState": 0,
  "developerPayload": "",
  "orderId": "GPA.3374-2691-3583-90384",
  "acknowledgementState": 1,
  "kind": "androidpublisher#productPurchase",
  "regionCode": "RU"
}

Transakcje produktowe zawierają znacznie mniej wartości, niż transakcje subskrypcyjne. Rzućmy okiem na kilka ważnych:

  • kind: rodzaj transakcji. W produktach zawsze ma wartość androidpublisher#productPurchase. Dzięki temu parametrowi możesz zrozumieć, czy masz do czynienia z subskrypcją, czy produktem, i odpowiednio wybrać logikę przetwarzania.
  • purchaseState: status płatności. Zauważ, że kluczowe wartości tutaj różnią się od parametru dla subskrypcji paymentState . Możliwe wartości to:
    0: zakup został zakończony.
    1: zakup został anulowany. Oznacza to, że zakup był w toku, ale użytkownik nigdy za niego nie zapłacił.
    2: zakup jest w toku. W niektórych krajach użytkownik może zapłacić za subskrypcję na oddzielnym urządzeniu. Oznacza to, że użytkownik inicjuje zakup subskrypcji ze swojego urządzenia, a płaci za nią w pobliskim terminalu. Ogólnie rzecz biorąc, jest to dość rzadki przypadek, ale nadal należy o nim pamiętać.
  • acknowledgementState: status potwierdzenia zakupu. Jest to ważny parametr, który potwierdza, czy użytkownik otrzymał dostęp do tego, za co zapłacił. Wartość "0" oznacza, że nie posiada dostępu, a "1" oznacza, że go ma. Deweloper jest odpowiedzialny za zdefiniowanie tego statusu, co można zrobić zarówno po stronie aplikacji mobilnej, jak i serwera. Jeśli nie potwierdzisz zakupu w ciągu 3 dni od jego dokonania, zostanie on automatycznie zwrócony. Polecam wdrożenie tej logiki: po otrzymaniu transakcji zawierającej acknowledgementState=0, parametr zostanie zmieniony przez serwer. Omówię, jak to zrobić poniżej. 
  • consumptionState: Stan użycia produktu. To właśnie iOS określa jako "consumable". Jest to zdefiniowane po stronie aplikacji mobilnej. Jeśli posiada wartość "0", oznacza to, że produkt nie został użyty; jeśli wynosi "1", został już użyty. Jeśli sprzedajesz dożywotni dostęp do aplikacji lub określoną funkcję premium, taki produkt nie powinien być użyty, to znaczy powinien posiadać status 0. Jeśli sprzedajesz monety, które użytkownik może kupować regularnie, takie produkty powinny być używane, to znaczy powinny mieć status 1. consumptionState=0 oznacza, że produkt można kupić tylko raz, natomiast consumptionState=1 oznacza, że można go kupić wiele razy.
  • orderId: unikalny identyfikator transakcji. Każdy zakup lub odnowienie subskrypcji będzie posiadało swój własny identyfikator, który można wykorzystać, aby dowiedzieć się, czy ta transakcja została już przetworzona wcześniej.
  • purchaseTimeMillis: data zakupu.
  • regionCode: kraj zakupu w formacie dwuliterowym, np. USA. Zauważ, że nazwa tego parametru jest inna niż w subskrypcjach, gdzie nazywa się on countryCode
  • purchaseType: rodzaj zakupu. Ten klucz nie będzie obecny w większości przypadków. Jest nadal ważne, aby wziąć go pod uwagę, ponieważ pomaga on zrozumieć, czy zakup został dokonany w środowisku Sandbox. Możliwe wartości to:
    0: zakup został dokonany w środowisku Sandbox, dlatego nie powinien być uwzględniany w danych analitycznych.
    1: zakup został dokonany przy użyciu kodu promocyjnego.
    2: zakup został przyznany za określone działanie, np. oglądanie reklamy w aplikacji zamiast płatności.

Jak widać, walidacja produktu jest bardzo podobna do walidacji subskrypcji. Jest jednak kilka punktów, na które warto zwrócić uwagę:

  • Cena nie jest zwracana, chociaż byłoby to dość przydatne dla analityki.
  • Wartości parametru purchaseState znacznie różni się od wartości parametru paymentState, który można znaleźć w subskrypcjach. Spowoduje to błędy, jeśli nie weźmie się tego pod uwagę. 
  • regionCode zostaje zwrócony, mimo że jest nazywany countryCode w przypadku subskrypcji.

Podobnie jak zakupy subskrypcji, zakupy produktów muszą zostać potwierdzone. W tym celu należy powołać się na metodę purchases.products.acknowledge, która wykona żądanie POST

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}:acknowledge

Jeśli zakup nie został jeszcze sfinalizowany, nie ma potrzeby potwierdzania go.

Śledzenie zwrotów za subskrypcje i produkty

Wysokiej jakości analityka jest niemożliwa bez rozliczania zwrotów środków. Niestety dane zwrotu nie są obecne w transakcji ani nie są wyświetlane jako osobne zdarzenie (event), jak ma to miejsce w systemie iOS. Aby otrzymać listę zwróconych transakcji, musisz wywołać purchases.voidedpurchases.list regularnie — na przykład raz dziennie. Ta metoda wykona żądanie GET:

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/voidedpurchases

W odpowiedzi na zapytanie otrzymasz listę wszystkich zwróconych transakcji. Polecam wyszukiwanie transakcji w bazie przez parametr orderId, w przeciwieństwie do purchaseToken. Po pierwsze, zajmie to mniej czasu. Po drugie, wszystkie odnowienia subskrypcji będą współdzielić ten sam token i wystarczy pobrać najnowszy.

Powiadomienia serwera (server notifications) o transakcjach

Powiadomienia serwera (powiadomienia deweloperów w czasie rzeczywistym) pomagają dowiedzieć się o wydarzeniach, które miały miejsce po stronie Google, na twoim serwerze, do tego prawie na żywo. Po ich skonfigurowaniu otrzymasz powiadomienia o nowych zakupach, odnowieniach, problemach z płatnościami itp. Może to pomóc w zbieraniu lepszych analiz, a także znacznie ułatwić zarządzanie statusem subskrybenta.

Aby rozpocząć otrzymywanie powiadomień serwera, musisz utworzyć temat Google Cloud Pub/Sub, który wyśle powiadomienia na żądany adres. Ten temat powinien zostać wskazany w sekcji ustawień monetyzacji konsoli Google Play. Szczegółowy przewodnik zawierający zrzuty ekranu można znaleźć w dokumentach Adapty.

Powiadomienie serwera:

{
  "message": {
    "data": "eyJ2ZXJzaW9uIjoiMS4wIiwicGFja2FnZU5hbWUiOiJjb20uYWRhcHR5LnNhbXBsZV9hcHAiLCJldmVudFRpbWVNaWxsaXMiOiIxNjMwNTI5Mzk3MTI1Iiwic3Vic2NyaXB0aW9uTm90aWZpY2F0aW9uIjp7InZlcnNpb24iOiIxLjAiLCJub3RpZmljYXRpb25UeXBlIjo2LCJwdXJjaGFzZVRva2VuIjoiY2o3anAuQU8tSjFPelIxMjMiLCJzdWJzY3JpcHRpb25JZCI6ImNvbS5hZGFwdHkuc2FtcGxlX2FwcC53ZWVrbHlfc3ViIn19",
    "messageId": "2829603729517390",
    "message_id": "2829603729517390",
    "publishTime": "2021-09-01T20:49:59.124Z",
    "publish_time": "2021-08-04T20:49:59.124Z"
  },
  "subscription": "projects/935083/subscriptions/adapty-rtdn"
}

Interesuje nas głównie klucz danych , zawierający dane transakcji zakodowane za pomocą base64. Klucz messageId może być używany do deduplikacji wiadomości, dzięki czemu nie trzeba przetwarzać zduplikowanych wiadomości. 

Oto transakcja w powiadomieniu serwera:

{
  "version": "1.0",
  "packageName": "com.adapty.sample_app",
  "eventTimeMillis": "1630529397125",
  "subscriptionNotification": {
    "version": "1.0",
    "notificationType": 6,
    "purchaseToken": "cj7jp.AO-J1OzR123",
    "subscriptionId": "com.adapty.sample_app.weekly_sub"
  }
}

Klucz packageName pomaga zrozumieć, do której aplikacji należy to wydarzenie. Klucz subscriptionId mówi Ci, która subskrypcja jest zaangażowana, a purchaseToken pomaga znaleźć konkretną transakcję. W przypadku subskrypcji zawsze będziesz szukał ostatniej transakcji w łańcuchu odnowienia, ponieważ jest to ta, do której będzie należeć to wydarzenie. Klucz notificationType zawiera typ zdarzenia. Moim zdaniem poniższe są najbardziej przydatne dla subskrypcji:

  • (2) SUBSCRIPTION_RENEWED: subskrypcja została pomyślnie odnowiona.
  • (3) SUBSCRIPTION_CANCELED: użytkownik wyłączył automatyczne odnawianie subskrypcji. Jeśli automatyczne odnawianie jest wyłączone, musisz spróbować przywrócić użytkownika jako aktywnego subskrybenta.
  • (5) SUBSCRIPTION_ON_HOLD, (6) SUBSCRIPTION_IN_GRACE_PERIOD: subskrypcja nie mogła zostać odnowiona z powodu problemów z płatnością. Powinieneś powiadomić o tym użytkownika, aby jego subskrypcja nie została automatycznie anulowana.
  • (12) SUBSCRIPTION_REVOKED: subskrypcja została odwołana. Oznacza to, że użytkownik powinien utracić dostęp do funkcji premium przyznanych wcześniej w ramach subskrypcji. 

Dla produktów (nie subskrypcji) otrzymasz oneTimeProductNotification w miejsce klucza subscriptionNotification. Będzie on również zawierał klucz sku zamiast klucza subscriptionId. Co więcej, otrzymasz tylko 2 rodzaje zdarzeń dla produktów:

  • (1) ONE_TIME_PRODUCT_PURCHASED: udany zakup produktu.
  • (2) ONE_TIME_PRODUCT_CANCELED: zakup produktu został anulowany, ponieważ użytkownik nie zapłacił za niego.

Wnioski

Walidacja po stronie serwera wspomaga dane analityczne, które będziesz mógł zbierać dla swojej aplikacji. Utrudnia ona oszustom dostęp do treści premium i może być wykorzystywana do realizacji subskrypcji między platformami. Jednak walidacja po stronie serwera może potrwać sporo czasu, zwłaszcza jeśli wymagana jest wysoka dokładność danych. Aby zapewnić wysokiej jakości dane, musisz uwzględnić wiele możliwych przypadków, takich jak aktualizacja subskrypcji, zmiany poziomu subskrypcji, okresy próbne, oferty promocyjne i wprowadzające, okres karencji, zwroty itp. Musisz także znać i uwzględniać wszystkie zasady, takie jak, że Google pobiera tylko 15% (zamiast 30%) prowizji od subskrypcji, które są odnawiane na ponad rok.

Further reading

What’s new in SKAdNetwork 4.0
What’s new in SKAdNetwork 4.0
June 30, 2022
5 min read
Paywall A/B testing guide, part 3: how to run A/B tests on paywalls and why it can be difficult
Paywall A/B testing guide, part 3: how to run A/B tests on paywalls and why it can be difficult
July 6, 2022
15 min read
Adapty March Updates: Home metrics, paywall and A/B tests duplication
Adapty March Updates: Home metrics, paywall and A/B tests duplication
April 6, 2022
3 min read