BlogRight arrowTutorialRight ArrowAndroid In-App-Käufe, Teil 5: Serverseitige Kaufvalidierung
BlogRight arrowTutorialRight ArrowAndroid In-App-Käufe, Teil 5: Serverseitige Kaufvalidierung

Android In-App-Käufe, Teil 5: Serverseitige Kaufvalidierung

Android In-App-Käufe, Teil 5: Serverseitige Kaufvalidierung
Listen to the episode
Android In-App-Käufe, Teil 5: Serverseitige Kaufvalidierung

Die serverseitige Überprüfung kann Ihnen helfen, die Kaufauthentizität zu validieren. Das Gerät wird eine Anfrage an die Google Server senden, um herauszufinden, ob der Kauf tatsächlich stattgefunden hat und ob er gültig ist.

In dieser Anleitung besprechen wir, wie Sie die serverseitige Validierung für Android Apps konfigurieren können.

Warum Käufe validieren

Es sollte erwähnt werden, dass die serverseitige Validierung kein Muss ist. In-App-Käufe funktionieren auch ohne diese Validierung. Sie bietet jedoch einige wichtige Vorteile:

  1. Umfangreiche Zahlungsanalysen, was besonders bei Abonnements wichtig ist, da alles, was nach der Aktivierung geschieht, nicht vom Gerät verarbeitet wird. Ohne serverseitige Kaufverarbeitung können Sie nicht den aktuellen Abonnement-Status abrufen und wissen nicht, ob der Nutzer das Abonnement verlängert hat oder nicht oder ob es Zahlungsprobleme gibt oder nicht.
  2. Die Möglichkeit, die Kaufauthentizität zu verifizieren. Sie können sicherstellen, dass die Transaktion kein Betrug ist und dass der Nutzer tatsächlich für Ihr Produkt bezahlt hat.
  3. Plattformübergreifende Abonnements. Wenn Sie den Abonnement-Status des Nutzers in Echtzeit überprüfen können, können Sie ihn auch mit anderen Plattformen synchronisieren. Nutzer, die beispielsweise das Abonnement mit einem iOS Gerät abgeschlossen haben, können es auch auf einem Android Gerät, online oder auf anderen Plattformen verwenden.
  4. Die Möglichkeit, Content-Zugang von der Serverseite zu kontrollieren. So schützen Sie sich vor Nutzern ohne Abonnement, die auf Ihre Daten zuzugreifen versuchen, indem Sie schlicht Anfragen an den Server senden.

Unsere Erfahrung besagt, dass der erste Vorteil allein ausreicht, um eine serverseitige Kaufverarbeitung einzurichten.

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

Zahlungsvalidierung

Wir können die Android-Zahlungsvalidierung mit diesem Schema zusammenfassen:

Authentifizierung für Google Play Developer API Anfragen

Um mit der Google Play Developer API zu arbeiten, müssen Sie zunächst einen Key generieren, um Anfragen zu unterschreiben. Als erstes müssen Sie Ihr Google Play Console Konto (wo Sie Ihre App verwalten) mit Ihrem Google Cloud Konto synchronisieren (wo Sie einen Key für das Unterschreiben von Anfragen generieren). Sobald dies erfolgt ist, müssen Sie dem Nutzer Kaufrechte erteilen. Es würde einen eigenen Artikel erfordern, diesen Vorgang zu beschreiben. Zum Glück haben wir bereits eine Schritt-für-Schritt Anleitung in der Adapty Dokumentation

Bitte beachten Sie, dass Sie nach der Generierung des Keys in der Regel 24 Stunden (oder länger) warten müssen, bevor Sie mit der Arbeit beginnen können. Aktualisieren Sie die Beschreibung für In-App-Produkte oder Abonnements, um diese Wartezeit zu umgehen, da so der Key umgehend aktiviert wird. 

Wir verwenden die offizielle google-api-python-client Library im Zusammenspiel mit der Google Play Developer API. Diese Library ist in den meisten Sprachen verfügbar und ich kann sie nur empfehlen, da sie alle benötigten Methoden unterstützt.

Validierung für Abonnement-Transaktionen

