Bezahlvorgang und Zahlung mit PayPal

von Erik Reitan

Wingtip Toys Sample Project (C#) oder E-Book herunterladen (PDF)

In dieser Tutorialreihe erfahren Sie die Grundlagen zum Erstellen einer ASP.NET Web Forms-Anwendung mit ASP.NET 4.5 und Microsoft Visual Studio Express 2013 für Web. Für diese Tutorialreihe steht ein Visual Studio 2013 Projekt mit C#-Quellcode zur Verfügung.

In diesem Tutorial wird beschrieben, wie Sie die Wingtip Toys-Beispielanwendung so ändern, dass sie die Benutzerautorisierung, Registrierung und Zahlung mit PayPal umfasst. Nur angemeldete Benutzer haben die Berechtigung zum Kauf von Produkten. Die integrierte Benutzerregistrierungsfunktion der ASP.NET 4.5 Web Forms Projektvorlage enthält bereits vieles, was Sie benötigen. Sie fügen die PayPal Express Checkout-Funktionalität hinzu. In diesem Tutorial verwenden Sie die PayPal-Entwicklertestumgebung, sodass keine tatsächlichen Mittel übertragen werden. Am Ende des Tutorials testen Sie die Anwendung, indem Sie Produkte auswählen, die zum Warenkorb hinzugefügt werden sollen, auf die Schaltfläche "Checkout" klicken und Daten zur PayPal-Testwebsite übertragen. Auf der PayPal-Testwebsite bestätigen Sie Ihre Versand- und Zahlungsinformationen und kehren dann zur lokalen Wingtip Toys-Beispielanwendung zurück, um den Kauf zu bestätigen und abzuschließen.

Es gibt mehrere erfahrene Zahlungsabwickler von Drittanbietern, die sich auf Online-Shopping spezialisiert haben, die sich mit Skalierbarkeit und Sicherheit befassen. ASP.NET Entwickler sollten die Vorteile der Verwendung einer Zahlungslösung von Drittanbietern berücksichtigen, bevor sie eine Einkaufs- und Kauflösung implementieren.

Hinweis

Die Wingtip Toys-Beispielanwendung wurde entwickelt, um spezifische ASP.NET Konzepte und Features zu zeigen, die ASP.NET Webentwicklern zur Verfügung stehen. Diese Beispielanwendung war nicht für alle möglichen Umstände hinsichtlich Skalierbarkeit und Sicherheit optimiert.

Sie lernen Folgendes:

  • Einschränken des Zugriffs auf bestimmte Seiten in einem Ordner
  • Erstellen eines bekannten Einkaufswagens aus einem anonymen Warenkorb
  • Aktivieren von SSL für das Projekt
  • So fügen Sie dem Projekt einen OAuth-Anbieter hinzu.
  • Verwenden von PayPal zum Kauf von Produkten mithilfe der PayPal-Testumgebung
  • So zeigen Sie Details aus PayPal in einem DetailsView-Steuerelement an .
  • So aktualisieren Sie die Datenbank der Wingtip Toys-Anwendung mit Details, die sie von PayPal erhalten haben.

Hinzufügen der Auftragsnachverfolgung

In diesem Tutorial erstellen Sie zwei neue Klassen, um Daten aus der Reihenfolge nachzuverfolgen, die ein Benutzer erstellt hat. Die Klassen verfolgen Daten zu Versandinformationen, Kaufsumme und Zahlungsbestätigung nach.

Hinzufügen der Order- und OrderDetail-Modellklassen

Zuvor in dieser Tutorialreihe haben Sie das Schema für Kategorien, Produkte und Warenkorbelemente definiert, indem Sie die CategoryKlassen , Productund CartItem im Ordner Models erstellen. Nun fügen Sie zwei neue Klassen hinzu, um das Schema für die Produktbestellung und die Details der Bestellung zu definieren.

  1. Fügen Sie im Ordner Models eine neue Klasse mit dem Namen Order.cs hinzu.
    Die neue Klassendatei wird im Editor angezeigt.

  2. Ersetzen Sie den Standardcode durch Folgendes:

    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; }
      }
    }
    
  3. Fügen Sie dem Ordner Models eine OrderDetail.cs-Klasse hinzu.

  4. Ersetzen Sie den Standardcode durch den folgenden Code:

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

Die Order Klassen und OrderDetail enthalten das Schema zum Definieren der Bestellinformationen, die für den Kauf und Versand verwendet werden.

Darüber hinaus müssen Sie die Datenbankkontextklasse aktualisieren, die die Entitätsklassen verwaltet und Datenzugriff auf die Datenbank ermöglicht. Dazu fügen Sie die neu erstellten Order- und OrderDetail Modellklassen zur Klasse hinzu ProductContext .

  1. Suchen Sie in Projektmappen-Explorer nach der Datei ProductContext.cs, und öffnen Sie sie.

  2. Fügen Sie den hervorgehobenen Code zur Datei ProductContext.cs hinzu, wie unten gezeigt:

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

Wie bereits in dieser Tutorialreihe erwähnt, fügt der Code in der Datei ProductContext.cs den System.Data.Entity Namespace hinzu, sodass Sie Zugriff auf alle Kernfunktionen von Entity Framework haben. Diese Funktionalität umfasst die Möglichkeit, Daten durch Arbeiten mit stark typisierten Objekten abzufragen, einzufügen, zu aktualisieren und zu löschen. Mit dem obigen Code in der ProductContext -Klasse wird Entity Framework-Zugriff auf die neu hinzugefügten Order Klassen und OrderDetail hinzugefügt.

Hinzufügen des Auscheckzugriffs

Die Wingtip Toys-Beispielanwendung ermöglicht anonymen Benutzern das Überprüfen und Hinzufügen von Produkten zu einem Einkaufswagen. Wenn anonyme Benutzer jedoch die Produkte kaufen, die sie dem Warenkorb hinzugefügt haben, müssen sie sich bei der Website anmelden. Sobald sie sich angemeldet haben, können sie auf die eingeschränkten Seiten der Webanwendung zugreifen, die den Auscheck- und Kaufvorgang verarbeiten. Diese eingeschränkten Seiten sind im Ordner Checkout der Anwendung enthalten.

