Bagikan melalui


Checkout dan Pembayaran dengan PayPal

oleh Erik Reitan

Unduh Proyek Sampel Mainan Wingtip (C#) atau Unduh E-book (PDF)

Seri tutorial ini akan mengajari Anda dasar-dasar membangun aplikasi ASP.NET Web Forms menggunakan ASP.NET 4.5 dan Microsoft Visual Studio Express 2013 untuk Web. Proyek Visual Studio 2013 dengan kode sumber C# tersedia untuk menyertai seri tutorial ini.

Tutorial ini menjelaskan cara memodifikasi aplikasi sampel Wingtip Toys untuk menyertakan otorisasi pengguna, pendaftaran, dan pembayaran menggunakan PayPal. Hanya pengguna yang masuk yang akan memiliki otorisasi untuk membeli produk. Fungsionalitas pendaftaran pengguna bawaan templat proyek ASP.NET 4.5 Web Forms sudah mencakup banyak hal yang Anda butuhkan. Anda akan menambahkan fungsionalitas PayPal Express Checkout. Dalam tutorial ini Anda menggunakan lingkungan pengujian pengembang PayPal, sehingga tidak ada dana aktual yang akan ditransfer. Di akhir tutorial, Anda akan menguji aplikasi dengan memilih produk untuk ditambahkan ke kedai belanja, mengklik tombol checkout, dan mentransfer data ke situs web pengujian PayPal. Di situs web pengujian PayPal, Anda akan mengonfirmasi informasi pengiriman dan pembayaran Anda dan kemudian kembali ke aplikasi sampel Wingtip Toys lokal untuk mengonfirmasi dan menyelesaikan pembelian.

Ada beberapa prosesor pembayaran pihak ketiga berpengalaman yang berspesialisasi dalam belanja online yang menangani skalabilitas dan keamanan. ASP.NET pengembang harus mempertimbangkan keuntungan menggunakan solusi pembayaran pihak ketiga sebelum menerapkan solusi belanja dan pembelian.

Catatan

Aplikasi sampel Wingtip Toys dirancang untuk menunjukkan konsep dan fitur ASP.NET tertentu yang tersedia untuk pengembang web ASP.NET. Aplikasi sampel ini tidak dioptimalkan untuk semua kemungkinan keadaan sehubungan dengan skalabilitas dan keamanan.

Yang akan Anda pelajari:

  • Cara membatasi akses ke halaman tertentu dalam folder.
  • Cara membuat kedai belanja yang dikenal dari kedai belanja anonim.
  • Cara mengaktifkan SSL untuk proyek.
  • Cara menambahkan penyedia OAuth ke proyek.
  • Cara menggunakan PayPal untuk membeli produk menggunakan lingkungan pengujian PayPal.
  • Cara menampilkan detail dari PayPal dalam kontrol DetailsView .
  • Cara memperbarui database aplikasi Wingtip Toys dengan detail yang diperoleh dari PayPal.

Menambahkan Pelacakan Pesanan

Dalam tutorial ini, Anda akan membuat dua kelas baru untuk melacak data dari pesanan yang telah dibuat pengguna. Kelas akan melacak data mengenai informasi pengiriman, total pembelian, dan konfirmasi pembayaran.

Menambahkan Kelas Model Order dan OrderDetail

Sebelumnya dalam seri tutorial ini, Anda menentukan skema untuk kategori, produk, dan item kelopak Categorybelanja dengan membuat kelas , Product, dan CartItem di folder Model . Sekarang Anda akan menambahkan dua kelas baru untuk menentukan skema untuk pesanan produk dan detail pesanan.

  1. Di folder Model , tambahkan kelas baru bernama Order.cs.
    File kelas baru ditampilkan di editor.

  2. Ganti kode default dengan yang berikut ini:

    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. Tambahkan kelas OrderDetail.cs ke folder Model .

  4. Ganti kode default dengan kode berikut:

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

Kelas Order dan OrderDetail berisi skema untuk menentukan informasi pesanan yang digunakan untuk pembelian dan pengiriman.

Selain itu, Anda harus memperbarui kelas konteks database yang mengelola kelas entitas dan yang menyediakan akses data ke database. Untuk melakukan ini, Anda akan menambahkan kelas Order dan OrderDetail model yang baru dibuat ke ProductContext kelas .

  1. Di Penjelajah Solusi, temukan dan buka file ProductContext.cs.

  2. Tambahkan kode yang disorot ke file ProductContext.cs seperti yang ditunjukkan di bawah ini:

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

Seperti disebutkan sebelumnya dalam seri tutorial ini, kode dalam file ProductContext.cs menambahkan System.Data.Entity namespace sehingga Anda memiliki akses ke semua fungsi inti Kerangka Kerja Entitas. Fungsionalitas ini mencakup kemampuan untuk mengkueri, menyisipkan, memperbarui, dan menghapus data dengan bekerja dengan objek yang sangat ditik. Kode di atas di ProductContext kelas menambahkan akses Entity Framework ke kelas dan OrderDetail yang baru ditambahkanOrder.

Menambahkan Akses Checkout

Aplikasi sampel Wingtip Toys memungkinkan pengguna anonim untuk meninjau dan menambahkan produk ke kedai belanja. Namun, ketika pengguna anonim memilih untuk membeli produk yang mereka tambahkan ke kedai belanja, mereka harus masuk ke situs. Setelah masuk, mereka dapat mengakses halaman terbatas aplikasi Web yang menangani proses pembayaran dan pembelian. Halaman terbatas ini terkandung dalam folder Checkout aplikasi.

Menambahkan Folder dan Halaman Checkout

Anda sekarang akan membuat folder Checkout dan halaman di dalamnya yang akan dilihat pelanggan selama proses checkout. Anda akan memperbarui halaman-halaman ini nanti dalam tutorial ini.

  1. Klik kanan nama proyek (Mainan Wingtip) di Penjelajah Solusi dan pilih Tambahkan Folder Baru.

    Checkout dan Pembayaran dengan PayPal - Folder Baru

  2. Beri nama folder baru Checkout.

  3. Klik kanan folder Checkout lalu pilih Tambahkan>Item Baru.

    Checkout dan Pembayaran dengan PayPal - Item Baru

  4. Kotak dialog Tambahkan Item Baru ditampilkan.

  5. Pilih grup Visual C# ->Templat web di sebelah kiri. Lalu, dari panel tengah, pilih Formulir Web dengan Halaman Masterdan beri nama CheckoutStart.aspx.

    Checkout dan Pembayaran dengan PayPal - Tambahkan Dialog Item Baru

  6. Seperti sebelumnya, pilih file Site.Master sebagai halaman master.

  7. Tambahkan halaman tambahan berikut ke folder Checkout menggunakan langkah yang sama di atas:

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

Menambahkan File Web.config

Dengan menambahkan file Web.config baru ke folder Checkout , Anda akan dapat membatasi akses ke semua halaman yang terkandung dalam folder.

  1. Klik kanan folder Checkout dan pilih Tambahkan ->Item Baru.
    Kotak dialog Tambahkan Item Baru ditampilkan.

  2. Pilih grup Visual C# ->Templat web di sebelah kiri. Kemudian, dari panel tengah, pilih File Konfigurasi Web, terima nama default Web.config, lalu pilih Tambahkan.

  3. Ganti konten XML yang sudah ada dalam file Web.config dengan yang berikut ini:

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <authorization>
          <deny users="?"/>
        </authorization>
      </system.web>
    </configuration>
    
  4. Simpan file Web.config.

File Web.config menentukan bahwa semua pengguna aplikasi Web yang tidak dikenal harus ditolak akses ke halaman yang terkandung dalam folder Checkout . Namun, jika pengguna telah mendaftarkan akun dan masuk, mereka akan menjadi pengguna yang dikenal dan akan memiliki akses ke halaman di folder Checkout .

Penting untuk dicatat bahwa konfigurasi ASP.NET mengikuti hierarki, di mana setiap file Web.config menerapkan pengaturan konfigurasi ke folder tempatnya berada dan ke semua direktori anak di bawahnya.

Mengaktifkan SSL untuk Proyek

Secure Sockets Layer (SSL) adalah protokol yang ditentukan untuk memungkinkan server Web dan klien Web berkomunikasi lebih aman melalui penggunaan enkripsi. Ketika SSL tidak digunakan, data yang dikirim antara klien dan server terbuka untuk mengemas sniffing oleh siapa pun dengan akses fisik ke jaringan. Selain itu, beberapa skema autentikasi umum tidak aman melalui HTTP biasa. Secara khusus, Autentikasi dasar dan autentikasi formulir mengirim kredensial yang tidak terenkripsi. Agar aman, skema autentikasi ini harus menggunakan SSL.

  1. Di Penjelajah Solusi, klik proyek WingtipToys, lalu tekan F4 untuk menampilkan jendela Properti.
  2. Ubah SSL Diaktifkan menjadi true.
  3. Salin URL SSL sehingga Anda dapat menggunakannya nanti.
    URL SSL akan menjadi https://localhost:44300/ kecuali Anda sebelumnya telah membuat Situs Web SSL (seperti yang ditunjukkan di bawah).
    Properti Proyek
  4. Di Penjelajah Solusi, klik kanan proyek WingtipToys dan klik Properti.
  5. Di tab sebelah kiri, klik Web.
  6. Ubah Url Proyek untuk menggunakan URL SSL yang Anda simpan sebelumnya.
    Properti Web Proyek
  7. Simpan halaman dengan menekan CTRL+S.
  8. Tekan Ctrl+F5 untuk menjalankan aplikasi. Visual Studio akan menampilkan opsi untuk memungkinkan Anda menghindari peringatan SSL.
  9. Klik Ya untuk mempercayai sertifikat IIS Express SSL dan lanjutkan.
    Detail sertifikat IIS Express SSL
    Peringatan Keamanan ditampilkan.
  10. Klik Ya untuk menginstal sertifikat ke localhost Anda.
    Kotak dialog Peringatan Keamanan
    Jendela browser akan ditampilkan.

Anda sekarang dapat dengan mudah menguji aplikasi Web Anda secara lokal menggunakan SSL.

Menambahkan Penyedia OAuth 2.0

ASP.NET Web Forms menyediakan opsi yang ditingkatkan untuk keanggotaan dan autentikasi. Penyempurnaan ini termasuk OAuth. OAuth adalah protokol terbuka yang memungkinkan otorisasi aman dalam metode sederhana dan standar dari aplikasi web, seluler, dan desktop. Templat ASP.NET Web Forms menggunakan OAuth untuk mengekspos Facebook, Twitter, Google, dan Microsoft sebagai penyedia autentikasi. Meskipun tutorial ini hanya menggunakan Google sebagai penyedia autentikasi, Anda dapat dengan mudah memodifikasi kode untuk menggunakan salah satu penyedia. Langkah-langkah untuk menerapkan penyedia lain sangat mirip dengan langkah-langkah yang akan Anda lihat dalam tutorial ini.

Selain autentikasi, tutorial juga akan menggunakan peran untuk menerapkan otorisasi. Hanya pengguna yang Anda tambahkan ke peran yang canEdit dapat mengubah data (membuat, mengedit, atau menghapus kontak).

Catatan

Aplikasi Windows Live hanya menerima URL langsung untuk situs web yang berfungsi, sehingga Anda tidak dapat menggunakan URL situs web lokal untuk menguji login.

Langkah-langkah berikut akan memungkinkan Anda menambahkan penyedia autentikasi Google.

  1. Buka file App_Start\Startup.Auth.cs .

  2. Hapus karakter komentar dari app.UseGoogleAuthentication() metode sehingga metode muncul sebagai berikut:

    app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
    {
        ClientId = "",
        ClientSecret = ""
    });
    
  3. Buka Konsol Pengembang Google. Anda juga harus masuk dengan akun email developer Google (gmail.com). Jika Anda tidak memiliki akun Google, pilih tautan Buat akun .
    Selanjutnya, Anda akan melihat Konsol Google Developers.
    Konsol Pengembang Google

  4. Klik tombol Buat Proyek dan masukkan nama proyek dan ID (Anda bisa menggunakan nilai default). Lalu, klik kotak centang perjanjian dan tombol Buat .

    Google - Proyek Baru

    Dalam beberapa detik, proyek baru akan dibuat dan browser Anda akan menampilkan halaman proyek baru.

  5. Di tab sebelah kiri, klik API & autentikasi, lalu klik Kredensial.

  6. Klik Buat ID Klien Baru di bawah OAuth.
    Dialog Buat ID Klien akan ditampilkan.
    Google - Buat ID Klien

  7. Dalam dialog Buat ID Klien , pertahankan aplikasi Web default untuk jenis aplikasi.

  8. Atur Asal JavaScript Resmi ke URL SSL yang Anda gunakan sebelumnya dalam tutorial ini (https://localhost:44300/ kecuali Anda telah membuat proyek SSL lainnya).
    URL ini adalah asal untuk aplikasi Anda. Untuk sampel ini, Anda hanya akan memasukkan URL pengujian localhost. Namun, Anda dapat memasukkan beberapa URL untuk mempertangungjawabkan localhost dan produksi.

  9. Atur URI Pengalihan Resmi ke yang berikut ini:

    https://localhost:44300/signin-google
    

    Nilai ini adalah URI yang ASP.NET pengguna OAuth untuk berkomunikasi dengan server google OAuth. Ingat URL SSL yang Anda gunakan di atas ( https://localhost:44300/ kecuali Anda telah membuat proyek SSL lainnya).

  10. Klik tombol Buat ID Klien .

  11. Di menu sebelah kiri Konsol Google Developers, klik item menu layar Persetujuan , lalu atur alamat email dan nama produk Anda. Setelah Anda mengisi formulir, klik Simpan.

  12. Klik item menu API , gulir ke bawah dan klik tombol nonaktif di samping Google+ API.
    Menerima opsi ini akan mengaktifkan Google+ API.

  13. Anda juga harus memperbarui paket NuGet Microsoft.Owin ke versi 3.0.0.
    Dari menu Alat , pilih Pengelola Paket NuGet lalu pilih Kelola Paket NuGet untuk Solusi.
    Dari jendela Kelola Paket NuGet , temukan dan perbarui paket Microsoft.Owin ke versi 3.0.0.

  14. Di Visual Studio, perbarui UseGoogleAuthentication metode halaman Startup.Auth.cs dengan menyalin dan menempelkan ID Klien dan Rahasia Klien ke dalam metode . NILAI ID Klien dan Rahasia Klien yang ditunjukkan di bawah ini adalah sampel dan tidak akan berfungsi.

    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. Tekan CTRL+F5 untuk membangun dan menjalankan aplikasi. Klik tautan Masuk .

  16. Di bawah Gunakan layanan lain untuk masuk, klik Google.
    Masuk

  17. Jika Anda perlu memasukkan kredensial, Anda akan diarahkan ke situs google tempat Anda akan memasukkan kredensial Anda.
    Google - Masuk

  18. Setelah memasukkan kredensial, Anda akan diminta untuk memberikan izin ke aplikasi web yang baru saja Anda buat.
    Akun Layanan Default Proyek

  19. Klik Terima. Anda sekarang akan diarahkan kembali ke halaman Daftar aplikasi WingtipToys tempat Anda dapat mendaftarkan akun Google Anda.
    Mendaftar dengan Akun Google Anda

  20. Anda memiliki opsi untuk mengubah nama pendaftaran email lokal yang digunakan untuk akun Gmail Anda, tetapi umumnya Anda ingin menyimpan alias email default (yaitu, yang Anda gunakan untuk autentikasi). Klik Masuk seperti yang ditunjukkan di atas.

Memodifikasi Fungsionalitas Masuk

Seperti yang disebutkan sebelumnya dalam seri tutorial ini, sebagian besar fungsi pendaftaran pengguna telah disertakan dalam templat ASP.NET Web Forms secara default. Sekarang Anda akan mengubah halaman Login.aspx dan Register.aspx default untuk memanggil MigrateCart metode . Metode ini MigrateCart mengaitkan pengguna yang baru masuk dengan ke cart belanja anonim. Dengan mengaitkan pengguna dan ke cart belanja, aplikasi sampel Wingtip Toys akan dapat mempertahankan ke cart belanja pengguna di antara kunjungan.

  1. Di Penjelajah Solusi, temukan dan buka folder Akun.

  2. Ubah halaman code-behind bernama Login.aspx.cs untuk menyertakan kode yang disorot dengan warna kuning, sehingga muncul sebagai berikut:

    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. Simpan file Login.aspx.cs .

Untuk saat ini, Anda dapat mengabaikan peringatan bahwa tidak ada definisi untuk metode .MigrateCart Anda akan menambahkannya sedikit nanti dalam tutorial ini.

File kode Login.aspx.cs-behind mendukung metode LogIn. Dengan memeriksa halaman Login.aspx, Anda akan melihat bahwa halaman ini menyertakan tombol "Masuk" yang saat klik memicu LogIn handler pada kode di belakang.

Login Ketika metode pada Login.aspx.cs dipanggil, instans baru ke cart belanja bernama usersShoppingCart dibuat. ID ke cart belanja (GUID) diambil dan diatur ke cartId variabel . Kemudian, MigrateCart metode ini dipanggil, meneruskan dan cartId nama pengguna yang masuk ke metode ini. Ketika ke cart belanja dimigrasikan, GUID yang digunakan untuk mengidentifikasi ke cart belanja anonim diganti dengan nama pengguna.

Selain memodifikasi file code-behind Login.aspx.cs untuk memigrasikan keranjang belanja saat pengguna masuk, Anda juga harus memodifikasi file code-behind Register.aspx.cs untuk memigrasikan keranjang belanja saat pengguna membuat akun baru dan masuk.

  1. Di folder Akun , buka file code-behind bernama Register.aspx.cs.

  2. Ubah file code-behind dengan menyertakan kode dalam warna kuning, sehingga muncul sebagai berikut:

    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. Simpan file Register.aspx.cs . Sekali lagi, abaikan peringatan tentang MigrateCart metode .

Perhatikan bahwa kode yang Anda gunakan dalam penanganan CreateUser_Click aktivitas sangat mirip dengan kode yang Anda gunakan dalam LogIn metode . Ketika pengguna mendaftar atau masuk ke situs, panggilan ke MigrateCart metode akan dilakukan.

Memigrasikan Kemudi Belanja

Setelah proses masuk dan pendaftaran diperbarui, Anda dapat menambahkan kode untuk memigrasikan keranjang belanja menggunakan MigrateCart metode .

  1. Di Penjelajah Solusi, temukan folder Logika dan buka file kelas ShoppingCartActions.cs.

  2. Tambahkan kode yang disorot dengan warna kuning ke kode yang ada di file ShoppingCartActions.cs , sehingga kode dalam file ShoppingCartActions.cs muncul sebagai berikut:

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

Metode ini MigrateCart menggunakan cartId yang ada untuk menemukan ke cart belanja pengguna. Selanjutnya, kode mengulangi semua item kelopak belanja dan mengganti CartId properti (seperti yang ditentukan oleh CartItem skema) dengan nama pengguna yang masuk.

Memperbarui Koneksi Database

Jika Anda mengikuti tutorial ini menggunakan aplikasi sampel Wingtip Toys bawaan, Anda harus membuat ulang database keanggotaan default. Dengan memodifikasi string koneksi default, database keanggotaan akan dibuat lain kali aplikasi berjalan.

  1. Buka file Web.config di akar proyek.

  2. Perbarui string koneksi default sehingga muncul sebagai berikut:

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

Mengintegrasikan PayPal

PayPal adalah platform penagihan berbasis web yang menerima pembayaran oleh pedagang online. Tutorial ini selanjutnya menjelaskan cara mengintegrasikan fungsionalitas Express Checkout PayPal ke dalam aplikasi Anda. Express Checkout memungkinkan pelanggan Anda menggunakan PayPal untuk membayar barang yang telah mereka tambahkan ke kedai belanja mereka.

Membuat Akun Pengujian PayPal

Untuk menggunakan lingkungan pengujian PayPal, Anda harus membuat dan memverifikasi akun pengujian pengembang. Anda akan menggunakan akun pengujian pengembang untuk membuat akun pengujian pembeli dan akun pengujian penjual. Info masuk akun pengujian pengembang juga akan memungkinkan aplikasi sampel Wingtip Toys mengakses lingkungan pengujian PayPal.

  1. Di browser, navigasikan ke situs pengujian pengembang PayPal:
    https://developer.paypal.com

  2. Jika Anda tidak memiliki akun pengembang PayPal, buat akun baru dengan mengklik Daftardan ikuti langkah-langkah pendaftaran. Jika Anda memiliki akun pengembang PayPal yang sudah ada, masuk dengan mengklik Masuk. Anda akan memerlukan akun pengembang PayPal Anda untuk menguji aplikasi sampel Wingtip Toys nanti dalam tutorial ini.

  3. Jika Anda baru saja mendaftar untuk akun pengembang PayPal, Anda mungkin perlu memverifikasi akun pengembang PayPal Anda dengan PayPal. Anda dapat memverifikasi akun Anda dengan mengikuti langkah-langkah yang dikirim PayPal ke akun email Anda. Setelah Anda memverifikasi akun pengembang PayPal Anda, masuk kembali ke situs pengujian pengembang PayPal.

  4. Setelah Anda masuk ke situs pengembang PayPal dengan akun pengembang PayPal Anda, Anda perlu membuat akun uji pembeli PayPal jika Anda belum memilikinya. Untuk membuat akun uji pembeli, pada situs PayPal klik tab Aplikasi lalu klik Akun sandbox.
    Halaman Akun pengujian Sandbox ditampilkan.

    Catatan

    Situs Pengembang PayPal sudah menyediakan akun uji pedagang.

    Cuplikan layar memperlihatkan halaman Akun uji Sandbox dengan tab Aplikasi disorot.

  5. Pada halaman Akun uji Sandbox, klik Buat Akun.

  6. Pada halaman Buat akun uji pilih email akun uji pembeli dan kata sandi pilihan Anda.

    Catatan

    Anda akan memerlukan alamat email pembeli dan kata sandi untuk menguji aplikasi sampel Wingtip Toys di akhir tutorial ini.

    Cuplikan layar halaman Buat akun pengujian yang menampilkan bidang akun yang sedang dibuat.

  7. Buat akun uji pembeli dengan mengklik tombol Buat Akun .
    Halaman Akun Uji Kotak Pasir ditampilkan.

    Checkout dan Pembayaran dengan PayPal - Akun PayPal

  8. Pada halaman Akun uji Sandbox , klik akun email fasilitator .
    Opsi Profil dan Pemberitahuan muncul.

  9. Pilih opsi Profil , lalu klik kredensial API untuk melihat kredensial API Anda untuk akun uji merchant.

  10. Salin kredensial TEST API ke notepad.

Anda akan memerlukan kredensial API UJI Klasik yang ditampilkan (Nama Pengguna, Kata Sandi, dan Tanda Tangan) untuk melakukan panggilan API dari aplikasi sampel Wingtip Toys ke lingkungan pengujian PayPal. Anda akan menambahkan kredensial di langkah berikutnya.

Menambahkan Kelas PayPal dan Kredensial API

Anda akan menempatkan sebagian besar kode PayPal ke dalam satu kelas. Kelas ini berisi metode yang digunakan untuk berkomunikasi dengan PayPal. Selain itu, Anda akan menambahkan kredensial PayPal Anda ke kelas ini.

  1. Di aplikasi sampel Wingtip Toys dalam Visual Studio, klik kanan folder Logika lalu pilih Tambahkan ->Item Baru.
    Kotak dialog Tambahkan Item Baru ditampilkan.

  2. Di bawah Visual C# dari panel Terinstal di sebelah kiri, pilih Kode.

  3. Dari panel tengah, pilih Kelas. Beri nama kelas baru ini PayPalFunctions.cs.

  4. Klik Tambahkan.
    File kelas baru ditampilkan di editor.

  5. Ganti kode default dengan kode berikut:

    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. Tambahkan kredensial MERCHANT API (Nama Pengguna, Kata Sandi, dan Tanda Tangan) yang Anda tampilkan sebelumnya dalam tutorial ini sehingga Anda dapat melakukan panggilan fungsi ke lingkungan pengujian PayPal.

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

Catatan

Dalam aplikasi sampel ini Anda hanya menambahkan kredensial ke file C# (.cs). Namun, dalam solusi yang diterapkan, Anda harus mempertimbangkan untuk mengenkripsi kredensial Anda dalam file konfigurasi.

Kelas NVPAPICaller berisi sebagian besar fungsi payPal. Kode di kelas menyediakan metode yang diperlukan untuk melakukan pembelian pengujian dari lingkungan pengujian PayPal. Tiga fungsi PayPal berikut digunakan untuk melakukan pembelian:

  • SetExpressCheckoutFungsi
  • GetExpressCheckoutDetailsFungsi
  • DoExpressCheckoutPaymentFungsi

Metode ini ShortcutExpressCheckout mengumpulkan informasi pembelian pengujian dan detail produk dari kedai belanja dan memanggil SetExpressCheckout fungsi PayPal. Metode ini GetCheckoutDetails mengonfirmasi detail pembelian dan memanggil GetExpressCheckoutDetails fungsi PayPal sebelum melakukan pembelian pengujian. Metode DoCheckoutPayment ini menyelesaikan pembelian pengujian dari lingkungan pengujian dengan memanggil DoExpressCheckoutPayment fungsi PayPal. Kode yang tersisa mendukung metode dan proses PayPal, seperti string pengodean, string decoding, array pemrosesan, dan menentukan kredensial.

Catatan

PayPal memungkinkan Anda menyertakan detail pembelian opsional berdasarkan spesifikasi API PayPal. Dengan memperluas kode dalam aplikasi sampel Wingtip Toys, Anda dapat menyertakan detail pelokalan, deskripsi produk, pajak, nomor layanan pelanggan, serta banyak bidang opsional lainnya.

Perhatikan bahwa URL pengembalian dan pembatalan yang ditentukan dalam metode ShortcutExpressCheckout menggunakan nomor port.

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

Saat Pengembang Web Visual menjalankan proyek web menggunakan SSL, biasanya port 44300 digunakan untuk server web. Seperti yang ditunjukkan di atas, nomor port adalah 44300. Ketika Anda menjalankan aplikasi, Anda dapat melihat nomor port yang berbeda. Nomor port Anda harus diatur dengan benar dalam kode sehingga Anda dapat berhasil menjalankan aplikasi sampel Wingtip Toys di akhir tutorial ini. Bagian berikutnya dari tutorial ini menjelaskan cara mengambil nomor port host lokal dan memperbarui kelas PayPal.

Memperbarui Nomor Port LocalHost di Kelas PayPal

Aplikasi sampel Wingtip Toys membeli produk dengan menavigasi ke situs pengujian PayPal dan kembali ke instans lokal aplikasi sampel Mainan Wingtip Anda. Agar PayPal kembali ke URL yang benar, Anda perlu menentukan nomor port aplikasi sampel yang berjalan secara lokal dalam kode PayPal yang disebutkan di atas.

  1. Klik kanan nama proyek (WingtipToys) di Penjelajah Solusi dan pilih Properti.

  2. Di kolom kiri, pilih tab Web .

  3. Ambil nomor port dari kotak Url Proyek .

  4. Jika diperlukan, perbarui returnURL dan cancelURL di kelas PayPal (NVPAPICaller) dalam file PayPalFunctions.cs untuk menggunakan nomor port aplikasi web Anda:

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

Sekarang kode yang Anda tambahkan akan cocok dengan port yang diharapkan untuk aplikasi Web lokal Anda. PayPal akan dapat kembali ke URL yang benar di komputer lokal Anda.

Menambahkan Tombol Pembayaran PayPal

Sekarang setelah fungsi PayPal utama telah ditambahkan ke aplikasi sampel, Anda dapat mulai menambahkan markup dan kode yang diperlukan untuk memanggil fungsi-fungsi ini. Pertama, Anda harus menambahkan tombol checkout yang akan dilihat pengguna di halaman kedai belanja.

  1. Buka file ShoppingCart.aspx .

  2. Gulir ke bagian bawah file dan temukan <!--Checkout Placeholder --> komentar.

  3. Ganti komentar dengan ImageButton kontrol sehingga mark up diganti sebagai berikut:

    <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. Dalam file ShoppingCart.aspx.cs , setelah UpdateBtn_Click penanganan aktivitas di dekat akhir file, tambahkan CheckOutBtn_Click penanganan aktivitas:

    protected void CheckoutBtn_Click(object sender, ImageClickEventArgs e)
    {
        using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
        {
            Session["payment_amt"] = usersShoppingCart.GetTotal();
        }
        Response.Redirect("Checkout/CheckoutStart.aspx");
    }
    
  5. Juga dalam file ShoppingCart.aspx.cs , tambahkan referensi ke CheckoutBtn, sehingga tombol gambar baru dirujuk sebagai berikut:

    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. Simpan perubahan Anda ke file ShoppingCart.aspx dan file ShoppingCart.aspx.cs .

  7. Dari menu, pilih Debug-Build>WingtipToys.
    Proyek akan dibangun kembali dengan kontrol ImageButton yang baru ditambahkan.

Kirim Detail Pembelian ke PayPal

Saat pengguna mengklik tombol Checkout di halaman keranjang belanja (ShoppingCart.aspx), mereka akan memulai proses pembelian. Kode berikut memanggil fungsi PayPal pertama yang diperlukan untuk membeli produk.

  1. Dari folder Checkout , buka file code-behind bernama CheckoutStart.aspx.cs.
    Pastikan untuk membuka file code-behind.

  2. Ganti kode yang ada dengan yang berikut ini:

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

Ketika pengguna aplikasi mengklik tombol Checkout di halaman kedai belanja, browser akan menavigasi ke halaman CheckoutStart.aspx . Saat halaman CheckoutStart.aspx dimuat, ShortcutExpressCheckout metode dipanggil. Pada titik ini, pengguna ditransfer ke situs web pengujian PayPal. Di situs PayPal, pengguna memasukkan kredensial PayPal mereka, meninjau detail pembelian, menerima perjanjian PayPal dan kembali ke aplikasi sampel Wingtip Toys tempat ShortcutExpressCheckout metode selesai. ShortcutExpressCheckout Ketika metode selesai, metode akan mengalihkan pengguna ke halaman CheckoutReview.aspx yang ditentukan dalam ShortcutExpressCheckout metode . Ini memungkinkan pengguna untuk meninjau detail pesanan dari dalam aplikasi sampel Wingtip Toys.

Tinjau Detail Pesanan

Setelah kembali dari PayPal, halaman CheckoutReview.aspx dari aplikasi sampel Wingtip Toys menampilkan detail pesanan. Halaman ini memungkinkan pengguna untuk meninjau detail pesanan sebelum membeli produk. Halaman CheckoutReview.aspx harus dibuat sebagai berikut:

  1. Di folder Checkout , buka halaman bernama CheckoutReview.aspx.

  2. Ganti markup yang sudah ada dengan yang berikut ini:

    <%@ 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. Buka halaman code-behind bernama CheckoutReview.aspx.cs dan ganti kode yang ada dengan yang berikut ini:

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

Kontrol DetailsView digunakan untuk menampilkan detail pesanan yang telah dikembalikan dari PayPal. Selain itu, kode di atas menyimpan detail pesanan ke database Wingtip Toys sebagai OrderDetail objek. Saat pengguna mengklik tombol Pesanan Lengkap , mereka dialihkan ke halaman CheckoutComplete.aspx .

Catatan

Tip

Di markup halaman CheckoutReview.aspx , perhatikan bahwa <ItemStyle> tag digunakan untuk mengubah gaya item dalam kontrol DetailsView di dekat bagian bawah halaman. Dengan melihat halaman dalam Tampilan Desain (dengan memilih Desain di sudut kiri bawah Visual Studio), lalu memilih kontrol DetailsView , dan memilih Tag Pintar (ikon panah di kanan atas kontrol), Anda akan dapat melihat DetailTampilan Tugas.

Pembayaran dan Pembayaran dengan PayPal - Edit Bidang

Dengan memilih Edit Bidang, kotak dialog Bidang akan muncul. Dalam kotak dialog ini Anda dapat dengan mudah mengontrol properti visual, seperti ItemStyle, dari kontrol DetailsView .

Checkout dan Pembayaran dengan PayPal - Dialog Bidang

Pembelian Lengkap

Halaman CheckoutComplete.aspx melakukan pembelian dari PayPal. Seperti disebutkan di atas, pengguna harus mengklik tombol Pesanan Lengkap sebelum aplikasi akan menavigasi ke halaman CheckoutComplete.aspx .

  1. Di folder Checkout , buka halaman bernama CheckoutComplete.aspx.

  2. Ganti markup yang sudah ada dengan yang berikut ini:

    <%@ 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. Buka halaman code-behind bernama CheckoutComplete.aspx.cs dan ganti kode yang ada dengan yang berikut ini:

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

Saat halaman CheckoutComplete.aspx dimuat, DoCheckoutPayment metode dipanggil. Seperti disebutkan sebelumnya, DoCheckoutPayment metode menyelesaikan pembelian dari lingkungan pengujian PayPal. Setelah PayPal menyelesaikan pembelian pesanan, halaman CheckoutComplete.aspx menampilkan transaksi ID pembayaran kepada pembeli.

Tangani Batalkan Pembelian

Jika pengguna memutuskan untuk membatalkan pembelian, mereka akan diarahkan ke halaman CheckoutCancel.aspx tempat mereka akan melihat bahwa pesanan mereka telah dibatalkan.

  1. Buka halaman bernama CheckoutCancel.aspx di folder Checkout .

  2. Ganti markup yang sudah ada dengan yang berikut ini:

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

Menangani Kesalahan Pembelian

Kesalahan selama proses pembelian akan ditangani oleh halaman CheckoutError.aspx . Kode di belakang halaman CheckoutStart.aspx , halaman CheckoutReview.aspx , dan halaman CheckoutComplete.aspx masing-masing akan dialihkan ke halaman CheckoutError.aspx jika terjadi kesalahan.

  1. Buka halaman bernama CheckoutError.aspx di folder Checkout .

  2. Ganti markup yang sudah ada dengan yang berikut ini:

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

Halaman CheckoutError.aspx ditampilkan dengan detail kesalahan saat terjadi kesalahan selama proses checkout.

Menjalankan Aplikasi

Jalankan aplikasi untuk melihat cara membeli produk. Perhatikan bahwa Anda akan berjalan di lingkungan pengujian PayPal. Tidak ada uang aktual yang ditukar.

  1. Pastikan semua file Anda disimpan di Visual Studio.

  2. Buka browser Web dan navigasikan ke https://developer.paypal.com.

  3. Masuk dengan akun pengembang PayPal yang Anda buat sebelumnya dalam tutorial ini.
    Untuk kotak pasir pengembang PayPal, Anda perlu masuk https://developer.paypal.com untuk menguji checkout ekspres. Ini hanya berlaku untuk pengujian sandbox PayPal, bukan untuk lingkungan langsung PayPal.

  4. Di Visual Studio, tekan F5 untuk menjalankan aplikasi sampel Wingtip Toys.
    Setelah database dibangun kembali, browser akan terbuka dan menampilkan halaman Default.aspx .

  5. Tambahkan tiga produk yang berbeda ke ke cart belanja dengan memilih kategori produk, seperti "Mobil" lalu klik Tambahkan ke Ke cart di samping setiap produk.
    Ke cart belanja akan menampilkan produk yang telah Anda pilih.

  6. Klik tombol PayPal untuk checkout.

    Checkout dan Pembayaran dengan PayPal - Cart

    Memeriksa akan mengharuskan Anda memiliki akun pengguna untuk aplikasi sampel Wingtip Toys.

  7. Klik tautan Google di sebelah kanan halaman untuk masuk dengan akun email gmail.com yang sudah ada.
    Jika Anda tidak memiliki akun gmail.com, Anda dapat membuatnya untuk tujuan pengujian di www.gmail.com. Anda juga dapat menggunakan akun lokal standar dengan mengklik "Daftar".

    Pembayaran dan Pembayaran dengan PayPal - Masuk

  8. Masuk dengan akun gmail dan kata sandi Anda.

    Pembayaran dan Pembayaran dengan PayPal - Masuk Gmail

  9. Klik tombol Masuk untuk mendaftarkan akun gmail Anda dengan nama pengguna aplikasi sampel Wingtip Toys Anda.

    Pembayaran dan Pembayaran dengan PayPal - Daftarkan Akun

  10. Di situs uji PayPal, tambahkan alamat email dan kata sandi pembeli yang Anda buat sebelumnya dalam tutorial ini, lalu klik tombol Masuk .

    Checkout dan Pembayaran dengan PayPal - PayPal Sign In

  11. Setujui kebijakan PayPal dan klik tombol Setuju dan Lanjutkan .
    Perhatikan bahwa halaman ini hanya ditampilkan saat pertama kali Anda menggunakan akun PayPal ini. Sekali lagi perhatikan bahwa ini adalah akun pengujian, tidak ada uang riil yang ditukar.

    Pembayaran dan Pembayaran dengan PayPal - Kebijakan PayPal

  12. Tinjau informasi pesanan di halaman tinjauan lingkungan pengujian PayPal dan klik Lanjutkan.

    Checkout dan Pembayaran dengan PayPal - Tinjau Informasi

  13. Pada halaman CheckoutReview.aspx , verifikasi jumlah pesanan dan lihat alamat pengiriman yang dihasilkan. Lalu, klik tombol Selesaikan Pesanan .

    Checkout dan Pembayaran dengan PayPal - Ulasan Pesanan

  14. Halaman CheckoutComplete.aspx ditampilkan dengan ID transaksi pembayaran.

    Checkout dan Pembayaran dengan PayPal - Checkout Selesai

Meninjau Database

Dengan meninjau data yang diperbarui di database aplikasi sampel Wingtip Toys setelah menjalankan aplikasi, Anda dapat melihat bahwa aplikasi berhasil merekam pembelian produk.

Anda dapat memeriksa data yang terkandung dalam file database Wingtiptoys.mdf dengan menggunakan jendela Database Explorer (jendela Penjelajah Server di Visual Studio) seperti yang Anda lakukan sebelumnya dalam seri tutorial ini.

  1. Tutup jendela browser jika masih terbuka.

  2. Di Visual Studio, pilih ikon Tampilkan Semua File di bagian atas Penjelajah Solusi untuk memungkinkan Anda memperluas folder App_Data.

  3. Perluas folder App_Data .
    Anda mungkin perlu memilih ikon Tampilkan Semua File untuk folder.

  4. Klik kanan file database Wingtiptoys.mdf dan pilih Buka.
    Penjelajah Server ditampilkan.

  5. Luaskan folder Tabel.

  6. Klik kanan tabel Pesanandan pilih Perlihatkan Data Tabel.
    Tabel Pesanan ditampilkan.

  7. Tinjau kolom PaymentTransactionID untuk mengonfirmasi keberhasilan transaksi.

    Checkout dan Pembayaran dengan PayPal - Tinjau Database

  8. Tutup jendela tabel Pesanan .

  9. Di Penjelajah Server, klik kanan tabel OrderDetails dan pilih Perlihatkan Data Tabel.

  10. OrderId Tinjau nilai dan Username dalam tabel OrderDetails. Perhatikan bahwa nilai ini cocok dengan OrderId nilai dan Username yang disertakan dalam tabel Pesanan .

  11. Tutup jendela tabel OrderDetails .

  12. Klik kanan file database Wingtip Toys (Wingtiptoys.mdf) dan pilih Tutup Koneksi.

  13. Jika Anda tidak melihat jendela Penjelajah Solusi, klik Penjelajah Solusi di bagian bawah jendela Server Explorer untuk menampilkan Penjelajah Solusi lagi.

Ringkasan

Dalam tutorial ini Anda menambahkan skema pesanan dan detail pesanan untuk melacak pembelian produk. Anda juga mengintegrasikan fungsionalitas PayPal ke dalam aplikasi sampel Wingtip Toys.

Sumber Daya Tambahan

Ringkasan Konfigurasi ASP.NET
Menyebarkan Aplikasi Formulir Web ASP.NET Aman dengan Keanggotaan, OAuth, dan SQL Database ke Azure App Service
Microsoft Azure - Uji Coba Gratis

Disclaimer

Tutorial ini berisi kode sampel. Kode sampel tersebut disediakan "apa adanya" tanpa jaminan apa pun. Dengan demikian, Microsoft tidak menjamin akurasi, integritas, atau kualitas kode sampel. Anda setuju untuk menggunakan kode sampel dengan risiko Anda sendiri. Dalam keadaan apa pun, Microsoft tidak akan bertanggung jawab kepada Anda dengan cara apa pun atas kode sampel, konten, termasuk tetapi tidak terbatas pada, kesalahan atau kelalaian apa pun dalam kode sampel, konten, atau kehilangan atau kerusakan apa pun yang terjadi sebagai akibat dari penggunaan kode sampel apa pun. Anda dengan ini diberi tahu dan dengan ini setuju untuk mengganti rugi, menyelamatkan, dan membebaskan Microsoft dari dan terhadap setiap dan semua kerugian, klaim kehilangan, cedera, atau kerusakan dalam bentuk apa pun termasuk, tanpa batasan, yang terjadi oleh atau timbul dari materi yang Anda posting, kirimkan, gunakan atau andalkan termasuk, tetapi tidak terbatas pada, tampilan yang dinyatakan di dalamnya.