Im Gegensatz zur iOS serverseitigen Validierung werden bei Android sowohl die Validierung für Abonnements als auch andere Produkte mit einer Vielzahl von Methoden implementiert. Wenn Sie also eine Transaktion validieren, müssen Sie wissen, ob Sie es mit einem Produkt oder einem Abonnement zu tun haben. In der Praxis heißt das, dass Sie diese Daten von der App übertragen und die Flag in der Datenbank behalten müssen, falls eine erneute Token-Validierung erforderlich sein sollte.

Der zweite wichtige Unterschied besteht darin, dass zwar jede Transaktion bei Android ihren Token hat, aber alle iOS-Transaktionen ein App-spezifisches Gemeinsames Geheimnis (Shared Secret) verwenden, um den gesamten Transaktionsverlauf zu lagern. Wenn Sie also die Käufe eines Nutzers zu einem beliebigen Zeitpunkt wiederherstellen möchten, müssen Sie alle Kauftokens lagern, anstatt einen beliebigen auszuwählen.

Zur Validierung des Abonnements nutzen Sie die purchases.subscriptions.get Methode.  Dabei handelt es sich im Grunde um einen GET Request Call:

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

Alle Parameter werden benötigt:

  • packageName: App-Erkenner, z.B. com.adapty.sample_app.
  • subscriptionId: Abonnement-Erkenner für Abonnements, die zu validieren sind, z.B. com.adapty.sample_app.weekly_sub.
  • token: Einmaliger Transaktion-Token. Dieser erscheint, sobald der Kauf in der App verarbeitet ist.

Lassen Sie uns zunächst die Fehlermeldungen ansehen, um die Sie sich kümmern müssen, damit alles wie gedacht funktioniert:

  • 400, Invalid grant: account not found: Diese Fehlernachricht bedeutet, dass der Key zur Anfragenauthentifizierung nicht richtig generiert wurde. Stellen Sie sicher, dass Ihre Konten synchronisiert sind, Sie das Konto mit den nötigen Rechten verwenden und dass alle benötigten APIs aktiv sind. Unten finden Sie eine Anleitung, wie Sie all dies konfigurieren. Beachten Sie bitte den Tipp zum Update der Produktbeschreibung.
  • 400, The purchase token does not match the package name: Diese Fehlermeldung tritt in der Regel bei betrügerischen Transaktionen auf. Wenn Sie diese beim Testen erhalten, stellen Sie bitte sicher, dass Sie  keinen App-Kauftoken verwenden, der zu einer anderen App gehört.
  • 403, Quota exceeded for quota metric 'Queries' and limit 'Queries per day' of service 'androidpublisher.googleapis.com': Dies bedeutet, dass die tägliche Google API Anfragenquote überschritten wurde. Standardmäßig können Sie bis zu 200.000 Anfragen per Tag versenden. Diese Quote kann erhöht werden, sollte aber den meisten Apps genügen. Wenn Sie das Limit erreichen, sollten Sie die Logik Ihrer App überprüfen und sicherstellen, dass alles korrekt ist.
  • 410, The subscription purchase is no longer available for query because it has been expired for too long: Diese Fehlermeldung erscheint in Transaktionen, bei denen das Abonnement schon vor mehr als 60 Tagen abgelaufen ist. Es ist keine tatsächliche Fehlermeldung und sollte nicht als solche verarbeitet werden.
Start for free

You don't need to write server code yourself,

because we did it for you. Try Adapty SDK!

Start for free

Abonnement-Transaktion 

War die Validierung erfolgreich, erhalten Sie Transaktionsdaten als Antwort.

Transaktionsdaten (für ein Abonnement):

{
    "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": ""
}

Um zu verstehen, ob der Nutzer auf die von der App angebotenen Premium-Optionen zugreifen kann (sprich ob es ein aktives Abonnement gibt), müssen Sie:

  1. Die startTimeMillis und expiryTimeMillis Parameter prüfen. Die aktuelle Zeit sollte zwischen diesen beiden liegen.
  2. Stellen Sie außerdem sicher, ob der paymentState Parameter nicht den Wert „0” hat. Dies würde nämlich bedeuten, dass der Kauf das Abonnements noch aussteht und kein Grund dafür besteht, dem Nutzer Zugang zum Premium-Feature zu gewähren.
  3. Hat die Transaktion die Eigenschaft autoResumeTimeMillis, ist das Abonnement pausiert. Dies bedeutet, dass der Nutzer vor dem genannten Datum keinen Zugang zu Premium-Features haben sollte.

