Share via


Kauf von Verbrauchsartikeln in Xamarin.iOS

Verbrauchsartikel sind am einfachsten zu implementieren, da es keine "Wiederherstellungsanforderung" gibt. Sie sind nützlich für Produkte wie In-Game-Währungen oder ein einmaliges Funktionalitätsstück. Benutzer können Verbrauchsartikel immer wieder kaufen.

Integrierte Produktbereitstellung

Der Beispielcode, der dieses Dokument begleitet, veranschaulicht integrierte Produkte – die Produkt-IDs sind in der Anwendung hartcodiert, da sie eng mit dem Code gekoppelt sind, der das Feature nach der Zahlung "entsperrt". Der Einkaufsprozess kann wie folgt dargestellt werden:

Die Visualisierung des Einkaufsprozesses

Der grundlegende Workflow lautet:

  1. Die App fügt der Warteschlange eine SKPayment hinzu. Falls erforderlich, wird der Benutzer zur Eingabe seiner Apple-ID aufgefordert und zur Bestätigung der Zahlung aufgefordert.

  2. StoreKit sendet die Anforderung zur Verarbeitung an den Server.

  3. Wenn die Transaktion abgeschlossen ist, antwortet der Server mit einem Transaktionsbeleg.

  4. Die SKPaymentTransactionObserver Unterklasse empfängt den Beleg und verarbeitet sie.

  5. Die Anwendung aktiviert das Produkt (durch Aktualisieren NSUserDefaults oder einen anderen Mechanismus), und ruft dann StoreKits FinishTransactionauf.

Es gibt einen anderen Workflowtyp – Server-Zugestellte Produkte – die weiter unten im Dokument erläutert werden (siehe Abschnitt Belegüberprüfung und Server-Zugestellte Produkte).

Beispiel für Verbrauchsartikel

Das Beispiel enthält ein Projekt namens Verbrauchsartikel , das eine grundlegende "Spielwährung" (als "Affenguthaben" bezeichnet) implementiert. Das Beispiel zeigt, wie zwei In-App-Kaufprodukte implementiert werden, damit der Benutzer so viele "Affenguthaben" wie gewünscht kaufen kann – in einer echten Anwendung würde es auch eine Möglichkeit geben, sie auszugeben!

Die Anwendung wird in diesen Screenshots angezeigt – jeder Kauf fügt dem Guthaben des Benutzers weitere "Affenguthaben" hinzu:

Jeder Kauf fügt dem Guthaben der Benutzer weitere Affenguthaben hinzu

Die Interaktionen zwischen benutzerdefinierten Klassen, StoreKit und dem App Store sehen wie folgt aus:

Die Interaktionen zwischen benutzerdefinierten Klassen, StoreKit und dem App Store

ViewController-Methoden

Zusätzlich zu den Eigenschaften und Methoden, die zum Abrufen von Produktinformationen erforderlich sind, benötigt der Ansichtscontroller zusätzliche Benachrichtigungsbeobachter, um kaufbezogene Benachrichtigungen abzuhören. Dies sind nur NSObjects dies, die in ViewWillAppear bzw ViewWillDisappear . entfernt werden.

NSObject succeededObserver, failedObserver;

Der Konstruktor erstellt außerdem die SKProductsRequestDelegate Unterklasse ( InAppPurchaseManager), die wiederum erstellt und registriert die SKPaymentTransactionObserver ( CustomPaymentObserver).

Der erste Teil der Verarbeitung einer In-App-Kauftransaktion besteht darin, die Taste zu verarbeiten, wenn der Benutzer etwas kaufen möchte, wie im folgenden Code aus der Beispielanwendung gezeigt:

buy5Button.TouchUpInside += (sender, e) => {
   iap.PurchaseProduct (Buy5ProductId);
};​
buy10Button.TouchUpInside += (sender, e) => {
   iap.PurchaseProduct (Buy10ProductId);
};

Der zweite Teil der Benutzeroberfläche behandelt die Benachrichtigung, dass die Transaktion erfolgreich war, in diesem Fall durch Aktualisieren des angezeigten Saldos:

succeededObserver = NSNotificationCenter.DefaultCenter.AddObserver (InAppPurchaseManager.InAppPurchaseManagerTransactionSucceededNotification,
(notification) => {
   balanceLabel.Text = CreditManager.Balance() + " monkey credits";
});

