Udostępnij za pośrednictwem


StoreKit Overview and Retrieving Product Info in Xamarin.iOS

Interfejs użytkownika do zakupu w aplikacji jest wyświetlany na poniższych zrzutach ekranu. Przed rozpoczęciem każdej transakcji aplikacja musi pobrać cenę i opis produktu do wyświetlenia. Następnie po naciśnięciu przycisku Kup aplikacja wysyła żądanie do sklepu StoreKit, które zarządza oknie dialogowym potwierdzenia i identyfikatorem Apple ID. Przy założeniu, że transakcja zakończy się powodzeniem, zestaw StoreKit powiadamia kod aplikacji, który musi przechowywać wynik transakcji i zapewnić użytkownikowi dostęp do zakupu.

StoreKit powiadamia kod aplikacji, który musi przechowywać wynik transakcji i zapewnić użytkownikowi dostęp do zakupu

Klasy

Implementowanie zakupów w aplikacji wymaga następujących klas z platformy StoreKit:

SKProductsRequest — żądanie sklepu StoreKit dla zatwierdzonych produktów do sprzedaży (App Store). Można skonfigurować przy użyciu wielu identyfikatorów produktów.

  • SKProductsRequestDelegate — deklaruje metody obsługi żądań produktów i odpowiedzi.
  • SKProductsResponse — odesłanie do delegata ze sklepu StoreKit (App Store). Zawiera elementy SKProducts zgodne z identyfikatorami produktu wysłanymi z żądaniem.
  • SKProduct — produkt pobrany z zestawu StoreKit (skonfigurowany w programie iTunes Połączenie). Zawiera informacje o produkcie, takie jak Identyfikator produktu, Tytuł, Opis i Cena.
  • SKPayment — utworzono przy użyciu identyfikatora produktu i dodano go do kolejki płatności w celu wykonania zakupu.
  • SKPaymentQueue — przesłane do firmy Apple żądania płatności w kolejce. Powiadomienia są wyzwalane w wyniku przetworzenia każdej płatności.
  • SKPaymentTransaction — reprezentuje ukończoną transakcję (żądanie zakupu przetworzone przez sklep App Store i wysłane z powrotem do aplikacji za pośrednictwem sklepu StoreKit). Transakcja może zostać zakupiona, przywrócona lub nieudana.
  • SKPaymentTransactionObserver — niestandardowa podklasa, która odpowiada na zdarzenia generowane przez kolejkę płatności StoreKit.
  • Operacje zestawu StoreKit są asynchroniczne — po uruchomieniu skProductRequest lub do kolejki zostanie dodana skPayment, kontrolka zostanie zwrócona do kodu. Zestaw StoreKit wywoła metody w podklasie SKProductsRequestDelegate lub SKPaymentTransactionObserver, gdy odbiera dane z serwerów firmy Apple.

Na poniższym diagramie przedstawiono relacje między różnymi klasami StoreKit (klasy abstrakcyjne muszą być zaimplementowane w aplikacji):

Relacje między różnymi klasami klasy StoreKit muszą być implementowane w aplikacji

Te klasy zostały szczegółowo wyjaśnione w dalszej części tego dokumentu.

Testowanie

Większość operacji StoreKit wymaga rzeczywistego urządzenia do testowania. Pobieranie informacji o produkcie (tj. cena i opis) będzie działać w symulatorze, ale operacje zakupu i przywracania zwróci błąd (na przykład FailedTransaction Code=5002 Wystąpił nieznany błąd).

Uwaga: Zestaw StoreKit nie działa w symulatorze systemu iOS. Podczas uruchamiania aplikacji w symulatorze systemu iOS zestaw StoreKit rejestruje ostrzeżenie, jeśli aplikacja próbuje pobrać kolejkę płatności. Testowanie magazynu musi odbywać się na rzeczywistych urządzeniach.