Lassen Sie uns die Schlüsseleigenschaften einer Abonnement-Transaktion ansehen:

  • kind: Transaktionstyp. Bei Abonnements hat diese immer den androidpublisher#subscriptionPurchase Wert. Mit diesem Parameter verstehen Sie, ob Sie es mit einem Abonnement oder einem Produkt zu tun haben und können entsprechend die Verarbeitungslogik auswählen.
  • paymentState: Zahlungsstatus. Diese Eigenschaft ist nicht für abgelaufene Transaktionen vorhanden. Die möglichen Werte sind:
    0: Der Kauf wurde noch nicht verarbeitet. In einigen Ländern kann der Benutzer das Abonnement vor Ort bezahlen. Das heißt, dass der Benutzer den Abonnementkauf über sein Gerät beginnt und dafür an einem nahe gelegenen Terminal bezahlt. Dies ist ein ziemlich seltener Fall, aber sollte trotzdem im Hinterkopf behalten werden.
    1: Das Abonnement wurde gekauft.
    2: Das Abonnement befindet sich in der Testphase.
    3: Das Abonnement wird im nächsten Zeitraum hoch- oder heruntergestuft. Dies bedeutet, dass sich der Abonnementplan ändern wird.
  • acknowledgementState: Kaufbestätigungsstatus. Dies ist ein wichtiger Parameter. Eer bestätigt, ob der Benutzer Zugang auf das erhalten hat, wofür er bezahlt hat. Der Wert „0“ bedeutet, dass kein Zugang besteht. „1“ bedeutet, dass Zugang besteht. Der Entwickler ist dafür verantwortlich, diesen Status zu definieren, was sowohl in der App als auch auf der Serverseite erfolgen kann. Wenn Sie den Kauf nicht innerhalb von 3 Tagen nach dem Kauf bestätigen, wird er automatisch zurückerstattet. Ich empfehle die Implementierung dieser Logik: Sobald Sie eine Transaktion mit dem Parameter acknowledgementState=0 erhalten, wird dieser vom Server geändert. Wie genau, verrate ich Ihnen unten. 
  • orderId: Eindeutige Transaktionskennung. Jeder Kauf eines Abonnements oder jede Verlängerung eines solchen hat eine eigene Kennung, mit der Sie erfahren können, ob diese Transaktion bereits früher verarbeitet wurde. Jede Verlängerungskennung hat eine konstante erste Hälfte, an die zwei Punkte und die Anzahl der Abonnementverlängerungen (die mit 0 beginnt) angehängt werden. Wenn das Abonnement bei der Aktivierung die Kennung GPA.3382-9215-9042-70164 hatte, wird die erste Verlängerung durch GPA.3382-9215-9042-70164..0 identifiziert, die zweite durch GPA.3382-9215-9042 -70164..1 usw. Auf diese Weise können Sie Transaktionsketten aufbauen und die Anzahl der Erneuerungen verfolgen.
  • startTimeMillis: Beginn des Abonnements.
  • expiryTimeMillis: Ablaufdatum des Abonnements.
  • autoRenewing: Dieses Flag zeigt an, ob das Abonnement in den nächsten Zeitraum verlängert werden soll oder nicht.
  • priceCurrencyCode: Kaufwährung im Drei-Buchstaben-Format (z. B. USD oder EUR).
  • priceAmountMicros: Kaufpreis. Um den normalen Preiswert zu erhalten, teilen Sie diesen Wert durch 1000000. So heißt 1990000 tatsächlich 1,99. 
  • countryCode: Kaufland im Zwei-Buchstaben-Format (z. B. US oder DE).
  • purchaseType: Art des Kaufs. Dieser Key wird in den meisten Fällen nicht vorhanden sein. Berücksichtigen Sie ihn jedoch, da er Ihnen anzeigt, ob der Kauf in einer Sandbox-Umgebung getätigt wurde. Die möglichen Werte sind:
    0: Der Kauf wurde in einer Sandbox-Umgebung getätigt und sollte daher nicht in die Analysedaten aufgenommen werden.
    1: Der Kauf wurde mit einem Promo-Code getätigt. 
  • autoResumeTimeMillis: Verlängerungsdatum des Abonnements. Dieses Datum besteht nur bei Abonnements, die zuvor pausiert wurden. Ist dieser Parameter vorhanden, können Sie dem Nutzer vor dem angegebenen Datum keinen Zugriff auf die Premium-Funktion gewähren.
  • cancelReason: Der Grund, warum das Abonnement nicht verlängert wird. Die möglichen Werte sind:
    0: Der Nutzer hat die automatische Verlängerung des Abonnements gekündigt.
    1: Das Abonnement wurde vom System gekündigt. Dies wird meistens durch ein Abrechnungsproblem verursacht.
    2: Der Nutzer hat zu einem anderen Abonnementplan gewechselt.
    3: Der Entwickler hat das Abonnement gekündigt.
  • userCancellationTimeMillis: Kündigungsdaten für die Verlängerung des Abonnements. Diese sind nur dann vorhanden, wenn CancelReason 0 ist. Das Abonnement kann noch aktiv sein — prüfen Sie daher den Wert des Parameters expiryTimeMillis.
  • cancelSurveyResult: Dieses Object speichert den Grund für die Kündigung des Abonnements und ist vorhanden, wenn der Nutzer einen Grund für die Kündigung angegeben hat.
  • introductoryPriceInfo: Dieses Object speichert die Daten zum Einführungspreis. Dies kann beispielsweise ein Sonderangebot sein (1 Monat mit 50% Rabatt).
  • promotionType: Promocode-Typ, der zum Aktivieren des Abonnements verwendet wurde. Die möglichen Werte sind:
    0: Einmaliger Promocode.
    1: Benutzerdefinierter Promocode, der von mehreren Kunden angewendet werden kann. Solche Codes werden normalerweise für Blogger-Partnerschaften verwendet. 
  • promotionCode: Benutzerdefinierter Promocode, der zur Aktivierung des Abonnements verwendet wurde. Dieser Parameter existiert nicht bei einmaligen Promocodes. 
  • priceChange: Dieses Object speichert die zukünftigen Preisänderungen und ob der Nutzer diesen zugestimmt hat. 

