Nákup spotřebních produktů v Xamarin.iOS

Spotřební produkty jsou nejjednodušší implementovat, protože neexistuje žádný požadavek na obnovení. Jsou užitečné pro produkty, jako je měna v hře nebo jedno použití funkce. Uživatelé si můžou znovu koupit spotřební produkty znovu a znovu.

Integrované doručování produktů

Vzorový kód, který tento dokument doprovází, ukazuje předdefinované produkty – ID produktů jsou pevně zakódovaná do aplikace, protože jsou úzce svázané s kódem, který funkci po zaplacení "odemkne". Proces nákupu lze vizualizovat takto:

Vizualizace nákupního procesu

Základní pracovní postup je:

  1. Aplikace přidá do SKPayment fronty. V případě potřeby se uživateli zobrazí výzva k zadání Apple ID a zobrazí se výzva k potvrzení platby.

  2. StoreKit odešle požadavek na server ke zpracování.

  3. Po dokončení transakce server odpoví účtem transakce.

  4. Podtřída SKPaymentTransactionObserver obdrží potvrzení a zpracuje ji.

  5. Aplikace povolí produkt (aktualizací NSUserDefaults nebo jiným mechanismem) a potom zavolá StoreKit FinishTransaction.

Existuje jiný typ pracovního postupu – Produkty doručené serverem – které jsou popsány dále v dokumentu (viz část Ověření příjmu a Produkty doručené serverem).

Příklad spotřebních produktů

Ukázka obsahuje projekt s názvem Spotřební materiál , který implementuje základní "herní měnu" (označovanou jako "opice kredity"). Ukázka ukazuje, jak implementovat dva produkty nákupu v aplikaci, aby si uživatel mohl koupit tolik "opičích kreditů", kolik si přeje – ve skutečné aplikaci by také nějaký způsob, jak je utratit!

Aplikace se zobrazí na těchto snímcích obrazovky – každý nákup přidá do zůstatku uživatele další kredity opice:

Každý nákup přidá do zůstatku uživatelů další kredity opice.

Interakce mezi vlastními třídami, StoreKitem a App Storem vypadají takto:

Interakce mezi vlastními třídami, StoreKitem a App Storem

Metody ViewController

Kromě vlastností a metod potřebných k načtení informací o produktu vyžaduje kontroler zobrazení k naslouchání oznámením souvisejícím s nákupem další pozorovatelé oznámení. Jedná se pouze NSObjects o to, že se zaregistrují a odeberou a ViewWillAppearViewWillDisappear v uvedeném pořadí.

NSObject succeededObserver, failedObserver;

Konstruktor vytvoří také podtřídu SKProductsRequestDelegate ( InAppPurchaseManager), která zase vytvoří a zaregistruje SKPaymentTransactionObserver ( CustomPaymentObserver).

První částí zpracování transakce nákupu v aplikaci je zpracovat tlačítko stisknout, když si uživatel přeje něco koupit, jak je znázorněno v následujícím kódu z ukázkové aplikace:

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

Druhá část uživatelského rozhraní zpracovává oznámení, že transakce byla úspěšná, v tomto případě aktualizací zobrazeného zůstatku:

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

Poslední část uživatelského rozhraní zobrazuje zprávu, pokud je transakce zrušena z nějakého důvodu. V ukázkovém kódu se zpráva jednoduše zapíše do okna výstupu:

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

Kromě těchto metod na kontroleru zobrazení, spotřební transakce nákupu produktu také vyžaduje kód na SKProductsRequestDelegate straně a SKPaymentTransactionObserver.

InAppPurchaseManager – metody

Ukázkový kód implementuje řadu metod souvisejících s nákupem ve třídě InAppPurchaseManager, včetně PurchaseProduct metody, která vytvoří SKPayment instanci a přidá ji do fronty ke zpracování:

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

Přidání platby do fronty je asynchronní operace. Aplikace znovu získá kontrolu, zatímco StoreKit zpracuje transakci a odešle ji na servery Společnosti Apple. V tomto okamžiku se v iOSu ověří, že je uživatel přihlášený do App Storu, a v případě potřeby ji vyzve k zadání Apple ID a hesla.

Za předpokladu, že se uživatel úspěšně ověří v App Storu a souhlasí s transakcí, SKPaymentTransactionObserver obdrží odpověď StoreKitu a zavolá následující metodu pro splnění transakce a dokončení transakce.

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

Posledním krokem je zajistit, abyste storeKit informovali, že jste úspěšně splnili transakci voláním 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);
       }
   }
}

Jakmile se produkt doručí, musí být volán, SKPaymentQueue.DefaultQueue.FinishTransaction aby se transakce odebrala z platební fronty.

Metody SKPaymentTransactionObserver (CustomPaymentObserver)

