Share via


StoreKit-Übersicht und Abrufen von Produktinformationen in Xamarin.iOS

Die Benutzeroberfläche für einen In-App-Kauf wird in den folgenden Screenshots angezeigt. Bevor eine Transaktion stattfindet, muss die Anwendung den Preis und die Beschreibung des Produkts für die Anzeige abrufen. Wenn der Benutzer dann "Kaufen" drückt, sendet die Anwendung eine Anforderung an StoreKit, die das Bestätigungsdialogfeld und die Apple-ID-Anmeldung verwaltet. Wenn die Transaktion dann erfolgreich ausgeführt wird, benachrichtigt StoreKit den Anwendungscode, der das Transaktionsergebnis speichern muss und dem Benutzer Zugriff auf seinen Kauf bietet.

StoreKit benachrichtigt den Anwendungscode, der das Transaktionsergebnis speichern muss und dem Benutzer Zugriff auf seinen Kauf bietet.

Klassen

Für die Implementierung von In-App-Käufen sind die folgenden Klassen aus dem StoreKit-Framework erforderlich:

SKProductsRequest – Eine Anforderung an StoreKit für genehmigte Produkte zum Verkauf (App Store). Kann mit einer Reihe von Produkt-IDs konfiguriert werden.

  • SKProductsRequestDelegate – Deklariert Methoden zum Verarbeiten von Produktanforderungen und -antworten.
  • SKProductsResponse – Zurück an die Stellvertretung von StoreKit (App Store). Enthält die SKProducts, die den Produkt-IDs entsprechen, die mit der Anforderung gesendet wurden.
  • SKProduct – Ein Aus StoreKit abgerufenes Produkt (das Sie in iTunes Verbinden konfiguriert haben). Enthält Informationen zum Produkt, z. B. Produkt-ID, Titel, Beschreibung und Preis.
  • SKPayment – Erstellt mit einer Produkt-ID und zur Zahlungswarteschlange hinzugefügt, um einen Kauf durchzuführen.
  • SKPaymentQueue – Zahlungsaufforderungen in der Warteschlange, die an Apple gesendet werden sollen. Benachrichtigungen werden ausgelöst, wenn jede Zahlung verarbeitet wird.
  • SKPaymentTransaction – Stellt eine abgeschlossene Transaktion dar (eine Kaufanforderung, die vom App Store verarbeitet und über StoreKit an Ihre Anwendung zurückgesendet wurde). Die Transaktion kann gekauft, wiederhergestellt oder fehlgeschlagen sein.
  • SKPaymentTransactionObserver – Benutzerdefinierte Unterklasse, die auf Ereignisse reagiert, die von der StoreKit-Zahlungswarteschlange generiert werden.
  • StoreKit-Vorgänge sind asynchron – nachdem eine SKProductRequest gestartet wurde oder ein SKPayment zur Warteschlange hinzugefügt wird, wird das Steuerelement an Ihren Code zurückgegeben. StoreKit ruft Methoden für Ihre SKProductsRequestDelegate- oder SKPaymentTransactionObserver-Unterklasse auf, wenn sie Daten von Apple-Servern empfängt.

Das folgende Diagramm zeigt die Beziehungen zwischen den verschiedenen StoreKit-Klassen (abstrakte Klassen müssen in Ihrer Anwendung implementiert werden):

Die Beziehungen zwischen den verschiedenen Abstrakten Klassen von StoreKit-Klassen müssen in der App implementiert werden.

Diese Klassen werden weiter unten in diesem Dokument ausführlicher erläutert.

Testen

Die meisten StoreKit-Vorgänge erfordern ein echtes Gerät zum Testen. Das Abrufen von Produktinformationen (d. h. Preis und Beschreibung) funktioniert im Simulator, aber Einkaufs- und Wiederherstellungsvorgänge geben einen Fehler zurück (z. B. FailedTransaction Code=5002 Ein unbekannter Fehler ist aufgetreten).