Hinzufügen eines Auscheckordners und von Seiten

Sie erstellen nun den Ordner Checkout und die Darin enthaltenen Seiten, die dem Kunden während des Auscheckvorgangs angezeigt werden. Sie werden diese Seiten weiter unten in diesem Tutorial aktualisieren.

  1. Klicken Sie mit der rechten Maustaste auf den Projektnamen (Wingtip Toys) in Projektmappen-Explorer, und wählen Sie Neuen Ordner hinzufügen aus.

    Auschecken und Bezahlen mit PayPal – Neuer Ordner

  2. Nennen Sie den neuen Ordner Checkout.

  3. Klicken Sie mit der rechten Maustaste auf den Ordner Checkout, und wählen Sie dann Neues Elementhinzufügen> aus.

    Checkout und Zahlung mit PayPal – Neuer Artikel

  4. Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  5. Wählen Sie links die Gruppe Visual C#->Webvorlagen aus. Wählen Sie dann im mittleren Bereich Webformular mit Gestaltungsvorlageaus, und nennen Sie es CheckoutStart.aspx.

    Checkout und Zahlung mit PayPal – Dialogfeld

  6. Wählen Sie wie zuvor die Datei Site.Master als master Seite aus.

  7. Fügen Sie dem Ordner Checkout die folgenden zusätzlichen Seiten mit den oben beschriebenen Schritten hinzu:

    • CheckoutReview.aspx
    • CheckoutComplete.aspx
    • CheckoutCancel.aspx
    • CheckoutError.aspx

Hinzufügen einer Web.config-Datei

Wenn Sie dem Ordner Checkout eine neue Web.config-Datei hinzufügen, können Sie den Zugriff auf alle im Ordner enthaltenen Seiten einschränken.

  1. Klicken Sie mit der rechten Maustaste auf den Ordner Auschecken , und wählen Sie Hinzufügen –>Neues Element aus.
    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  2. Wählen Sie links die Gruppe Visual C#->Webvorlagen aus. Wählen Sie dann im mittleren Bereich Webkonfigurationsdatei aus, übernehmen Sie den Standardnamen Web.config, und wählen Sie dann Hinzufügen aus.

  3. Ersetzen Sie den vorhandenen XML-Inhalt in der Datei Web.config durch den folgenden Code:

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <authorization>
          <deny users="?"/>
        </authorization>
      </system.web>
    </configuration>
    
  4. Speichern Sie die Datei Web.config .

Die Web.config-Datei gibt an, dass allen unbekannten Benutzern der Webanwendung der Zugriff auf die im Ordner Checkout enthaltenen Seiten verweigert werden muss. Wenn der Benutzer jedoch ein Konto registriert und angemeldet ist, ist er ein bekannter Benutzer und hat Zugriff auf die Seiten im Ordner Checkout .

Es ist wichtig zu beachten, dass ASP.NET Konfiguration einer Hierarchie folgt, in der jede Web.config Datei Konfigurationseinstellungen auf den Ordner anwendet, in dem sie sich befindet, und auf alle untergeordneten Verzeichnisse darunter.

Aktivieren von SSL für das Projekt

Secure Sockets Layer (SSL) ist ein Protokoll, das Webservern und Webclients eine sichere Kommunikation durch Verschlüsselung ermöglicht. Wird kein SSL verwendet, können die zwischen Client und Server gesendeten Daten von jedem mit physischem Zugriff auf das Netzwerk per Paket-Sniffing ausgespäht werden. Außerdem sind verschiedene häufig verwendete Authentifizierungsschemas über einfaches HTTP nicht sicher. Insbesondere senden die einfache Authentifizierung und Formularauthentifizierung unverschlüsselte Anmeldeinformationen. Aus Sicherheitsgründen sollten diese Authentifizierungsschemas SSL verwenden.

  1. Klicken Sie in Projektmappen-Explorer auf das Projekt WingtipToys, und drücken Sie dann F4, um das Eigenschaftenfenster anzuzeigen.
  2. Ändern Sie SSL-aktiviert in true.
  3. Kopieren Sie die SSL-URL , damit Sie sie später verwenden können.
    Die SSL-URL lautet https://localhost:44300/ , es sei denn, Sie haben zuvor SSL-Websites erstellt (wie unten dargestellt).
    Projekteigenschaften
  4. Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Projekt WingtipToys, und klicken Sie dann auf Eigenschaften.
  5. Klicken Sie auf der linken Registerkarte auf Web.
  6. Ändern Sie die Projekt-URL , um die zuvor gespeicherte SSL-URL zu verwenden.
    Projektwebeigenschaften
  7. Drücken Sie STRG+S, um die Seite zu speichern.
  8. Drücken Sie STRG+F5 , um die Anwendung auszuführen. Visual Studio zeigt eine Option an, die es Ihnen ermöglicht, SSL-Warnungen zu vermeiden.
  9. Klicken Sie auf Ja , um dem IIS Express SSL-Zertifikat zu vertrauen und fortzufahren.
    IIS Express SSL-Zertifikatdetails
    Es wird eine Sicherheitswarnung angezeigt.
  10. Klicken Sie auf Ja , um das Zertifikat zu Ihrem Localhost zu installieren.
    Dialogfeld
    Das Browserfenster wird angezeigt.

Sie können Ihre Webanwendung jetzt ganz einfach lokal mithilfe von SSL testen.

Hinzufügen eines OAuth 2.0-Anbieters

ASP.NET Web Forms bietet erweiterte Optionen für Mitgliedschaft und Authentifizierung. Diese Erweiterungen umfassen OAuth. OAuth ist ein offenes Protokoll, das die sichere Autorisierung in einer einfachen und Standardmethode von Web-, Mobil- und Desktopanwendungen ermöglicht. Die vorlage ASP.NET Web Forms verwendet OAuth, um Facebook, Twitter, Google und Microsoft als Authentifizierungsanbieter verfügbar zu machen. Auch wenn in diesem Lernprogramm nur Google als Authentifizierungsanbieter eingesetzt wird, können Sie den Code problemlos für die Verwendung einer der anderen Anbieter anpassen. Die Schritte zur Implementierung anderer Anbieter unterscheiden sich kaum von den Schritten in diesem Lernprogramm.

