
Tutorial
September 7, 2022
Updated: März 20, 2023
Apple hat letztens während der WWDC 2021 eine neue Version von StoreKit 2 präsentiert. Dabei handelt es sich um ein Framework, das für Käufe in iOS verantwortlich ist. Der Anteil an Apps mit In-App-Käufen und Abonnements wächst stetig und Apple hat mit der Veröffentlichung von StoreKit 2 die Integration von In-App-Käufen in die App deutlich vereinfacht. In dem heutigen Artikel beleuchten wir die Arbeit mit StoreKit 2 auf der Serverseite (sprich mit Hilfe der App Store Server API).
In der aktuellen API-Version benötigen Sie das gemeinsame Geheimnis (shared secret), um eine Anfrage zu senden. Dies ist eine geheime feste Zeichenfolge, die Sie in App Store Connect erhalten. Die neue Version der API verwendet den JSON Web Token (JWT)-Standard für die Anforderung der Authentifizierung.
Zunächst müssen Sie einen privaten Key erstellen, der zur Autorisierung der Anfragen verwendet wird. Öffnen Sie App Store Connect und gehen Sie zum Abschnitt Nnutzer und Zugriff und anschließend zur Registerkarte Key. Wählen Sie den Key-Typ für den In-App-Kauf aus und laden Sie einen neuen Key herunter. Sie benötigen auch seine ID. Diese können Sie auf derselben Seite wie die Problem-ID kopieren, die auf der Registerkarte App Store Connect API zu finden ist.
Als nächstes erstellen Sie einen Token, der zum Autorisieren der Anforderungen verwendet wird. Dieser Vorgang wird in der Dokumentation ausführlich beschrieben, weswegen wir an dieser Stelle nicht weiter darauf eingehen. Stattdessen zeigen wir Ihnen ein Beispiel für eine fertige Implementierung für Python. Es ergibt keinen Sinn, für jede neue Anfrage einen neuen Token zu generieren. Beim Erstellen eines Tokens legen Sie dessen Lebensdauer auf bis zu 60 Minuten fest und verwenden in dieser Zeit denselben Token.
import time, uuid
from authlib.jose import jwt
BUNDLE_ID = 'com.adapty.sample_app'
ISSUER_ID = '4336a124-f214-4d40-883b-6db275b5e4aa'
KEY_ID = 'J65UYBDA74'
PRIVATE_KEY = '''
-----BEGIN PRIVATE KEY-----
MIGTAgMGByqGSMBHkAQQgR/fR+3Lkg4...
-----END PRIVATE KEY-----
'''
issue_time = round(time.time())
expiration_time = issue_time + 60 * 60 # 1 hour expiration
header = {
'alg': 'ES256',
'kid': KEY_ID,
'typ': 'JWT'
}
payload = {
'iss': ISSUER_ID,
'iat': issue_time,
'exp': expiration_time,
'aud': 'appstoreconnect-v1',
'nonce': str(uuid.uuid4()),
'bid': BUNDLE_ID
}
token_encoded = jwt.encode(header, payload, PRIVATE_KEY)
token_decoded = token_encoded.decode()
authorization_header = {
'Authorization': f'Bearer {token_decoded}'
}
In der neuen API-Version werden alle Transaktionen im JSON Web Signature (JWS)-Standard zurückgegeben. Dies ist eine Zeichenfolge, die aus drei Teilen besteht, die durch Punkte getrennt sind.
Base64(header) + "." + Base64(payload) + "." + sign(Base64(header) + "." + Base64(payload))
Der Header ist wichtig, damit Sie sicher sein können, dass die Transaktion echt ist. Der Alg-Key enthält einen Verschlüsselungsalgorithmus, der x5c-Key enthält eine Zertifikatskette.
{
"kid": "AMP/DEV",
"alg": "ES256",
"x5c": [
"MIIEO...",
"MIIDK..."
]
}
{
"transactionId": "1000000831360853",
"originalTransactionId": "1000000806937552",
"webOrderLineItemId": "1000000063561721",
"bundleId": "com.adapty.sample_app",
"productId": "basic_subscription_1_month",
"subscriptionGroupIdentifier": "27636320",
"purchaseDate": 1624446341000,
"originalPurchaseDate": 1619686337000,
"expiresDate": 1624446641000,
"quantity": 1,
"type": "Auto-Renewable Subscription",
"appAccountToken": "fd12746f-2d3a-46c8-bff8-55b75ed06aca",
"inAppOwnershipType": "PURCHASED",
"signedDate": 1624446484882,
"offerType": 2,
"offerIdentifier": "basic_subscription_1_month.pay_as_you_go.3_months"
}
Apple hat das Transaktionsformat sowohl geändert als auch erweitert. Für mich ist es jetzt einfacher zu verwenden. Einzelheiten zum neuen Format finden Sie in der Dokumentation. Im Folgenden beschreibe ich die wichtigsten Änderungen.
Wurde ein Aktionsangebot oder ein Promo-Code verwendet, enthält der offerIdentifier-Key die ID des verwendeten Angebots. Früher war es unmöglich, die Nutzung des Angebots serverseitig nachzuvollziehen, was Analysen unmöglich machte. Jetzt können Sie Promo-Codes für Analysen verwenden.
Subscribe to Adapty newsletter
Get fresh paywall ideas, subscription insights, and mobile app news every month!
Um den Abonnementstatus des Nutzers zu prüfen, senden Sie eine GET-Anfrage an https://api.storekit.itunes.apple.com/inApps/v1/subscriptions/{originalTransactionId}, wobei {originalTransactionId} die ID einer beliebigen Transaktionskette des Nutzers ist. Sie erhalten nun Transaktionen samt Status für jede Abonnement-Gruppe.
{
"environment": "Sandbox",
"bundleId": "com.adapty.sample_app",
"data": [
{
"subscriptionGroupIdentifier": "39636320",
"lastTransactions": [
{
"originalTransactionId": "1000000819078552",
"status": 2,
"signedTransactionInfo": "eyJraWQiOi...",
"signedRenewalInfo": "eyJraWQiOi..."
}
]
}
]
}
Der Status-Key zeigt den aktuellen Abonnementstatus an. Darauf aufbauend können Sie entscheiden, ob Sie einem Nutzer Zugriff auf die kostenpflichtigen Funktionen der App gewähren möchten. Mögliche Werte:
Der SignedTransactionInfo-Key enthält Informationen über die letzte Transaktion in der Kette. Einzelheiten zum Format finden Sie oben.
Der SignedRenewalInfo-Key enthält Informationen zur Abonnementverlängerung.
{
"expirationIntent": 1,
"originalTransactionId": "1000000819078552",
"autoRenewProductId": "basic_subscription_1_month",
"productId": "basic_subscription_1_month",
"autoRenewStatus": 0,
"isInBillingRetryPeriod": false,
"signedDate": 1624520884048
}
Dank dieser Informationen können wir nachvollziehen, was mit dem Abonnement während der nächsten Zahlungsperiode geschehen wird. Sehen Sie beispielsweise, dass ein Nutzer die automatische Verlängerung gekündigt hat, können Sie ihm anbieten, zu einem anderen Abonnementplan zu wechseln oder ihm ein Werbeangebot machen. Sie können diese Art von Ereignissen mit Hilfe von Serverbenachrichtigungen ganz einfach verfolgen.
Um den Transaktionsverlauf des Nutzers abzurufen, senden Sie eine GET-Anforderung an https://api.storekit.itunes.apple.com/inApps/v1/history/{originalTransactionId}, wobei {originalTransactionId} die ID einer beliebigen Transaktionskette des Nutzers ist. Dafür erhalten Sie eine Reihe von Transaktionen, die chronologisch sortiert sind.
{
"revision": "1625872984000_1000000212854038",
"bundleId": "com.adapty.sample_app",
"environment": "Sandbox",
"hasMore": true,
"signedTransactions": [
"eyJraWQiOiJ...",
"joiRVMyNeyX...",
"5MnkvOTlOZl...",
...
]
}
Eine Anfrage darf maximal 20 Transaktionen enthalten. Wenn ein Nutzer mehr Transaktionen hat, ist der Wert des hasMore-Flags wahr. Benötigen Sie die nächste Transaktionsseite, senden Sie die Anfrage erneut mit dem GET-Parameter. Sie enthält den Wert aus demselben Key.
Serverbenachrichtigungen helfen Ihnen, Informationen über neue Käufe, Verlängerungen, Abrechnungsprobleme usw. zu erhalten. Damit können Sie zudem genauere Analysen erstellen und die Verwaltung des Abonnementstatus vereinfachen.
Die existierenden Serverbenachrichtigungen (V1) können die meisten Probleme lösen, sind aber oft unpraktisch. Meistens erhalten Sie für nur eine Aktion eines Nutzers mehrere Benachrichtigungen. Wenn ein Nutzer beispielsweise ein Abonnement aktualisiert, sendet Apple zwei Benachrichtigungen: DID_CHANGE_RENEWAL_STATUS und INTERACTIVE_RENEWAL. Um diesen Fall zu bearbeiten, müssen Sie den Status irgendwie speichern und prüfen, ob die zweite Benachrichtigung gesendet wurde. In einer neuen Version von Serverbenachrichtigungen (V2) gibt es nur eine Benachrichtigung für eine Aktion eines Nutzers. Das ist viel bequemer.
Die zweite Version der Serverbenachrichtigungen enthält neue Ereignisse – OFFER_REDEEMED, EXPIRED und GRACE_PERIOD_EXPIRED. Sie erleichtern die Verwaltung des Abonnentenstatus erheblich. SUBSCRIBED und PRICE_INCREASE Ereignisse sind verbesserte Ereignisse aus der ersten Version.
Die Benachrichtigungen haben jetzt Typen, sodass eine Benachrichtigung für jede Aktion eines Nutzers ausreicht, um zu verstehen, was passiert ist.
Benachrichtigungstypen
{
"notificationType": "SUBSCRIBED",
"subtype": "INITIAL_BUY",
"version": 2,
"data": {
"environment": "Sandbox",
"bundleId": "com.adapty.sample_app",
"appAppleId": 739104078,
"bundleVersion": 1,
"signedTransactionInfo": "eyJraWQiOi...",
"signedRenewalInfo": "eyJraWQiOi..."
}
}
Serverbenachrichtigungen enthalten wie bereits beschrieben Informationen im JWS-Format über Transaktionen und Verlängerungen.
Verwenden Sie die URL der Sandbox-Umgebung, um Einkäufe zu testen: https://api.storekit-sandbox.itunes.apple.com.
Die neue Version der Serverbenachrichtigungen steht noch nicht zum Testen zur Verfügung. Sobald sie verfügbar ist, können unterschiedliche URLs für Produktions- und Sandbox-Benachrichtigungen angegeben werden. Sie können die V2 für die Sandbox-Umgebung und die V1 für die Produktion und das Testen nutzen.
Mit App Store Connect können Sie jetzt Folgendes tun:
Apple hat die Arbeit mit In-App-Käufen und Abonnements auf der Serverseite erheblich verbessert. Dies sind aus meiner Sicht die nützlichsten neuen Funktionen:
Der Wechsel zu einer neuen API ist nicht schwierig. Es reicht aus, die originalTransactionId für jeden Kauf zu erhalten. Vermutlich sind diese bereits in Ihrer Basis enthalten.
Das Schwierigste bei der Integration von Abonnements in eine App ist der Aufbau eines Analysesystems und die Optimierung der Wirtschaftlichkeit. Adapty kann Ihnen dabei helfen:
Erfahren Sie mehr über diese Features, um Abonnements schneller in Ihre App zu implementieren und Ihre App schneller und besser zu monetarisieren.
Further reading
Tutorial
September 7, 2022