Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
par Erik Reitan
Télécharger l’exemple de projet Wingtip Toys (C#) ou télécharger le livre électronique (PDF)
Cette série de tutoriels vous apprend les principes de base de la création d’une application Web Forms ASP.NET à l’aide de ASP.NET 4.5 et de Microsoft Visual Studio Express 2013 pour le web. Un projet Visual Studio 2013 avec du code source C# est disponible pour accompagner cette série de tutoriels.
Ce tutoriel explique comment modifier l’exemple d’application Wingtip Toys pour inclure l’autorisation utilisateur, l’inscription et le paiement à l’aide de PayPal. Seuls les utilisateurs connectés auront l’autorisation d’acheter des produits. La fonctionnalité d’inscription utilisateur intégrée du modèle de projet Web Forms ASP.NET 4.5 inclut déjà une grande partie de ce dont vous avez besoin. Vous allez ajouter la fonctionnalité Express Checkout de PayPal. Dans ce tutoriel, vous utilisez l’environnement de test PayPal développeur, donc aucun fonds réel ne sera transféré. À la fin du tutoriel, vous allez tester l’application en sélectionnant les produits à ajouter au panier d’achat, en cliquant sur le bouton de caisse et en transférant les données vers le site web de test PayPal. Sur le site de test PayPal, vous allez confirmer vos informations d’expédition et de paiement, puis revenir à l'application de démonstration locale de Wingtip Toys pour confirmer et terminer l'achat.
Il existe plusieurs processeurs de paiement tiers expérimentés qui se spécialisent dans les achats en ligne qui traitent de l’extensibilité et de la sécurité. Les développeurs ASP.NET doivent prendre en compte les avantages de l’utilisation d’une solution de paiement tierce avant d’implémenter une solution de shopping et d'achat.
Note
L’exemple d’application Wingtip Toys a été conçu pour montrer des concepts et fonctionnalités spécifiques ASP.NET disponibles pour ASP.NET développeurs web. Cet exemple d’application n’a pas été optimisé pour toutes les circonstances possibles en ce qui concerne l’extensibilité et la sécurité.
Ce que vous allez apprendre :
- Comment restreindre l’accès à des pages spécifiques dans un dossier.
- Comment créer un panier d’achat connu à partir d’un panier d’achat anonyme.
- Comment activer SSL pour le projet.
- Comment ajouter un fournisseur OAuth au projet.
- Comment utiliser PayPal pour acheter des produits à l’aide de l’environnement de test PayPal.
- Comment afficher les détails de PayPal dans un contrôle DetailsView .
- Comment mettre à jour la base de données de l’application Wingtip Toys avec les détails obtenus à partir de PayPal.
Ajout du suivi des commandes
Dans ce tutoriel, vous allez créer deux nouvelles classes pour suivre les données de la commande qu'un utilisateur a passée. Les classes effectuent le suivi des données relatives aux informations d’expédition, au total de l’achat et à la confirmation de paiement.
Ajouter les classes de modèle Order et OrderDetail
Plus tôt dans cette série de tutoriels, vous avez défini le schéma pour les catégories, les produits et les articles du panier en créant les classes Category, Product, et CartItem dans le dossier Models. Vous allez maintenant ajouter deux nouvelles classes pour définir le schéma de la commande de produit et les détails de la commande.
Dans le dossier Models , ajoutez une nouvelle classe nommée Order.cs.
Le nouveau fichier de classe s’affiche dans l’éditeur.Remplacez le code par défaut par les éléments suivants :
using System; using System.ComponentModel.DataAnnotations; using System.Collections.Generic; using System.ComponentModel; namespace WingtipToys.Models { public class Order { public int OrderId { get; set; } public DateTime OrderDate { get; set; } public string Username { get; set; } [Required(ErrorMessage = "First Name is required")] [DisplayName("First Name")] [StringLength(160)] public string FirstName { get; set; } [Required(ErrorMessage = "Last Name is required")] [DisplayName("Last Name")] [StringLength(160)] public string LastName { get; set; } [Required(ErrorMessage = "Address is required")] [StringLength(70)] public string Address { get; set; } [Required(ErrorMessage = "City is required")] [StringLength(40)] public string City { get; set; } [Required(ErrorMessage = "State is required")] [StringLength(40)] public string State { get; set; } [Required(ErrorMessage = "Postal Code is required")] [DisplayName("Postal Code")] [StringLength(10)] public string PostalCode { get; set; } [Required(ErrorMessage = "Country is required")] [StringLength(40)] public string Country { get; set; } [StringLength(24)] public string Phone { get; set; } [Required(ErrorMessage = "Email Address is required")] [DisplayName("Email Address")] [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "Email is is not valid.")] [DataType(DataType.EmailAddress)] public string Email { get; set; } [ScaffoldColumn(false)] public decimal Total { get; set; } [ScaffoldColumn(false)] public string PaymentTransactionId { get; set; } [ScaffoldColumn(false)] public bool HasBeenShipped { get; set; } public List<OrderDetail> OrderDetails { get; set; } } }Ajoutez une classe OrderDetail.cs au dossier Models .
Remplacez le code par défaut par le code suivant :
using System.ComponentModel.DataAnnotations; namespace WingtipToys.Models { public class OrderDetail { public int OrderDetailId { get; set; } public int OrderId { get; set; } public string Username { get; set; } public int ProductId { get; set; } public int Quantity { get; set; } public double? UnitPrice { get; set; } } }
Les classes Order et OrderDetail contiennent le schéma pour définir les informations de commande utilisées pour l’achat et l’expédition.
En outre, vous devez mettre à jour la classe de contexte de base de données qui gère les classes d’entité et qui fournit l’accès aux données à la base de données. Pour ce faire, vous allez ajouter les classes Order et OrderDetail model nouvellement créées à ProductContext la classe.
Dans l’Explorateur de solutions, recherchez et ouvrez le fichier ProductContext.cs .
Ajoutez le code mis en surbrillance au fichier ProductContext.cs , comme indiqué ci-dessous :
using System.Data.Entity; namespace WingtipToys.Models { public class ProductContext : DbContext { public ProductContext() : base("WingtipToys") { } public DbSet<Category> Categories { get; set; } public DbSet<Product> Products { get; set; } public DbSet<CartItem> ShoppingCartItems { get; set; } public DbSet<Order> Orders { get; set; } public DbSet<OrderDetail> OrderDetails { get; set; } } }
Comme mentionné précédemment dans cette série de tutoriels, le code du fichier ProductContext.cs ajoute l’espace System.Data.Entity de noms afin que vous ayez accès à toutes les fonctionnalités principales de Entity Framework. Cette fonctionnalité inclut la possibilité d’interroger, d’insérer, de mettre à jour et de supprimer des données en travaillant avec des objets fortement typés. Le code ci-dessus dans la classe ProductContext ajoute l'accès à Entity Framework aux nouvelles classes Order et OrderDetail.
Ajout de l’accès à la caisse
L’exemple d’application Wingtip Toys permet aux utilisateurs anonymes d’examiner et d’ajouter des produits à un panier d’achat. Toutefois, lorsque les utilisateurs anonymes choisissent d’acheter les produits qu’ils ont ajoutés au panier d’achat, ils doivent se connecter au site. Une fois connectés, ils peuvent accéder aux pages restreintes de l'application Web qui gèrent le processus de paiement et d'achat. Ces pages restreintes sont contenues dans le dossier Checkout de l’application.
Ajouter un dossier de commande et des pages
Vous allez maintenant créer le dossier Checkout et les pages que le client verra pendant le processus de commande. Vous allez mettre à jour ces pages plus loin dans ce tutoriel.
Cliquez avec le bouton droit sur le nom du projet (Wingtip Toys) dans l’Explorateur de solutions , puis sélectionnez Ajouter un nouveau dossier.
Nommez le nouveau dossier Checkout.
Cliquez avec le bouton droit sur le dossier Checkout, puis sélectionnez Ajouter>un nouvel élément.
La boîte de dialogue Ajouter un nouvel élément s’affiche.
Sélectionnez le groupe de modèles Visual C# ->Web à gauche. Ensuite, dans le volet central, sélectionnez Formulaire web avec la page maîtreet nommez-le CheckoutStart.aspx.
Comme précédemment, sélectionnez le fichier Site.Master comme page maître.
Ajoutez les pages supplémentaires suivantes au dossier Caisse en utilisant les mêmes étapes mentionnées ci-dessus :
- CheckoutReview.aspx
- CheckoutComplete.aspx
- CheckoutCancel.aspx
- CheckoutError.aspx
Ajouter un fichier Web.config
En ajoutant un nouveau fichier Web.config au dossier Checkout, vous pourrez restreindre l’accès à toutes les pages contenues dans le dossier.
Cliquez avec le bouton droit sur le dossier Checkout, puis sélectionnez Ajouter ->un nouvel élément.
La boîte de dialogue Ajouter un nouvel élément s’affiche.Sélectionnez le groupe de modèles Visual C# ->Web à gauche. Ensuite, dans le volet central, sélectionnez Fichier de configuration web, acceptez le nom par défaut de Web.config, puis sélectionnez Ajouter.
Remplacez le contenu XML existant dans le fichier Web.config par les éléments suivants :
<?xml version="1.0"?> <configuration> <system.web> <authorization> <deny users="?"/> </authorization> </system.web> </configuration>Enregistrez le fichier Web.config .
Le fichier Web.config spécifie que tous les utilisateurs non authentifiés de l’application web doivent se voir interdire l'accès aux pages contenues dans le dossier Checkout. Toutefois, si l’utilisateur a enregistré un compte et qu’il est connecté, il est un utilisateur connu et aura accès aux pages dans le dossier Checkout.
Il est important de noter que ASP.NET configuration suit une hiérarchie, où chaque fichier Web.config applique les paramètres de configuration au dossier dans lequel il se trouve et à tous les répertoires enfants ci-dessous.
Activer SSL pour le projet
Ssl (Secure Sockets Layer) est un protocole défini pour permettre aux serveurs web et aux clients web de communiquer de manière plus sécurisée via l’utilisation du chiffrement. Quand SSL n’est pas utilisé, les données envoyées entre le client et le serveur sont ouvertes à la détection de paquets par toute personne disposant d’un accès physique au réseau. En outre, plusieurs schémas d’authentification courants ne sont pas sécurisés via http brut. En particulier, l’authentification de base et l’authentification par formulaire envoient des informations d’identification non chiffrées. Pour être sécurisé, ces schémas d’authentification doivent utiliser SSL.
- Dans l’Explorateur de solutions, cliquez sur le projet WingtipToys , puis appuyez sur F4 pour afficher la fenêtre Propriétés .
- Remplacez SSL activé par
true. - Copiez l’URL SSL pour pouvoir l’utiliser ultérieurement.
L’URL SSL serahttps://localhost:44300/, sauf si vous avez précédemment créé des sites web SSL (comme indiqué ci-dessous).
- Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet WingtipToys , puis cliquez sur Propriétés.
- Sous l’onglet gauche, cliquez sur Web.
- Modifiez l’URL du projet pour utiliser l’URL SSL que vous avez enregistrée précédemment.
- Enregistrez la page en appuyant sur Ctrl+S.
- Appuyez sur Ctrl+F5 pour exécuter l’application. Visual Studio affiche une option permettant d’éviter les avertissements SSL.
- Cliquez sur Oui pour approuver le certificat IIS Express SSL et continuer.
Un avertissement de sécurité s’affiche. - Cliquez sur Oui pour installer le certificat sur votre localhost.
La fenêtre du navigateur s’affiche.
Vous pouvez maintenant tester facilement votre application web localement à l’aide de SSL.
Ajouter un fournisseur OAuth 2.0
ASP.NET Web Forms fournit des options améliorées pour l’appartenance et l’authentification. Ces améliorations incluent OAuth. OAuth est un protocole ouvert qui permet une autorisation sécurisée dans une méthode simple et standard à partir d’applications web, mobiles et de bureau. Le modèle ASP.NET Web Forms utilise OAuth pour exposer Facebook, Twitter, Google et Microsoft en tant que fournisseurs d’authentification. Bien que ce tutoriel utilise uniquement Google comme fournisseur d’authentification, vous pouvez facilement modifier le code pour utiliser l’un des fournisseurs. Les étapes d’implémentation d’autres fournisseurs sont très similaires aux étapes que vous verrez dans ce tutoriel.
Outre l’authentification, le didacticiel utilise également des rôles pour implémenter l’autorisation. Seuls les utilisateurs que vous ajoutez au canEdit rôle pourront modifier les données (créer, modifier ou supprimer des contacts).
Note
Les applications Windows Live acceptent uniquement une URL dynamique pour un site web opérationnel. Vous ne pouvez donc pas utiliser une URL de site web local pour tester les connexions.
Les étapes suivantes vous permettent d’ajouter un fournisseur d’authentification Google.
Ouvrez le fichier App_Start\Startup.Auth.cs .
Supprimez les caractères de commentaire de la
app.UseGoogleAuthentication()méthode afin que la méthode apparaisse comme suit :app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() { ClientId = "", ClientSecret = "" });Accédez à la console Google Developers. Vous devrez également vous connecter avec votre compte de messagerie de développeur Google (gmail.com). Si vous n’avez pas de compte Google, sélectionnez le lien Créer un compte .
Ensuite, vous verrez la console Google Developers.
Cliquez sur le bouton Créer un projet et entrez un nom et un ID de projet (vous pouvez utiliser les valeurs par défaut). Cliquez ensuite sur la case à cocher Contrat et sur le bouton Créer .
En quelques secondes, le nouveau projet est créé et votre navigateur affiche la page des nouveaux projets.
Sous l’onglet gauche, cliquez sur API et authentification, puis sur Informations d’identification.
Cliquez sur Créer un nouvel ID client sous OAuth.
La boîte de dialogue Créer un ID client s’affiche.
Dans la boîte de dialogue Créer un ID client , conservez l’application web par défaut pour le type d’application.
Définissez les origines JavaScript autorisées sur l’URL SSL que vous avez utilisée précédemment dans ce didacticiel (
https://localhost:44300/sauf si vous avez créé d’autres projets SSL).
Cette URL est l’origine de votre application. Pour cet exemple, vous n’entrez que l’URL de test localhost. Toutefois, vous pouvez entrer plusieurs URL pour prendre en compte localhost et production.Définissez l’URI de redirection autorisé sur ce qui suit :
https://localhost:44300/signin-googleCette valeur est l'URI qu'ASP.NET utilise pour permettre aux utilisateurs OAuth de communiquer avec le serveur OAuth de Google. N’oubliez pas l’URL SSL que vous avez utilisée ci-dessus (
https://localhost:44300/sauf si vous avez créé d’autres projets SSL).Cliquez sur le bouton Créer un ID client .
Dans le menu de gauche de la console Google Developers, cliquez sur l’élément de menu d’écran Consentement , puis définissez votre adresse e-mail et le nom du produit. Une fois le formulaire terminé, cliquez sur Enregistrer.
Cliquez sur l’élément de menu APIs, faites défiler vers le bas et cliquez sur le bouton désactivé en regard de l’API Google+.
L’acceptation de cette option active l’API Google+.Vous devez également mettre à jour le package NuGet Microsoft.Owin vers la version 3.0.0.
Dans le menu Outils , sélectionnez Gestionnaire de package NuGet , puis Gérer les packages NuGet pour la solution.
Dans la fenêtre Gérer les packages NuGet , recherchez et mettez à jour le package Microsoft.Owin vers la version 3.0.0.Dans Visual Studio, mettez à jour la
UseGoogleAuthenticationméthode de la page Startup.Auth.cs en copiant et en collant l’ID client et la clé secrète client dans la méthode. Les valeurs d’ID client et de clé secrète client indiquées ci-dessous sont des exemples et ne fonctionneront pas.using System; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework; using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.DataProtection; using Microsoft.Owin.Security.Google; using Owin; using WingtipToys.Models; namespace WingtipToys { public partial class Startup { // For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301883 public void ConfigureAuth(IAppBuilder app) { // Configure the db context, user manager and signin manager to use a single instance per request app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create); // Enable the application to use a cookie to store information for the signed in user // and to use a cookie to temporarily store information about a user logging in with a third party login provider // Configure the sign in cookie app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), Provider = new CookieAuthenticationProvider { OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>( validateInterval: TimeSpan.FromMinutes(30), regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) } }); // Use a cookie to temporarily store information about a user logging in with a third party login provider app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process. app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)); // Enables the application to remember the second login verification factor such as phone or email. // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from. // This is similar to the RememberMe option when you log in. app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie); // Uncomment the following lines to enable logging in with third party login providers //app.UseMicrosoftAccountAuthentication( // clientId: "", // clientSecret: ""); //app.UseTwitterAuthentication( // consumerKey: "", // consumerSecret: ""); //app.UseFacebookAuthentication( // appId: "", // appSecret: ""); app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() { ClientId = "000000000000.apps.googleusercontent.com", ClientSecret = "00000000000" }); } } }Appuyez sur Ctrl+F5 pour générer et exécuter l’application. Cliquez sur le lien Se connecter .
Sous Utiliser un autre service pour vous connecter, cliquez sur Google.
Si vous devez entrer vos informations d’identification, vous êtes redirigé vers le site google où vous entrez vos informations d’identification.
Une fois que vous avez entré vos informations d’identification, vous serez invité à accorder des autorisations à l’application web que vous venez de créer.
Cliquez sur Accepter. Vous êtes maintenant redirigé vers la page Inscrire de l’application WingtipToys dans laquelle vous pouvez inscrire votre compte Google.
Vous avez la possibilité de modifier le nom d’inscription de courrier local utilisé pour votre compte Gmail, mais vous souhaitez généralement conserver l’alias de messagerie par défaut (autrement dit, celui que vous avez utilisé pour l’authentification). Cliquez sur Se connecter comme indiqué ci-dessus.
Modification de la fonctionnalité de connexion
Comme mentionné précédemment dans cette série de tutoriels, la plupart des fonctionnalités d’inscription des utilisateurs ont été incluses dans le modèle ASP.NET Web Forms par défaut. Vous allez maintenant modifier les Login.aspx et Register.aspx pages par défaut pour appeler la MigrateCart méthode. La MigrateCart méthode associe un utilisateur nouvellement connecté à un panier d’achat anonyme. En associant l’utilisateur et le panier d’achat, l’exemple d’application Wingtip Toys pourra conserver le panier d’achat de l’utilisateur entre les visites.
Dans l’Explorateur de solutions, recherchez et ouvrez le dossier Compte .
Modifiez la page code-behind nommée Login.aspx.cs pour inclure le code mis en surbrillance en jaune afin qu’il apparaisse comme suit :
using System; using System.Web; using System.Web.UI; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using Owin; using WingtipToys.Models; namespace WingtipToys.Account { public partial class Login : Page { protected void Page_Load(object sender, EventArgs e) { RegisterHyperLink.NavigateUrl = "Register"; // Enable this once you have account confirmation enabled for password reset functionality //ForgotPasswordHyperLink.NavigateUrl = "Forgot"; OpenAuthLogin.ReturnUrl = Request.QueryString["ReturnUrl"]; var returnUrl = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]); if (!String.IsNullOrEmpty(returnUrl)) { RegisterHyperLink.NavigateUrl += "?ReturnUrl=" + returnUrl; } } protected void LogIn(object sender, EventArgs e) { if (IsValid) { // Validate the user password var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); var signinManager = Context.GetOwinContext().GetUserManager<ApplicationSignInManager>(); // This doen't count login failures towards account lockout // To enable password failures to trigger lockout, change to shouldLockout: true var result = signinManager.PasswordSignIn(Email.Text, Password.Text, RememberMe.Checked, shouldLockout: false); switch (result) { case SignInStatus.Success: WingtipToys.Logic.ShoppingCartActions usersShoppingCart = new WingtipToys.Logic.ShoppingCartActions(); String cartId = usersShoppingCart.GetCartId(); usersShoppingCart.MigrateCart(cartId, Email.Text); IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); break; case SignInStatus.LockedOut: Response.Redirect("/Account/Lockout"); break; case SignInStatus.RequiresVerification: Response.Redirect(String.Format("/Account/TwoFactorAuthenticationSignIn?ReturnUrl={0}&RememberMe={1}", Request.QueryString["ReturnUrl"], RememberMe.Checked), true); break; case SignInStatus.Failure: default: FailureText.Text = "Invalid login attempt"; ErrorMessage.Visible = true; break; } } } } }Enregistrez le fichier Login.aspx.cs .
Pour l’instant, vous pouvez ignorer l’avertissement indiquant qu’il n’existe aucune définition pour la MigrateCart méthode. Vous allez l’ajouter un peu plus loin dans ce tutoriel.
Le fichier Login.aspx.cs code-behind implémente la méthode LogIn. En inspectant la page Login.aspx, vous verrez que cette page inclut un bouton « Se connecter » qui, lorsqu'un clic dessus déclenche le LogIn gestionnaire sur le code-behind.
Lorsque la Login méthode sur le Login.aspx.cs est appelée, une nouvelle instance du panier d’achat nommé usersShoppingCart est créée. L’ID du panier d’achat (un GUID) est récupéré et défini sur la cartId variable. Ensuite, la méthode MigrateCart est appelée, en passant à la fois le cartId et le nom de l'utilisateur connecté à cette méthode. Lorsque le panier d’achat est migré, le GUID utilisé pour identifier le panier d’achat anonyme est remplacé par le nom d’utilisateur.
Outre la modification du fichier code-behind Login.aspx.cs pour migrer le panier d’achat lorsque l’utilisateur se connecte, vous devez également modifier le fichier Register.aspx.cs code-behind pour migrer le panier d’achat lorsque l’utilisateur crée un compte et se connecte.
Dans le dossier Compte , ouvrez le fichier code-behind nommé Register.aspx.cs.
Modifiez le fichier code-behind en incluant le code en jaune afin qu’il apparaisse comme suit :
using System; using System.Linq; using System.Web; using System.Web.UI; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using Owin; using WingtipToys.Models; namespace WingtipToys.Account { public partial class Register : Page { protected void CreateUser_Click(object sender, EventArgs e) { var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text }; IdentityResult result = manager.Create(user, Password.Text); if (result.Succeeded) { // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771 //string code = manager.GenerateEmailConfirmationToken(user.Id); //string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request); //manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>."); IdentityHelper.SignIn(manager, user, isPersistent: false); using (WingtipToys.Logic.ShoppingCartActions usersShoppingCart = new WingtipToys.Logic.ShoppingCartActions()) { String cartId = usersShoppingCart.GetCartId(); usersShoppingCart.MigrateCart(cartId, user.Id); } IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); } else { ErrorMessage.Text = result.Errors.FirstOrDefault(); } } } }Enregistrez le fichier Register.aspx.cs . Une fois de plus, ignorez l’avertissement concernant la
MigrateCartméthode.
Notez que le code que vous avez utilisé dans le CreateUser_Click gestionnaire d’événements est très similaire au code que vous avez utilisé dans la LogIn méthode. Lorsque l’utilisateur inscrit ou se connecte au site, un appel à la MigrateCart méthode est effectué.
Migration du panier d’achat
Maintenant que vous disposez du processus de connexion et d’inscription mis à jour, vous pouvez ajouter le code pour migrer le panier d’achat à l’aide de la MigrateCart méthode.
Dans l’Explorateur de solutions, recherchez le dossier Logique et ouvrez le fichier de classe ShoppingCartActions.cs .
Ajoutez le code mis en surbrillance en jaune au code existant dans le fichier ShoppingCartActions.cs , afin que le code du fichier ShoppingCartActions.cs apparaisse comme suit :
using System; using System.Collections.Generic; using System.Linq; using System.Web; using WingtipToys.Models; namespace WingtipToys.Logic { public class ShoppingCartActions : IDisposable { public string ShoppingCartId { get; set; } private ProductContext _db = new ProductContext(); public const string CartSessionKey = "CartId"; public void AddToCart(int id) { // Retrieve the product from the database. ShoppingCartId = GetCartId(); var cartItem = _db.ShoppingCartItems.SingleOrDefault( c => c.CartId == ShoppingCartId && c.ProductId == id); if (cartItem == null) { // Create a new cart item if no cart item exists. cartItem = new CartItem { ItemId = Guid.NewGuid().ToString(), ProductId = id, CartId = ShoppingCartId, Product = _db.Products.SingleOrDefault( p => p.ProductID == id), Quantity = 1, DateCreated = DateTime.Now }; _db.ShoppingCartItems.Add(cartItem); } else { // If the item does exist in the cart, // then add one to the quantity. cartItem.Quantity++; } _db.SaveChanges(); } public void Dispose() { if (_db != null) { _db.Dispose(); _db = null; } } public string GetCartId() { if (HttpContext.Current.Session[CartSessionKey] == null) { if (!string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name)) { HttpContext.Current.Session[CartSessionKey] = HttpContext.Current.User.Identity.Name; } else { // Generate a new random GUID using System.Guid class. Guid tempCartId = Guid.NewGuid(); HttpContext.Current.Session[CartSessionKey] = tempCartId.ToString(); } } return HttpContext.Current.Session[CartSessionKey].ToString(); } public List<CartItem> GetCartItems() { ShoppingCartId = GetCartId(); return _db.ShoppingCartItems.Where( c => c.CartId == ShoppingCartId).ToList(); } public decimal GetTotal() { ShoppingCartId = GetCartId(); // Multiply product price by quantity of that product to get // the current price for each of those products in the cart. // Sum all product price totals to get the cart total. decimal? total = decimal.Zero; total = (decimal?)(from cartItems in _db.ShoppingCartItems where cartItems.CartId == ShoppingCartId select (int?)cartItems.Quantity * cartItems.Product.UnitPrice).Sum(); return total ?? decimal.Zero; } public ShoppingCartActions GetCart(HttpContext context) { using (var cart = new ShoppingCartActions()) { cart.ShoppingCartId = cart.GetCartId(); return cart; } } public void UpdateShoppingCartDatabase(String cartId, ShoppingCartUpdates[] CartItemUpdates) { using (var db = new WingtipToys.Models.ProductContext()) { try { int CartItemCount = CartItemUpdates.Count(); List<CartItem> myCart = GetCartItems(); foreach (var cartItem in myCart) { // Iterate through all rows within shopping cart list for (int i = 0; i < CartItemCount; i++) { if (cartItem.Product.ProductID == CartItemUpdates[i].ProductId) { if (CartItemUpdates[i].PurchaseQuantity < 1 || CartItemUpdates[i].RemoveItem == true) { RemoveItem(cartId, cartItem.ProductId); } else { UpdateItem(cartId, cartItem.ProductId, CartItemUpdates[i].PurchaseQuantity); } } } } } catch (Exception exp) { throw new Exception("ERROR: Unable to Update Cart Database - " + exp.Message.ToString(), exp); } } } public void RemoveItem(string removeCartID, int removeProductID) { using (var _db = new WingtipToys.Models.ProductContext()) { try { var myItem = (from c in _db.ShoppingCartItems where c.CartId == removeCartID && c.Product.ProductID == removeProductID select c).FirstOrDefault(); if (myItem != null) { // Remove Item. _db.ShoppingCartItems.Remove(myItem); _db.SaveChanges(); } } catch (Exception exp) { throw new Exception("ERROR: Unable to Remove Cart Item - " + exp.Message.ToString(), exp); } } } public void UpdateItem(string updateCartID, int updateProductID, int quantity) { using (var _db = new WingtipToys.Models.ProductContext()) { try { var myItem = (from c in _db.ShoppingCartItems where c.CartId == updateCartID && c.Product.ProductID == updateProductID select c).FirstOrDefault(); if (myItem != null) { myItem.Quantity = quantity; _db.SaveChanges(); } } catch (Exception exp) { throw new Exception("ERROR: Unable to Update Cart Item - " + exp.Message.ToString(), exp); } } } public void EmptyCart() { ShoppingCartId = GetCartId(); var cartItems = _db.ShoppingCartItems.Where( c => c.CartId == ShoppingCartId); foreach (var cartItem in cartItems) { _db.ShoppingCartItems.Remove(cartItem); } // Save changes. _db.SaveChanges(); } public int GetCount() { ShoppingCartId = GetCartId(); // Get the count of each item in the cart and sum them up int? count = (from cartItems in _db.ShoppingCartItems where cartItems.CartId == ShoppingCartId select (int?)cartItems.Quantity).Sum(); // Return 0 if all entries are null return count ?? 0; } public struct ShoppingCartUpdates { public int ProductId; public int PurchaseQuantity; public bool RemoveItem; } public void MigrateCart(string cartId, string userName) { var shoppingCart = _db.ShoppingCartItems.Where(c => c.CartId == cartId); foreach (CartItem item in shoppingCart) { item.CartId = userName; } HttpContext.Current.Session[CartSessionKey] = userName; _db.SaveChanges(); } } }
La MigrateCart méthode utilise le cartId existant pour rechercher le panier d’achat de l’utilisateur. Ensuite, le code effectue une boucle dans tous les éléments du panier d’achat et remplace la CartId propriété (comme spécifié par le CartItem schéma) par le nom d’utilisateur connecté.
Mise à jour de la connexion de base de données
Si vous suivez ce tutoriel à l’aide de l’exemple d’application Wingtip Toys prédéfini , vous devez recréer la base de données d’appartenance par défaut. En modifiant la chaîne de connexion par défaut, la base de données d’appartenance sera créée la prochaine fois que l’application s’exécute.
Ouvrez le fichier Web.config à la racine du projet.
Mettez à jour la chaîne de connexion par défaut pour qu’elle apparaisse comme suit :
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=aspnet-WingtipToys;Integrated Security=True" providerName="System.Data.SqlClient" />
Intégration de PayPal
PayPal est une plateforme de facturation basée sur le web qui accepte les paiements par les marchands en ligne. Ce tutoriel explique ensuite comment intégrer la fonctionnalité Express Checkout de PayPal dans votre application. Express Checkout permet à vos clients d’utiliser PayPal pour payer les articles qu’ils ont ajoutés à leur panier d’achat.
Créer des comptes de test PayPal
Pour utiliser l’environnement de test PayPal, vous devez créer et vérifier un compte de test de développeur. Vous allez utiliser le compte de test du développeur pour créer un compte de test acheteur et un compte de test vendeur. Les informations d’identification du compte de test du développeur permettent également à l’exemple d’application Wingtip Toys d’accéder à l’environnement de test PayPal.
Dans un navigateur, accédez au site de test PayPal développeur :
https://developer.paypal.comSi vous n’avez pas de compte de développeur PayPal, créez un compte en cliquant sur S’inscrireet en suivant les étapes d’inscription. Si vous disposez d’un compte de développeur PayPal existant, connectez-vous en cliquant sur Se connecter. Vous aurez besoin de votre compte de développeur PayPal pour tester l’exemple d’application Wingtip Toys plus loin dans ce tutoriel.
Si vous venez de vous inscrire à votre compte de développeur PayPal, vous devrez peut-être vérifier votre compte de développeur PayPal avec PayPal. Vous pouvez vérifier votre compte en suivant les étapes que PayPal vous a envoyées à votre adresse e-mail. Une fois que vous avez vérifié votre compte de développeur PayPal, reconnectez-vous au site de test PayPal développeur.
Une fois connecté au site PayPal développeur avec votre compte de développeur PayPal, vous devez créer un compte de test PayPal acheteur si vous n’en avez pas déjà. Pour créer un compte de test acheteur, sur le site PayPal cliquez sur l’onglet Applications , puis sur Comptes de bac à sable.
La page des comptes de test Sandbox s’affiche.Note
Le site PayPal Développeur fournit déjà un compte de test marchand.
Dans la page des comptes de test bac à sable, cliquez sur Créer un compte.
Dans la page Créer un compte de test , choisissez un e-mail et un mot de passe de compte de test acheteur de votre choix.
Note
Vous aurez besoin des adresses e-mail de l’acheteur et du mot de passe pour tester l’exemple d’application Wingtip Toys à la fin de ce tutoriel.
Créez le compte de test de l’acheteur en cliquant sur le bouton Créer un compte .
La page Les comptes de test Sandbox s’affiche.
Sur la page comptes de test Sandbox, cliquez sur le compte de messagerie de l'animateur.
Les options profil et notification s’affichent.Sélectionnez l’option Profil , puis cliquez sur Informations d’identification de l’API pour afficher vos informations d’identification d’API pour le compte de test marchand.
Copiez les informations d’identification de l’API TEST dans le Bloc-notes.
Vous aurez besoin de vos informations d’identification de l’API TEST classique affichées (nom d’utilisateur, mot de passe et signature) pour effectuer des appels d’API à partir de l’exemple d’application Wingtip Toys vers l’environnement de test PayPal. Vous allez ajouter les informations d’identification à l’étape suivante.
Ajouter la classe PayPal et les informations d’identification de l’API
Vous placez la majorité du code PayPal dans une seule classe. Cette classe contient les méthodes utilisées pour communiquer avec PayPal. En outre, vous allez ajouter vos informations d’identification PayPal à cette classe.
Dans l’exemple d’application Wingtip Toys dans Visual Studio, cliquez avec le bouton droit sur le dossier Logique , puis sélectionnez Ajouter ->Nouvel élément.
La boîte de dialogue Ajouter un nouvel élément s’affiche.Sous Visual C# dans le volet Installé à gauche, sélectionnez Code.
Dans le volet central, sélectionnez Classe. Nommez cette nouvelle classe PayPalFunctions.cs.
Cliquez sur Ajouter.
Le nouveau fichier de classe s’affiche dans l’éditeur.Remplacez le code par défaut par le code suivant :
using System; using System.Collections; using System.Collections.Specialized; using System.IO; using System.Net; using System.Text; using System.Data; using System.Configuration; using System.Web; using WingtipToys; using WingtipToys.Models; using System.Collections.Generic; using System.Linq; public class NVPAPICaller { //Flag that determines the PayPal environment (live or sandbox) private const bool bSandbox = true; private const string CVV2 = "CVV2"; // Live strings. private string pEndPointURL = "https://api-3t.paypal.com/nvp"; private string host = "www.paypal.com"; // Sandbox strings. private string pEndPointURL_SB = "https://api-3t.sandbox.paypal.com/nvp"; private string host_SB = "www.sandbox.paypal.com"; private const string SIGNATURE = "SIGNATURE"; private const string PWD = "PWD"; private const string ACCT = "ACCT"; //Replace <Your API Username> with your API Username //Replace <Your API Password> with your API Password //Replace <Your Signature> with your Signature public string APIUsername = "<Your API Username>"; private string APIPassword = "<Your API Password>"; private string APISignature = "<Your Signature>"; private string Subject = ""; private string BNCode = "PP-ECWizard"; //HttpWebRequest Timeout specified in milliseconds private const int Timeout = 15000; private static readonly string[] SECURED_NVPS = new string[] { ACCT, CVV2, SIGNATURE, PWD }; public void SetCredentials(string Userid, string Pwd, string Signature) { APIUsername = Userid; APIPassword = Pwd; APISignature = Signature; } public bool ShortcutExpressCheckout(string amt, ref string token, ref string retMsg) { if (bSandbox) { pEndPointURL = pEndPointURL_SB; host = host_SB; } string returnURL = "https://localhost:44300/Checkout/CheckoutReview.aspx"; string cancelURL = "https://localhost:44300/Checkout/CheckoutCancel.aspx"; NVPCodec encoder = new NVPCodec(); encoder["METHOD"] = "SetExpressCheckout"; encoder["RETURNURL"] = returnURL; encoder["CANCELURL"] = cancelURL; encoder["BRANDNAME"] = "Wingtip Toys Sample Application"; encoder["PAYMENTREQUEST_0_AMT"] = amt; encoder["PAYMENTREQUEST_0_ITEMAMT"] = amt; encoder["PAYMENTREQUEST_0_PAYMENTACTION"] = "Sale"; encoder["PAYMENTREQUEST_0_CURRENCYCODE"] = "USD"; // Get the Shopping Cart Products using (WingtipToys.Logic.ShoppingCartActions myCartOrders = new WingtipToys.Logic.ShoppingCartActions()) { List<CartItem> myOrderList = myCartOrders.GetCartItems(); for (int i = 0; i < myOrderList.Count; i++) { encoder["L_PAYMENTREQUEST_0_NAME" + i] = myOrderList[i].Product.ProductName.ToString(); encoder["L_PAYMENTREQUEST_0_AMT" + i] = myOrderList[i].Product.UnitPrice.ToString(); encoder["L_PAYMENTREQUEST_0_QTY" + i] = myOrderList[i].Quantity.ToString(); } } string pStrrequestforNvp = encoder.Encode(); string pStresponsenvp = HttpCall(pStrrequestforNvp); NVPCodec decoder = new NVPCodec(); decoder.Decode(pStresponsenvp); string strAck = decoder["ACK"].ToLower(); if (strAck != null && (strAck == "success" || strAck == "successwithwarning")) { token = decoder["TOKEN"]; string ECURL = "https://" + host + "/cgi-bin/webscr?cmd=_express-checkout" + "&token=" + token; retMsg = ECURL; return true; } else { retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" + "Desc=" + decoder["L_SHORTMESSAGE0"] + "&" + "Desc2=" + decoder["L_LONGMESSAGE0"]; return false; } } public bool GetCheckoutDetails(string token, ref string PayerID, ref NVPCodec decoder, ref string retMsg) { if (bSandbox) { pEndPointURL = pEndPointURL_SB; } NVPCodec encoder = new NVPCodec(); encoder["METHOD"] = "GetExpressCheckoutDetails"; encoder["TOKEN"] = token; string pStrrequestforNvp = encoder.Encode(); string pStresponsenvp = HttpCall(pStrrequestforNvp); decoder = new NVPCodec(); decoder.Decode(pStresponsenvp); string strAck = decoder["ACK"].ToLower(); if (strAck != null && (strAck == "success" || strAck == "successwithwarning")) { PayerID = decoder["PAYERID"]; return true; } else { retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" + "Desc=" + decoder["L_SHORTMESSAGE0"] + "&" + "Desc2=" + decoder["L_LONGMESSAGE0"]; return false; } } public bool DoCheckoutPayment(string finalPaymentAmount, string token, string PayerID, ref NVPCodec decoder, ref string retMsg) { if (bSandbox) { pEndPointURL = pEndPointURL_SB; } NVPCodec encoder = new NVPCodec(); encoder["METHOD"] = "DoExpressCheckoutPayment"; encoder["TOKEN"] = token; encoder["PAYERID"] = PayerID; encoder["PAYMENTREQUEST_0_AMT"] = finalPaymentAmount; encoder["PAYMENTREQUEST_0_CURRENCYCODE"] = "USD"; encoder["PAYMENTREQUEST_0_PAYMENTACTION"] = "Sale"; string pStrrequestforNvp = encoder.Encode(); string pStresponsenvp = HttpCall(pStrrequestforNvp); decoder = new NVPCodec(); decoder.Decode(pStresponsenvp); string strAck = decoder["ACK"].ToLower(); if (strAck != null && (strAck == "success" || strAck == "successwithwarning")) { return true; } else { retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" + "Desc=" + decoder["L_SHORTMESSAGE0"] + "&" + "Desc2=" + decoder["L_LONGMESSAGE0"]; return false; } } public string HttpCall(string NvpRequest) { string url = pEndPointURL; string strPost = NvpRequest + "&" + buildCredentialsNVPString(); strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode); HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url); objRequest.Timeout = Timeout; objRequest.Method = "POST"; objRequest.ContentLength = strPost.Length; try { using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream())) { myWriter.Write(strPost); } } catch (Exception) { // No logging for this tutorial. } //Retrieve the Response returned from the NVP API call to PayPal. HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse(); string result; using (StreamReader sr = new StreamReader(objResponse.GetResponseStream())) { result = sr.ReadToEnd(); } return result; } private string buildCredentialsNVPString() { NVPCodec codec = new NVPCodec(); if (!IsEmpty(APIUsername)) codec["USER"] = APIUsername; if (!IsEmpty(APIPassword)) codec[PWD] = APIPassword; if (!IsEmpty(APISignature)) codec[SIGNATURE] = APISignature; if (!IsEmpty(Subject)) codec["SUBJECT"] = Subject; codec["VERSION"] = "88.0"; return codec.Encode(); } public static bool IsEmpty(string s) { return s == null || s.Trim() == string.Empty; } } public sealed class NVPCodec : NameValueCollection { private const string AMPERSAND = "&"; private const string EQUALS = "="; private static readonly char[] AMPERSAND_CHAR_ARRAY = AMPERSAND.ToCharArray(); private static readonly char[] EQUALS_CHAR_ARRAY = EQUALS.ToCharArray(); public string Encode() { StringBuilder sb = new StringBuilder(); bool firstPair = true; foreach (string kv in AllKeys) { string name = HttpUtility.UrlEncode(kv); string value = HttpUtility.UrlEncode(this[kv]); if (!firstPair) { sb.Append(AMPERSAND); } sb.Append(name).Append(EQUALS).Append(value); firstPair = false; } return sb.ToString(); } public void Decode(string nvpstring) { Clear(); foreach (string nvp in nvpstring.Split(AMPERSAND_CHAR_ARRAY)) { string[] tokens = nvp.Split(EQUALS_CHAR_ARRAY); if (tokens.Length >= 2) { string name = HttpUtility.UrlDecode(tokens[0]); string value = HttpUtility.UrlDecode(tokens[1]); Add(name, value); } } } public void Add(string name, string value, int index) { this.Add(GetArrayName(index, name), value); } public void Remove(string arrayName, int index) { this.Remove(GetArrayName(index, arrayName)); } public string this[string name, int index] { get { return this[GetArrayName(index, name)]; } set { this[GetArrayName(index, name)] = value; } } private static string GetArrayName(int index, string name) { if (index < 0) { throw new ArgumentOutOfRangeException("index", "index cannot be negative : " + index); } return name + index; } }Ajoutez les informations d’identification de l’API marchand (nom d’utilisateur, mot de passe et signature) que vous avez affichées précédemment dans ce didacticiel afin de pouvoir effectuer des appels de fonction à l’environnement de test PayPal.
public string APIUsername = "<Your API Username>"; private string APIPassword = "<Your API Password>"; private string APISignature = "<Your Signature>";
Note
Dans cet exemple d’application, vous ajoutez simplement des informations d’identification à un fichier C# (.cs). Toutefois, dans une solution implémentée, vous devez envisager de chiffrer vos informations d’identification dans un fichier de configuration.
La classe NVPAPICaller contient la majorité des fonctionnalités PayPal. Le code de la classe fournit les méthodes nécessaires pour effectuer un achat de test à partir de l’environnement de test PayPal. Les trois fonctions PayPal suivantes sont utilisées pour effectuer des achats :
-
SetExpressCheckoutFonction -
GetExpressCheckoutDetailsFonction -
DoExpressCheckoutPaymentFonction
La méthode ShortcutExpressCheckout collecte les informations relatives aux achats de test et les détails du produit depuis le panier et appelle la fonction PayPal SetExpressCheckout. La GetCheckoutDetails méthode confirme les détails de l’achat et appelle la GetExpressCheckoutDetails fonction PayPal avant d’effectuer l’achat de test. La méthode DoCheckoutPayment termine l'achat de test depuis l'environnement de test en appelant la fonction DoExpressCheckoutPayment PayPal. Le code restant prend en charge les méthodes et processus PayPal, tels que les chaînes d’encodage, les chaînes de décodage, les tableaux de traitement et la détermination des informations d’identification.
Note
PayPal vous permet d’inclure des détails d’achat facultatifs en fonction de la spécification de l’API de PayPal. En étendant le code dans l’exemple d’application Wingtip Toys, vous pouvez inclure des détails de localisation, des descriptions de produits, des taxes, un numéro de service client, ainsi que de nombreux autres champs facultatifs.
Notez que les URL de retour et d’annulation spécifiées dans la méthode ShortcutExpressCheckout utilisent un numéro de port.
string returnURL = "https://localhost:44300/Checkout/CheckoutReview.aspx";
string cancelURL = "https://localhost:44300/Checkout/CheckoutCancel.aspx";
Lorsque Visual Web Developer exécute un projet web à l’aide de SSL, le port 44300 est généralement utilisé pour le serveur web. Comme indiqué ci-dessus, le numéro de port est 44300. Lorsque vous exécutez l’application, vous pouvez voir un autre numéro de port. Votre numéro de port doit être correctement défini dans le code afin que vous puissiez exécuter l’exemple d’application Wingtip Toys à la fin de ce tutoriel. La section suivante de ce didacticiel explique comment récupérer le numéro de port hôte local et mettre à jour la classe PayPal.
Mettre à jour le numéro de port LocalHost dans la classe PayPal
L’exemple d’application Wingtip Toys achète des produits en accédant au site de test PayPal et en retournant à votre instance locale de l’exemple d’application Wingtip Toys. Pour que PayPal retourne à l’URL correcte, vous devez spécifier le numéro de port de l’application exemple en cours d’exécution localement dans le code PayPal indiqué ci-dessus.
Cliquez avec le bouton droit sur le nom du projet (WingtipToys) dans l’Explorateur de solutions , puis sélectionnez Propriétés.
Dans la colonne de gauche, sélectionnez l’onglet Web .
Récupérez le numéro de port dans le champ URL du projet.
Si nécessaire, mettez à jour les
returnURLetcancelURLdans la classe PayPal (NVPAPICaller) dans le fichier PayPalFunctions.cs pour utiliser le numéro de port de votre application web :string returnURL = "https://localhost:<Your Port Number>/Checkout/CheckoutReview.aspx"; string cancelURL = "https://localhost:<Your Port Number>/Checkout/CheckoutCancel.aspx";
À présent, le code que vous avez ajouté correspondra au port attendu pour votre application web locale. PayPal pourra revenir à l’URL correcte sur votre ordinateur local.
Ajouter le bouton de paiement PayPal
Maintenant que les fonctions PayPal principales ont été ajoutées à l’exemple d’application, vous pouvez commencer à ajouter le balisage et le code nécessaires pour appeler ces fonctions. Dans un premier temps, vous devez ajouter le bouton de paiement que l'utilisateur verra sur la page panier d'achat.
Ouvrez le fichier ShoppingCart.aspx .
Faites défiler jusqu’au bas du fichier et recherchez le
<!--Checkout Placeholder -->commentaire.Remplacez le commentaire par un
ImageButtoncontrôle afin que le marquage soit remplacé comme suit :<asp:ImageButton ID="CheckoutImageBtn" runat="server" ImageUrl="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" Width="145" AlternateText="Check out with PayPal" OnClick="CheckoutBtn_Click" BackColor="Transparent" BorderWidth="0" />Dans le fichier ShoppingCart.aspx.cs , après que le
UpdateBtn_Clickgestionnaire d’événements se rapproche de la fin du fichier, ajoutez leCheckOutBtn_Clickgestionnaire d’événements :protected void CheckoutBtn_Click(object sender, ImageClickEventArgs e) { using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions()) { Session["payment_amt"] = usersShoppingCart.GetTotal(); } Response.Redirect("Checkout/CheckoutStart.aspx"); }Également dans le fichier ShoppingCart.aspx.cs , ajoutez une référence au
CheckoutBtnbouton , afin que le nouveau bouton d’image soit référencé comme suit :protected void Page_Load(object sender, EventArgs e) { using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions()) { decimal cartTotal = 0; cartTotal = usersShoppingCart.GetTotal(); if (cartTotal > 0) { // Display Total. lblTotal.Text = String.Format("{0:c}", cartTotal); } else { LabelTotalText.Text = ""; lblTotal.Text = ""; ShoppingCartTitle.InnerText = "Shopping Cart is Empty"; UpdateBtn.Visible = false; CheckoutImageBtn.Visible = false; } } }Enregistrez vos modifications dans le fichier ShoppingCart.aspx et le fichier ShoppingCart.aspx.cs .
Dans le menu, sélectionnez Debug-Build>WingtipToys.
Le projet sera reconstruit avec le contrôle ImageButton nouvellement ajouté.
Envoyer les détails de l’achat à PayPal
Lorsque l’utilisateur clique sur le bouton Caisse sur la page du panier d’achat (ShoppingCart.aspx), il commence le processus d’achat. Le code suivant appelle la première fonction PayPal nécessaire pour acheter des produits.
Dans le dossier Checkout , ouvrez le fichier code-behind nommé CheckoutStart.aspx.cs.
Veillez à ouvrir le fichier code-behind.Remplacez le code existant par le code ci-dessous :
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace WingtipToys.Checkout { public partial class CheckoutStart : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { NVPAPICaller payPalCaller = new NVPAPICaller(); string retMsg = ""; string token = ""; if (Session["payment_amt"] != null) { string amt = Session["payment_amt"].ToString(); bool ret = payPalCaller.ShortcutExpressCheckout(amt, ref token, ref retMsg); if (ret) { Session["token"] = token; Response.Redirect(retMsg); } else { Response.Redirect("CheckoutError.aspx?" + retMsg); } } else { Response.Redirect("CheckoutError.aspx?ErrorCode=AmtMissing"); } } } }
Lorsque l’utilisateur de l’application clique sur le bouton Extraire sur la page du panier d’achat, le navigateur accède à la page CheckoutStart.aspx . Lorsque la page CheckoutStart.aspx se charge, la ShortcutExpressCheckout méthode est appelée. À ce stade, l’utilisateur est transféré vers le site web de test PayPal. Sur le site PayPal, l’utilisateur entre ses informations d’identification PayPal, passe en revue les détails de l’achat, accepte le contrat de PayPal et retourne à l’exemple d’application Wingtip Toys où la ShortcutExpressCheckout méthode se termine. Une fois la ShortcutExpressCheckout méthode terminée, elle redirige l’utilisateur vers la page CheckoutReview.aspx spécifiée dans la ShortcutExpressCheckout méthode. Cela permet à l’utilisateur de passer en revue les détails de la commande à partir de l’exemple d’application Wingtip Toys.
Vérifier les détails de la commande
Après le retour de PayPal, la page CheckoutReview.aspx de l’exemple d’application Wingtip Toys affiche les détails de la commande. Cette page permet à l’utilisateur de passer en revue les détails de la commande avant d’acheter les produits. La page CheckoutReview.aspx doit être créée comme suit :
Dans le dossier Checkout, ouvrez la page nommée CheckoutReview.aspx.
Remplacez le balisage existant par les éléments suivants :
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="CheckoutReview.aspx.cs" Inherits="WingtipToys.Checkout.CheckoutReview" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <h1>Order Review</h1> <p></p> <h3 style="padding-left: 33px">Products:</h3> <asp:GridView ID="OrderItemList" runat="server" AutoGenerateColumns="False" GridLines="Both" CellPadding="10" Width="500" BorderColor="#efeeef" BorderWidth="33"> <Columns> <asp:BoundField DataField="ProductId" HeaderText=" Product ID" /> <asp:BoundField DataField="Product.ProductName" HeaderText=" Product Name" /> <asp:BoundField DataField="Product.UnitPrice" HeaderText="Price (each)" DataFormatString="{0:c}"/> <asp:BoundField DataField="Quantity" HeaderText="Quantity" /> </Columns> </asp:GridView> <asp:DetailsView ID="ShipInfo" runat="server" AutoGenerateRows="false" GridLines="None" CellPadding="10" BorderStyle="None" CommandRowStyle-BorderStyle="None"> <Fields> <asp:TemplateField> <ItemTemplate> <h3>Shipping Address:</h3> <br /> <asp:Label ID="FirstName" runat="server" Text='<%#: Eval("FirstName") %>'></asp:Label> <asp:Label ID="LastName" runat="server" Text='<%#: Eval("LastName") %>'></asp:Label> <br /> <asp:Label ID="Address" runat="server" Text='<%#: Eval("Address") %>'></asp:Label> <br /> <asp:Label ID="City" runat="server" Text='<%#: Eval("City") %>'></asp:Label> <asp:Label ID="State" runat="server" Text='<%#: Eval("State") %>'></asp:Label> <asp:Label ID="PostalCode" runat="server" Text='<%#: Eval("PostalCode") %>'></asp:Label> <p></p> <h3>Order Total:</h3> <br /> <asp:Label ID="Total" runat="server" Text='<%#: Eval("Total", "{0:C}") %>'></asp:Label> </ItemTemplate> <ItemStyle HorizontalAlign="Left" /> </asp:TemplateField> </Fields> </asp:DetailsView> <p></p> <hr /> <asp:Button ID="CheckoutConfirm" runat="server" Text="Complete Order" OnClick="CheckoutConfirm_Click" /> </asp:Content>Ouvrez la page code-behind nommée CheckoutReview.aspx.cs et remplacez le code existant par les éléments suivants :
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using WingtipToys.Models; namespace WingtipToys.Checkout { public partial class CheckoutReview : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { NVPAPICaller payPalCaller = new NVPAPICaller(); string retMsg = ""; string token = ""; string PayerID = ""; NVPCodec decoder = new NVPCodec(); token = Session["token"].ToString(); bool ret = payPalCaller.GetCheckoutDetails(token, ref PayerID, ref decoder, ref retMsg); if (ret) { Session["payerId"] = PayerID; var myOrder = new Order(); myOrder.OrderDate = Convert.ToDateTime(decoder["TIMESTAMP"].ToString()); myOrder.Username = User.Identity.Name; myOrder.FirstName = decoder["FIRSTNAME"].ToString(); myOrder.LastName = decoder["LASTNAME"].ToString(); myOrder.Address = decoder["SHIPTOSTREET"].ToString(); myOrder.City = decoder["SHIPTOCITY"].ToString(); myOrder.State = decoder["SHIPTOSTATE"].ToString(); myOrder.PostalCode = decoder["SHIPTOZIP"].ToString(); myOrder.Country = decoder["SHIPTOCOUNTRYCODE"].ToString(); myOrder.Email = decoder["EMAIL"].ToString(); myOrder.Total = Convert.ToDecimal(decoder["AMT"].ToString()); // Verify total payment amount as set on CheckoutStart.aspx. try { decimal paymentAmountOnCheckout = Convert.ToDecimal(Session["payment_amt"].ToString()); decimal paymentAmoutFromPayPal = Convert.ToDecimal(decoder["AMT"].ToString()); if (paymentAmountOnCheckout != paymentAmoutFromPayPal) { Response.Redirect("CheckoutError.aspx?" + "Desc=Amount%20total%20mismatch."); } } catch (Exception) { Response.Redirect("CheckoutError.aspx?" + "Desc=Amount%20total%20mismatch."); } // Get DB context. ProductContext _db = new ProductContext(); // Add order to DB. _db.Orders.Add(myOrder); _db.SaveChanges(); // Get the shopping cart items and process them. using (WingtipToys.Logic.ShoppingCartActions usersShoppingCart = new WingtipToys.Logic.ShoppingCartActions()) { List<CartItem> myOrderList = usersShoppingCart.GetCartItems(); // Add OrderDetail information to the DB for each product purchased. for (int i = 0; i < myOrderList.Count; i++) { // Create a new OrderDetail object. var myOrderDetail = new OrderDetail(); myOrderDetail.OrderId = myOrder.OrderId; myOrderDetail.Username = User.Identity.Name; myOrderDetail.ProductId = myOrderList[i].ProductId; myOrderDetail.Quantity = myOrderList[i].Quantity; myOrderDetail.UnitPrice = myOrderList[i].Product.UnitPrice; // Add OrderDetail to DB. _db.OrderDetails.Add(myOrderDetail); _db.SaveChanges(); } // Set OrderId. Session["currentOrderId"] = myOrder.OrderId; // Display Order information. List<Order> orderList = new List<Order>(); orderList.Add(myOrder); ShipInfo.DataSource = orderList; ShipInfo.DataBind(); // Display OrderDetails. OrderItemList.DataSource = myOrderList; OrderItemList.DataBind(); } } else { Response.Redirect("CheckoutError.aspx?" + retMsg); } } } protected void CheckoutConfirm_Click(object sender, EventArgs e) { Session["userCheckoutCompleted"] = "true"; Response.Redirect("~/Checkout/CheckoutComplete.aspx"); } } }
Le contrôle DetailsView est utilisé pour afficher les détails de commande retournés par PayPal. En outre, le code ci-dessus enregistre les détails de l’ordre dans la base de données Wingtip Toys en tant qu’objet OrderDetail . Lorsque l’utilisateur clique sur le bouton Commande complète , il est redirigé vers la page CheckoutComplete.aspx .
Note
Conseil
Dans le balisage de la page CheckoutReview.aspx , notez que la <ItemStyle> balise est utilisée pour modifier le style des éléments dans le contrôle DetailsView en bas de la page. En affichant la page en mode Création (en sélectionnant Création dans le coin inférieur gauche de Visual Studio), puis en sélectionnant le contrôle DetailsView et en sélectionnant l’étiquette active (l’icône de flèche en haut à droite du contrôle), vous pourrez voir les tâches DetailsView.
En sélectionnant Modifier les champs, la boîte de dialogue Champs s’affiche. Dans cette boîte de dialogue, vous pouvez facilement contrôler les propriétés visuelles, telles que ItemStyle, du contrôle DetailsView .
Achat complet
CheckoutComplete.aspx page effectue l’achat à partir de PayPal. Comme mentionné ci-dessus, l’utilisateur doit cliquer sur le bouton Commande complète avant que l’application accède à la page CheckoutComplete.aspx .
Dans le dossier Checkout, ouvrez la page nommée CheckoutComplete.aspx.
Remplacez le balisage existant par les éléments suivants :
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="CheckoutComplete.aspx.cs" Inherits="WingtipToys.Checkout.CheckoutComplete" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <h1>Checkout Complete</h1> <p></p> <h3>Payment Transaction ID:</h3> <asp:Label ID="TransactionId" runat="server"></asp:Label> <p></p> <h3>Thank You!</h3> <p></p> <hr /> <asp:Button ID="Continue" runat="server" Text="Continue Shopping" OnClick="Continue_Click" /> </asp:Content>Ouvrez la page code-behind nommée CheckoutComplete.aspx.cs et remplacez le code existant par les éléments suivants :
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using WingtipToys.Models; namespace WingtipToys.Checkout { public partial class CheckoutComplete : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Verify user has completed the checkout process. if ((string)Session["userCheckoutCompleted"] != "true") { Session["userCheckoutCompleted"] = string.Empty; Response.Redirect("CheckoutError.aspx?" + "Desc=Unvalidated%20Checkout."); } NVPAPICaller payPalCaller = new NVPAPICaller(); string retMsg = ""; string token = ""; string finalPaymentAmount = ""; string PayerID = ""; NVPCodec decoder = new NVPCodec(); token = Session["token"].ToString(); PayerID = Session["payerId"].ToString(); finalPaymentAmount = Session["payment_amt"].ToString(); bool ret = payPalCaller.DoCheckoutPayment(finalPaymentAmount, token, PayerID, ref decoder, ref retMsg); if (ret) { // Retrieve PayPal confirmation value. string PaymentConfirmation = decoder["PAYMENTINFO_0_TRANSACTIONID"].ToString(); TransactionId.Text = PaymentConfirmation; ProductContext _db = new ProductContext(); // Get the current order id. int currentOrderId = -1; if (Session["currentOrderId"] != string.Empty) { currentOrderId = Convert.ToInt32(Session["currentOrderID"]); } Order myCurrentOrder; if (currentOrderId >= 0) { // Get the order based on order id. myCurrentOrder = _db.Orders.Single(o => o.OrderId == currentOrderId); // Update the order to reflect payment has been completed. myCurrentOrder.PaymentTransactionId = PaymentConfirmation; // Save to DB. _db.SaveChanges(); } // Clear shopping cart. using (WingtipToys.Logic.ShoppingCartActions usersShoppingCart = new WingtipToys.Logic.ShoppingCartActions()) { usersShoppingCart.EmptyCart(); } // Clear order id. Session["currentOrderId"] = string.Empty; } else { Response.Redirect("CheckoutError.aspx?" + retMsg); } } } protected void Continue_Click(object sender, EventArgs e) { Response.Redirect("~/Default.aspx"); } } }
Lorsque la page CheckoutComplete.aspx est chargée, la DoCheckoutPayment méthode est appelée. Comme mentionné précédemment, la DoCheckoutPayment méthode termine l’achat à partir de l’environnement de test PayPal. Une fois PayPal a terminé l’achat de la commande, la page CheckoutComplete.aspx affiche une transaction ID de paiement à l’acheteur.
Gérer l'annulation de l'achat
Si l’utilisateur décide d’annuler l’achat, il est dirigé vers la page CheckoutCancel.aspx où il verra que sa commande a été annulée.
Ouvrez la page nommée CheckoutCancel.aspx dans le dossier Checkout.
Remplacez le balisage existant par les éléments suivants :
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="CheckoutCancel.aspx.cs" Inherits="WingtipToys.Checkout.CheckoutCancel" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <h1>Checkout Cancelled</h1> <p></p> <h3>Your purchase has been cancelled.</h3> </asp:Content>
Gérer les erreurs d’achat
Les erreurs pendant le processus d’achat sont gérées par la page CheckoutError.aspx . Le code-behind de la page CheckoutStart.aspx , la page CheckoutReview.aspx et la page CheckoutComplete.aspx redirigent chacune vers la page CheckoutError.aspx si une erreur se produit.
Ouvrez la page nommée CheckoutError.aspx dans le dossier Checkout.
Remplacez le balisage existant par les éléments suivants :
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="CheckoutError.aspx.cs" Inherits="WingtipToys.Checkout.CheckoutError" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <h1>Checkout Error</h1> <p></p> <table id="ErrorTable"> <tr> <td class="field"></td> <td><%=Request.QueryString.Get("ErrorCode")%></td> </tr> <tr> <td class="field"></td> <td><%=Request.QueryString.Get("Desc")%></td> </tr> <tr> <td class="field"></td> <td><%=Request.QueryString.Get("Desc2")%></td> </tr> </table> <p></p> </asp:Content>
La page CheckoutError.aspx s’affiche avec les détails de l’erreur lorsqu’une erreur se produit pendant le processus d’extraction.
Exécution de l’application
Exécutez l’application pour voir comment acheter des produits. Veuillez noter que vous fonctionnerez dans l'environnement de test PayPal. Aucun argent réel n’est échangé.
Vérifiez que tous vos fichiers sont enregistrés dans Visual Studio.
Ouvrez un navigateur web et accédez à https://developer.paypal.com.
Connectez-vous avec votre compte de développeur PayPal que vous avez créé précédemment dans ce tutoriel.
Pour le bac à sable du développeur de PayPal, vous devez être connecté sur https://developer.paypal.com pour tester le paiement express. Cela s’applique uniquement aux tests de bac à sable de PayPal, pas à l’environnement en direct de PayPal.Dans Visual Studio, appuyez sur F5 pour exécuter l’exemple d’application Wingtip Toys.
Une fois la base de données reconstruite, le navigateur s’ouvre et affiche la page Default.aspx .Ajoutez trois produits différents au panier d’achat en sélectionnant la catégorie de produit, par exemple « Voitures », puis cliquez sur Ajouter au panier en regard de chaque produit.
Le panier d’achat affiche le produit que vous avez sélectionné.Cliquez sur le bouton PayPal pour finaliser votre achat.
La validation nécessite que vous disposiez d’un compte d’utilisateur pour l’application d'exemple Wingtip Toys.
Cliquez sur le lien Google à droite de la page pour vous connecter avec un compte de messagerie gmail.com existant.
Si vous n’avez pas de compte gmail.com, vous pouvez en créer un à des fins de test à www.gmail.com. Vous pouvez également utiliser un compte local standard en cliquant sur « Inscrire ».
Connectez-vous avec votre compte gmail et votre mot de passe.
Cliquez sur le bouton Se connecter pour inscrire votre compte gmail avec votre exemple de nom d’utilisateur d’application Wingtip Toys.
Sur le site de test PayPal, ajoutez votre adresse e-mail d’acheteur et votre mot de passe que vous avez créés précédemment dans ce didacticiel, puis cliquez sur le bouton Se connecter .
Acceptez la stratégie de PayPal, puis cliquez sur le bouton Accepter et Continuer .
Notez que cette page s’affiche uniquement la première fois que vous utilisez ce compte PayPal. Là encore, notez qu’il s’agit d’un compte de test, aucun argent réel n’est échangé.
Passez en revue les informations de commande sur la page de révision de l’environnement de test PayPal, puis cliquez sur Continuer.
Dans la page CheckoutReview.aspx , vérifiez le montant de la commande et affichez l’adresse d’expédition générée. Cliquez ensuite sur le bouton Commande complète .
La page CheckoutComplete.aspx s’affiche avec un ID de transaction de paiement.
Examen de la base de données
En examinant les données mises à jour dans l’exemple de base de données d’application Wingtip Toys après l’exécution de l’application, vous pouvez voir que l’application a correctement enregistré l’achat des produits.
Vous pouvez inspecter les données contenues dans le fichier de base de données Wingtiptoys.mdf à l’aide de la fenêtre Explorateur de bases de données (fenêtre Explorateur de serveurs dans Visual Studio) comme vous l’avez fait précédemment dans cette série de tutoriels.
Fermez la fenêtre du navigateur si elle est toujours ouverte.
Dans Visual Studio, sélectionnez l’icône Afficher tous les fichiers en haut de l’Explorateur de solutions pour vous permettre de développer le dossier App_Data .
Développez le dossier App_Data .
Vous devrez peut-être sélectionner l’icône Afficher tous les fichiers pour le dossier.Cliquez avec le bouton droit sur le fichier de base de données Wingtiptoys.mdf , puis sélectionnez Ouvrir.
L’Explorateur de serveurs s’affiche.Développez le dossier Tables .
Cliquez avec le bouton droit sur la table Commandes, puis sélectionnez Afficher les données de table.
La table Orders s’affiche.Passez en revue la colonne PaymentTransactionID pour confirmer les transactions réussies.
Fermez la fenêtre de la table Commandes .
Dans l’Explorateur de serveurs, cliquez avec le bouton droit sur la table OrderDetails et sélectionnez Afficher les données de table.
Passez en revue les valeurs
OrderIdetUsernamedans la table OrderDetails. Notez que ces valeurs correspondent aux valeursOrderIdetUsernameincluses dans la table Orders.Fermez la fenêtre de la table OrderDetails .
Cliquez avec le bouton droit sur le fichier de base de données Wingtip Toys (Wingtiptoys.mdf), puis sélectionnez Fermer la connexion.
Si vous ne voyez pas la fenêtre Explorateur de solutions, cliquez sur l’Explorateur de solutions en bas de la fenêtre Explorateur de serveurs pour afficher à nouveau l’Explorateur de solutions .
Résumé
Dans ce tutoriel, vous avez ajouté des schémas de commande et de détails de commande pour suivre l’achat de produits. Vous avez également intégré la fonctionnalité PayPal dans l'application d'exemple Wingtip Toys.
Ressources additionnelles
Vue d’ensemble de la configuration ASP.NET
Déployer une application Web Forms sécurisée ASP.NET avec appartenance, OAuth et SQL Database sur Azure App Service
Microsoft Azure - Version d’évaluation gratuite
Clause d’exclusion de responsabilité
Ce tutoriel contient des exemples de code. Un tel exemple de code est fourni « tel quel » sans garantie quelconque. En conséquence, Microsoft ne garantit pas la précision, l’intégrité ou la qualité de l’exemple de code. Vous acceptez d’utiliser l’exemple de code à votre propre risque. En aucun cas, Microsoft ne vous sera responsable d’un exemple de code, de contenu, y compris, sans s’y limiter, d’erreurs ou d’omissions dans n’importe quel exemple de code, de contenu ou de perte ou de dommages de tout type encouru suite à l’utilisation d’un exemple de code. Vous êtes informé par la présente et acceptez par la présente d’indemniser, d’enregistrer et de conserver Microsoft inoffensif contre toute perte, réclamations de perte, blessures ou dommages d’un type quelconque, y compris, sans limitation, ceux que vous avez occasionnés ou découlant de matériel que vous publiez, transmettez, utilisez ou reposez sur y compris, mais pas limité à, les vues exprimées dans ce document.