Abgesehen von der Authentifizierung werden in diesem Lernprogramm auch Rollen verwendet, um die Autorisierung zu implementieren. Nur Benutzer, die Sie der Rolle canEdit hinzufügen, können Daten ändern (Kontakte erstellen, bearbeiten oder löschen.

Hinweis

Windows Live-Anwendungen akzeptieren nur eine Live-URL für eine funktionierende Website, sodass Sie keine lokale Website-URL zum Testen von Anmeldungen verwenden können.

Mit den folgenden Schritten können Sie einen Google-Authentifizierungsanbieter hinzufügen.

  1. Öffnen Sie die Datei App_Start\Startup.Auth.cs .

  2. Entfernen Sie die Kommentarzeichen aus der app.UseGoogleAuthentication() -Methode, sodass sie wie folgt aussieht:

    app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
    {
        ClientId = "",
        ClientSecret = ""
    });
    
  3. Navigieren Sie zur Google Developers Console. Außerdem müssen Sie sich mit Ihrem Google Entwickler-E-Mail-Konto anmelden (gmail.com). Wenn Sie nicht über ein Google-Konto verfügen, wählen Sie den Link Konto erstellen aus.
    Danach sehen Sie die Google Entwickler-Konsole.
    Google Developers Console

  4. Klicken Sie auf die Schaltfläche Projekt erstellen, und geben Sie einen Projektnamen und eine ID ein (Sie können die Standardwerte verwenden). Klicken Sie dann auf das Kontrollkästchen vereinbarung und auf die Schaltfläche Erstellen .

    Google - Neues Projekt

    In wenigen Sekunden wird das neue Projekt erstellt, und Ihr Browser zeigt die Seite für neue Projekte an.

  5. Klicken Sie auf der linken Registerkarte auf APIs & Authentifizierung, und klicken Sie dann auf Anmeldeinformationen.

  6. Klicken Sie unter OAuth auf Neue Client-ID erstellen.
    Das Dialogfeld Client-ID erstellen wird angezeigt.
    Google – Erstellen der Client-ID

  7. Behalten Sie im Dialogfeld Client-ID erstellen die Standardwebanwendung für den Anwendungstyp bei.

  8. Legen Sie die autorisierten JavaScript-Ursprünge auf die SSL-URL fest, die Sie zuvor in diesem Tutorial verwendet haben (https://localhost:44300/ es sei denn, Sie haben andere SSL-Projekte erstellt).
    Diese URL ist der Ursprung für Ihre Anwendung. In diesem Beispiel geben Sie nur die Test-URL "localhost" ein. Sie können jedoch mehrere URLs eingeben, um localhost und production zu berücksichtigen.

  9. Legen Sie Authorized Redirect URI folgendermaßen fest:

    https://localhost:44300/signin-google
    

    Dieser Wert steht für den URI, den ASP.NET OAuth-Benutzer zur Kommunikation mit dem Google OAuth-Server verwenden. Merken Sie sich die SSL-URL, die Sie oben verwendet haben ( https://localhost:44300/ es sei denn, Sie haben andere SSL-Projekte erstellt).

  10. Klicken Sie auf die Schaltfläche Client-ID erstellen .

  11. Klicken Sie im linken Menü der Google Developers Console auf das Menüelement Zustimmungsbildschirm , und legen Sie dann Ihre E-Mail-Adresse und Ihren Produktnamen fest. Wenn Sie das Formular ausgefüllt haben, klicken Sie auf Speichern.

  12. Klicken Sie auf das Menüelement APIs, scrollen Sie nach unten, und klicken Sie neben Google+ API auf die Schaltfläche aus.
    Wenn Sie diese Option akzeptieren, wird die Google+-API aktiviert.

  13. Außerdem müssen Sie das NuGet-Paket Microsoft.Owin auf Version 3.0.0 aktualisieren.
    Wählen Sie im Menü Extras die Option NuGet-Paket-Manager und dann NuGet-Pakete für Projektmappe verwalten aus.
    Suchen Sie im Fenster NuGet-Pakete verwalten nach dem Microsoft.Owin-Paket , und aktualisieren Sie es auf Version 3.0.0.

  14. Aktualisieren Sie in Visual Studio die UseGoogleAuthentication -Methode der Seite Startup.Auth.cs , indem Sie die Client-ID und den geheimen Clientschlüssel in die -Methode kopieren und einfügen. Die unten gezeigten Werte client-ID und geheimer Clientschlüssel sind Beispiele und funktionieren nicht.

    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"
                });
            }
        }
    }
    
  15. Drücken Sie STRG+F5 , um die Anwendung zu erstellen und auszuführen. Klicken Sie auf den Link Log in .

  16. Klicken Sie unter Anderen Dienst zum Anmelden verwenden auf Google.
    Anmelden

  17. Wenn Sie Ihre Anmeldeinformationen eingeben müssen, werden Sie zur Google-Website umgeleitet, wo Sie Ihre Anmeldeinformationen eingeben.
    Google - Anmeldung

  18. Nachdem Sie Ihre Anmeldeinformationen eingegeben haben, werden Sie aufgefordert, der soeben erstellten Webanwendung Berechtigungen zu erteilen.
    Standard-Dienstkonto für Projekt

  19. Klicken Sie auf Annehmen. Sie werden nun zurück zur Registrierungsseite der WingtipToys-Anwendung weitergeleitet, wo Sie Ihr Google-Konto registrieren können.
    Registrieren Sie sich mit Ihrem Google-Konto

  20. Sie können zwar den lokalen E-Mail-Registrierungsnamen in Ihr Gmail-Konto ändern, im Allgemeinen sollten Sie jedoch den Standard-E-Mail-Aliasnamen beibehalten (den Sie für die Authentifizierung verwendet haben). Klicken Sie wie oben gezeigt auf Anmelden .

Ändern der Anmeldefunktionalität

