Udostępnij za pośrednictwem


Kupowanie produktów eksploatacyjnych na platformie Xamarin.iOS

Produkty eksploatacyjne są najprostsze do zaimplementowania, ponieważ nie ma wymagania "przywracania". Są one przydatne w przypadku produktów, takich jak waluta w grze lub pojedynczy element funkcjonalności. Użytkownicy mogą ponownie zakupić produkty eksploatacyjne ponownie.

Dostarczanie wbudowanych produktów

Przykładowy kod towarzyszący temu dokumentowi pokazuje wbudowane produkty — identyfikatory produktów są zakodowane w aplikacji, ponieważ są ściśle powiązane z kodem, który "odblokowuje" funkcję po płatności. Proces zakupu można zwizualizować w następujący sposób:

Wizualizacja procesu zakupu

Podstawowy przepływ pracy to:

  1. Aplikacja dodaje element SKPayment do kolejki. Jeśli jest to wymagane, zostanie wyświetlony monit o podanie identyfikatora Apple ID i prośba o potwierdzenie płatności.

  2. StoreKit wysyła żądanie do serwera w celu przetworzenia.

  3. Po zakończeniu transakcji serwer odpowiada potwierdzeniem transakcji.

  4. Podklasa SKPaymentTransactionObserver odbiera potwierdzenie i przetwarza je.

  5. Aplikacja włącza produkt (przez aktualizację NSUserDefaults lub inny mechanizm), a następnie wywołuje bibliotekę FinishTransactionStoreKit .

Istnieje inny typ przepływu pracy — Produkty dostarczane przez serwer — omówiony w dalszej części dokumentu (zobacz sekcję Weryfikacja paragonu i Produkty dostarczane przez serwer).

Przykład produktów eksploatacyjnych

Przykład zawiera projekt o nazwie Eksploatacyjne, który implementuje podstawową "walutę w grze" (zwaną "kredytami małpy"). W przykładzie pokazano, jak zaimplementować dwa produkty zakupu w aplikacji, aby umożliwić użytkownikowi zakup jak najwięcej "środków małpy", jak chcą — w prawdziwej aplikacji będzie również jakiś sposób ich wydawania!

Aplikacja jest wyświetlana na tych zrzutach ekranu — każdy zakup dodaje więcej "środków małpy" do salda użytkownika:

Każdy zakup dodaje więcej środków małpy do salda użytkowników

Interakcje między klasami niestandardowymi, StoreKit i App Store wyglądają następująco:

Interakcje między klasami niestandardowymi, StoreKit i App Store

ViewController, metody

Oprócz właściwości i metod wymaganych do pobrania informacji o produkcie kontroler widoku wymaga dodatkowych obserwatorów powiadomień, aby nasłuchiwać powiadomień związanych z zakupem. Są to tylko NSObjects te, które zostaną zarejestrowane i usunięte odpowiednio w ViewWillAppear i ViewWillDisappear .

NSObject succeededObserver, failedObserver;

Konstruktor utworzy również podklasę SKProductsRequestDelegate ( InAppPurchaseManager), która z kolei tworzy i rejestruje SKPaymentTransactionObserver element ( CustomPaymentObserver).

Pierwszą częścią przetwarzania transakcji zakupu w aplikacji jest obsługa naciśnięcia przycisku, gdy użytkownik chce coś kupić, jak pokazano w poniższym kodzie z przykładowej aplikacji:

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

Druga część interfejsu użytkownika obsługuje powiadomienie o pomyślnym zakończeniu transakcji, w tym przypadku przez zaktualizowanie wyświetlanego salda:

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

Ostatnia część interfejsu użytkownika wyświetla komunikat, jeśli transakcja zostanie anulowana z jakiegoś powodu. W przykładowym kodzie komunikat jest po prostu zapisywany w oknie danych wyjściowych:

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

Oprócz tych metod na kontrolerze widoku, transakcja zakupu produktu eksploatacyjnego wymaga również kodu na SKProductsRequestDelegate i SKPaymentTransactionObserver.

InAppPurchaseManager, metody

Przykładowy kod implementuje szereg metod związanych z zakupem w klasie InAppPurchaseManager, w tym PurchaseProduct metodę tworzącą SKPayment wystąpienie i dodaje ją do kolejki do przetwarzania:

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

Dodawanie płatności do kolejki jest operacją asynchroniczną. Aplikacja odzyskuje kontrolę, gdy StoreKit przetwarza transakcję i wysyła ją do serwerów firmy Apple. W tym momencie system iOS sprawdzi, czy użytkownik jest zalogowany w sklepie App Store i monituje o podanie identyfikatora Apple ID i hasła, jeśli jest to wymagane.

Zakładając, że użytkownik pomyślnie uwierzytelnia się w sklepie App Store i zgadza się na transakcję, SKPaymentTransactionObserver otrzyma odpowiedź StoreKit i wywoła następującą metodę, aby zrealizować transakcję i sfinalizować ją.

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

Ostatnim krokiem jest upewnienie się, że powiadomisz zestaw StoreKit o pomyślnym spełnieniu transakcji, wywołując polecenie 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);
       }
   }
}

Po dostarczeniu produktu należy wywołać metodę , SKPaymentQueue.DefaultQueue.FinishTransaction aby usunąć transakcję z kolejki płatności.

METODY SKPaymentTransactionObserver (CustomPaymentObserver)

StoreKit wywołuje UpdatedTransactions metodę, gdy odbiera odpowiedź z serwerów firmy Apple i przekazuje tablicę SKPaymentTransaction obiektów dla kodu w celu sprawdzenia. Metoda wykonuje pętlę przez każdą transakcję i wykonuje inną funkcję na podstawie stanu transakcji (jak pokazano tutaj):

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