Hinweis: StoreKit funktioniert nicht im iOS Simulator. Wenn Sie Ihre Anwendung im iOS Simulator ausführen, protokolliert StoreKit eine Warnung, wenn Ihre Anwendung versucht, die Zahlungswarteschlange abzurufen. Das Testen des Speichers muss auf tatsächlichen Geräten erfolgen.

Wichtig: Melden Sie sich nicht mit Ihrem Testkonto in der Einstellungen Anwendung an. Sie können die Einstellungen Anwendung verwenden, um sich von einem vorhandenen Apple ID-Konto abzumelden, und Sie müssen warten, bis Sie in Ihrer In-App-Kaufsequenz aufgefordert werden, sich mit einer Apple-Test-ID anzumelden.

Wenn Sie versuchen, sich mit einem Testkonto beim echten Store anzumelden, wird sie automatisch in eine echte Apple-ID konvertiert. Dieses Konto kann nicht mehr zum Testen verwendet werden.

Um StoreKit-Code zu testen, müssen Sie sich von Ihrem regulären iTunes-Testkonto abmelden und sich mit einem speziellen Testkonto anmelden (erstellt in iTunes Verbinden), das mit dem Testspeicher verknüpft ist. Um sich vom aktuellen Konto abzumelden, besuchen Sie Einstellungen > iTunes und App Store wie hier gezeigt:

Um sich vom aktuellen Konto abzumelden, besuchen Sie Einstellungen iTunes und App Store

melden Sie sich dann mit einem Testkonto an, wenn sie von StoreKit in Ihrer App angefordert werden:

Um Testbenutzer in iTunes zu erstellen, Verbinden auf der Seite Standard auf "Benutzer und Rollen" klicken.

So erstellen Sie Testbenutzer in iTunes Verbinden auf der Seite Standard auf

Auswählen von Sandbox-Testern

Auswählen von Sandbox-Testern

Die Liste der vorhandenen Benutzer wird angezeigt. Sie können einen neuen Benutzer hinzufügen oder einen vorhandenen Datensatz löschen. Im Portal können Sie vorhandene Testbenutzer (derzeit) nicht anzeigen oder bearbeiten. Daher wird empfohlen, dass Sie einen guten Überblick über jeden erstellten Testbenutzer behalten (insbesondere das kennwort, das Sie zuweisen). Nachdem Sie einen Testbenutzer gelöscht haben, kann die E-Mail-Adresse nicht für ein anderes Testkonto erneut verwendet werden.

Die Liste der vorhandenen Benutzer wird angezeigt.

Neue Testbenutzer haben ähnliche Attribute wie eine echte Apple-ID (z. B. Name, Kennwort, geheime Frage und Antwort). Bewahren Sie alle hier eingegebenen Details auf. Das Feld "iTunes Store auswählen" bestimmt, welche Währung und Sprache die In-App-Käufe verwenden, wenn er als dieser Benutzer angemeldet ist.

Das Feld

Abrufen von Produktinformationen

Der erste Schritt beim Verkauf eines In-App-Kaufprodukts zeigt es an: Abrufen des aktuellen Preises und der aktuellen Beschreibung aus dem App Store für die Anzeige.

Unabhängig davon, welche Art von Produkten eine App verkauft (Verbrauchsartikel, nicht konsumierbar oder abonnementtyp), ist der Vorgang zum Abrufen von Produktinformationen für die Anzeige identisch. Der InAppPurchaseSample-Code, der zu diesem Artikel gehört, enthält ein Projekt mit dem Namen "Consumables ", das veranschaulicht, wie Produktionsinformationen für die Anzeige abgerufen werden. Es zeigt Folgendes:

  • Erstellen Sie eine Implementierung der SKProductsRequestDelegate abstrakten Methode, und implementieren Sie sie ReceivedResponse . Der Beispielcode ruft diese InAppPurchaseManager Klasse auf.
  • Überprüfen Sie mit StoreKit, ob Zahlungen zulässig sind (mit SKPaymentQueue.CanMakePayments ).
  • Instanziieren Sie eine SKProductsRequest mit den Produkt-IDs, die in iTunes Verbinden definiert wurden. Dies erfolgt in der Methode des Beispiels InAppPurchaseManager.RequestProductData .
  • Rufen Sie die Start-Methode für die SKProductsRequest . Dadurch wird ein asynchroner Aufruf der App Store-Server ausgelöst. Die Stellvertretung ( InAppPurchaseManager ) wird mit den Ergebnissen zurückgerufen.
  • Die Methode ( InAppPurchaseManager ) ReceivedResponse des Delegaten aktualisiert die Benutzeroberfläche mit den daten, die aus dem App Store zurückgegeben werden (Produktpreise und Beschreibungen oder Nachrichten zu ungültigen Produkten).