StoreKit volá metodu UpdatedTransactions , když obdrží odpověď ze serverů Společnosti Apple a předá pole SKPaymentTransaction objektů, aby váš kód zkontroloval. Metoda prochází každou transakci a provádí jinou funkci na základě stavu transakce (jak je znázorněno zde):

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 byla popsána dříve v této části – uloží podrobnosti o nákupu do NSUserDefaults, finalizuje transakci pomocí StoreKitu a nakonec oznámí uživatelskému rozhraní, aby se aktualizovalo.

Nákup více produktů

Pokud v aplikaci dává smysl nakupovat více produktů, použijte SKMutablePayment třídu a nastavte pole Množství:

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

Kód, který zpracovává dokončenou transakci, musí také dotazovat vlastnost Quantity, aby správně splnil nákup:

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

Když si uživatel koupí více množství, zobrazí se v potvrzovací výstraze StoreKitu množství, jednotková cena a celková cena, na kterou se budou účtovat, jak je znázorněno na následujícím snímku obrazovky:

Potvrzení nákupu

Zpracování výpadků sítě

Nákupy v aplikaci vyžadují funkční síťové připojení pro StoreKit ke komunikaci se servery Apple. Pokud síťové připojení není dostupné, nákup v aplikaci nebude dostupný.

Žádosti o produkty

Pokud síť není při vytváření , SKProductRequestRequestFailed metoda SKProductsRequestDelegate podtřídy ( InAppPurchaseManager) bude volána, jak je znázorněno níže:

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

ViewController pak naslouchá oznámení a zobrazí zprávu v nákupních tlačítkách:

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

Vzhledem k tomu, že síťové připojení může být na mobilních zařízeních přechodné, můžou aplikace chtít monitorovat stav sítě pomocí architektury SystemConfiguration a znovu zkusit, když je síťové připojení k dispozici. Podívejte se na apple nebo na to, co ho používá.

Nákupní transakce

Pokud je to možné, platební fronta StoreKitu bude ukládat a předávat žádosti o nákupy, takže účinek výpadku sítě se bude lišit v závislosti na tom, kdy síť během procesu nákupu selhala.

Pokud dojde k chybě během transakce, SKPaymentTransactionObserver podtřída ( CustomPaymentObserver) bude mít UpdatedTransactions volána metodu a SKPaymentTransaction třída bude ve stavu selhání.

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 zjistí, jestli byla chyba způsobená zrušením uživatele, jak je znázorněno tady:

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

I když transakce selže, FinishTransaction musí být volána metoda pro odebrání transakce z platební fronty:

SKPaymentQueue.DefaultQueue.FinishTransaction(transaction);

Ukázkový kód pak odešle oznámení, aby ViewController mohl zobrazit zprávu. Aplikace by neměly zobrazit další zprávu, pokud uživatel zrušil transakci. Mezi další kódy chyb, ke kterým může dojít, patří:

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.

Omezení zpracování

Funkce Nastavení > Obecná > omezení v iOSu umožňuje uživatelům uzamknout určité funkce svého zařízení.

Pomocí této metody můžete zadat dotaz, jestli má uživatel povoleno provádět nákupy SKPaymentQueue.CanMakePayments v aplikaci. Pokud se vrátí hodnota false, nemůže uživatel získat přístup k nákupu v aplikaci. StoreKit uživateli při pokusu o nákup automaticky zobrazí chybovou zprávu. Zaškrtnutím této hodnoty může aplikace místo toho skrýt tlačítka nákupu nebo provést nějakou jinou akci, která uživateli pomůže.

InAppPurchaseManager.cs V souboru CanMakePayments metoda zabalí funkci StoreKit takto:

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

Pokud chcete tuto metodu otestovat, pomocí funkce Omezení v iOSu zakažte nákupy v aplikaci:

Zakázání nákupů v aplikaci pomocí funkce Omezení v iOSu

Tento ukázkový kód z ConsumableViewController reakce na CanMakePayments vrácení nepravda zobrazením zakázaného textu AppStore na zakázaných tlačítkách.

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

Aplikace vypadá takto, když je funkce Nákupy v aplikaci omezená – tlačítka nákupu jsou zakázaná.

Aplikace vypadá takto, když je funkce Nákupy v aplikaci omezená, jsou tlačítka nákupu zakázaná.

Informace o produktu se dají vyžádat, i když CanMakePayments jsou nepravdivé, aby aplikace stále načítala a zobrazovala ceny. To znamená, že pokud jsme odebrali CanMakePayments kontrolu z kódu, tlačítka nákupu by stále byla aktivní, ale při pokusu o nákup se uživateli zobrazí zpráva, že nákupy v aplikaci nejsou povolené (vygeneruje StoreKit při přístupu do platební fronty):

Nákupy v aplikaci nejsou povolené.

Aplikace z reálného světa můžou použít jiný přístup ke zpracování omezení, například úplné skrytí tlačítek a možná nabízejí podrobnější zprávu než upozornění, které StoreKit zobrazuje automaticky.