Abonnementbestätigung

Wie bereits oben erwähnt, wird das Abonnement automatisch storniert und das Geld erstattet, falls es nicht innerhalb von 3 Tagen nach dem Kauf bestätigt wird. Um ehrlich zu sein, verstehe ich die Logik dahinter nicht wirklich und habe auch bei anderen Zahlungssystemen (etwa im iOS-System) nie eine solche Logik gesehen. Wenn Sie also eine Transaktion mit acknowledgementState=0 erhalten, bestätigen Sie das Abonnement.

Dafür verwenden Sie die purchases.subscriptions.acknowledge Methode. Diese Methode führt eine POST Anfrage aus.

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

Die Parameter sind die gleichen wie bei der Validierung der Anforderung. Wenn die Anfrage erfolgreich ausgeführt wird, wird das Abonnement bestätigt. Das bedeutet, dass Sie Ihr Geld nicht verlieren. 

Wenn das Abonnement noch nicht gekauft wurde, müssen Sie es auch nicht bestätigen. 

Stornierung, Widerruf, Rückerstattung und Aufschub der Abonnementverlängerung

Abgesehen von der Abonnementvalidierung und -bestätigung kann die Google Play Developer API auch für andere Abonnementvorgänge verwendet werden. Beachten Sie bitte, dass diese ziemlich selten sind und bis auf die Verlängerung alle von Google Play Console unterstützt werden. Ich werde sie dennoch erwähnen, um Ihnen ein allgemeines Verständnis des Umfangs von API-Lösungen zu vermitteln. Alle diese Anfragen haben dieselben erforderlichen Parameter wie die zuvor erwähnten Methoden, nämlich packageName, subscriptionId und token.

  • Stornierung der Verlängerung. Die purchases.subscriptions.cancel Methode. Diese Methode storniert die automatische Verlängerung für das ausgewählte Abonnement. Das Abonnement ist jedoch während des gesamten aktuellen Abrechnungszeitraums verfügbar.
  • Rückerstattung des Abonnements. Die purchases.subscriptions.refund Methode. Sie erstattet das Abonnement. Der Benutzer behält jedoch weiterhin den Abonnementzugriff und wird in der nächsten Periode automatisch verlängert. In den meisten Fällen sollten Sie bei der Erstattung auch das Abonnement kündigen.
  • Widerruf des Abonnements. Die purchases.subscriptions.revoke Methode. Sie widerruft das Abonnement sofort. Das bedeutet, dass der Benutzer nicht mehr auf die Premium-Funktionen zugreifen kann. Das Abonnement wird nicht verlängert. Diese Methode wird normalerweise zusammen mit der Ausgabe einer Rückerstattung aufgerufen.
  • Aufschub des Abonnementkaufs. Die purchases.subscriptions.defer Methode. Sie verlängert das Abonnement bis zum angegebenen Datum. Geben Sie in der Anfrage das Ablaufdatum des Abonnements sowie das Datum an, durch das Sie es ersetzen möchten. Letzteres muss zu einer längeren Abonnementdauer führen als Ersteres.