Die allgemeine Interaktion sieht wie folgt aus ( StoreKit ist in iOS integriert, und der App Store stellt die Server von Apple dar):

Abrufen des Produktinformationsdiagramms

Anzeigen von Produktinformationen (Beispiel)

Der Beispielcode für Verbrauchsartikel veranschaulicht, wie Produktinformationen abgerufen werden können. Im Standard Bildschirm des Beispiels werden Informationen für zwei Produkte angezeigt, die aus dem App Store abgerufen werden:

Auf dem Bildschirm Standard werden Informationsprodukte angezeigt, die aus dem App Store abgerufen wurden.

Der Beispielcode zum Abrufen und Anzeigen von Produktinformationen wird unten ausführlicher erläutert.

ViewController-Methoden

Die ConsumableViewController Klasse verwaltet die Anzeige der Preise für zwei Produkte, deren Produkt-IDs in der Klasse hartcodiert sind.

public static string Buy5ProductId = "com.xamarin.storekit.testing.consume5credits",
   Buy10ProductId = "com.xamarin.storekit.testing.consume10credits";
List<string> products;
InAppPurchaseManager iap;
public ConsumableViewController () : base()
{
   // two products for sale on this page
   products = new List<string>() {Buy5ProductId, Buy10ProductId};
   iap = new InAppPurchaseManager();
}

Auf Klassenebene sollte auch ein NSObject deklariert werden, das zum Einrichten eines NSNotificationCenter Beobachters verwendet wird:

NSObject priceObserver;

In der ViewWillAppear-Methode wird der Beobachter mithilfe des Standardbenachrichtigungscenters erstellt und zugewiesen:

priceObserver = NSNotificationCenter.DefaultCenter.AddObserver (
  InAppPurchaseManager.InAppPurchaseManagerProductsFetchedNotification,
(notification) => {
   // display code goes here, to handle the response from the App Store
}

Rufen Sie am Ende der ViewWillAppear Methode die RequestProductData Methode auf, um die StoreKit-Anforderung zu initiieren. Nachdem diese Anforderung gestellt wurde, kontaktiert StoreKit asynchron die Apple-Server, um die Informationen abzurufen und sie zurück zu Ihrer App zu feeden. Dies wird durch die SKProductsRequestDelegate Unterklasse ( InAppPurchaseManager) erreicht, die im nächsten Abschnitt erläutert wird.

iap.RequestProductData(products);

Der Code zum Anzeigen des Preises und der Beschreibung ruft einfach die Informationen aus dem SKProduct ab und weist sie UIKit-Steuerelementen zu (beachten Sie, dass wir den LocalizedTitle und LocalizedDescription – StoreKit automatisch den richtigen Text und preise basierend auf den Kontoeinstellungen des Benutzers auflösen). Der folgende Code gehört zur oben erstellten Benachrichtigung:

priceObserver = NSNotificationCenter.DefaultCenter.AddObserver (
  InAppPurchaseManager.InAppPurchaseManagerProductsFetchedNotification,
(notification) => {
   // display code goes here, to handle the response from the App Store
   var info = notification.UserInfo;
   if (info.ContainsKey(NSBuy5ProductId)) {
       var product = (SKProduct) info.ObjectForKey(NSBuy5ProductId);
       buy5Button.Enabled = true;
       buy5Title.Text = product.LocalizedTitle;
       buy5Description.Text = product.LocalizedDescription;
       buy5Button.SetTitle("Buy " + product.Price, UIControlState.Normal); // price display should be localized
   }
}

Schließlich sollte die ViewWillDisappear Methode sicherstellen, dass der Beobachter entfernt wird:

NSNotificationCenter.DefaultCenter.RemoveObserver (priceObserver);

SKProductRequestDelegate (InAppPurchaseManager) Methoden

Die RequestProductData Methode wird aufgerufen, wenn die Anwendung Produktpreise und andere Informationen abrufen möchte. Es analysiert die Sammlung von Produkt-IDs in den richtigen Datentyp und erstellt dann eine SKProductsRequest mit diesen Informationen. Das Aufrufen der Startmethode bewirkt, dass eine Netzwerkanforderung an die Server von Apple gestellt wird. Die Anforderung wird asynchron ausgeführt und die ReceivedResponse Methode des Delegaten aufgerufen, wenn sie erfolgreich abgeschlossen wurde.

public void RequestProductData (List<string> productIds)
{
   var array = new NSString[productIds.Count];
   for (var i = 0; i < productIds.Count; i++) {
       array[i] = new NSString(productIds[i]);
   }
   NSSet productIdentifiers = NSSet.MakeNSObjectSet<NSString>(array);​​​
   productsRequest = new SKProductsRequest(productIdentifiers);
   productsRequest.Delegate = this; // for SKProductsRequestDelegate.ReceivedResponse
   productsRequest.Start();
}

iOS leitet die Anforderung automatisch an die Version "Sandbox" oder "Produktion" des App Store weiter, je nachdem, mit welchem Bereitstellungsprofil die Anwendung ausgeführt wird. Wenn Sie also Ihre App entwickeln oder testen, hat die Anforderung Zugriff auf jedes produkt, das in iTunes Verbinden konfiguriert ist (auch diejenigen, die noch nicht übermittelt oder von Apple genehmigt wurden). Wenn sich Ihre Anwendung in der Produktion befindet, werden von StoreKit-Anforderungen nur Informationen für genehmigte Produkte zurückgegeben.

Die ReceivedResponse überschriebene Methode wird aufgerufen, nachdem die Apple-Server mit Daten geantwortet haben. Da dies im Hintergrund aufgerufen wird, sollte der Code die gültigen Daten analysieren und eine Benachrichtigung verwenden, um die Produktinformationen an alle ViewController zu senden, die diese Benachrichtigung "überwachen". Der Code zum Sammeln gültiger Produktinformationen und Senden einer Benachrichtigung wird unten angezeigt:

public override void ReceivedResponse (SKProductsRequest request, SKProductsResponse response)
{
   SKProduct[] products = response.Products;
   NSDictionary userInfo = null;
   if (products.Length > 0) {
       NSObject[] productIdsArray = new NSObject[response.Products.Length];
       NSObject[] productsArray = new NSObject[response.Products.Length];
       for (int i = 0; i < response.Products.Length; i++) {
           productIdsArray[i] = new NSString(response.Products[i].ProductIdentifier);
           productsArray[i] = response.Products[i];
       }
       userInfo = NSDictionary.FromObjectsAndKeys (productsArray, productIdsArray);
   }
   NSNotificationCenter.DefaultCenter.PostNotificationName (InAppPurchaseManagerProductsFetchedNotification, this, userInfo);
}

Obwohl nicht im Diagramm dargestellt, sollte die RequestFailed Methode auch außer Kraft gesetzt werden, damit Sie dem Benutzer feedback geben können, falls die App Store-Server nicht erreichbar sind (oder ein anderer Fehler auftritt). Der Beispielcode schreibt lediglich in die Konsole, aber eine echte Anwendung kann auswählen, ob eigenschaften error.Code und benutzerdefiniertes Verhalten implementiert werden soll (z. B. eine Benachrichtigung für den Benutzer).

public override void RequestFailed (SKRequest request, NSError error)
{
   Console.WriteLine (" ** InAppPurchaseManager RequestFailed() " + error.LocalizedDescription);
}

Dieser Screenshot zeigt die Beispielanwendung unmittelbar nach dem Laden (wenn keine Produktinformationen verfügbar sind):

Die Beispiel-App unmittelbar nach dem Laden, wenn keine Produktinformationen verfügbar sind

Ungültige Produkte

Eine SKProductsRequest Liste ungültiger Produkt-IDs kann auch zurückgegeben werden. Ungültige Produkte werden in der Regel aufgrund einer der folgenden Produkte zurückgegeben:

Die Produkt-ID wurde falsch eingegeben – Es werden nur gültige Produkt-IDs akzeptiert.

Produkt wurde nicht genehmigt – Während der Prüfung sollten alle Produkte, die für den Verkauf gelöscht werden, von einem SKProductsRequestzurückgegeben werden; in der Produktion werden jedoch nur genehmigte Produkte zurückgegeben.

App-ID ist nicht explizit – Wild Karte App-IDs (mit einem Sternchen) lassen den In-App-Einkauf nicht zu.

Falsches Bereitstellungsprofil – Wenn Sie Änderungen an Ihrer Anwendungskonfiguration im Bereitstellungsportal vornehmen (z. B. das Aktivieren von In-App-Käufen), denken Sie daran, das richtige Bereitstellungsprofil beim Erstellen der App erneut zu generieren und zu verwenden.

Der Vertrag für kostenpflichtige iOS-Anwendungen ist nicht vorhanden – StoreKit-Features funktionieren überhaupt nicht, es sei denn, es gibt einen gültigen Vertrag für Ihr Apple-Entwicklerkonto.

Die Binärdatei befindet sich im Status "Abgelehnt" – Wenn eine zuvor übermittelte Binärdatei im Status "Abgelehnt" (entweder vom App Store-Team oder vom Entwickler) vorhanden ist, funktionieren die StoreKit-Features nicht.

Die ReceivedResponse Methode im Beispielcode gibt die ungültigen Produkte in der Konsole aus:

public override void ReceivedResponse (SKProductsRequest request, SKProductsResponse response)
{
   // code removed for clarity
   foreach (string invalidProductId in response.InvalidProducts) {
       Console.WriteLine("Invalid product id: " + invalidProductId );
   }
}

Anzeigen lokalisierter Preise

Preisniveaus geben einen bestimmten Preis für jedes Produkt in allen internationalen App Stores an. Um sicherzustellen, dass die Preise für jede Währung korrekt angezeigt werden, verwenden Sie die folgende Erweiterungsmethode (definiert in SKProductExtension.cs) anstelle der Price-Eigenschaft der einzelnen SKProductWährungen:

public static class SKProductExtension {
   public static string LocalizedPrice (this SKProduct product)
   {
       var formatter = new NSNumberFormatter ();
       formatter.FormatterBehavior = NSNumberFormatterBehavior.Version_10_4;  
       formatter.NumberStyle = NSNumberFormatterStyle.Currency;
       formatter.Locale = product.PriceLocale;
       var formattedString = formatter.StringFromNumber(product.Price);
       return formattedString;
   }
}

Der Code, der den Titel der Schaltfläche festlegt, verwendet die Erweiterungsmethode wie folgt:

string Buy = "Buy {0}"; // or a localizable string
buy5Button.SetTitle(String.Format(Buy, product.LocalizedPrice()), UIControlState.Normal);

Die Verwendung von zwei verschiedenen iTunes-Testkonten (eines für den amerikanischen Store und eines für den japanischen Store) führt zu den folgenden Screenshots:

Zwei verschiedene iTunes-Testkonten mit sprachspezifischen Ergebnissen

Beachten Sie, dass sich der Store auf die Sprache auswirkt, die für Produktinformationen und Preiswährung verwendet wird, während sich die Spracheinstellung des Geräts auf Bezeichnungen und andere lokalisierte Inhalte auswirkt.

Denken Sie daran, dass Sie sich beim Einstellungen > iTunes und App Store abmelden und die Anwendung erneut starten müssen, um sich mit einem anderen Konto anzumelden. Um die Sprache des Geräts zu ändern, wechseln Sie zu Einstellungen > Allgemeine > internationale > Sprache.