Wie bereits in dieser Tutorialreihe erwähnt, ist ein Großteil der Benutzerregistrierungsfunktion standardmäßig in der vorlage ASP.NET Web Forms enthalten. Jetzt ändern Sie die Standardseiten Login.aspx und Register.aspx , um die MigrateCart -Methode aufzurufen. Die MigrateCart -Methode ordnet einem neu angemeldeten Benutzer einen anonymen Einkaufswagen zu. Durch die Zuordnung des Benutzers und des Einkaufswagens ist die Wingtip Toys-Beispielanwendung in der Lage, den Einkaufswagen des Benutzers zwischen den Besuchen zu verwalten.

  1. Suchen Und öffnen Sie in Projektmappen-Explorer den Ordner Konto.

  2. Ändern Sie die CodeBehind-Seite Login.aspx.cs so, dass sie den gelb hervorgehobenen Code enthält, sodass er wie folgt angezeigt wird:

    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;
                    }
                }
            }
        }
    }
    
  3. Speichern Sie die Datei Login.aspx.cs .

Vorerst können Sie die Warnung ignorieren, dass keine Definition für die MigrateCart -Methode vorhanden ist. Sie werden es später in diesem Tutorial hinzufügen.

Die CodeBehind-Datei Login.aspx.cs unterstützt eine LogIn-Methode. Wenn Sie die Seite Login.aspx überprüfen, sehen Sie, dass diese Seite eine Schaltfläche "Anmelden" enthält, die beim Klicken den LogIn Handler für das CodeBehind auslöst.

Wenn die Login Methode für Login.aspx.cs aufgerufen wird, wird eine neue instance des Einkaufswagens mit dem Namen usersShoppingCart erstellt. Die ID des Warenkorbs (eine GUID) wird abgerufen und auf die cartId Variable festgelegt. Anschließend wird die MigrateCart -Methode aufgerufen, wobei sowohl der cartId - als auch der Name des angemeldeten Benutzers an diese Methode übergeben werden. Wenn der Warenkorb migriert wird, wird die GUID, die zum Identifizieren des anonymen Einkaufswagens verwendet wird, durch den Benutzernamen ersetzt.

Zusätzlich zum Ändern der Codebehinddatei Login.aspx.cs , um den Einkaufswagen zu migrieren, wenn sich der Benutzer anmeldet, müssen Sie auch die CodeBehind-Datei Register.aspx.cs ändern, um den Einkaufswagen zu migrieren, wenn der Benutzer ein neues Konto erstellt und sich anmeldet.

  1. Öffnen Sie im Ordner Konto die CodeBehind-Datei namens Register.aspx.cs.

  2. Ändern Sie die CodeBehind-Datei, indem Sie den Code in gelb einfügen, sodass er wie folgt angezeigt wird:

    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();
                }
            }
        }
    }
    
  3. Speichern Sie die Datei Register.aspx.cs . Ignorieren Sie erneut die Warnung zur MigrateCart -Methode.

Beachten Sie, dass der Code, den CreateUser_Click Sie im Ereignishandler verwendet haben, dem Code, den Sie in der LogIn -Methode verwendet haben, sehr ähnlich ist. Wenn sich der Benutzer bei der Website registriert oder sich bei dieser anmeldet, wird ein Aufruf der MigrateCart -Methode ausgeführt.

Migrieren des Warenkorbs

Nachdem Sie den Anmelde- und Registrierungsvorgang aktualisiert haben, können Sie den Code zum Migrieren des Einkaufswagens mithilfe der MigrateCart -Methode hinzufügen.

  1. Suchen Sie in Projektmappen-Explorer den Ordner Logic, und öffnen Sie die Klassendatei ShoppingCartActions.cs.

  2. Fügen Sie den gelb hervorgehobenen Code dem vorhandenen Code in der Datei ShoppingCartActions.cs hinzu, damit der Code in der Datei ShoppingCartActions.cs wie folgt angezeigt wird:

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

Die MigrateCart -Methode verwendet die vorhandene cartId, um den Warenkorb des Benutzers zu finden. Als Nächstes durchläuft der Code alle Warenkorbelemente und ersetzt die CartId -Eigenschaft (wie im CartItem Schema angegeben) durch den angemeldeten Benutzernamen.

Aktualisieren der Datenbankverbindung

Wenn Sie dieses Tutorial mithilfe der vordefinierten Wingtip Toys-Beispielanwendung ausführen, müssen Sie die Standardmitgliedschaftsdatenbank neu erstellen. Durch Ändern der Standard-Verbindungszeichenfolge wird die Mitgliedschaftsdatenbank erstellt, wenn die Anwendung das nächste Mal ausgeführt wird.

  1. Öffnen Sie die Web.config-Datei im Stammverzeichnis des Projekts.

  2. Aktualisieren Sie die Standard-Verbindungszeichenfolge, sodass sie wie folgt angezeigt wird:

    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=aspnet-WingtipToys;Integrated Security=True" providerName="System.Data.SqlClient" />
    

Integrieren von PayPal

PayPal ist eine webbasierte Abrechnungsplattform, die Zahlungen von Onlinehändlern akzeptiert. In diesem Tutorial erfahren Sie, wie Sie die Express Checkout-Funktionalität von PayPal in Ihre Anwendung integrieren. Express Checkout ermöglicht Es Ihren Kunden, PayPal zu verwenden, um die Artikel zu bezahlen, die sie ihrem Warenkorb hinzugefügt haben.

Erstellen von PayPal-Testkonten

