Transaktionen und Überprüfung in Xamarin.iOS
Wiederherstellen vergangener Transaktionen
Wenn Ihre Anwendung wiederherzustellende Produkttypen unterstützt, müssen Sie einige Benutzeroberflächenelemente einschließen, damit Benutzer diese Käufe wiederherstellen können. Diese Funktion ermöglicht es einem Kunden, das Produkt zusätzlichen Geräten hinzuzufügen oder das Produkt auf demselben Gerät wiederherzustellen, nachdem er sauber zurückgesetzt oder die App entfernt und erneut installiert hat. Die folgenden Produkttypen können wiederhergestellt werden:
- Nicht verbrauchsbare Produkte
- Abonnements mit automatischer Erneuerbarkeit
- Kostenlose Abonnements
Der Wiederherstellungsvorgang sollte die Datensätze aktualisieren, die Sie auf dem Gerät aufbewahren, um Ihre Produkte zu erfüllen. Der Kunde kann die Wiederherstellung jederzeit auf jedem seiner Geräte auswählen. Der Wiederherstellungsprozess sendet alle vorherigen Transaktionen für diesen Benutzer erneut. Der Anwendungscode muss dann bestimmen, welche Aktion mit diesen Informationen durchgeführt werden soll (z. B. überprüfen, ob bereits ein Datensatz dieses Kaufs auf dem Gerät vorhanden ist, und andernfalls einen Datensatz des Kaufs erstellen und das Produkt für den Benutzer aktivieren).
Implementieren der Wiederherstellung
Die Schaltfläche "Wiederherstellen " der Benutzeroberfläche ruft die folgende Methode auf, die RestoreCompletedTransactions für SKPaymentQueue
auslöst.
public void Restore()
{
// theObserver will be notified of when the restored transactions start arriving <- AppStore
SKPaymentQueue.DefaultQueue.RestoreCompletedTransactions();
}
StoreKit sendet die Wiederherstellungsanforderung asynchron an die Server von Apple.
Da der CustomPaymentObserver
als Transaktionsbeobachter registriert ist, empfängt es Nachrichten, wenn die Apple-Server antworten. Die Antwort enthält alle Transaktionen, die dieser Benutzer jemals in dieser Anwendung ausgeführt hat (auf allen Geräten). Der Code durchläuft jede Transaktion, erkennt den Wiederhergestellten Zustand und ruft die UpdatedTransactions
Methode auf, um sie wie unten dargestellt zu verarbeiten:
// called when the transaction status is updated
public override void UpdatedTransactions (SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
foreach (SKPaymentTransaction transaction in transactions)
{
switch (transaction.TransactionState)
{
case SKPaymentTransactionState.Purchased:
theManager.CompleteTransaction(transaction);
break;
case SKPaymentTransactionState.Failed:
theManager.FailedTransaction(transaction);
break;
case SKPaymentTransactionState.Restored:
theManager.RestoreTransaction(transaction);
break;
default:
break;
}
}
}
Wenn keine wiederherstellbaren Produkte für den Benutzer vorhanden sind, UpdatedTransactions
wird nicht aufgerufen.
Der einfachste mögliche Code zum Wiederherstellen einer bestimmten Transaktion im Beispiel führt die gleichen Aktionen wie beim Kauf aus, mit der Ausnahme, dass die OriginalTransaction
Eigenschaft für den Zugriff auf die Produkt-ID verwendet wird:
public void RestoreTransaction (SKPaymentTransaction transaction)
{
// Restored Transactions always have an 'original transaction' attached
var productId = transaction.OriginalTransaction.Payment.ProductIdentifier;
// Register the purchase, so it is remembered for next time
PhotoFilterManager.Purchase(productId); // it's as though it was purchased again
FinishTransaction(transaction, true);
}
Eine komplexere Implementierung überprüft möglicherweise andere transaction.OriginalTransaction
Eigenschaften, z. B. das ursprüngliche Datum und die Eingangsnummer. Diese Informationen sind für einige Produkttypen (z. B. Abonnements) nützlich.
Wiederherstellungsabschluss
Die CustomPaymentObserver
verfügt über zwei zusätzliche Methoden, die von StoreKit aufgerufen werden, wenn der Wiederherstellungsvorgang (entweder erfolgreich oder mit einem Fehler) abgeschlossen wurde, siehe unten:
public override void PaymentQueueRestoreCompletedTransactionsFinished (SKPaymentQueue queue)
{
Console.WriteLine(" ** RESTORE Finished ");
}
public override void RestoreCompletedTransactionsFailedWithError (SKPaymentQueue queue, NSError error)
{
Console.WriteLine(" ** RESTORE FailedWithError " + error.LocalizedDescription);
}
Im Beispiel tun diese Methoden nichts, aber eine echte Anwendung kann sich dafür entscheiden, eine Nachricht für den Benutzer oder eine andere Funktionalität zu implementieren.
Sichern von Einkäufen
Die beiden Beispiele in diesem Dokument werden verwendet NSUserDefaults
, um Käufe nachzuverfolgen:
Verbrauchsmaterialien : Der "Saldo" von Kreditkäufen ist ein einfacher NSUserDefaults
ganzzahliger Wert, der mit jedem Kauf erhöht wird.
Nicht verbrauchsbare Elemente : Jeder Fotofilterkauf wird als Schlüssel-Wert-Paar in NSUserDefaults
gespeichert.
Die Verwendung NSUserDefaults
hält den Beispielcode einfach, bietet aber keine sehr sichere Lösung, da es technisch versierte Benutzer möglicherweise möglich ist, die Einstellungen zu aktualisieren (unter Umgehung des Zahlungsmechanismus).
Hinweis: Reale Anwendungen sollten einen sicheren Mechanismus zum Speichern von gekauften Inhalten übernehmen, die nicht von Benutzern manipuliert werden. Dies kann verschlüsselungs- und/oder andere Techniken umfassen, einschließlich der Remoteserverauthentifizierung.
Der Mechanismus sollte auch so konzipiert sein, dass er die integrierten Sicherungs- und Wiederherstellungsfunktionen von iOS, iTunes und iCloud nutzt. Dadurch wird sichergestellt, dass nach der Wiederherstellung einer Sicherung die vorherigen Käufe sofort verfügbar sind.
Weitere iOS-spezifische Richtlinien finden Sie im Leitfaden zur sicheren Codierung von Apple.
Belegüberprüfung und Server-Delivered Produkte
Die bisherigen Beispiele in diesem Dokument bestanden ausschließlich aus der Direkten Kommunikation der Anwendung mit dem App Store Servern, um Kauftransaktionen durchzuführen, die bereits in der App programmierte Features oder Funktionen freischalten.
Apple bietet ein zusätzliches Maß an Kaufsicherheit, indem kaufbelege von einem anderen Server unabhängig überprüft werden können, was nützlich sein kann, um eine Anforderung zu überprüfen, bevor digitale Inhalte im Rahmen eines Kaufs (z. B. ein digitales Buch oder eine Zeitschrift) bereitgestellt werden.
Integrierte Produkte : Wie in den Beispielen in diesem Dokument ist das gekaufte Produkt als Funktionalität vorhanden, die mit der Anwendung geliefert wird. Ein In-App-Kauf ermöglicht dem Benutzer den Zugriff auf die Funktionalität. Produkt-IDs sind hartcodiert.
Vom Server bereitgestellte Produkte : Das Produkt besteht aus herunterladbarem Inhalt, der auf einem Remoteserver gespeichert wird, bis eine erfolgreiche Transaktion dazu führt, dass der Inhalt heruntergeladen wird. Beispiele hierfür sind Bücher oder Zeitschriftenhefte. Produkt-IDs werden in der Regel von einem externen Server bezogen (auf dem auch der Produktinhalt gehostet wird). Anwendungen müssen eine robuste Methode zur Aufzeichnung implementieren, wenn eine Transaktion abgeschlossen wurde, damit bei einem Fehler beim Herunterladen von Inhalten erneut versucht werden kann, ohne den Benutzer zu verwirren.
Server-Delivered Produkte
Einige Produktinhalte, z. B. Bücher und Zeitschriften (oder sogar eine Spielebene), müssen während des Kaufvorgangs von einem Remoteserver heruntergeladen werden. Dies bedeutet, dass ein zusätzlicher Server erforderlich ist, um den Produktinhalt nach dem Kauf zu speichern und bereitzustellen.
Preise für Server-Delivered Produkte erhalten
Da die Produkte remote geliefert werden, ist es auch möglich, im Laufe der Zeit weitere Produkte hinzuzufügen (ohne den App-Code zu aktualisieren), z. B. das Hinzufügen weiterer Bücher oder neuer Ausgaben eines Magazins. Damit die Anwendung diese Nachrichtenprodukte entdecken und dem Benutzer anzeigen kann, sollte der zusätzliche Server diese Informationen speichern und bereitstellen.
Produktinformationen müssen an mehreren Orten gespeichert werden: auf Ihrem Server und in iTunes Connect. Darüber hinaus sind jedem Produkt Inhaltsdateien zugeordnet. Diese Dateien werden nach einem erfolgreichen Kauf übermittelt.
Wenn der Benutzer ein Produkt kaufen möchte, muss die Anwendung bestimmen, welche Produkte verfügbar sind. Diese Informationen können zwischengespeichert werden, sollten aber von einem Remoteserver übermittelt werden, auf dem die master Liste der Produkte gespeichert ist.
Der Server gibt eine Liste von Produkt-IDs zurück, die die Anwendung analysieren soll.
Die Anwendung bestimmt dann, welche dieser Produkt-IDs an StoreKit gesendet werden sollen, um Preise und Beschreibungen abzurufen.
StoreKit sendet die Liste der Produkt-IDs an die Server von Apple.
Die iTunes-Server antworten mit gültigen Produktinformationen (Beschreibung und aktueller Preis).
Die Produktinformationen der
SKProductsRequestDelegate
Anwendung werden zur Anzeige an den Benutzer übergeben.
Kauf Server-Delivered Produkte
Da der Remoteserver eine Möglichkeit benötigt, um zu überprüfen, dass eine Inhaltsanforderung gültig ist (also bezahlt wurde), werden die Empfangsinformationen für die Authentifizierung übergeben. Der Remoteserver leitet diese Daten zur Überprüfung an iTunes weiter und schließt bei erfolgreicher Ausführung den Produktinhalt in die Antwort auf die Anwendung ein.
Die App fügt der Warteschlange einen hinzu
SKPayment
. Bei Bedarf wird der Benutzer zur Eingabe seiner Apple-ID aufgefordert und aufgefordert, die Zahlung zu bestätigen.StoreKit sendet die Anforderung zur Verarbeitung an den Server.
Wenn die Transaktion abgeschlossen ist, antwortet der Server mit einer Transaktionsbestätigung.
Die
SKPaymentTransactionObserver
Unterklasse empfängt den Beleg und verarbeitet ihn. Da das Produkt von einem Server heruntergeladen werden muss, initiiert die Anwendung eine Netzwerkanforderung an den Remoteserver.Die Downloadanforderung wird von den Empfangsdaten begleitet, damit der Remoteserver überprüfen kann, ob er für den Zugriff auf den Inhalt autorisiert ist. Der Netzwerkclient der Anwendung wartet auf eine Antwort auf diese Anforderung.
Wenn der Server eine Anforderung für Inhalte empfängt, analysiert er die Empfangsdaten und sendet eine Anforderung direkt an die iTunes-Server, um zu überprüfen, ob der Beleg für eine gültige Transaktion ist. Der Server sollte eine gewisse Logik verwenden, um zu bestimmen, ob die Anforderung an die Produktions- oder Sandbox-URL gesendet werden soll. Apple schlägt vor, immer die Produktions-URL zu verwenden und zur Sandbox zu wechseln, wenn Sie status 21007 (Sandboxbestätigung an den Produktionsserver gesendet) erhalten. Weitere Informationen finden Sie im Programmierhandbuch zur Belegüberprüfung von Apple.
iTunes überprüft den Beleg und gibt einen status von 0 zurück, wenn er gültig ist.
Der Server wartet auf die Antwort von iTunes. Wenn er eine gültige Antwort empfängt, sollte der Code die zugeordnete Produktinhaltsdatei suchen, die in die Antwort an die Anwendung aufgenommen werden soll.
Die Anwendung empfängt und analysiert die Antwort und speichert den Produktinhalt im Dateisystem des Geräts.
Die Anwendung aktiviert das Produkt und ruft dann storeKits auf
FinishTransaction
. Die Anwendung kann dann optional den gekauften Inhalt anzeigen (z. B. die erste Seite eines gekauften Buches oder einer Zeitschrift anzeigen).
Eine alternative Implementierung für sehr große Produktinhaltsdateien könnte darin bestehen, einfach den Transaktionsbeleg in Schritt 9 zu speichern, damit die Transaktion schnell abgeschlossen werden kann, und eine Benutzeroberfläche für den Benutzer bereitstellen, um den tatsächlichen Produktinhalt zu einem späteren Zeitpunkt herunterzuladen. Die nachfolgende Downloadanforderung kann den gespeicherten Beleg erneut senden, um auf die erforderliche Produktinhaltsdatei zuzugreifen.
Schreiben Server-Side Belegüberprüfungscodes
Das Überprüfen eines Belegs im serverseitigen Code kann mit einer einfachen HTTP POST-Anforderung/-Antwort erfolgen, die die Schritte #5 bis 8 im Workflowdiagramm umfasst.
Extrahieren Sie die SKPaymentTansaction.TransactionReceipt
-Eigenschaft in der App. Dies sind die Daten, die zur Überprüfung an iTunes gesendet werden müssen (Schritt 5).
Base64-codieren Sie die Transaktionsbestätigungsdaten (entweder in Schritt #5 oder #6).
Erstellen Sie eine einfache JSON-Nutzlast wie folgt:
{
"receipt-data" : "(base-64 encoded receipt here)"
}
HTTP POSTet den JSON-Code für die https://buy.itunes.apple.com/verifyReceipt Produktion oder https://sandbox.itunes.apple.com/verifyReceipt zum Testen.
Die JSON-Antwort enthält die folgenden Schlüssel:
{
"status" : 0,
"receipt" : { (receipt repeated here) }
}
Ein status von 0 gibt einen gültigen Beleg an. Ihr Server kann fortfahren, den Inhalt des gekauften Produkts zu erfüllen. Der Belegschlüssel enthält ein JSON-Wörterbuch mit den gleichen Eigenschaften wie das SKPaymentTransaction
Objekt, das von der App empfangen wurde, sodass der Servercode dieses Wörterbuch abfragen kann, um Informationen wie den product_id und die Menge des Kaufs abzurufen.
Weitere Informationen finden Sie in der Dokumentation zum Programmierhandbuch für die Belegüberprüfung von Apple.