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:
Podstawowy przepływ pracy to:
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.StoreKit wysyła żądanie do serwera w celu przetworzenia.
Po zakończeniu transakcji serwer odpowiada potwierdzeniem transakcji.
Podklasa
SKPaymentTransactionObserver
odbiera potwierdzenie i przetwarza je.Aplikacja włącza produkt (przez aktualizację
NSUserDefaults
lub inny mechanizm), a następnie wywołuje bibliotekęFinishTransaction
StoreKit .
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:
Interakcje między klasami niestandardowymi, StoreKit i App Store wyglądają następująco:
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 NSUserDefaults
pliku , 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:
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 SKProductRequest
klasy , 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:
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.
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):
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.