Um die PayPal-Testumgebung verwenden zu können, müssen Sie ein Entwicklertestkonto erstellen und überprüfen. Sie verwenden das Entwicklertestkonto, um ein Käufertestkonto und ein Verkäufertestkonto zu erstellen. Die Anmeldeinformationen des Entwicklertestkontos ermöglichen der Wingtip Toys-Beispielanwendung auch den Zugriff auf die PayPal-Testumgebung.

  1. Navigieren Sie in einem Browser zur Testwebsite für PayPal-Entwickler:
    https://developer.paypal.com

  2. Wenn Sie kein PayPal-Entwicklerkonto besitzen, erstellen Sie ein neues Konto, indem Sie auf Registrierenklicken und die Schritte zur Registrierung befolgen. Wenn Sie über ein vorhandenes PayPal-Entwicklerkonto verfügen, melden Sie sich an, indem Sie auf Anmelden klicken. Sie benötigen Ihr PayPal-Entwicklerkonto, um die Wingtip Toys-Beispielanwendung später in diesem Tutorial zu testen.

  3. Wenn Sie sich gerade für Ihr PayPal-Entwicklerkonto registriert haben, müssen Sie möglicherweise Ihr PayPal-Entwicklerkonto bei PayPal überprüfen. Sie können Ihr Konto überprüfen, indem Sie die Schritte ausführen, die PayPal an Ihr E-Mail-Konto gesendet hat. Nachdem Sie Ihr PayPal-Entwicklerkonto überprüft haben, melden Sie sich wieder bei der PayPal-Entwicklertestwebsite an.

  4. Nachdem Sie mit Ihrem PayPal-Entwicklerkonto bei der PayPal-Entwicklerwebsite angemeldet sind, müssen Sie ein PayPal-Käufertestkonto erstellen, falls Sie noch keins besitzen. Um ein Käufertestkonto zu erstellen, klicken Sie auf der PayPal-Website auf die Registerkarte Anwendungen und dann auf Sandboxkonten.
    Die Seite Sandbox-Testkonten wird angezeigt.

    Hinweis

    Die PayPal Developer-Website stellt bereits ein Händler-Testkonto bereit.

    Screenshot: Seite

  5. Klicken Sie auf der Seite Sandbox-Testkonten auf Konto erstellen.

  6. Wählen Sie auf der Seite Testkonto erstellen die E-Mail-Adresse und das Kennwort des Käufertestkontos Ihrer Wahl aus.

    Hinweis

    Sie benötigen die E-Mail-Adressen und das Kennwort des Käufers, um die Wingtip Toys-Beispielanwendung am Ende dieses Tutorials zu testen.

    Screenshot der Seite

  7. Erstellen Sie das Käufertestkonto, indem Sie auf die Schaltfläche Konto erstellen klicken.
    Die Seite Sandbox-Testkonten wird angezeigt.

    Kasse und Zahlung mit PayPal - PayPal-Konten

  8. Klicken Sie auf der Seite Sandbox-Testkonten auf das E-Mail-Konto des Vermittlers .
    Profil - und Benachrichtigungsoptionen werden angezeigt.

  9. Wählen Sie die Option Profil aus, und klicken Sie dann auf API-Anmeldeinformationen , um Ihre API-Anmeldeinformationen für das Händlertestkonto anzuzeigen.

  10. Kopieren Sie die TEST-API-Anmeldeinformationen in den Editor.

Sie benötigen Ihre angezeigten Anmeldeinformationen der klassischen TEST-API (Benutzername, Kennwort und Signatur), um API-Aufrufe von der Wingtip Toys-Beispielanwendung an die PayPal-Testumgebung zu tätigen. Sie fügen die Anmeldeinformationen im nächsten Schritt hinzu.

Hinzufügen von PayPal-Klassen- und API-Anmeldeinformationen

Sie platzieren den Großteil des PayPal-Codes in einer einzelnen Klasse. Diese Klasse enthält die Methoden, die für die Kommunikation mit PayPal verwendet werden. Außerdem fügen Sie dieser Klasse Ihre PayPal-Anmeldeinformationen hinzu.

  1. Klicken Sie in der Wingtip Toys-Beispielanwendung in Visual Studio mit der rechten Maustaste auf den Ordner Logic , und wählen Sie dann Hinzufügen –>Neues Element aus.
    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  2. Wählen Sie unter Visual C# im Bereich Installiert auf der linken Seite Code aus.

  3. Wählen Sie im mittleren Bereich Die Option Klasse aus. Nennen Sie diese neue Klasse PayPalFunctions.cs.

  4. Klicken Sie auf Hinzufügen.
    Die neue Klassendatei wird im Editor angezeigt.

  5. Ersetzen Sie den Standardcode durch den folgenden Code:

    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;
      }
    }
    
  6. Fügen Sie die Anmeldeinformationen der Händler-API (Benutzername, Kennwort und Signatur) hinzu, die Sie weiter oben in diesem Tutorial angezeigt haben, damit Sie Funktionsaufrufe an die PayPal-Testumgebung durchführen können.

    public string APIUsername = "<Your API Username>";
    private string APIPassword = "<Your API Password>";
    private string APISignature = "<Your Signature>";
    

Hinweis

In dieser Beispielanwendung fügen Sie einfach Anmeldeinformationen zu einer C#-Datei (CS) hinzu. In einer implementierten Lösung sollten Sie jedoch erwägen, Ihre Anmeldeinformationen in einer Konfigurationsdatei zu verschlüsseln.

Die NVPAPICaller-Klasse enthält den Großteil der PayPal-Funktionalität. Der Code in der -Klasse stellt die Methoden bereit, die für einen Testkauf aus der PayPal-Testumgebung erforderlich sind. Die folgenden drei PayPal-Funktionen werden für Einkäufe verwendet:

  • SetExpressCheckout-Funktion
  • GetExpressCheckoutDetails-Funktion
  • DoExpressCheckoutPayment-Funktion

Die ShortcutExpressCheckout Methode sammelt die Test-Kaufinformationen und Produktdetails aus dem Warenkorb und ruft die SetExpressCheckout PayPal-Funktion auf. Die GetCheckoutDetails -Methode bestätigt die Kaufdetails und ruft die GetExpressCheckoutDetails PayPal-Funktion auf, bevor sie den Testkauf durchführt. Die DoCheckoutPayment -Methode schließt den Testkauf aus der Testumgebung ab, indem die DoExpressCheckoutPayment PayPal-Funktion aufgerufen wird. Der verbleibende Code unterstützt die PayPal-Methoden und -Prozesse, z. B. Codierungszeichenfolgen, Decodieren von Zeichenfolgen, Verarbeiten von Arrays und Bestimmen von Anmeldeinformationen.

Hinweis

Mit PayPal können Sie optionale Kaufdetails basierend auf der API-Spezifikation von PayPal angeben. Indem Sie den Code in der Wingtip Toys-Beispielanwendung erweitern, können Sie Lokalisierungsdetails, Produktbeschreibungen, Steuern, eine Kundendienstnummer sowie viele andere optionale Felder einschließen.

Beachten Sie, dass die Rückgabe- und Abbruch-URLs, die in der ShortcutExpressCheckout-Methode angegeben sind, eine Portnummer verwenden.