Ważne: nie loguj się przy użyciu konta testowego w aplikacji Ustawienia. Możesz użyć aplikacji Ustawienia, aby wylogować się z dowolnego istniejącego konta Apple ID, a następnie poczekać, aż zostanie wyświetlony monit w ramach sekwencji zakupów w aplikacji, aby zalogować się przy użyciu testowego identyfikatora Apple ID.

Jeśli spróbujesz zalogować się do rzeczywistego sklepu przy użyciu konta testowego, zostanie on automatycznie przekonwertowany na rzeczywisty identyfikator Apple ID. To konto nie będzie już możliwe do użycia do testowania.

Aby przetestować kod StoreKit, musisz wylogować się ze swojego zwykłego konta testowego iTunes i zalogować się przy użyciu specjalnego konta testowego (utworzonego w programie iTunes Połączenie), które jest połączone ze sklepem testowym. Aby wylogować się z bieżącego konta, odwiedź stronę Ustawienia > iTunes i App Store, jak pokazano poniżej:

Aby wylogować się z bieżącego konta, odwiedź witrynę Ustawienia iTunes i App Store

następnie zaloguj się przy użyciu konta testowego, gdy zażądasz go za pomocą zestawu StoreKit w aplikacji:

Aby utworzyć użytkowników testowych w programie iTunes Połączenie kliknij pozycję Użytkownicy i role na stronie głównej.

Aby utworzyć użytkowników testowych w programie iTunes Połączenie kliknij pozycję Użytkownicy i role na stronie głównej

Wybieranie testerów piaskownicy

Wybieranie testerów piaskownicy

Zostanie wyświetlona lista istniejących użytkowników. Możesz dodać nowego użytkownika lub usunąć istniejący rekord. Portal nie umożliwia obecnie wyświetlania ani edytowania istniejących użytkowników testowych, dlatego zaleca się przechowywanie dobrego rekordu każdego utworzonego użytkownika testowego (zwłaszcza przypisanego hasła). Po usunięciu użytkownika testowego nie można ponownie użyć adresu e-mail dla innego konta testowego.

Zostanie wyświetlona lista istniejących użytkowników

Nowi użytkownicy testowi mają podobne atrybuty do rzeczywistego identyfikatora Apple ID (takiego jak nazwa, hasło, tajne pytanie i odpowiedź). Zachowaj rekord wszystkich wprowadzonych tutaj szczegółów. W polu Wybierz sklep iTunes Store określi, która waluta i język zakupów w aplikacji będą używane podczas logowania się jako ten użytkownik.

Pole Wybierz sklep iTunes Store określi walutę i język użytkownika dla zakupów w aplikacji

Pobieranie informacji o produkcie

Pierwszym krokiem sprzedaży produktu zakupu w aplikacji jest jego wyświetlenie: pobieranie bieżącej ceny i opisu ze sklepu App Store w celu wyświetlenia.

Niezależnie od tego, jakiego typu produkty sprzedaje aplikacja (Eksploatacyjne, Nieożywne lub Typ subskrypcji), proces pobierania informacji o produkcie do wyświetlenia jest taki sam. Kod InAppPurchaseSample, który towarzyszy temu artykułowi, zawiera projekt o nazwie Eksploatacyjne , który pokazuje sposób pobierania informacji produkcyjnych na potrzeby wyświetlania. Pokazano w nim, jak:

  • Utwórz implementację metody abstrakcyjnej SKProductsRequestDelegate i zaimplementuj metodę abstrakcyjną ReceivedResponse . Przykładowy kod wywołuje tę klasę InAppPurchaseManager .
  • Sprawdź zestaw StoreKit, aby sprawdzić, czy płatności są dozwolone (przy użyciu metody SKPaymentQueue.CanMakePayments ).
  • Utwórz wystąpienie SKProductsRequest elementu przy użyciu identyfikatorów produktów zdefiniowanych w programie iTunes Połączenie. Jest to wykonywane w metodzie przykładu InAppPurchaseManager.RequestProductData .
  • Wywołaj metodę Start w obiekcie SKProductsRequest . Spowoduje to wywołanie asynchroniczne na serwerach ze sklepu App Store. Delegat ( InAppPurchaseManager ) zostanie wywołany z powrotem z wynikami.
  • Metoda Delegata ( InAppPurchaseManager ) ReceivedResponse aktualizuje interfejs użytkownika przy użyciu danych zwracanych ze sklepu App Store (ceny produktów i opisy lub komunikaty dotyczące nieprawidłowych produktów).