Validierung des Produkts (nicht des Abonnements).

Die Produktvalidierung ähnelt der Abonnementvalidierung. Sie müssen auch hier die purchases.products.get Methode verwenden, um die GET Anfrage auszuführen.

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

Wir kennen bereits all diese Parameter aus den oben skizzierten Beispielen.

Transaktionsdaten (für ein Produkt):

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

Produkttransaktionen umfassen deutlich weniger Eigenschaften als Abonnementtransaktionen. Lassen Sie einige wichtige näher betrachten:

  • kind: Transaktionstyp. Bei Produkten hat dies den Wert androidpublisher#productPurchase. Mit diesem Parameter wissen Sie, ob es sich um ein Abonnement oder ein Produkt handelt und können die entsprechende Verarbeitungslogik wählen.
  • purchaseState: Zahlungsstatus. Die Schlüsselwerte unterscheiden sich hierbei vom paymentState Parameter für Abonnements. Die möglichen Werte sind:
    0: Der Kauf wurde abgeschlossen.
    1: Der Kauf wurde storniert. Der Kauf war also ausstehend, aber der Nutzer hat nie bezahlt.
    2: Ausstehender Kauf. In einigen Ländern kann der Benutzer das Abonnement vor Ort bezahlen. Das heißt, dass der Benutzer den Abonnementkauf über sein Gerät beginnt und dafür an einem nahe gelegenen Terminal bezahlt. Dies ist ein ziemlich seltener Fall, aber sollte trotzdem im Hinterkopf behalten werden.
  • acknowledgementState: Status der Kaufbestätigung. Dies ist ein wichtiger Parameter. Eer bestätigt, ob der Benutzer Zugang auf das erhalten hat, wofür er bezahlt hat. Der Wert „0“ bedeutet, dass kein Zugang besteht. „1“ bedeutet, dass Zugang besteht. Der Entwickler ist dafür verantwortlich, diesen Status zu definieren, was sowohl in der App als auch auf der Serverseite erfolgen kann. Wenn Sie den Kauf nicht innerhalb von 3 Tagen nach dem Kauf bestätigen, wird er automatisch zurückerstattet. Ich empfehle die Implementierung dieser Logik: Sobald Sie eine Transaktion mit dem Parameter acknowledgementState=0 erhalten, wird dieser vom Server geändert. Wie genau, verrate ich Ihnen unten.
  • consumptionState: Status des Produktverbrauchs. So nennt iOS ein “Verbrauchsmaterial”. Es wird in der App definiert. Beträgt der Wert „0“, wurde das Produkt nicht verbraucht. Beträgt er „1“, wurde es verbraucht. Wenn Sie einen lebenslangen Zugriff auf Ihre App oder ein bestimmtes Premium-Feature verkaufen, sollte ein solches Produkt nicht konsumiert werden. Das heißt, es sollte den Wert 0 haben. Wenn Sie Coins verkaufen, die der Benutzer immer wieder kaufen kann, sollten solche Produkte konsumiert werden und daher den Wert 1 haben. consumptionState=0 bedeutet also, dass das Produkt nur einmalig gekauft werden kann, während consumptionState=1 bedeutet, dass es mehrfach gekauft werden kann.
  • orderId: Eindeutige Transaktionskennung. Jeder Kauf hat eine eigene Kennung, die verwendet werden kann, um zu erfahren, ob diese Transaktion bereits früher verarbeitet wurde.
  • purchaseTimeMillis: Kaufdatum.
  • regionCode: Kaufland im Zwei-Buchstaben-Format (z. B. US oder DE). Beachten Sie bitte, dass sich der Name dieses Parameters von dem in Abonnements unterscheidet, wo er countryCode heißt. 
  • purchaseType: Art des Kaufs. Dieser Key wird in den meisten Fällen nicht vorhanden sein. Berücksichtigen Sie ihn jedoch, da er Ihnen anzeigt, ob der Kauf in einer Sandbox-Umgebung getätigt wurde. Die möglichen Werte sind:
    0: Der Kauf wurde in einer Sandbox-Umgebung getätigt und sollte daher nicht in die Analysedaten aufgenommen werden.
    1: Der Kauf wurde mit einem Promo-Code getätigt.
    2: Der Kauf wurde für eine gezielte Promo gewährt (z. B. das Ansehen einer In-App-Werbung anstelle einer Zahlung).