string returnURL = "https://localhost:44300/Checkout/CheckoutReview.aspx";
       string cancelURL = "https://localhost:44300/Checkout/CheckoutCancel.aspx";

Wenn Visual Web Developer ein Webprojekt mit SSL ausführt, wird häufig der Port 44300 für den Webserver verwendet. Wie oben gezeigt, lautet die Portnummer 44300. Wenn Sie die Anwendung ausführen, wird möglicherweise eine andere Portnummer angezeigt. Ihre Portnummer muss im Code richtig festgelegt sein, damit Sie die Wingtip Toys-Beispielanwendung am Ende dieses Tutorials erfolgreich ausführen können. Im nächsten Abschnitt dieses Tutorials wird erläutert, wie Sie die lokale Hostportnummer abrufen und die PayPal-Klasse aktualisieren.

Aktualisieren der LocalHost-Portnummer in der PayPal-Klasse

Die Wingtip Toys-Beispielanwendung kauft Produkte, indem Sie zur PayPal-Testwebsite navigieren und zu Ihrem lokalen instance der Wingtip Toys-Beispielanwendung zurückkehren. Damit PayPal zur richtigen URL zurückkehrt, müssen Sie die Portnummer der lokal ausgeführten Beispielanwendung im oben genannten PayPal-Code angeben.

  1. Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf den Projektnamen (WingtipToys), und wählen Sie Eigenschaften aus.

  2. Wählen Sie in der linken Spalte die Registerkarte Web aus.

  3. Rufen Sie die Portnummer aus dem Feld Projekt-URL ab.

  4. Aktualisieren Sie bei Bedarf die returnURL und cancelURL in der PayPal-Klasse (NVPAPICaller) in der Datei PayPalFunctions.cs , um die Portnummer Ihrer Webanwendung zu verwenden:

    string returnURL = "https://localhost:<Your Port Number>/Checkout/CheckoutReview.aspx";
    string cancelURL = "https://localhost:<Your Port Number>/Checkout/CheckoutCancel.aspx";
    

Nun stimmt der hinzugefügte Code mit dem erwarteten Port für Ihre lokale Webanwendung überein. PayPal kann zur richtigen URL auf Ihrem lokalen Computer zurückkehren.

Hinzufügen der Schaltfläche "PayPal Checkout"

Nachdem der Beispielanwendung die primären PayPal-Funktionen hinzugefügt wurden, können Sie damit beginnen, das Markup und den Code hinzuzufügen, der zum Aufrufen dieser Funktionen erforderlich ist. Zuerst müssen Sie die Schaltfläche zum Auschecken hinzufügen, die dem Benutzer auf der Warenkorbseite angezeigt wird.

  1. Öffnen Sie die Datei ShoppingCart.aspx .

  2. Scrollen Sie zum Ende der Datei, und suchen Sie den <!--Checkout Placeholder --> Kommentar.

  3. Ersetzen Sie den Kommentar durch ein ImageButton Steuerelement, sodass der Aufschlag wie folgt ersetzt wird:

    <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" />
    
  4. Fügen Sie in der Datei ShoppingCart.aspx.cs nach dem UpdateBtn_Click Ereignishandler am Ende der Datei den CheckOutBtn_Click Ereignishandler hinzu:

    protected void CheckoutBtn_Click(object sender, ImageClickEventArgs e)
    {
        using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
        {
            Session["payment_amt"] = usersShoppingCart.GetTotal();
        }
        Response.Redirect("Checkout/CheckoutStart.aspx");
    }
    
  5. Fügen Sie auch in der Datei ShoppingCart.aspx.cs einen Verweis auf hinzu CheckoutBtn, damit auf die Schaltfläche für das neue Bild wie folgt verwiesen wird:

    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;
            }
        }
    }
    
  6. Speichern Sie Ihre Änderungen sowohl in der Datei ShoppingCart.aspx als auch in der Datei ShoppingCart.aspx.cs .

  7. Wählen Sie im Menü Debug-Build>WingtipToys aus.
    Das Projekt wird mit dem neu hinzugefügten ImageButton-Steuerelement neu erstellt.

Senden von Kaufdetails an PayPal

Wenn der Benutzer auf der Warenkorbseite (ShoppingCart.aspx) auf die Schaltfläche Auschecken klickt, beginnt er mit dem Kaufvorgang. Der folgende Code ruft die erste PayPal-Funktion auf, die für den Kauf von Produkten erforderlich ist.

  1. Öffnen Sie im Ordner Checkout die CodeBehind-Datei mit dem Namen CheckoutStart.aspx.cs.
    Stellen Sie sicher, dass Sie die CodeBehind-Datei öffnen.

  2. Ersetzen Sie den vorhandenen Code durch folgenden Code:

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

Wenn der Benutzer der Anwendung auf der Warenkorbseite auf die Schaltfläche Auschecken klickt, navigiert der Browser zur Seite CheckoutStart.aspx . Wenn die Seite CheckoutStart.aspx geladen wird, wird die ShortcutExpressCheckout -Methode aufgerufen. An dieser Stelle wird der Nutzer auf die PayPal-Testwebsite weitergeleitet. Auf der PayPal-Website gibt der Benutzer seine PayPal-Anmeldeinformationen ein, überprüft die Kaufdetails, akzeptiert den PayPal-Vertrag und kehrt zur Wingtip Toys-Beispielanwendung zurück, in der die ShortcutExpressCheckout Methode abgeschlossen ist. Wenn die ShortcutExpressCheckout Methode abgeschlossen ist, leitet sie den Benutzer zur Seite CheckoutReview.aspx um, die in der ShortcutExpressCheckout -Methode angegeben ist. Dadurch kann der Benutzer die Bestelldetails in der Wingtip Toys-Beispielanwendung überprüfen.

Überprüfen der Bestelldetails

Nach der Rückkehr von PayPal werden auf der Seite CheckoutReview.aspx der Wingtip Toys-Beispielanwendung die Bestelldetails angezeigt. Auf dieser Seite kann der Benutzer die Bestelldetails vor dem Kauf der Produkte überprüfen. Die Seite CheckoutReview.aspx muss wie folgt erstellt werden:

  1. Öffnen Sie im Ordner Checkout die Seite CheckoutReview.aspx.

  2. Ersetzen Sie das vorhandene Markup durch Folgendes:

    <%@ 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>
    
  3. Öffnen Sie die CodeBehind-Seite mit dem Namen CheckoutReview.aspx.cs , und ersetzen Sie den vorhandenen Code durch Folgendes:

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