Metoda CompleteTransaction została omówiona wcześniej w tej sekcji — zapisuje szczegóły zakupu w NSUserDefaultspliku , finalizuje transakcję za pomocą zestawu StoreKit, a na koniec powiadamia interfejs użytkownika o aktualizacji.

Kupowanie wielu produktów

Jeśli w aplikacji warto kupić wiele produktów, użyj SKMutablePayment klasy i ustaw pole Quantity:

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

Kod obsługujący ukończoną transakcję musi również wysłać zapytanie do właściwości Quantity, aby poprawnie zrealizować zakup:

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

Gdy użytkownik kupuje wiele ilości, alert potwierdzenia StoreKit będzie odzwierciedlać ilość, cenę jednostkową i łączną cenę, którą zostaną naliczone, jak pokazano na poniższym zrzucie ekranu:

Potwierdzanie zakupu

Obsługa awarii sieci

Zakupy w aplikacji wymagają działającego połączenia sieciowego dla sklepu StoreKit w celu komunikowania się z serwerami firmy Apple. Jeśli połączenie sieciowe jest niedostępne, zakup w aplikacji będzie niedostępny.

Żądania produktów

Jeśli sieć jest niedostępna podczas tworzenia SKProductRequestklasy , RequestFailed metoda SKProductsRequestDelegate podklasy ( InAppPurchaseManager) zostanie wywołana, jak pokazano poniżej:

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

Kontrolka ViewController nasłuchuje powiadomienia i wyświetla komunikat w przyciskach zakupu:

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

Ponieważ połączenie sieciowe może być przejściowe na urządzeniach przenośnych, aplikacje mogą chcieć monitorować stan sieci przy użyciu struktury SystemConfiguration i spróbować ponownie, gdy jest dostępne połączenie sieciowe. Zapoznaj się z elementami firmy Apple lub używanymi przez nią.

Transakcje zakupu

Kolejka płatności StoreKit będzie przechowywać i przekazywać żądania zakupu, jeśli to możliwe, więc wpływ awarii sieci będzie się różnić w zależności od tego, kiedy sieć nie powiodła się podczas procesu zakupu.

Jeśli podczas transakcji wystąpi błąd, SKPaymentTransactionObserver podklasa ( CustomPaymentObserver) będzie miała UpdatedTransactions wywołaną metodę, a SKPaymentTransaction klasa będzie w stanie Niepowodzenie.

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

Metoda FailedTransaction wykrywa, czy błąd był spowodowany anulowaniem użytkownika, jak pokazano poniżej:

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

Nawet jeśli transakcja nie powiedzie się, należy wywołać metodę , FinishTransaction aby usunąć transakcję z kolejki płatności:

SKPaymentQueue.DefaultQueue.FinishTransaction(transaction);

Przykładowy kod wysyła następnie powiadomienie, aby element ViewController mógł wyświetlić komunikat. Aplikacje nie powinny wyświetlać dodatkowego komunikatu, jeśli użytkownik anulował transakcję. Inne kody błędów, które mogą wystąpić, to:

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.

Ograniczenia obsługi

Funkcja Ustawienia > Ogólne > ograniczenia systemu iOS umożliwia użytkownikom blokowanie niektórych funkcji urządzenia.

Możesz zapytać, czy użytkownik może dokonać zakupów w aplikacji za pomocą SKPaymentQueue.CanMakePayments metody . Jeśli zwraca wartość false, użytkownik nie może uzyskać dostępu do zakupu w aplikacji. Zestaw StoreKit automatycznie wyświetli użytkownikowi komunikat o błędzie, jeśli zostanie podjęta próba zakupu. Sprawdzając tę wartość, aplikacja może zamiast tego ukryć przyciski zakupu lub wykonać inną akcję, aby pomóc użytkownikowi.

InAppPurchaseManager.cs W pliku CanMakePayments metoda opakowuje funkcję StoreKit w następujący sposób:

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

Aby przetestować tę metodę, użyj funkcji Ograniczenia systemu iOS, aby wyłączyć zakupy w aplikacji:

Użyj funkcji Ograniczenia systemu iOS, aby wyłączyć zakupy w aplikacji

Ten przykładowy kod z ConsumableViewController odpowiedzi na CanMakePayments zwracanie wartości false przez wyświetlenie tekstu wyłączonego sklepu AppStore na wyłączonych przyciskach.

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

Aplikacja wygląda następująco, gdy funkcja Zakupów w aplikacji jest ograniczona — przyciski zakupu są wyłączone.

Aplikacja wygląda następująco, gdy funkcja Zakupów w aplikacji jest ograniczona, przyciski zakupu są wyłączone

Informacje o produkcie mogą być nadal wymagane, gdy CanMakePayments wartość jest fałszem, więc aplikacja nadal może pobierać i wyświetlać ceny. Oznacza to, że jeśli usunęliśmy CanMakePayments kontrolę z kodu, przyciski zakupu będą nadal aktywne, jednak po podjęciu próby zakupu użytkownik zobaczy komunikat, że zakupy w aplikacji nie są dozwolone (generowane przez StoreKit po dokonaniu dostępu do kolejki płatności):

Zakupy w aplikacji są niedozwolone

Rzeczywiste aplikacje mogą podjąć inne podejście do obsługi ograniczenia, takie jak całkowite ukrywanie przycisków i być może oferowanie bardziej szczegółowego komunikatu niż alert wyświetlany automatycznie przez zestaw StoreKit.