Ogólna interakcja wygląda następująco ( StoreKit jest wbudowany w system iOS, a sklep App Store reprezentuje serwery firmy Apple):

Pobieranie grafu informacji o produkcie

Przykład wyświetlania informacji o produkcie

Przykładowy kod eksploatacyjnych pokazuje sposób pobierania informacji o produkcie. Na głównym ekranie przykładu są wyświetlane informacje dotyczące dwóch produktów pobranych ze sklepu App Store:

Na ekranie głównym są wyświetlane informacje o produktach pobranych ze sklepu App Store

Przykładowy kod umożliwiający pobranie i wyświetlenie informacji o produkcie zostało wyjaśnione bardziej szczegółowo poniżej.

ViewController, metody

Klasa ConsumableViewController będzie zarządzać wyświetlaniem cen dla dwóch produktów, których identyfikatory produktów są zakodowane na stałe w klasie.

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();
}

Na poziomie klasy powinien być również zadeklarowany obiekt NSObject, który będzie używany do konfigurowania obserwatora NSNotificationCenter :

NSObject priceObserver;

W metodzie ViewWillAppear obserwator jest tworzony i przypisywany przy użyciu domyślnego centrum powiadomień:

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

Na końcu ViewWillAppear metody wywołaj metodę RequestProductData , aby zainicjować żądanie StoreKit. Po utworzeniu tego żądania zestaw StoreKit asynchronicznie skontaktuje się z serwerami firmy Apple, aby uzyskać informacje i podawać je z powrotem do aplikacji. Jest to osiągane przez podklasę SKProductsRequestDelegate ( InAppPurchaseManager), która jest wyjaśniona w następnej sekcji.

iap.RequestProductData(products);

Kod wyświetlający cenę i opis po prostu pobiera informacje ze skProduct i przypisuje je do kontrolek UIKit (zwróć uwagę, że wyświetlamy LocalizedTitle element i LocalizedDescription — StoreKit automatycznie rozpoznaje prawidłowy tekst i ceny na podstawie ustawień konta użytkownika). Poniższy kod należy do utworzonego powyżej powiadomienia:

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

ViewWillDisappear Na koniec metoda powinna zapewnić usunięcie obserwatora:

NSNotificationCenter.DefaultCenter.RemoveObserver (priceObserver);

METODY SKProductRequestDelegate (InAppPurchaseManager)

Metoda jest wywoływana RequestProductData , gdy aplikacja chce pobrać ceny produktów i inne informacje. Analizuje ona kolekcję identyfikatorów produktu w prawidłowy typ danych, a następnie tworzy element SKProductsRequest z informacjami. Wywołanie metody Start powoduje wysyłanie żądania sieciowego do serwerów firmy Apple. Żądanie zostanie uruchomione asynchronicznie i wywoła ReceivedResponse metodę delegata po pomyślnym zakończeniu.

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();
}

System iOS automatycznie wyśle żądanie do wersji "piaskownicy" lub "produkcyjnej" sklepu App Store w zależności od profilu aprowizacji uruchomionego przez aplikację — więc podczas tworzenia lub testowania aplikacji żądanie będzie miało dostęp do każdego produktu skonfigurowanego w programie iTunes Połączenie (nawet tych, które nie zostały jeszcze przesłane lub zatwierdzone przez firmę Apple). Gdy aplikacja jest w środowisku produkcyjnym, żądania StoreKit będą zwracać tylko informacje dotyczące zatwierdzonych produktów.