Das DetailsView-Steuerelement wird verwendet, um die Bestelldetails anzuzeigen, die von PayPal zurückgegeben wurden. Außerdem speichert der obige Code die Bestelldetails in der Wingtip Toys-Datenbank als OrderDetail Objekt. Wenn der Benutzer auf die Schaltfläche Bestellung abschließen klickt, wird er zur Seite CheckoutComplete.aspx umgeleitet.

Hinweis

Tipp

Beachten Sie im Markup der Seite CheckoutReview.aspx , dass das <ItemStyle> -Tag verwendet wird, um den Stil der Elemente im DetailsView-Steuerelement am unteren Rand der Seite zu ändern. Wenn Sie die Seite in der Entwurfsansicht anzeigen (indem Sie in der unteren linken Ecke von Visual Studio Entwurf auswählen), dann das Steuerelement DetailsView auswählen und das Smarttag (das Pfeilsymbol oben rechts im Steuerelement) auswählen, können Sie die DetailsView-Aufgaben sehen.

Auschecken und Bezahlen mit PayPal – Felder bearbeiten

Wenn Sie Felder bearbeiten auswählen, wird das Dialogfeld Felder angezeigt. In diesem Dialogfeld können Sie die visuellen Eigenschaften, z. B . ItemStyle, des DetailsView-Steuerelements ganz einfach steuern.

Auschecken und Bezahlen mit PayPal – Dialogfeld

Abschließen des Kaufs

CheckoutComplete.aspx-Seite macht den Kauf bei PayPal. Wie bereits erwähnt, muss der Benutzer auf die Schaltfläche Bestellung abschließen klicken, bevor die Anwendung zur Seite CheckoutComplete.aspx navigiert.

  1. Öffnen Sie im Ordner Checkout die Seite CheckoutComplete.aspx.

  2. Ersetzen Sie das vorhandene Markup durch Folgendes:

    <%@ 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>
    
  3. Öffnen Sie die CodeBehind-Seite mit dem Namen CheckoutComplete.aspx.cs , und ersetzen Sie den vorhandenen Code durch Folgendes:

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

Wenn die Seite CheckoutComplete.aspx geladen wird, wird die DoCheckoutPayment -Methode aufgerufen. Wie bereits erwähnt, schließt die DoCheckoutPayment Methode den Kauf aus der PayPal-Testumgebung ab. Nachdem PayPal den Kauf der Bestellung abgeschlossen hat, wird auf der Seite CheckoutComplete.aspx eine Zahlungstransaktion ID für den Käufer angezeigt.

Abbrechen des Kaufs behandeln

Wenn der Benutzer entscheidet, den Kauf zu stornieren, wird er zur Seite CheckoutCancel.aspx weitergeleitet, auf der er sehen wird, dass seine Bestellung storniert wurde.

  1. Öffnen Sie die Seite Mit dem Namen CheckoutCancel.aspx im Ordner Checkout .

  2. Ersetzen Sie das vorhandene Markup durch Folgendes:

    <%@ 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>
    

Behandeln von Kauffehlern

Fehler während des Kaufvorgangs werden von der Seite CheckoutError.aspx behandelt. Der CodeBehind der Seite CheckoutStart.aspx , der Seite CheckoutReview.aspx und der Seite CheckoutComplete.aspx werden bei Auftreten eines Fehlers jeweils zur Seite CheckoutError.aspx umgeleitet.

  1. Öffnen Sie die Seite Mit dem Namen CheckoutError.aspx im Ordner Checkout .

  2. Ersetzen Sie das vorhandene Markup durch Folgendes:

    <%@ 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>
    

Die Seite CheckoutError.aspx wird mit den Fehlerdetails angezeigt, wenn während des Auscheckvorgangs ein Fehler auftritt.

Ausführen der Anwendung

Führen Sie die Anwendung aus, um zu sehen, wie Produkte erworben werden. Beachten Sie, dass Sie in der PayPal-Testumgebung ausgeführt werden. Es wird kein tatsächliches Geld umgetauscht.

  1. Stellen Sie sicher, dass alle Ihre Dateien in Visual Studio gespeichert sind.

  2. Öffnen Sie einen Webbrowser, und navigieren Sie zu https://developer.paypal.com.

  3. Melden Sie sich mit Ihrem PayPal-Entwicklerkonto an, das Sie zuvor in diesem Tutorial erstellt haben.
    Für die Entwicklersandbox von PayPal müssen Sie unter https://developer.paypal.com angemeldet sein, um die Express-Kasse testen zu können. Dies gilt nur für Die Sandboxtests von PayPal, nicht für die Liveumgebung von PayPal.

  4. Drücken Sie in Visual Studio F5 , um die Wingtip Toys-Beispielanwendung auszuführen.
    Nachdem die Datenbank neu erstellt wurde, wird der Browser geöffnet und die Seite Default.aspx angezeigt.

  5. Fügen Sie dem Warenkorb drei verschiedene Produkte hinzu, indem Sie die Produktkategorie auswählen, z. B. "Autos", und klicken Sie dann neben jedem Produkt auf In den Warenkorb hinzufügen .
    Im Warenkorb wird das ausgewählte Produkt angezeigt.

  6. Klicken Sie zum Auschecken auf die PayPal-Schaltfläche .

    Kasse und Zahlung mit PayPal - Warenkorb

    Beim Auschecken müssen Sie über ein Benutzerkonto für die Wingtip Toys-Beispielanwendung verfügen.

  7. Klicken Sie auf den Google-Link rechts neben der Seite, um sich mit einem vorhandenen gmail.com E-Mail-Konto anzumelden.
    Wenn Sie nicht über ein gmail.com-Konto verfügen, können Sie eines zu Testzwecken auf www.gmail.com erstellen. Sie können auch ein lokales Standardkonto verwenden, indem Sie auf "Registrieren" klicken.

    Kasse und Zahlung mit PayPal – Anmelden

  8. Melden Sie sich mit Ihrem Gmail-Konto und Kennwort an.

    Auschecken und Bezahlen mit PayPal – Gmail-Anmeldung

  9. Klicken Sie auf die Schaltfläche Anmelden , um Ihr Gmail-Konto mit dem Benutzernamen Ihrer Wingtip Toys-Beispielanwendung zu registrieren.

    Kasse und Zahlung mit PayPal – Konto registrieren

  10. Fügen Sie auf der PayPal-Testwebsite Ihre Käufer-E-Mail-Adresse und ihr Kennwort hinzu, die Sie zuvor in diesem Tutorial erstellt haben, und klicken Sie dann auf die Schaltfläche Anmelden.

    Auschecken und Bezahlen mit PayPal - PayPal-Anmeldung

  11. Stimmen Sie der PayPal-Richtlinie zu, und klicken Sie auf die Schaltfläche Zustimmen und Fortfahren .
    Beachten Sie, dass diese Seite nur angezeigt wird, wenn Sie dieses PayPal-Konto zum ersten Mal verwenden. Beachten Sie erneut, dass dies ein Testkonto ist, kein echtes Geld umgetauscht wird.

    Auschecken und Bezahlen mit PayPal - PayPal-Richtlinie

  12. Überprüfen Sie die Bestellinformationen auf der Überprüfungsseite der PayPal-Testumgebung, und klicken Sie auf Weiter.

    Auschecken und Bezahlen mit PayPal – Informationen überprüfen

  13. Überprüfen Sie auf der Seite CheckoutReview.aspx den Bestellbetrag, und zeigen Sie die generierte Lieferadresse an. Klicken Sie dann auf die Schaltfläche Bestellung abschließen .

    Kasse und Zahlung mit PayPal - Bestellüberprüfung

  14. Die Seite CheckoutComplete.aspx wird mit einer Zahlungstransaktions-ID angezeigt.

    Checkout und Zahlung mit PayPal - Checkout Complete