Wie Sie sehen, ist Validierung für Abonnements und Produkte ziemlich ähnlich. Es gilt jedoch, einige Punkte zu beachten:

  • Der Preis wird nicht zurückerstattet, obwohl das für die Analyse sehr praktisch wäre.
  • Die Werte des Parameters PurchaseState unterscheiden sich erheblich von den Werten des Parameters PaymentState, die in Abonnements zu finden sind. Berücksichtigen Sie diesen Unterschied nicht, wird es zu Fehlern kommen.
  • Sie erhalten regionCode, obwohl es bei Abonnements countryCode heißt.

Wie bei Käufen von Abonnements müssen auch Käufe bestätigt werden. Nutzen Sie dafür die purchases.products.acknowledge Methode, welche eine POST Anfrage ausführen wird.

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

Wenn der Kauf noch nicht abgeschlossen ist, muss er auch nicht bestätigt werden.

Verfolgung der Rückerstattung für Abonnements und Produkte

Qualitativ hochwertige Analysen sind ohne die Berücksichtigung von Rückerstattungen kaum möglich. Leider sind Rückerstattungsdaten im Gegensatz zu iOS weder in der Transaktion vorhanden noch werden sie als separates Ereignis angefordert. Um die Liste der erstatteten Transaktionen zu erhalten, verwenden Sie bitte regelmäßig die purchases.voidedpurchases.list (z. B. einmalig täglich). Diese Methode wird eine GET Anfrage ausführen:

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

Als Antwort auf diese Anfrage erhalten Sie eine Liste aller erstatteten Transaktionen. Suchen Sie in der Datenbank nach Transaktionen, indem Sie den orderId Parameter (und nicht den purchaseToken Parameter) verwenden. Dies geht einerseits schneller, hat aber noch einen anderen Grund. Denn alle Abonnement-Verlängerungen teilen denselben Token und Sie müssen nur den neuesten heraussuchen.

Serverbenachrichtigungen für Transaktionen

Dank der Serverbenachrichtigungen (Entwicklerbenachrichtigungen in Echtzeit) können Sie Ereignisse nachvollziehen, die bei Google, auf Ihrem Server und quasi live passiert sind. Sobald diese konfiguriert sind, werden Sie über neue Käufe, Verlängerungen, Zahlungsprobleme usw. benachrichtigt. Dies kann Ihnen helfen, bessere Analysen zu sammeln und die Verwaltung des Abonnentenstatus erheblich zu vereinfachen.

Um Serverbenachrichtigungen zu erhalten, müssen Sie ein Google Cloud Pub/Sub-Thema erstellen, das Benachrichtigungen an Ihre gewünschte Adresse sendet. Dieses Thema sollte dann im Abschnitt Monetarisierung der Google Play Console angezeigt werden. Weitere Einzelheiten mit Screenshots finden Sie in den Adapty Docs.