Metoda ReceivedResponse przesłonięta jest wywoływana po tym, jak serwery firmy Apple odpowiedziały danymi. Ponieważ jest to wywoływane w tle, kod powinien przeanalizować prawidłowe dane i użyć powiadomienia, aby wysłać informacje o produkcie do dowolnych kontrolek ViewControllers, które "nasłuchiwanie" dla tego powiadomienia. Poniższy kod do zbierania prawidłowych informacji o produkcie i wysyłania powiadomienia:

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);
}

Chociaż nie pokazano na diagramie, RequestFailed metoda powinna zostać również zastąpiona, aby można było przekazać użytkownikowi opinię na wypadek, gdyby serwery ze sklepu App Store nie są osiągalne (lub wystąpił inny błąd). Przykładowy kod tylko zapisuje w konsoli, ale prawdziwa aplikacja może zdecydować się na wykonanie zapytania względem error.Code właściwości i zaimplementowanie zachowania niestandardowego (na przykład alertu dla użytkownika).

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

Ten zrzut ekranu przedstawia przykładową aplikację natychmiast po załadowaniu (jeśli nie są dostępne żadne informacje o produkcie):

Przykładowa aplikacja natychmiast po załadowaniu, gdy nie są dostępne żadne informacje o produkcie

Nieprawidłowe produkty

Element SKProductsRequest może również zwrócić listę nieprawidłowych identyfikatorów produktów. Nieprawidłowe produkty są zwykle zwracane z powodu jednego z następujących elementów:

Identyfikator produktu został błędnie wtypowany — akceptowane są tylko prawidłowe identyfikatory produktów.

Produkt nie został zatwierdzony — podczas testowania wszystkie produkty, które zostały wyczyszczone do sprzedaży, powinny być zwracane przez obiekt SKProductsRequest; jednak w środowisku produkcyjnym zwracane są tylko zatwierdzone produkty.

Identyfikator aplikacji nie jest jawny — identyfikatory aplikacji wieloznacznych (z gwiazdką) nie zezwalają na zakup w aplikacji.

Nieprawidłowy profil aprowizacji — jeśli wprowadzisz zmiany w konfiguracji aplikacji w portalu aprowizacji (np. włączanie zakupów w aplikacji), pamiętaj o ponownym wygenerowaniu i użyciu poprawnego profilu aprowizacji podczas kompilowania aplikacji.

Nie ma umowy płatnej aplikacji dla systemu iOS — funkcje StoreKit nie będą działać w ogóle, chyba że istnieje prawidłowa umowa dla Konta dewelopera Apple.

Plik binarny jest w stanie Odrzucone — jeśli w stanie Odrzucono (przez zespół sklepu App Store lub przez dewelopera) istnieje wcześniej przesłany plik binarny, funkcje StoreKit nie będą działać.

Metoda ReceivedResponse w przykładowym kodzie zwraca nieprawidłowe produkty do konsoli:

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

Wyświetlanie zlokalizowanych cen

Warstwy cenowe określają określoną cenę dla każdego produktu we wszystkich międzynarodowych sklepach App Store. Aby upewnić się, że ceny są wyświetlane poprawnie dla każdej waluty, użyj następującej metody rozszerzenia (zdefiniowanej w pliku SKProductExtension.cs) zamiast właściwości Price każdego SKProductelementu :

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;
   }
}

Kod ustawiający tytuł przycisku używa metody rozszerzenia w następujący sposób:

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

Użycie dwóch różnych kont testowych iTunes (jeden dla amerykańskiego sklepu i jeden dla japońskiego sklepu) powoduje wykonanie następujących zrzutów ekranu:

Dwa różne konta testowe iTunes pokazujące wyniki specyficzne dla języka

Zwróć uwagę, że sklep ma wpływ na język używany na potrzeby informacji o produkcie i walucie cen, podczas gdy ustawienie języka urządzenia wpływa na etykiety i inną zlokalizowaną zawartość.

Pamiętaj, że aby użyć innego konta testowego sklepu, musisz wylogować się w Ustawienia > iTunes i App Store i ponownie uruchomić aplikację, aby zalogować się przy użyciu innego konta. Aby zmienić język urządzenia, przejdź do Ustawienia > Ogólne > języki międzynarodowe>.