Der letzte Teil der Benutzeroberfläche zeigt eine Meldung an, wenn eine Transaktion aus irgendeinem Grund abgebrochen wird. Im Beispielcode wird eine Nachricht einfach in das Ausgabefenster geschrieben:

failedObserver = NSNotificationCenter.DefaultCenter.AddObserver (InAppPurchaseManager.InAppPurchaseManagerTransactionFailedNotification,
(notification) => {
   Console.WriteLine ("Transaction Failed");
});

Zusätzlich zu diesen Methoden auf dem Ansichtscontroller erfordert eine Verbrauchsproduktkauftransaktion auch Code für die SKProductsRequestDelegate und die SKPaymentTransactionObserver.

InAppPurchaseManager-Methoden

Der Beispielcode implementiert eine Reihe von einkaufsbezogenen Methoden für die InAppPurchaseManager-Klasse, einschließlich der Methode, mit der PurchaseProduct eine SKPayment Instanz erstellt wird, und fügt sie zur Verarbeitungswarteschlange hinzu:

public void PurchaseProduct(string appStoreProductId)
{
   SKPayment payment = SKPayment.PaymentWithProduct (appStoreProductId);​
   SKPaymentQueue.DefaultQueue.AddPayment (payment);
}

Das Hinzufügen der Zahlung zur Warteschlange ist ein asynchroner Vorgang. Die Anwendung erhält die Kontrolle wieder, während StoreKit die Transaktion verarbeitet und an die Server von Apple sendet. An diesem Punkt überprüft iOS, ob der Benutzer beim App Store angemeldet ist, und fordert ihn bei Bedarf zur Eingabe einer Apple-ID und eines Kennworts auf.

Wenn sich der Benutzer erfolgreich beim App Store authentifiziert und der Transaktion zustimmt, empfängt der SKPaymentTransactionObserver StoreKit die Antwort und ruft die folgende Methode auf, um die Transaktion zu erfüllen und abzuschließen.

public void CompleteTransaction (SKPaymentTransaction transaction)
{
   var productId = transaction.Payment.ProductIdentifier;
   // Register the purchase, so it is remembered for next time
   PhotoFilterManager.Purchase(productId);
   FinishTransaction(transaction, true);
}

Der letzte Schritt besteht darin, sicherzustellen, dass Sie StoreKit benachrichtigen, dass Sie die Transaktion erfolgreich erfüllt haben, indem Sie folgendes aufrufen FinishTransaction:

public void FinishTransaction(SKPaymentTransaction transaction, bool wasSuccessful)
{
   // remove the transaction from the payment queue.
   SKPaymentQueue.DefaultQueue.FinishTransaction(transaction);  // THIS IS IMPORTANT - LET'S APPLE KNOW WE'RE DONE !!!!
   using (var pool = new NSAutoreleasePool()) {
       NSDictionary userInfo = NSDictionary.FromObjectsAndKeys(new NSObject[] {transaction},new NSObject[] {new NSString("transaction")});
       if (wasSuccessful) {
           // send out a notification that we've finished the transaction
           NSNotificationCenter.DefaultCenter.PostNotificationName (InAppPurchaseManagerTransactionSucceededNotification, this, userInfo);
       } else {
           // send out a notification for the failed transaction
           NSNotificationCenter.DefaultCenter.PostNotificationName (InAppPurchaseManagerTransactionFailedNotification, this, userInfo);
       }
   }
}

Nachdem das Produkt geliefert wurde, muss aufgerufen werden, SKPaymentQueue.DefaultQueue.FinishTransaction um die Transaktion aus der Zahlungswarteschlange zu entfernen.

SKPaymentTransactionObserver (CustomPaymentObserver)-Methoden

StoreKit ruft die UpdatedTransactions Methode auf, wenn sie eine Antwort von Apple-Servern empfängt, und übergibt ein Array von SKPaymentTransaction Objekten für ihren Code zu prüfen. Die Methode durchläuft jede Transaktion und führt eine andere Funktion basierend auf dem Transaktionsstatus aus (wie hier gezeigt):

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;
           default:
               break;
       }
   }
}

