Vue d’ensemble de StoreKit et récupération des informations sur le produit dans Xamarin.iOS
L’interface utilisateur d’un achat dans l’application s’affiche dans les captures d’écran ci-dessous. Avant toute transaction, l’application doit récupérer le prix et la description du produit pour l’affichage. Ensuite, lorsque l’utilisateur appuie sur Acheter, l’application envoie une demande au StoreKit qui gère la boîte de dialogue de confirmation et la connexion d’ID Apple. En supposant que la transaction réussit, StoreKit informe le code de l’application, qui doit stocker le résultat de la transaction et fournir à l’utilisateur l’accès à son achat.
Classes
L’implémentation d’achats dans l’application nécessite les classes suivantes à partir de l’infrastructure StoreKit :
SKProductsRequest : demande à StoreKit pour les produits approuvés à vendre (App Store). Peut être configuré avec un certain nombre d’ID de produit.
- SKProductsRequestDelegate : déclare des méthodes pour gérer les demandes et réponses du produit.
- SKProductsResponse : renvoyé au délégué à partir du StoreKit (App Store). Contient les skProducts qui correspondent aux ID de produit envoyés avec la demande.
- SKProduct : produit récupéré à partir de StoreKit (que vous avez configuré dans iTunes Connecter). Contient des informations sur le produit, telles que l’ID de produit, le titre, la description et le prix.
- SKPayment : créé avec un ID de produit et ajouté à la file d’attente de paiement pour effectuer un achat.
- SKPaymentQueue – Demandes de paiement mises en file d’attente à envoyer à Apple. Les notifications sont déclenchées suite au traitement de chaque paiement.
- SKPaymentTransaction : représente une transaction terminée (une demande d’achat qui a été traitée par l’App Store et renvoyée à votre application via StoreKit). La transaction peut être achetée, restaurée ou ayant échoué.
- SKPaymentTransactionObserver : sous-classe personnalisée qui répond aux événements générés par la file d’attente de paiement StoreKit.
- Les opérations StoreKit sont asynchrones : une fois qu’une référence SKProductRequest est démarrée ou qu’une référence SKPayment est ajoutée à la file d’attente, le contrôle est retourné à votre code. StoreKit appelle des méthodes sur votre sous-classe SKProductsRequestDelegate ou SKPaymentTransactionObserver lorsqu’il reçoit des données des serveurs d’Apple.
Le diagramme suivant montre les relations entre les différentes classes StoreKit (les classes abstraites doivent être implémentées dans votre application) :
Ces classes sont expliquées plus en détail plus loin dans ce document.
Test
La plupart des opérations StoreKit nécessitent un appareil réel pour les tests. La récupération des informations sur le produit (par exemple, prix et description) fonctionne dans le simulateur, mais les opérations d’achat et de restauration retournent une erreur (par exemple, FailedTransaction Code=5002 Une erreur inconnue s’est produite).
Remarque : StoreKit ne fonctionne pas dans le simulateur iOS. Lors de l’exécution de votre application dans iOS Simulator, StoreKit enregistre un avertissement si votre application tente de récupérer la file d’attente de paiement. Le test du magasin doit être effectué sur les appareils réels.
Important : Ne vous connectez pas avec votre compte de test dans l’application Paramètres. Vous pouvez utiliser l’application Paramètres pour vous déconnecter de n’importe quel compte d’ID Apple existant. Vous devez attendre d’être invité dans votre séquence d’achat dans l’application pour vous connecter à l’aide d’un ID Apple de test.
Si vous tentez de vous connecter au magasin réel avec un compte de test, il est automatiquement converti en un véritable ID Apple. Ce compte ne sera plus utilisable pour les tests.
Pour tester le code StoreKit, vous devez vous déconnecter de votre compte de test iTunes standard et vous connecter avec un compte de test spécial (créé dans iTunes Connecter) lié au magasin de tests. Pour vous déconnecter du compte actuel, visitez Paramètres > iTunes et App Store comme indiqué ici :
connectez-vous avec un compte de test lorsque vous avez demandé par StoreKit au sein de votre application :
Pour créer des utilisateurs de test dans iTunes Connecter cliquez sur Utilisateurs et rôles sur la page principale.
Sélectionner des testeurs de bac à sable
La liste des utilisateurs existants s’affiche. Vous pouvez ajouter un nouvel utilisateur ou supprimer un enregistrement existant. Le portail ne vous permet pas (actuellement) d’afficher ou de modifier les utilisateurs de test existants. Il est donc recommandé de conserver un bon enregistrement de chaque utilisateur de test créé (en particulier le mot de passe que vous attribuez). Une fois que vous avez supprimé un utilisateur de test, l’adresse e-mail ne peut pas être réutilisée pour un autre compte de test.
Les nouveaux utilisateurs de test ont des attributs similaires à un id Apple réel (par exemple, nom, mot de passe, question secrète et réponse). Conservez un enregistrement de tous les détails entrés ici. Le champ Sélectionner iTunes Store détermine la devise et la langue que les achats dans l’application utiliseront lors de la connexion en tant qu’utilisateur.
Récupération des informations sur le produit
La première étape de la vente d’un produit d’achat dans l’application s’affiche : récupérer le prix actuel et la description de l’App Store pour l’affichage.
Quel que soit le type de produits qu’une application vend (consommable, non consommable ou type d’abonnement), le processus de récupération des informations sur les produits à afficher est le même. Le code InAppPurchaseSample qui accompagne cet article contient un projet nommé Consommables qui montre comment récupérer des informations de production à afficher. Il montre comment :
- Créez une implémentation et
SKProductsRequestDelegate
implémentez laReceivedResponse
méthode abstraite. L’exemple de code appelle cetteInAppPurchaseManager
classe. - Vérifiez avec StoreKit pour déterminer si les paiements sont autorisés (à l’aide
SKPaymentQueue.CanMakePayments
de ). - Instanciez un
SKProductsRequest
id de produit défini dans iTunes Connecter. Cette opération est effectuée dans la méthode de l’exempleInAppPurchaseManager.RequestProductData
. - Appelez la méthode Start sur le
SKProductsRequest
. Cela déclenche un appel asynchrone aux serveurs App Store. Le délégué (InAppPurchaseManager
) sera rappelé avec les résultats. - La méthode du délégué met
InAppPurchaseManager
ReceivedResponse
à jour l’interface utilisateur avec les données retournées par l’App Store (prix du produit et descriptions, ou messages sur les produits non valides).
L’interaction globale ressemble à ceci ( StoreKit est intégré à iOS et l’App Store représente les serveurs d’Apple) :
Affichage de l’exemple d’informations sur le produit
L’exemple de code Consommables montre comment les informations sur le produit peuvent être récupérées. L’écran principal de l’exemple affiche des informations pour deux produits récupérés à partir de l’App Store :
L’exemple de code permettant de récupérer et d’afficher des informations sur le produit est expliqué plus en détail ci-dessous.
ViewController, méthodes
La ConsumableViewController
classe gérera l’affichage des prix pour deux produits dont les ID de produit sont codés en dur dans la classe.
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();
}
Au niveau de la classe, il doit également y avoir un NSObject déclaré qui sera utilisé pour configurer un NSNotificationCenter
observateur :
NSObject priceObserver;
Dans la méthode ViewWillAppear, l’observateur est créé et affecté à l’aide du centre de notification par défaut :
priceObserver = NSNotificationCenter.DefaultCenter.AddObserver (
InAppPurchaseManager.InAppPurchaseManagerProductsFetchedNotification,
(notification) => {
// display code goes here, to handle the response from the App Store
}
À la fin de la ViewWillAppear
méthode, appelez la RequestProductData
méthode pour lancer la requête StoreKit. Une fois cette demande effectuée, StoreKit contacte de manière asynchrone les serveurs d’Apple pour obtenir les informations et les alimenter dans votre application. Cette opération est obtenue par la SKProductsRequestDelegate
sous-classe ( InAppPurchaseManager
) qui est expliquée dans la section suivante.
iap.RequestProductData(products);
Le code permettant d’afficher le prix et la description récupère simplement les informations du SKProduct et l’affecte aux contrôles UIKit (notez que nous affichons et LocalizedTitle
LocalizedDescription
– StoreKit résout automatiquement le texte et les prix corrects en fonction des paramètres du compte de l’utilisateur). Le code suivant appartient à la notification que nous avons créée ci-dessus :
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
}
}
Enfin, la ViewWillDisappear
méthode doit s’assurer que l’observateur est supprimé :
NSNotificationCenter.DefaultCenter.RemoveObserver (priceObserver);
SkProductRequestDelegate (InAppPurchaseManager), méthodes
La RequestProductData
méthode est appelée lorsque l’application souhaite récupérer les prix du produit et d’autres informations. Il analyse la collection d’ID de produit dans le type de données correct, puis crée une SKProductsRequest
information avec ces informations. L’appel de la méthode Start entraîne l’envoi d’une requête réseau aux serveurs d’Apple. La requête s’exécute de manière asynchrone et appelle la ReceivedResponse
méthode du délégué une fois terminée.
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 acheminera automatiquement la requête vers la version « bac à sable » ou « production » de l’App Store en fonction du profil d’approvisionnement avec lequel l’application s’exécute. Par conséquent, lorsque vous développez ou testez votre application, la demande aura accès à chaque produit configuré dans iTunes Connecter (même ceux qui n’ont pas encore été soumis ou approuvés par Apple). Lorsque votre application est en production, les demandes StoreKit retournent uniquement des informations pour les produits approuvés .
La ReceivedResponse
méthode substituée est appelée une fois que les serveurs d’Apple ont répondu avec des données. Comme cela est appelé en arrière-plan, le code doit analyser les données valides et utiliser une notification pour envoyer les informations de produit à tous les ViewControllers qui « écoutent » pour cette notification. Le code permettant de collecter des informations de produit valides et d’envoyer une notification est illustré ci-dessous :
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);
}
Bien qu’elle ne soit pas affichée dans le diagramme, la RequestFailed
méthode doit également être substituée afin que vous puissiez fournir des commentaires à l’utilisateur au cas où les serveurs App Store ne sont pas accessibles (ou une autre erreur se produit). L’exemple de code écrit simplement dans la console, mais une application réelle peut choisir d’interroger sur error.Code
la propriété et d’implémenter un comportement personnalisé (par exemple, une alerte à l’utilisateur).
public override void RequestFailed (SKRequest request, NSError error)
{
Console.WriteLine (" ** InAppPurchaseManager RequestFailed() " + error.LocalizedDescription);
}
Cette capture d’écran montre l’exemple d’application immédiatement après le chargement (quand aucune information sur le produit n’est disponible) :
Produits non valides
Un SKProductsRequest
peut également renvoyer une liste d’ID de produit non valides. Les produits non valides sont généralement retournés en raison de l’une des opérations suivantes :
ID de produit mal typé : seuls les ID de produit valides sont acceptés.
Le produit n’a pas été approuvé : lors du test, tous les produits qui sont effacés pour la vente doivent être retournés par un SKProductsRequest
; toutefois, en production, seuls les produits approuvés sont retournés.
L’ID d’application n’est pas explicite : les ID d’application wild carte (avec un astérisque) n’autorisent pas l’achat dans l’application.
Profil d’approvisionnement incorrect : si vous apportez des modifications à la configuration de votre application dans le portail d’approvisionnement (par exemple, l’activation des achats dans l’application), n’oubliez pas de générer et d’utiliser le profil d’approvisionnement correct lors de la génération de l’application.
Le contrat Applications payantes iOS n’est pas en place : les fonctionnalités storeKit ne fonctionnent pas du tout, sauf s’il existe un contrat valide pour votre compte de développeur Apple.
Le fichier binaire est dans l’état Rejeté : s’il existe un fichier binaire précédemment envoyé dans l’état Rejeté (par l’équipe App Store ou par le développeur), les fonctionnalités StoreKit ne fonctionneront pas.
La ReceivedResponse
méthode de l’exemple de code génère les produits non valides dans la console :
public override void ReceivedResponse (SKProductsRequest request, SKProductsResponse response)
{
// code removed for clarity
foreach (string invalidProductId in response.InvalidProducts) {
Console.WriteLine("Invalid product id: " + invalidProductId );
}
}
Affichage des prix localisés
Les niveaux de prix spécifient un prix spécifique pour chaque produit dans tous les Magasins d’applications internationaux. Pour vous assurer que les prix sont affichés correctement pour chaque devise, utilisez la méthode d’extension suivante (définie dans SKProductExtension.cs
) plutôt que la propriété Price de chaque SKProduct
:
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;
}
}
Le code qui définit le titre du bouton utilise la méthode d’extension comme suit :
string Buy = "Buy {0}"; // or a localizable string
buy5Button.SetTitle(String.Format(Buy, product.LocalizedPrice()), UIControlState.Normal);
L’utilisation de deux comptes de test iTunes différents (un pour le magasin américain et un pour le magasin japonais) entraîne les captures d’écran suivantes :
Notez que le magasin affecte la langue utilisée pour les informations sur le produit et la devise du prix, tandis que le paramètre de langue de l’appareil affecte les étiquettes et d’autres contenus localisés.
Rappelez-vous que pour utiliser un autre compte de test store, vous devez vous déconnecter dans le Paramètres > iTunes et App Store et redémarrer l’application pour vous connecter avec un autre compte. Pour modifier la langue de l’appareil, accédez à Paramètres > langue internationale > générale>.