Serverbenachrichtigung:

{
  "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"
}

Wir beschäftigen uns hauptsächlich mit dem Data Key, der mit Base64 codierte Transaktionsdaten enthält. Der messageId Key kann für die Deduplizierung von Nachrichten verwendet werden, sodass Sie keine doppelten Nachrichten verarbeiten müssen. 

Hier ist eine Transaktion in einer Serverbenachrichtigung:

{
  "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"
  }
}

Der packageName Key zeigt an, zu welcher App dieses Ereignis gehört. Der subscriptionId Key verrät, welches Abonnement involviert ist und purchaseToken hilft Ihnen, die jeweilige Transaktion zu finden. Bei Abonnements suchen Sie immer nach der letzten Transaktion in der Verlängerungskette, da diese Transaktion jene ist, zu der das Ereignis gehört. Der notificationType Key enthält den Ereignistyp. Meiner Meinung nach sind diese die praktischsten für Abonnements:

  • (2) SUBSCRIPTION_RENEWED: Das Abonnement wurde erfolgreich verlängert.
  • (3) SUBSCRIPTION_CANCELED: Der Nutzer hat die automatische Verlängerung des Abonnements deaktiviert. Wenn die automatische Verlängerung deaktiviert ist, müssen Sie versuchen, den Benutzer als aktiven Abonnenten zurückzugewinnen.
  • (5) SUBSCRIPTION_ON_HOLD, (6) SUBSCRIPTION_IN_GRACE_PERIOD: Das Abonnement konnte aufgrund von Zahlungsproblemen nicht verlängert werden. Sie sollten den Nutzer darüber informieren, damit sein Abonnement nicht automatisch gekündigt wird.
  • (12) SUBSCRIPTION_REVOKED: Das Abonnement wurde widerrufen. Dies bedeutet, dass der Nutzer den Zugriff auf die zuvor durch das Abonnement gewährten Premium-Funktionen verlieren sollte.

Bei Produkten (nicht Abonnements) erhalten Sie den Key oneTimeProductNotification statt subscriptionNotification. Dieser enthält auch die SKU Key statt des subscriptionId Keys. Für Produkte erhalten Sie immer nur zwei Arten von Ereignissen:

  • (1) ONE_TIME_PRODUCT_PURCHASED: Erfolgreicher Kauf des Produkts.
  • (2) ONE_TIME_PRODUCT_CANCELED: Der Kauf des Produkts wurde storniert, da der Nutzer keine Zahlung getätigt hat.

Fazit

Die serverseitige Validierung verbessert die Analysen, die Sie für Ihre App sammeln können. Sie erschwert Betrügern den Zugriff auf Premium-Inhalte und kann verwendet werden, um plattformübergreifende Abonnements zu implementieren. Die Implementierung der serverseitigen Validierung kann jedoch einige Zeit in Anspruch nehmen, insbesondere wenn eine hohe Datengenauigkeit erforderlich ist. Um qualitativ hochwertige Daten bereitzustellen, müssen Sie eine Vielzahl von Nebenfällen berücksichtigen (z. B. Abonnement-Upgrade, Abonnement-Crossgrade, Testzeiträume, Werbe- und Einführungsangebote, Nachfrist, Rückerstattungen usw.). Außerdem müssen Sie alle Einzelheiten zu den Richtlinien beachten. Dazu gehört beispielsweise, dass Google nur eine Provision von 15 % (statt 30 %) auf Abonnements berechnet, die um mehr als ein Jahr verlängert werden.

Further reading

Making a Sales Funnel for a Subscription App
Making a Sales Funnel for a Subscription App
December 2, 2019
5 min read
Adapty October updates: comparison in charts, remote config table, and more
Adapty October updates: comparison in charts, remote config table, and more
November 10, 2022
5 min read
Adapty April Updates: all new cohorts, SearchAdsHQ integration and hiring new team members!
Adapty April Updates: all new cohorts, SearchAdsHQ integration and hiring new team members!
May 5, 2022
3 min read