Pokladna a platba přes PayPal
Stáhnout ukázkový projekt Wingtip Toys (C#) nebo Stáhnout elektronickou knihu (PDF)
Tato série kurzů vás naučí základy vytváření ASP.NET Web Forms aplikace pomocí ASP.NET 4.5 a Microsoft Visual Studio Express 2013 pro web. K této sérii kurzů je k dispozici Visual Studio 2013 projekt se zdrojovým kódem jazyka C#.
Tento kurz popisuje, jak upravit ukázkovou aplikaci Wingtip Toys tak, aby zahrnovala autorizaci uživatelů, registraci a platbu pomocí PayPalu. Oprávnění k nákupu produktů budou mít jenom uživatelé, kteří jsou přihlášení. Integrovaná funkce registrace uživatelů v šabloně projektu ASP.NET 4.5 Web Forms už obsahuje většinu toho, co potřebujete. Přidáte funkci expresní pokladny PayPal. V tomto kurzu používáte vývojové testovací prostředí paypalu, takže se nepřevedou žádné skutečné prostředky. Na konci kurzu otestujete aplikaci tak, že vyberete produkty, které chcete přidat do nákupního košíku, kliknete na tlačítko pokladny a přenesete data na testovací web PayPal. Na testovacím webu PayPal potvrdíte své dodací a platební údaje a pak se vrátíte do místní ukázkové aplikace Wingtip Toys, abyste nákup potvrdili a dokončili.
Existuje několik zkušených platebních procesorů třetích stran, které se specializují na online nákupy, které řeší škálovatelnost a zabezpečení. ASP.NET vývojáři by měli před implementací řešení nákupu a nákupu zvážit výhody využití řešení plateb třetí strany.
Poznámka
Ukázková aplikace Wingtip Toys byla navržena tak, aby zobrazovala konkrétní ASP.NET koncepty a funkce dostupné ASP.NET webovým vývojářům. Tato ukázková aplikace nebyla optimalizovaná pro všechny možné okolnosti z hlediska škálovatelnosti a zabezpečení.
Naučíte se:
- Jak omezit přístup ke konkrétním stránkám ve složce.
- Jak vytvořit známý nákupní košík z anonymního nákupního košíku.
- Postup povolení PROTOKOLU SSL pro projekt
- Postup přidání zprostředkovatele OAuth do projektu
- Jak používat PayPal k nákupu produktů pomocí testovacího prostředí PayPal.
- Jak zobrazit podrobnosti z PayPalu v ovládacím prvku DetailsView .
- Jak aktualizovat databázi aplikace Wingtip Toys s podrobnostmi získanými ze služby PayPal.
Přidání sledování objednávky
V tomto kurzu vytvoříte dvě nové třídy pro sledování dat z pořadí, ve které uživatel vytvořil. Třídy budou sledovat data týkající se informací o dopravě, celkovém nákupu a potvrzení platby.
Přidání modelových tříd Order a OrderDetail
Dříve v této sérii kurzů jste definovali schéma pro kategorie, produkty a položky nákupního košíku vytvořením Category
tříd , Product
a CartItem
ve složce Modely . Nyní přidáte dvě nové třídy pro definování schématu pro objednávku produktu a podrobnosti objednávky.
Do složky Models přidejte novou třídu s názvem Order.cs.
Nový soubor třídy se zobrazí v editoru.Nahraďte výchozí kód následujícím kódem:
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; } } }
Do složky Models přidejte třídu OrderDetail.cs.
Nahraďte výchozí kód následujícím kódem:
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; } } }
Třídy Order
a OrderDetail
obsahují schéma definující informace o objednávce používané pro nákup a dodání.
Kromě toho budete muset aktualizovat třídu kontextu databáze, která spravuje třídy entit a poskytuje přístup k datům k databázi. Uděláte to tak, že do třídy přidáte nově vytvořené třídy ProductContext
Order a OrderDetail
model.
V Průzkumník řešení vyhledejte a otevřete soubor ProductContext.cs.
Přidejte zvýrazněný kód do souboru ProductContext.cs , jak je znázorněno níže:
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; } } }
Jak bylo zmíněno dříve v této sérii kurzů, kód v souboru ProductContext.cs přidává System.Data.Entity
obor názvů, abyste měli přístup ke všem základním funkcím Entity Frameworku. Tato funkce zahrnuje možnost dotazování, vkládání, aktualizace a odstraňování dat pomocí práce s objekty silného typu. Výše uvedený kód ve ProductContext
třídě přidá přístup entity Framework k nově přidanám Order
třídám a OrderDetail
.
Přidání přístupu k pokladně
Ukázková aplikace Wingtip Toys umožňuje anonymním uživatelům kontrolovat a přidávat produkty do nákupního košíku. Pokud se ale anonymní uživatelé rozhodnou koupit produkty, které přidali do nákupního košíku, musí se k webu přihlásit. Po přihlášení mají přístup k omezeným stránkám webové aplikace, které zpracovávají proces placení a nákupu. Tyto stránky s omezeným přístupem jsou obsažené ve složce Rezervace aplikace.
Přidání složky a stránek pokladny
Teď vytvoříte složku Pokladna a v ní stránky, které zákazník uvidí během procesu rezervace. Tyto stránky budete aktualizovat později v tomto kurzu.
V Průzkumník řešení klikněte pravým tlačítkem na název projektu (Wingtip Toys) a vyberte Přidat novou složku.
Pojmenujte novou složku Checkout.
Klikněte pravým tlačítkem na složku Rezervovat a pak vyberte Přidat>novou položku.
Zobrazí se dialogové okno Přidat novou položku.
Na levé straně vyberte skupinu Šablony Visual C# ->Web . Potom v prostředním podokně vyberte Webový formulář se stránkou předlohya pojmenujte ho CheckoutStart.aspx.
Stejně jako předtím vyberte soubor Site.Master jako stránku předlohy.
Přidejte následující další stránky do složky Checkout pomocí stejných kroků výše:
- CheckoutReview.aspx
- CheckoutComplete.aspx
- CheckoutCancel.aspx
- CheckoutError.aspx
Přidání souboru Web.config
Když do složky Rezervace přidáte nový souborWeb.config, budete moct omezit přístup ke všem stránkám obsaženým ve složce.
Klikněte pravým tlačítkem na složku Rezervovat a vyberte Přidat ->Nová položka.
Zobrazí se dialogové okno Přidat novou položku.Na levé straně vyberte skupinu Šablony Visual C# ->Web . Pak v prostředním podokně vyberte Soubor konfigurace webu, přijměte výchozí název Web.configa pak vyberte Přidat.
Nahraďte existující obsah XML v souboruWeb.config následujícím kódem:
<?xml version="1.0"?> <configuration> <system.web> <authorization> <deny users="?"/> </authorization> </system.web> </configuration>
Uložte souborWeb.config .
SouborWeb.config určuje, že všem neznámým uživatelům webové aplikace musí být odepřen přístup ke stránkám obsaženým ve složce Rezervovat. Pokud však uživatel zaregistroval účet a je přihlášený, bude známým uživatelem a bude mít přístup ke stránkám ve složce Rezervace .
Je důležité si uvědomit, že konfigurace ASP.NET následuje po hierarchii, kde každý Web.config soubor aplikuje nastavení konfigurace na složku, ve které se nachází, a na všechny podřízené adresáře pod ním.
Povolení PROTOKOLU SSL pro projekt
Ssl (Secure Sockets Layer) je protokol definovaný tak, aby webovým serverům a webovým klientům umožňoval zabezpečenější komunikaci prostřednictvím šifrování. Pokud se protokol SSL nepoužívá, data odesílaná mezi klientem a serverem jsou otevřená komukoli s fyzickým přístupem k síti. Kromě toho několik běžných schémat ověřování není bezpečné přes prostý protokol HTTP. Konkrétně základní ověřování a ověřování pomocí formulářů odesílají nešifrované přihlašovací údaje. Aby byla tato schémata ověřování zabezpečená, musí používat SSL.
- V Průzkumník řešení klikněte na projekt WingtipToys a stisknutím klávesyF4 zobrazte okno Vlastnosti.
- Změňte SSL Povoleno na
true
. - Zkopírujte adresu URL protokolu SSL , abyste ji mohli později použít.
Adresa URL protokolu SSL budehttps://localhost:44300/
, pokud jste předtím nevytvořili weby SSL (jak je znázorněno níže).
- V Průzkumník řešení klikněte pravým tlačítkem na projekt WingtipToys a klikněte na Vlastnosti.
- Na levé kartě klikněte na Web.
- Změňte adresu URL projektu tak, aby používala adresu URL PROTOKOLU SSL , kterou jste si uložili dříve.
- Uložte stránku stisknutím kombinace kláves CTRL+S.
- Stisknutím kláves Ctrl+F5 spusťte aplikaci. Visual Studio zobrazí možnost, abyste se vyhnuli upozorněním SSL.
- Kliknutím na Ano důvěřujte IIS Express certifikátu SSL a pokračujte.
Zobrazí se upozornění zabezpečení. - Kliknutím na Ano nainstalujte certifikát do místního hostitele.
Zobrazí se okno prohlížeče.
Webovou aplikaci teď můžete snadno otestovat místně pomocí PROTOKOLU SSL.
Přidání zprostředkovatele OAuth 2.0
ASP.NET Web Forms poskytuje rozšířené možnosti členství a ověřování. Mezi tato vylepšení patří OAuth. OAuth je otevřený protokol, který umožňuje zabezpečenou autorizaci pomocí jednoduché a standardní metody z webových, mobilních a desktopových aplikací. Šablona ASP.NET Web Forms používá OAuth k zveřejnění Facebook, Twitteru, Googlu a Microsoftu jako zprostředkovatelů ověřování. I když tento kurz jako zprostředkovatele ověřování používá pouze Google, můžete kód snadno upravit tak, aby používal některého z těchto poskytovatelů. Postup implementace dalších zprostředkovatelů se velmi podobá krokům, které uvidíte v tomto kurzu.
Kromě ověřování bude kurz také používat role k implementaci autorizace. Jenom uživatelé, které přidáte do canEdit
role, budou moct měnit data (vytvářet, upravovat nebo odstraňovat kontakty).
Poznámka
Aplikace Windows Live přijímají jenom živou adresu URL pro pracovní web, takže pro testování přihlášení nemůžete použít adresu URL místního webu.
Následující kroky vám umožní přidat zprostředkovatele ověřování Google.
Otevřete soubor App_Start\Startup.Auth.cs .
Odeberte z
app.UseGoogleAuthentication()
metody znaky komentáře, aby se metoda zobrazila takto:app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() { ClientId = "", ClientSecret = "" });
Přejděte do konzoly Google Developers Console. Budete se také muset přihlásit pomocí svého vývojářského e-mailového účtu Google (gmail.com). Pokud účet Google nemáte, vyberte odkaz Vytvořit účet .
Dále se zobrazí konzola Google Developers Console.
Klikněte na tlačítko Vytvořit projekt a zadejte název a ID projektu (můžete použít výchozí hodnoty). Potom klikněte na zaškrtávací políčko smlouvy a na tlačítko Vytvořit .
Za několik sekund se vytvoří nový projekt a v prohlížeči se zobrazí stránka nových projektů.
Na levé kartě klikněte na rozhraní API & ověřování a potom klikněte na Přihlašovací údaje.
V části OAuth klikněte na Vytvořit nové ID klienta.
Zobrazí se dialogové okno Vytvořit ID klienta .
V dialogovém okně Vytvořit ID klienta ponechte výchozí webovou aplikaci pro typ aplikace.
Nastavte autorizované původy JavaScriptu na adresu URL SSL, kterou jste použili dříve v tomto kurzu (
https://localhost:44300/
pokud jste nevytvořili jiné projekty SSL).
Tato adresa URL je zdrojem vaší aplikace. Pro tuto ukázku zadáte pouze testovací adresu URL místního hostitele. Můžete ale zadat několik adres URL, které budou zohledňovat místní hostitele a produkční prostředí.Nastavte identifikátor URI autorizovaného přesměrování na následující:
https://localhost:44300/signin-google
Tato hodnota je identifikátor URI, který ASP.NET uživatele OAuth ke komunikaci se serverem google OAuth. Zapamatujte si adresu URL protokolu SSL, kterou jste použili výše (
https://localhost:44300/
pokud jste nevytvořili jiné projekty SSL).Klikněte na tlačítko Vytvořit ID klienta .
V levé nabídce konzoly Google Developers Console klikněte na položku nabídky obrazovky Souhlas a nastavte e-mailovou adresu a název produktu. Po dokončení formuláře klikněte na Uložit.
Klikněte na položku nabídky ROZHRANÍ API , posuňte se dolů a klikněte na tlačítko Vypnuto vedle google+ API.
Přijetím této možnosti povolíte rozhraní API Google+.Musíte také aktualizovat balíček NuGet Microsoft.Owin na verzi 3.0.0.
V nabídce Nástroje vyberte Správce balíčků NuGet a pak vyberte Spravovat balíčky NuGet pro řešení.
V okně Spravovat balíčky NuGet vyhledejte a aktualizujte balíček Microsoft.Owin na verzi 3.0.0.V sadě Visual Studio aktualizujte
UseGoogleAuthentication
metodu stránky Startup.Auth.cs zkopírováním a vložením ID klienta a tajného klíče klienta do metody. Hodnoty ID klienta a Tajný klíč klienta jsou ukázkové a nebudou fungovat.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" }); } } }
Stisknutím kombinace kláves CTRL+F5 sestavte a spusťte aplikaci. Klikněte na odkaz Přihlásit se .
V části Přihlášení pomocí jiné služby klikněte na Google.
Pokud potřebujete zadat svoje přihlašovací údaje, budete přesměrováni na web Google, kde zadáte svoje přihlašovací údaje.
Po zadání přihlašovacích údajů se zobrazí výzva k udělení oprávnění webové aplikaci, kterou jste právě vytvořili.
Klikněte na Přijmout. Teď budete přesměrováni zpět na stránku Registrace aplikace WingtipToys , kde si můžete zaregistrovat svůj účet Google.
Máte možnost změnit místní název registrace e-mailu používaný pro váš účet Gmail, ale obecně chcete zachovat výchozí e-mailový alias (to znamená ten, který jste použili pro ověřování). Klikněte na Přihlásit se , jak je znázorněno výše.
Úprava funkce přihlášení
Jak jsme už zmínili v této sérii kurzů, většina funkcí registrace uživatelů byla ve výchozím nastavení zahrnuta do šablony ASP.NET Web Forms. Teď upravíte výchozí stránky Login.aspx a Register.aspx tak, aby volaly metodu MigrateCart
. Metoda MigrateCart
přidruží nově přihlášeného uživatele k anonymnímu nákupnímu košíku. Díky přidružení uživatele a nákupního košíku bude ukázková aplikace Wingtip Toys schopna udržovat nákupní košík uživatele mezi návštěvami.
V Průzkumník řešení vyhledejte a otevřete složku Účet.
Upravte stránku kódu na pozadí s názvem Login.aspx.cs tak, aby obsahovala kód zvýrazněný žlutě, aby se zobrazil takto:
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; } } } } }
Uložte soubor Login.aspx.cs .
Prozatím můžete ignorovat upozornění, že pro metodu MigrateCart
neexistuje žádná definice. Přidáte ho o něco později v tomto kurzu.
Soubor kódu Login.aspx.cs podporuje metodu LogIn. Při kontrole stránky Login.aspx uvidíte, že tato stránka obsahuje tlačítko Přihlásit se, které po kliknutí aktivuje obslužnou rutinu LogIn
na kódu na pozadí.
Při zavolání Login
metody v souboru Login.aspx.cs se vytvoří nová instance nákupního košíku s názvem usersShoppingCart
. Načte se ID nákupního košíku (IDENTIFIKÁTOR GUID) a nastaví se na proměnnou cartId
. MigrateCart
Pak je volána metoda, která této metodě předá cartId
jméno a jméno přihlášeného uživatele. Při migraci nákupního košíku se identifikátor GUID použitý k identifikaci anonymního nákupního košíku nahradí uživatelským jménem.
Kromě úpravy souboru s kódem na pozadí Login.aspx.cs pro migraci nákupního košíku při přihlášení uživatele je také nutné upravit soubor kódu Register.aspx.cs pro migraci nákupního košíku, když uživatel vytvoří nový účet a přihlásí se.
Ve složce Účet otevřete soubor s kódem na pozadí s názvem Register.aspx.cs.
Upravte soubor kódu na pozadí tak, že kód zahrnete žlutě, aby se zobrazil takto:
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(); } } } }
Uložte soubor Register.aspx.cs . Opět ignorujte upozornění týkající se
MigrateCart
metody.
Všimněte si, že kód, který jste použili v obslužné CreateUser_Click
rutině události, je velmi podobný kódu, který jste použili LogIn
v metodě. Když se uživatel zaregistruje nebo se přihlásí k webu, provede se MigrateCart
volání metody.
Migrace nákupního košíku
Teď, když máte aktualizovaný proces přihlášení a registrace, můžete přidat kód pro migraci nákupního košíku MigrateCart
pomocí metody .
V Průzkumník řešení vyhledejte složku Logic a otevřete soubor třídy ShoppingCartActions.cs.
Do existujícího kódu v souboru ShoppingCartActions.cs přidejte žlutě zvýrazněný kód, aby se kód v souboru ShoppingCartActions.cs zobrazil takto:
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(); } } }
Metoda MigrateCart
používá existující cartId k vyhledání nákupního košíku uživatele. Dále kód projde všemi položkami nákupního košíku a nahradí CartId
vlastnost (podle schématu CartItem
) přihlášeným uživatelským jménem.
Aktualizace připojení k databázi
Pokud tento kurz sledujete pomocí předem vytvořené ukázkové aplikace Wingtip Toys, musíte znovu vytvořit výchozí databázi členství. Úpravou výchozího připojovací řetězec se databáze členství vytvoří při příštím spuštění aplikace.
Otevřete souborWeb.config v kořenovém adresáři projektu.
Aktualizujte výchozí připojovací řetězec tak, aby se zobrazil takto:
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=aspnet-WingtipToys;Integrated Security=True" providerName="System.Data.SqlClient" />
Integrace PayPalu
PayPal je webová fakturační platforma, která přijímá platby od online obchodníků. Tento kurz dále vysvětluje, jak integrovat funkci expresní pokladny PayPalu do vaší aplikace. Expresní pokladna umožňuje zákazníkům platit za položky, které si přidali do nákupního košíku, payPal.
Vytvoření testovacích účtů PayPal
Pokud chcete používat testovací prostředí PayPal, musíte vytvořit a ověřit testovací účet vývojáře. Testovací účet vývojáře použijete k vytvoření testovacího účtu kupujícího a testovacího účtu prodejce. Přihlašovací údaje pro testovací účet vývojáře také umožní ukázkové aplikaci Wingtip Toys přístup k testovacímu prostředí PayPal.
V prohlížeči přejděte na testovací web pro vývojáře PayPal:
https://developer.paypal.comPokud nemáte vývojářský účet PayPal, vytvořte si nový účet kliknutím na Zaregistrovat sea postupem podle pokynů pro registraci. Pokud máte existující vývojářský účet PayPal, přihlaste se kliknutím na Přihlásit se. K otestování ukázkové aplikace Wingtip Toys později v tomto kurzu budete potřebovat svůj vývojářský účet PayPal.
Pokud jste si právě zaregistrovali svůj vývojářský účet PayPal, možná budete muset ověřit svůj vývojářský účet PayPal pomocí služby PayPal. Svůj účet můžete ověřit podle kroků, které payPal odeslal na váš e-mailový účet. Jakmile ověříte svůj vývojářský účet PayPal, přihlaste se zpátky k webu pro testování vývojářů PayPal.
Po přihlášení k webu pro vývojáře PayPal pomocí svého vývojářského účtu PayPal musíte vytvořit účet kupujícího PayPal, pokud ho ještě nemáte. Pokud chcete vytvořit zkušební účet kupujícího, klikněte na webu PayPal na kartu Aplikace a potom klikněte na Účty sandboxu.
Zobrazí se stránka Testovací účty sandboxu .Poznámka
Web pro vývojáře PayPal již poskytuje zkušební účet obchodníka.
Na stránce Testovací účty sandboxu klikněte na Vytvořit účet.
Na stránce Vytvořit zkušební účet zvolte e-mail a heslo k účtu kupujícího podle svého výběru.
Poznámka
K otestování ukázkové aplikace Wingtip Toys na konci tohoto kurzu budete potřebovat e-mailové adresy a heslo kupujícího.
Zkušební účet kupujícího vytvoříte kliknutím na tlačítko Vytvořit účet .
Zobrazí se stránka Testovací účty sandboxu .Na stránce Testovací účty sandboxu klikněte na e-mailový účet zprostředkovatele .
Zobrazí se možnosti Profil a Oznámení.Vyberte možnost Profil a pak kliknutím na Přihlašovací údaje rozhraní API zobrazte přihlašovací údaje rozhraní API pro testovací účet obchodníka.
Zkopírujte přihlašovací údaje rozhraní TEST API do Poznámkového bloku.
K volání rozhraní API z ukázkové aplikace Wingtip Toys do testovacího prostředí PayPal budete potřebovat zobrazené přihlašovací údaje rozhraní Classic TEST API (uživatelské jméno, heslo a podpis). Přihlašovací údaje přidáte v dalším kroku.
Přidání přihlašovacích údajů rozhraní API a třídy PayPal
Většinu kódu PayPal umístíte do jedné třídy. Tato třída obsahuje metody používané ke komunikaci se službou PayPal. Do této třídy také přidáte svoje přihlašovací údaje paypalu.
V ukázkové aplikaci Wingtip Toys v sadě Visual Studio klikněte pravým tlačítkem na složku Logic a pak vyberte Přidat ->Nová položka.
Zobrazí se dialogové okno Přidat novou položku.V části Visual C# v podokně Nainstalované na levé straně vyberte Kód.
V prostředním podokně vyberte Třída. Pojmenujte tuto novou třídu PayPalFunctions.cs.
Klikněte na Přidat.
Nový soubor třídy se zobrazí v editoru.Nahraďte výchozí kód následujícím kódem:
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; } }
Přidejte přihlašovací údaje rozhraní API pro obchodníky (uživatelské jméno, heslo a podpis), které jste zobrazili dříve v tomto kurzu, abyste mohli volat funkce do testovacího prostředí PayPal.
public string APIUsername = "<Your API Username>"; private string APIPassword = "<Your API Password>"; private string APISignature = "<Your Signature>";
Poznámka
V této ukázkové aplikaci jednoduše přidáváte přihlašovací údaje do souboru C# (.cs). V implementovaném řešení byste ale měli zvážit šifrování přihlašovacích údajů v konfiguračním souboru.
Třída NVPAPICaller obsahuje většinu funkcí Služby PayPal. Kód ve třídě poskytuje metody potřebné k provedení testovacího nákupu z testovacího prostředí PayPal. K nákupům se používají následující tři funkce Služby PayPal:
- Funkce
SetExpressCheckout
- Funkce
GetExpressCheckoutDetails
- Funkce
DoExpressCheckoutPayment
Metoda ShortcutExpressCheckout
shromažďuje informace o testovacím nákupu a podrobnosti o produktu z nákupního košíku a volá SetExpressCheckout
funkci PayPal. Metoda GetCheckoutDetails
před provedením testovacího GetExpressCheckoutDetails
nákupu potvrdí podrobnosti o nákupu a zavolá funkci PayPal. Metoda DoCheckoutPayment
dokončí testovací nákup z testovacího prostředí zavoláním DoExpressCheckoutPayment
funkce PayPal. Zbývající kód podporuje metody a procesy PayPal, například kódování řetězců, dekódování řetězců, zpracování polí a určování přihlašovacích údajů.
Poznámka
PayPal umožňuje zahrnout volitelné podrobnosti o nákupu na základě specifikace rozhraní API služby PayPal. Rozšířením kódu v ukázkové aplikaci Wingtip Toys můžete zahrnout podrobnosti o lokalizaci, popisy produktů, daň, číslo služby zákazníkům a mnoho dalších volitelných polí.
Všimněte si, že adresy URL pro vrácení a zrušení, které jsou zadány v Metodě ShortcutExpressCheckout používají číslo portu.
string returnURL = "https://localhost:44300/Checkout/CheckoutReview.aspx";
string cancelURL = "https://localhost:44300/Checkout/CheckoutCancel.aspx";
Když Visual Web Developer spustí webový projekt pomocí SSL, obvykle se pro webový server používá port 44300. Jak je znázorněno výše, číslo portu je 44300. Když aplikaci spustíte, uvidíte jiné číslo portu. Vaše číslo portu musí být správně nastavené v kódu, abyste mohli na konci tohoto kurzu úspěšně spustit ukázkovou aplikaci Wingtip Toys. Další část tohoto kurzu vysvětluje, jak načíst číslo portu místního hostitele a aktualizovat třídu PayPal.
Aktualizace čísla portu LocalHost ve třídě PayPal
Ukázková aplikace Wingtip Toys nakupuje produkty tak, že přejde na testovací web PayPal a vrátí se do místní instance ukázkové aplikace Wingtip Toys. Aby se služba PayPal vrátila na správnou adresu URL, musíte v kódu PayPal uvedeného výše zadat číslo portu místně spuštěné ukázkové aplikace.
Klikněte pravým tlačítkem na název projektu (WingtipToys) v Průzkumník řešení a vyberte Vlastnosti.
V levém sloupci vyberte kartu Web .
Načtěte číslo portu z pole Adresa URL projektu .
V případě potřeby aktualizujte
returnURL
acancelURL
ve třídě PayPal (NVPAPICaller
) v souboru PayPalFunctions.cs tak, aby používaly číslo portu vaší webové aplikace:string returnURL = "https://localhost:<Your Port Number>/Checkout/CheckoutReview.aspx"; string cancelURL = "https://localhost:<Your Port Number>/Checkout/CheckoutCancel.aspx";
Kód, který jste přidali, se teď bude shodovat s očekávaným portem pro vaši místní webovou aplikaci. PayPal se bude moct vrátit na správnou adresu URL na vašem místním počítači.
Přidání tlačítka PayPal Checkout
Teď, když byly do ukázkové aplikace přidány primární funkce PayPal, můžete začít přidávat kód a kód potřebný k volání těchto funkcí. Nejprve musíte přidat tlačítko pokladny, které se uživateli zobrazí na stránce nákupního košíku.
Otevřete soubor ShoppingCart.aspx .
Posuňte se na konec souboru a najděte
<!--Checkout Placeholder -->
komentář.Nahraďte komentář ovládacím prvek
ImageButton
, aby se označení nahradilo následujícím způsobem:<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" />
V souboru ShoppingCart.aspx.cs přidejte za obslužnou rutinu
UpdateBtn_Click
události blízko konce souboru obslužnou rutinuCheckOutBtn_Click
události:protected void CheckoutBtn_Click(object sender, ImageClickEventArgs e) { using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions()) { Session["payment_amt"] = usersShoppingCart.GetTotal(); } Response.Redirect("Checkout/CheckoutStart.aspx"); }
Do souboru ShoppingCart.aspx.cs také přidejte odkaz na
CheckoutBtn
, aby se na tlačítko nový obrázek odkazoval takto: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; } } }
Uložte změny do souboru ShoppingCart.aspx i do souboru ShoppingCart.aspx.cs .
V nabídce vyberte Debug-Build>WingtipToys.
Projekt bude znovu sestaven s nově přidaným ovládacím prvku ImageButton .
Odeslání podrobností o nákupu na PayPal
Když uživatel klikne na tlačítko Pokladna na stránce nákupního košíku (ShoppingCart.aspx), zahájí proces nákupu. Následující kód volá první funkci PayPal potřebnou k nákupu produktů.
Ze složky Checkout otevřete soubor s kódem na pozadí s názvem CheckoutStart.aspx.cs.
Nezapomeňte otevřít soubor s kódem na pozadí.Nahraďte stávající kód následujícím kódem:
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"); } } } }
Když uživatel aplikace klikne na tlačítko Rezervovat na stránce nákupního košíku, prohlížeč přejde na stránku CheckoutStart.aspx . Při načtení ShortcutExpressCheckout
stránky CheckoutStart.aspx je volána metoda . V tomto okamžiku je uživatel převeden na testovací web služby PayPal. Na webu PayPal uživatel zadá své přihlašovací údaje k účtu PayPal, zkontroluje podrobnosti o nákupu, přijme smlouvu PayPal a vrátí se do ukázkové aplikace Wingtip Toys, kde se ShortcutExpressCheckout
metoda dokončí. ShortcutExpressCheckout
Po dokončení metody se uživatel přesměruje na stránku CheckoutReview.aspx zadanou ShortcutExpressCheckout
v metodě . To uživateli umožňuje zkontrolovat podrobnosti objednávky z ukázkové aplikace Wingtip Toys.
Kontrola podrobností objednávky
Po návratu ze služby PayPal se na stránce CheckoutReview.aspx ukázkové aplikace Wingtip Toys zobrazí podrobnosti objednávky. Tato stránka umožňuje uživateli zkontrolovat podrobnosti objednávky před nákupem produktů. Stránka CheckoutReview.aspx musí být vytvořená takto:
Ve složce Checkout otevřete stránku s názvem CheckoutReview.aspx.
Existující kód nahraďte následujícím kódem:
<%@ 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>
Otevřete stránku s kódem na pozadí s názvem CheckoutReview.aspx.cs a nahraďte stávající kód následujícím kódem:
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"); } } }
Ovládací prvek DetailsView slouží k zobrazení podrobností objednávky, které byly vráceny ze služby PayPal. Výše uvedený kód také uloží podrobnosti objednávky do databáze Wingtip Toys jako OrderDetail
objekt. Když uživatel klikne na tlačítko Dokončit objednávku , bude přesměrován na stránku CheckoutComplete.aspx .
Poznámka
Tip
V kódu stránky CheckoutReview.aspx si všimněte, že <ItemStyle>
značka se používá ke změně stylu položek v ovládacím prvku DetailsView v dolní části stránky. Zobrazením stránky v návrhovém zobrazení (výběrem možnosti Návrh v levém dolním rohu sady Visual Studio), výběrem ovládacího prvku DetailsView a výběrem inteligentní značky (ikona šipky v pravém horním rohu ovládacího prvku) uvidíte úlohy DetailsView.
Když vyberete Upravit pole, zobrazí se dialogové okno Pole . V tomto dialogovém okně můžete snadno ovládat vlastnosti vizuálu, například ItemStyle ovládacího prvku DetailsView .
Dokončit nákup
Stránka CheckoutComplete.aspx provádí nákup na paypalu. Jak je uvedeno výše, uživatel musí kliknout na tlačítko Dokončit objednávku , aby aplikace přešla na stránku CheckoutComplete.aspx .
Ve složce Checkout otevřete stránku s názvem CheckoutComplete.aspx.
Existující kód nahraďte následujícím kódem:
<%@ 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>
Otevřete stránku kódu na pozadí s názvem CheckoutComplete.aspx.cs a nahraďte stávající kód následujícím kódem:
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"); } } }
Při načtení stránky DoCheckoutPayment
CheckoutComplete.aspx je volána metoda . Jak už bylo zmíněno dříve, DoCheckoutPayment
metoda dokončí nákup z testovacího prostředí PayPal. Jakmile PayPal dokončí nákup objednávky, zobrazí se na stránce CheckoutComplete.aspx platební transakce ID
pro kupujícího.
Zpracování zrušení nákupu
Pokud se uživatel rozhodne nákup zrušit, bude přesměrován na stránku CheckoutCancel.aspx , kde uvidí, že jeho objednávka byla zrušena.
Otevřete stránku s názvem CheckoutCancel.aspx ve složce Checkout .
Existující kód nahraďte následujícím kódem:
<%@ 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>
Zpracování chyb nákupu
Chyby během procesu nákupu bude zpracovávat stránka CheckoutError.aspx . Kód stránky CheckoutStart.aspx , stránky CheckoutReview.aspx a CheckoutComplete.aspx se v případě chyby přesměruje na stránku CheckoutError.aspx .
Otevřete stránku s názvem CheckoutError.aspx ve složce Checkout .
Existující kód nahraďte následujícím kódem:
<%@ 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>
Stránka CheckoutError.aspx se zobrazí s podrobnostmi o chybě, když během procesu rezervace dojde k chybě.
Spuštění aplikace
Spusťte aplikaci a zjistěte, jak koupit produkty. Mějte na paměti, že budete používat testovací prostředí PayPal. Žádné skutečné peníze se nevyměňují.
Ujistěte se, že jsou všechny soubory uložené v sadě Visual Studio.
Otevřete webový prohlížeč a přejděte na https://developer.paypal.comadresu .
Přihlaste se pomocí svého vývojářského účtu PayPal, který jste vytvořili dříve v tomto kurzu.
V sandboxu pro vývojáře PayPalu musíte být přihlášení na adrese https://developer.paypal.com , abyste mohli otestovat expresní pokladnu. To se týká pouze testování v sandboxu služby PayPal, nikoli živého prostředí PayPalu.V sadě Visual Studio stisknutím klávesy F5 spusťte ukázkovou aplikaci Wingtip Toys.
Po opětovném sestavení databáze se otevře prohlížeč a zobrazí se stránka Default.aspx .Přidejte do nákupního košíku tři různé produkty tak, že vyberete kategorii produktů, například Auta, a pak kliknete na Přidat do košíku vedle každého produktu.
V nákupním košíku se zobrazí produkt, který jste vybrali.Kliknutím na tlačítko PayPal přejděte k pokladně.
Rezervace bude vyžadovat, abyste měli uživatelský účet pro ukázkovou aplikaci Wingtip Toys.
Klikněte na odkaz Google v pravé části stránky a přihlaste se pomocí existujícího gmail.com e-mailového účtu.
Pokud nemáte účet gmail.com, můžete si ho pro účely testování vytvořit na www.gmail.com. Můžete také použít standardní místní účet kliknutím na Registrovat.Přihlaste se pomocí účtu Gmail a hesla.
Klikněte na tlačítko Přihlásit se a zaregistrujte svůj účet Gmail s uživatelským jménem ukázkové aplikace Wingtip Toys.
Na testovacím webu PayPal přidejte e-mailovou adresu a heslo kupujícího , které jste vytvořili dříve v tomto kurzu, a pak klikněte na tlačítko Přihlásit se .
Vy agree to the PayPal policy and click the Agree and Continue button.
Upozorňujeme, že tato stránka se zobrazí pouze při prvním použití tohoto účtu PayPal. Opět si všimněte, že se jedná o zkušební účet, žádné skutečné peníze se nevyměňují.Na stránce kontroly testovacího prostředí PayPal zkontrolujte informace o objednávce a klikněte na Pokračovat.
Na stránce CheckoutReview.aspx ověřte částku objednávky a podívejte se na vygenerovanou dodací adresu. Potom klikněte na tlačítko Dokončit objednávku .
Stránka CheckoutComplete.aspx se zobrazí s ID platební transakce.
Kontrola databáze
Kontrolou aktualizovaných dat v ukázkové databázi aplikace Wingtip Toys po spuštění aplikace můžete zjistit, že aplikace nákup produktů úspěšně zaznamenala.
Data obsažená v databázovém souboru Wingtiptoys.mdf můžete zkontrolovat pomocí okna Průzkumníka databáze (okno Průzkumníka serveru v sadě Visual Studio) jako dříve v této sérii kurzů.
Pokud je okno prohlížeče stále otevřené, zavřete ho.
V sadě Visual Studio vyberte ikonu Zobrazit všechny soubory v horní části Průzkumník řešení, abyste mohli rozbalit složku App_Data.
Rozbalte složku App_Data .
Možná budete muset pro složku vybrat ikonu Zobrazit všechny soubory .Klikněte pravým tlačítkem na databázový soubor Wingtiptoys.mdf a vyberte Otevřít.
Zobrazí se Průzkumník serveru.Rozbalte složku Tabulky .
Klikněte pravým tlačítkem na tabulku Orders (Objednávky) a vyberte Show Table Data (Zobrazit data tabulky).
Zobrazí se tabulka Orders (Objednávky ).Zkontrolujte sloupec PaymentTransactionID a potvrďte úspěšné transakce.
Zavřete okno tabulky Objednávky .
V Průzkumníku serveru klikněte pravým tlačítkem na tabulku OrderDetails a vyberte Zobrazit data tabulky.
OrderId
Zkontrolujte hodnoty aUsername
v tabulce OrderDetails. Všimněte si, že tyto hodnoty odpovídají hodnotámOrderId
aUsername
zahrnutým v tabulce Objednávky .Zavřete okno tabulky OrderDetails .
Klikněte pravým tlačítkem na databázový soubor Wingtip Toys (Wingtiptoys.mdf) a vyberte Zavřít připojení.
Pokud se okno Průzkumník řešení nezobrazí, klikněte na Průzkumník řešení v dolní části okna Průzkumník serveru a znovu zobrazte Průzkumník řešení.
Souhrn
V tomto kurzu jste přidali schémata objednávek a podrobností objednávek pro sledování nákupu produktů. Také jste integrli funkce PayPal do ukázkové aplikace Wingtip Toys.
Další materiály
Přehled konfigurace ASP.NET
Nasazení aplikace Secure ASP.NET Web Forms s členstvím, OAuth a SQL Database do Azure App Service
Microsoft Azure – bezplatná zkušební verze
Disclaimer
Tento kurz obsahuje ukázkový kód. Takový vzorový kód je poskytován "tak, jak je" bez jakékoli záruky. Společnost Microsoft proto nezaručuje přesnost, integritu ani kvalitu ukázkového kódu. Souhlasíte s používáním ukázkového kódu na vlastní nebezpečí. Za žádných okolností nebude společnost Microsoft vůči vám žádným způsobem odpovědná za vzorový kód, obsah, včetně mimo jiné, chyb nebo opomenutí v ukázkovém kódu, obsahu nebo jakékoli ztrátě či škodě jakéhokoli druhu, které vznikly v důsledku použití vzorového kódu. Tímto jste upozorněni a souhlasíte s tím, že odškodníte, uložíte a ochráníte společnost Microsoft před jakoukoli ztrátou, nároky na ztrátu, újmu nebo škodu jakéhokoli druhu, včetně mimo jiné těch, které vznikly nebo vznikly z materiálů, které publikujete, přenášíte, používáte nebo spoléháte na ně, mimo jiné včetně názorů v nich uvedených.