Überprüfen der Datenbank

Wenn Sie die aktualisierten Daten in der Wingtip Toys-Beispielanwendungsdatenbank nach dem Ausführen der Anwendung überprüfen, können Sie sehen, dass die Anwendung den Kauf der Produkte erfolgreich aufgezeichnet hat.

Sie können die in der Datenbankdatei Wingtiptoys.mdf enthaltenen Daten wie zuvor in dieser Tutorialreihe über das Fenster Datenbank Explorer (Fenster Server Explorer in Visual Studio) überprüfen.

  1. Schließen Sie das Browserfenster, wenn es noch geöffnet ist.

  2. Wählen Sie in Visual Studio oben in Projektmappen-Explorer das Symbol Alle Dateien anzeigen aus, damit Sie den Ordner App_Data erweitern können.

  3. Erweitern Sie den Ordner App_Data .
    Möglicherweise müssen Sie das Symbol Alle Dateien anzeigen für den Ordner auswählen.

  4. Klicken Sie mit der rechten Maustaste auf die Datenbankdatei Wingtiptoys.mdf , und wählen Sie Öffnen aus.
    Server Explorer wird angezeigt.

  5. Erweitern Sie den Ordner Tabellen .

  6. Klicken Sie mit der rechten Maustaste auf die Tabelle Orders,und wählen Sie Tabellendaten anzeigen aus.
    Die Tabelle Orders wird angezeigt.

  7. Überprüfen Sie die Spalte PaymentTransactionID , um erfolgreiche Transaktionen zu bestätigen.

    Auschecken und Bezahlen mit PayPal – Datenbank überprüfen

  8. Schließen Sie das Tabellenfenster Orders .

  9. Klicken Sie im Explorer Server mit der rechten Maustaste auf die Tabelle OrderDetails, und wählen Sie Tabellendaten anzeigen aus.

  10. Überprüfen Sie die OrderId Werte und Username in der Tabelle OrderDetails . Beachten Sie, dass diese Werte mit den OrderId werten und Username übereinstimmen, die in der Tabelle Orders enthalten sind.

  11. Schließen Sie das Tabellenfenster OrderDetails .

  12. Klicken Sie mit der rechten Maustaste auf die Wingtip Toys-Datenbankdatei (Wingtiptoys.mdf), und wählen Sie Verbindung schließen aus.

  13. Wenn das fenster Projektmappen-Explorer nicht angezeigt wird, klicken Sie unten im Fenster Server Explorer auf Projektmappen-Explorer, um die Projektmappen-Explorer erneut anzuzeigen.

Zusammenfassung

In diesem Tutorial haben Sie Schemas für Bestell- und Bestelldetails hinzugefügt, um den Kauf von Produkten nachzuverfolgen. Außerdem haben Sie die PayPal-Funktionalität in die Wingtip Toys-Beispielanwendung integriert.

Weitere Ressourcen

Übersicht über die ASP.NET-Konfiguration
Bereitstellen einer Secure ASP.NET Web Forms-App mit Mitgliedschaft, OAuth und SQL-Datenbank für Azure App Service
Microsoft Azure – Kostenlose Testversion

Haftungsausschluss

Dieses Tutorial enthält Beispielcode. Ein solcher Beispielcode wird "wie ben" ohne jegliche Gewährleistung bereitgestellt. Dementsprechend garantiert Microsoft nicht die Genauigkeit, Integrität oder Qualität des Beispielcodes. Sie erklären sich damit einverstanden, den Beispielcode auf eigenes Risiko zu verwenden. Microsoft haftet Ihnen unter keinen Umständen in irgendeiner Weise für Beispielcode, Inhalte, einschließlich, aber nicht beschränkt auf, Fehler oder Auslassungen in Beispielcode, Inhalten oder Verlusten oder Schäden jeglicher Art, die durch die Verwendung von Beispielcode entstehen. Sie werden hiermit benachrichtigt und erklären sich damit einverstanden, Microsoft von und von allen Verlusten, Verlustansprüchen, Verletzungen oder Schäden jeglicher Art freizustellen, zu speichern und schadlos zu halten, einschließlich, aber nicht beschränkt auf solche, die durch Material verursacht werden, das Sie posten, übertragen, nutzen oder darauf vertrauen, einschließlich, aber nicht beschränkt auf, die darin ausgedrückten Ansichten.