Die CompleteTransaction Methode wurde weiter oben in diesem Abschnitt behandelt – sie speichert die Kaufdetails in NSUserDefaults, schließt die Transaktion mit StoreKit ab und benachrichtigt die Benutzeroberfläche schließlich, um die Aktualisierung zu aktualisieren.

Kauf mehrerer Produkte

Wenn es in Ihrer Anwendung sinnvoll ist, mehrere Produkte zu kaufen, verwenden Sie die SKMutablePayment Klasse, und legen Sie das Feld "Menge" fest:

public void PurchaseProduct(string appStoreProductId)
{
   SKMutablePayment payment = SKMutablePayment.PaymentWithProduct (appStoreProductId);
   payment.Quantity = 4; // hardcoded as an example
   SKPaymentQueue.DefaultQueue.AddPayment (payment);
}

Der Code, der die abgeschlossene Transaktion verarbeitet, muss auch die Eigenschaft "Quantity" abfragen, um den Kauf ordnungsgemäß zu erfüllen:

public void CompleteTransaction (SKPaymentTransaction transaction)
{
   var productId = transaction.Payment.ProductIdentifier;
   var qty = transaction.Payment.Quantity;
   if (productId == ConsumableViewController.Buy5ProductId)
       CreditManager.Add(5 * qty);
   else if (productId == ConsumableViewController.Buy10ProductId)
       CreditManager.Add(10 * qty);
   else
       Console.WriteLine ("Shouldn't happen, there are only two products");
   FinishTransaction(transaction, true);
}

Wenn der Benutzer mehrere Mengen kauft, gibt die StoreKit-Bestätigungsbenachrichtigung die Menge, den Einzelpreis und den Gesamtpreis an, den er in Rechnung gestellt wird, wie im folgenden Screenshot gezeigt:

Bestätigen eines Kaufs

Behandeln von Netzwerkausfällen

In-App-Käufe erfordern eine funktionierende Netzwerkverbindung für StoreKit, um mit den Servern von Apple zu kommunizieren. Wenn keine Netzwerkverbindung verfügbar ist, steht der In-App-Kauf nicht zur Verfügung.

Produktanforderungen

Wenn das Netzwerk beim Erstellen einer SKProductRequestKlasse nicht verfügbar ist, wird die RequestFailed Methode der SKProductsRequestDelegate Unterklasse ( InAppPurchaseManager) aufgerufen, wie unten dargestellt:

public override void RequestFailed (SKRequest request, NSError error)
{
   using (var pool = new NSAutoreleasePool()) {
       NSDictionary userInfo = NSDictionary.FromObjectsAndKeys(new NSObject[] {error},new NSObject[] {new NSString("error")});
       // send out a notification for the failed transaction
       NSNotificationCenter.DefaultCenter.PostNotificationName (InAppPurchaseManagerRequestFailedNotification, this, userInfo);
   }
}

Der ViewController lauscht dann auf die Benachrichtigung und zeigt eine Meldung in den Kaufschaltflächen an:

requestObserver = NSNotificationCenter.DefaultCenter.AddObserver (InAppPurchaseManager.InAppPurchaseManagerRequestFailedNotification,
(notification) => {
   Console.WriteLine ("Request Failed");
   buy5Button.SetTitle ("Network down?", UIControlState.Disabled);
   buy10Button.SetTitle ("Network down?", UIControlState.Disabled);
});

Da eine Netzwerkverbindung auf mobilen Geräten vorübergehend sein kann, können Anwendungen den Netzwerkstatus mithilfe des SystemConfiguration-Frameworks überwachen und es erneut versuchen, wenn eine Netzwerkverbindung verfügbar ist. Verweisen Sie auf Apples oder die Verwendung.

Kauftransaktionen

Die StoreKit-Zahlungswarteschlange speichert und leitet Einkaufsanfragen nach Möglichkeit weiter, sodass die Auswirkungen eines Netzwerkausfalls abhängig davon variieren, wann das Netzwerk während des Kaufvorgangs fehlgeschlagen ist.

Wenn während einer Transaktion ein Fehler auftritt, hat die SKPaymentTransactionObserver Unterklasse ( CustomPaymentObserver) die UpdatedTransactions Methode aufgerufen, und die SKPaymentTransaction Klasse befindet sich im Status "Fehlgeschlagen".

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;
           default:
               break;
       }
   }
}

Die FailedTransaction Methode erkennt, ob der Fehler aufgrund eines Benutzerabbruchs aufgetreten ist, wie hier gezeigt:

public void FailedTransaction (SKPaymentTransaction transaction)
{
   //SKErrorPaymentCancelled == 2
   if (transaction.Error.Code == 2) // user cancelled
       Console.WriteLine("User CANCELLED FailedTransaction Code=" + transaction.Error.Code + " " + transaction.Error.LocalizedDescription);
   else // error!
       Console.WriteLine("FailedTransaction Code=" + transaction.Error.Code + " " + transaction.Error.LocalizedDescription);
   FinishTransaction(transaction,false);
}

Auch wenn eine Transaktion fehlschlägt, muss die FinishTransaction Methode aufgerufen werden, um die Transaktion aus der Zahlungswarteschlange zu entfernen:

SKPaymentQueue.DefaultQueue.FinishTransaction(transaction);

Der Beispielcode sendet dann eine Benachrichtigung, sodass der ViewController eine Meldung anzeigen kann. Anwendungen sollten keine zusätzliche Meldung anzeigen, wenn der Benutzer die Transaktion abgebrochen hat. Weitere Fehlercodes, die auftreten können, sind:

FailedTransaction Code=0 Cannot connect to iTunes Store
FailedTransaction Code=5002 An unknown error has occurred
FailedTransaction Code=5020 Forget Your Password?
Applications may detect and respond to specific error codes, or handle them in the same way.

Behandeln von Einschränkungen

Mit dem Feature "Einstellungen > allgemeine > Einschränkungen" von iOS können Benutzer bestimmte Features ihres Geräts sperren.

Sie können abfragen, ob der Benutzer In-App-Käufe über die SKPaymentQueue.CanMakePayments Methode tätigen darf. Wenn dies "false" zurückgibt, kann der Benutzer nicht auf den In-App-Einkauf zugreifen. StoreKit zeigt dem Benutzer automatisch eine Fehlermeldung an, wenn ein Kauf versucht wird. Durch Überprüfen dieses Werts kann Ihre Anwendung stattdessen die Kaufschaltflächen ausblenden oder eine andere Aktion ausführen, um dem Benutzer zu helfen.

In der InAppPurchaseManager.cs Datei umschließt die CanMakePayments Methode die StoreKit-Funktion wie folgt:

public bool CanMakePayments()
{
   return SKPaymentQueue.CanMakePayments;​
}

Verwenden Sie zum Testen dieser Methode das Feature "Einschränkungen" von iOS, um In-App-Käufe zu deaktivieren:

Verwenden des Features

Dieser Beispielcode von ConsumableViewController reacts to CanMakePayments returning false by displaying AppStore Disabled text on the disabled buttons.

// only if we can make payments, request the prices
if (iap.CanMakePayments()) {
   // now go get prices, if we don't have them already
   if (!pricesLoaded)
       iap.RequestProductData(products); // async request via StoreKit -> App Store
} else {
   // can't make payments (purchases turned off in Settings?)
   // the buttons are disabled by default, and only enabled when prices are retrieved
   buy5Button.SetTitle ("AppStore disabled", UIControlState.Disabled);
   buy10Button.SetTitle ("AppStore disabled", UIControlState.Disabled);
}

Die Anwendung sieht so aus, wenn das Feature " In-App-Käufe " eingeschränkt ist – die Kaufschaltflächen sind deaktiviert.

Die Anwendung sieht wie folgt aus, wenn das Feature

Produktinformationen können weiterhin angefordert werden, wenn CanMakePayments "false" ist, sodass die App weiterhin Preise abrufen und anzeigen kann. Dies bedeutet, dass, wenn wir die CanMakePayments Überprüfung aus dem Code entfernt haben, die Kaufschaltflächen weiterhin aktiv sind, aber wenn ein Kauf versucht wird, wird dem Benutzer eine Meldung angezeigt, dass In-App-Käufe nicht zulässig sind (generiert durch StoreKit, wenn auf die Zahlungswarteschlange zugegriffen wird):

In-App-Käufe sind nicht zulässig

Reale Anwendungen können einen anderen Ansatz für die Behandlung der Einschränkung haben, z. B. das Ausblenden der Schaltflächen insgesamt und vielleicht eine detailliertere Meldung als die Warnung, die Von StoreKit automatisch angezeigt wird.