精算と PayPal による支払い

作成者 : Erik Reitan

Wingtip Toys サンプル プロジェクトのダウンロード (C#) または 電子書籍のダウンロード (PDF)

このチュートリアル シリーズでは、ASP.NET 4.5 と Microsoft Visual Studio Express 2013 for Web を使用して ASP.NET Web Forms アプリケーションを構築する基本について説明します。 C# ソース コードを含むVisual Studio 2013 プロジェクトは、このチュートリアル シリーズに付属しています。

このチュートリアルでは、ユーザーの承認、登録、PayPal を使用した支払いを含むように Wingtip Toys サンプル アプリケーションを変更する方法について説明します。 製品を購入する権限を持つのは、ログインしているユーザーのみです。 ASP.NET 4.5 Web Forms プロジェクト テンプレートの組み込みのユーザー登録機能には、既に必要なものの多くが含まれています。 PayPal Express Checkout 機能を追加します。 このチュートリアルでは、PayPal 開発者テスト環境を使用しているため、実際の資金は転送されません。 チュートリアルの最後に、ショッピング カートに追加する製品を選択し、チェックアウト ボタンをクリックし、PayPal テスト Web サイトにデータを転送することで、アプリケーションをテストします。 PayPal テスト Web サイトでは、配送と支払いの情報を確認してから、ローカル Wingtip Toys サンプル アプリケーションに戻り、購入を確認して完了します。

スケーラビリティとセキュリティに対応するオンライン ショッピングを専門とする経験豊富なサードパーティの支払いプロセッサがいくつかあります。 ASP.NET 開発者は、ショッピングおよび購入ソリューションを実装する前に、サード パーティの支払いソリューションを利用する利点を考慮する必要があります。

注意

Wingtip Toys サンプル アプリケーションは、ASP.NET Web 開発者が利用できる特定の ASP.NET の概念と機能を示すように設計されています。 このサンプル アプリケーションは、スケーラビリティとセキュリティに関して考えられるすべての状況に対して最適化されていませんでした。

ここでは、次の内容について学習します。

  • フォルダー内の特定のページへのアクセスを制限する方法。
  • 匿名ショッピング カートから既知のショッピング カートを作成する方法。
  • プロジェクトの SSL を有効にする方法。
  • OAuth プロバイダーをプロジェクトに追加する方法。
  • PayPal を使用して PayPal テスト環境を使用して製品を購入する方法。
  • DetailsView コントロールで PayPal の詳細を表示する方法。
  • PayPal から取得した詳細を使用して Wingtip Toys アプリケーションのデータベースを更新する方法。

注文追跡の追加

このチュートリアルでは、ユーザーが作成した順序のデータを追跡する 2 つの新しいクラスを作成します。 クラスでは、出荷情報、購入合計、支払い確認に関するデータを追跡します。

Order モデル クラスと OrderDetail モデル クラスを追加する

このチュートリアル シリーズの前半では、Models フォルダーに 、、および CartItem クラスをCategoryProduct作成して、カテゴリ、製品、ショッピング カートアイテムのスキーマを定義しました。 次に、2 つの新しいクラスを追加して、製品注文のスキーマと注文の詳細を定義します。

  1. Models フォルダーにOrder.cs という名前の新しいクラスを追加します。
    新しいクラス ファイルがエディターに表示されます。

  2. 既定のコードを次のコードに置き換えます。

    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. OrderDetail.cs クラスを Models フォルダーに追加します。

  4. 既定のコードを以下のコードに置き換えます。

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

Orderクラスと OrderDetail クラスには、購入と出荷に使用される注文情報を定義するスキーマが含まれています。

さらに、エンティティ クラスを管理し、データベースへのデータ アクセスを提供するデータベース コンテキスト クラスを更新する必要があります。 これを行うには、新しく作成された Order クラスと OrderDetail モデル クラスを クラスに ProductContext 追加します。

  1. ソリューション エクスプローラーで、ProductContext.cs ファイルを見つけて開きます。

  2. 次に示すように、強調表示されたコードを ProductContext.cs ファイルに追加します。

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

このチュートリアル シリーズで前述したように、 ProductContext.cs ファイルのコードは名前空間を System.Data.Entity 追加して、Entity Framework のすべてのコア機能にアクセスできるようにします。 この機能には、厳密に型指定されたオブジェクトを操作してデータのクエリ、挿入、更新、削除を行う機能が含まれます。 クラスの上記のコードは、ProductContext新しく追加された クラスと OrderDetail クラスに Entity Framework アクセスを追加Orderします。

チェックアウト アクセスの追加

Wingtip Toys サンプル アプリケーションを使用すると、匿名ユーザーは製品を確認してショッピング カートに追加できます。 ただし、匿名ユーザーがショッピング カートに追加した製品を購入する場合は、サイトにログオンする必要があります。 ログオンすると、チェックアウトと購入プロセスを処理する Web アプリケーションの制限付きページにアクセスできます。 これらの制限付きページは、アプリケーションの Checkout フォルダーに含まれています。

チェックアウト フォルダーとページを追加する

次に、チェックアウト フォルダーと、 チェックアウト プロセス中に顧客に表示されるページを作成します。 これらのページは、このチュートリアルの後半で更新します。

  1. ソリューション エクスプローラーでプロジェクト名 (Wingtip Toys) を右クリックし、[新しいフォルダーの追加] を選択します。

    PayPal でのチェックアウトと支払い - 新しいフォルダー

  2. 新しいフォルダーに Checkout という名前を付けます。

  3. [チェックアウト] フォルダーを右クリックし、[Add-New Item]\(新しい項目追加\>) を選択します。

    PayPal でのチェックアウトと支払い - 新しいアイテム

  4. [新しい項目の追加] ダイアログ ボックスが表示されます。

  5. 左側の [Visual C# ->Web テンプレート] グループを選択します。 次に、中央のウィンドウから [ Web フォームとマスター ページ] を選択し、 CheckoutStart.aspx という名前を付けます。

    PayPal を使用したチェックアウトと支払い - [新しい項目の追加] ダイアログ

  6. 前と同様に、マスター ページとして Site.Master ファイルを選択します。

  7. 上記と同じ手順を使用して、 チェックアウト フォルダーに次のページを追加します。

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

Web.config ファイルを追加する

チェックアウト フォルダーに新しい Web.config ファイルを追加することで、フォルダーに含まれるすべてのページへのアクセスを制限できます。

  1. [チェックアウト] フォルダーを右クリックし、[追加] ->[新しい項目] の順に選択します。
    [新しい項目の追加] ダイアログ ボックスが表示されます。

  2. 左側の [Visual C# ->Web テンプレート] グループを選択します。 次に、中央のウィンドウで [ Web 構成ファイル] を選択し、既定の名前 Web.config受け入れて、[ 追加] を選択します。

  3. Web.config ファイルの XML の内容を次の内容で置き換えます。

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <authorization>
          <deny users="?"/>
        </authorization>
      </system.web>
    </configuration>
    
  4. Web.config ファイルを保存します。

Web.config ファイルは、Web アプリケーションのすべての不明なユーザーが Checkout フォルダーに含まれるページへのアクセスを拒否する必要があることを指定します。 ただし、ユーザーがアカウントを登録し、ログオンしている場合は、既知のユーザーになり、 Checkout フォルダー内のページにアクセスできます。

ASP.NET 構成は階層に従い、各 Web.config ファイルは、そのフォルダーとその下にあるすべての子ディレクトリに構成設定を適用します。

プロジェクトに対して SSL を有効にする

Secure Sockets Layer (SSL) は、Web サーバーと Web クライアント間の通信に定義されたプロトコルで、暗号化によって通信の安全性を強化することができます。 SSL を使わないと、クライアントとサーバー間で送信されるデータが、ネットワークに物理的にアクセスできる第三者によるパケット スニッフィングの標的になります。 また、プレーンな HTTP を使用すると、いくつかの一般的な認証方式の安全性も低下します。 具体的には、基本認証とフォーム認証で送信する資格情報が暗号化されません。 安全性を確保するには、これらの認証方式で SSL を使用する必要があります。

  1. ソリューション エクスプローラーWingtipToys プロジェクトをクリックし、F4 キーを押して [プロパティ] ウィンドウを表示します。
  2. [SSL 有効]true に変更します。
  3. 後で使用するための SSL URL をコピーします。
    SSL Web サイトを https://localhost:44300/ 以前に作成していない限り、SSL URL はになります (次に示すように)。
    プロジェクトのプロパティ
  4. ソリューション エクスプローラーWingtipToys プロジェクトを右クリックし、[プロパティ] をクリックします。
  5. 左側のタブで [Web]をクリックします。
  6. 先ほど保存した SSL URL を 使用するように Project URL を 変更します。
    Project Web プロパティ
  7. CTRL + S キーを押してページを保存します。
  8. Ctrl キーを押しながら F5 キーを押して アプリケーションを実行します。 Visual Studio により、SSL の警告を回避するためのオプションが表示されます。
  9. IIS Express SSL 証明書を信頼する場合は [はい] をクリックして続行します。
    SSL 証明書の詳細をIIS Expressする
    セキュリティ警告が表示されます。
  10. [はい] をクリックしてローカルホストに証明書をインストールします。
    [セキュリティの警告] ダイアログ ボックス
    ブラウザー ウィンドウが表示されます。

SSL を使用して Web アプリケーションをローカルで簡単にテストできるようになりました。

OAuth 2.0 プロバイダーを追加する

ASP.NET Web フォームは、メンバーシップと認証のオプションが強化されています。 OAuth もこうした強化点の 1 つです。 OAuth は、Web、モバイル、およびデスクトップのアプリケーションからシンプルで標準的な方法で安全に認証するためのオープン プロトコルです。 ASP.NET Web Forms テンプレートは OAuth を使用して、認証プロバイダーとしてFacebook、Twitter、Google、Microsoft を公開します。 このチュートリアルでは Google のみを認証プロバイダーとして使用しますが、コードを少し変更すれば他のプロバイダーも使用できます。 他のプロバイダーを実装する手順は、このチュートリアルで説明する手順とほとんど同じです。

このチュートリアルでは、認証の他にロールを使用して権限を付与します。 canEdit ロールに追加したユーザーだけが連絡先を変更 (作成、編集、削除) できます。

注意

Windows Live アプリケーションは、動作中の Web サイトのライブ URL のみを受け入れるため、ログインのテストにローカル Web サイトの URL を使用することはできません。

次の手順を実行することで、Google 認証プロバイダーを追加できます。

  1. App_Start\Startup.Auth.cs ファイルを開きます。

  2. app.UseGoogleAuthentication() メソッドのコメント文字を削除して、メソッドを次のような記述にします。

    app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
    {
        ClientId = "",
        ClientSecret = ""
    });
    
  3. Google Developers Consoleにアクセスします。 Google デベロッパーの電子メール アカウント (gmail.com) でサインインする必要があります。 Google アカウントを持っていない場合は、 [Create an account] リンクを選択します。
    Google Developers Consoleが表示されます。
    Google 開発者コンソール

  4. [ プロジェクトの作成 ] ボタンをクリックし、プロジェクト名と ID を入力します (既定値を使用できます)。 次に、 契約のチェックボックス と [ 作成 ] ボタンをクリックします。

    Google - 新しいプロジェクト

    新しいプロジェクトが数秒で作成され、新しいプロジェクトのページがブラウザーに表示されます。

  5. 左側のタブで、[ 認証 & API] をクリックし、[ 資格情報] をクリックします。

  6. [OAuth] の [新しいクライアント ID の作成] をクリックします。
    [Create Client ID] ダイアログ ボックスが表示されます。
    Google - クライアント ID を作成する

  7. [ クライアント ID の作成 ] ダイアログで、アプリケーションの種類の既定の Web アプリケーション をそのまま使用します。

  8. 承認された JavaScript Origins を、このチュートリアルで前に使用した SSL URL に設定します (https://localhost:44300/他の SSL プロジェクトを作成していない限り)。
    この URL は、アプリケーションの配信元です。 このサンプルでは、localhost テスト URL のみを入力します。 ただし、localhost と production を考慮して複数の URL を入力できます。

  9. [Authorized Redirect URI] には次の値を設定します。

    https://localhost:44300/signin-google
    

    この値は、ASP.NET OAuth ユーザーが Google の OAuth サーバーとの通信に使用する URI です。 上記で使用した SSL URL を覚えておいてください ( https://localhost:44300/ 他の SSL プロジェクトを作成していない限り)。

  10. [ クライアント ID の作成 ] ボタンをクリックします。

  11. Google 開発者コンソールの左側のメニューで、[ 同意] 画面 のメニュー項目をクリックし、メール アドレスと製品名を設定します。 フォームが完了したら、[保存] をクリック します

  12. [API] メニュー項目をクリックし、下にスクロールし、[Google+ API] の横にある [オフ] ボタンをクリックします。
    このオプションを受け入れると、Google+ API が有効になります。

  13. Microsoft.Owin NuGet パッケージをバージョン 3.0.0 に更新する必要もあります。
    [ツール] メニューの [NuGet パッケージ マネージャー] を選択し、[ソリューションの NuGet パッケージの管理] を選択します。
    [ NuGet パッケージの管理 ] ウィンドウで、 Microsoft.Owin パッケージを見つけてバージョン 3.0.0 に更新します。

  14. Visual Studio で、クライアント IDクライアント シークレットUseGoogleAuthenticationコピーしてメソッドに貼り付けることで、Startup.Auth.cs ページのメソッドを更新します。 次に示す クライアント IDクライアント シークレット の値はサンプルであり、機能しません。

    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. Ctrl キーを押しながら F5 キーを押して、アプリケーションをビルドして実行します。 [Log in] リンクをクリックします。

  16. [ 別のサービスを使用してログインする] で、[ Google] をクリックします。
    ログイン

  17. 資格情報の入力が必要な場合、Google のサイトにリダイレクトされるので、リダイレクト先のサイトで資格情報を入力します。
    Google - サインイン

  18. 資格情報を入力すると、先ほど作成した Web アプリケーションにアクセス許可を付与するように求められます。
    プロジェクトのデフォルト サービス アカウント

  19. [Accept](受け入れる) をクリックします。 これで、Google アカウントを登録できる WingtipToys アプリケーションの [登録] ページにリダイレクトされます。
    Google アカウントに登録する

  20. Google アカウントに使用するローカルの電子メール登録名を変更できますが、通常は既定の電子メール エイリアス (認証に使用したエイリアス) を変更しません。 上記のように [ログイン] をクリック します

ログイン機能の変更

このチュートリアル シリーズで既に説明したように、ユーザー登録機能の多くは既定で ASP.NET Web Forms テンプレートに含まれています。 次に、既定の Login.aspx ページと Register.aspx ページを変更して、 メソッドを MigrateCart 呼び出します。 メソッドは MigrateCart 、新しくログインしたユーザーを匿名ショッピング カートに関連付けます。 ユーザーとショッピング カートを関連付けることで、Wingtip Toys サンプル アプリケーションは、訪問の間にユーザーのショッピング カートを維持できます。

  1. ソリューション エクスプローラーで、[アカウント] フォルダーを見つけて開きます。

  2. Login.aspx.cs という名前の分離コード ページを変更して、黄色で強調表示されたコードを含め、次のように表示されるようにします。

    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. Login.aspx.cs ファイルを保存します。

ここでは、 メソッドの定義が存在しないという警告を MigrateCart 無視できます。 このチュートリアルでは、もう少し後で追加します。

Login.aspx.cs 分離コード ファイルでは、LogIn メソッドがサポートされています。 Login.aspx ページを調べることで、このページに "ログイン" ボタンが含まれていることが確認できます。このボタンをクリックすると、分離コードのハンドラーがトリガー LogIn されます。

LoginLogin.aspx.cs の メソッドが呼び出されると、 という名前usersShoppingCartのショッピング カートの新しいインスタンスが作成されます。 ショッピング カート (GUID) の ID が取得され、 変数に設定されます cartId 。 次に MigrateCart 、 メソッドが呼び出され、ログインしているユーザーの 名前と 名前の両方 cartId をこのメソッドに渡します。 ショッピング カートが移行されると、匿名ショッピング カートを識別するために使用される GUID がユーザー名に置き換えられます。

ユーザーがログインしたときにショッピング カートを移行するように Login.aspx.cs 分離コード ファイルを変更するだけでなく、 Register.aspx.cs 分離コード ファイル を変更して、ユーザーが新しいアカウントを作成してログインしたときにショッピング カートを移行する必要もあります。

  1. [アカウント] フォルダーで、Register.aspx.cs という名前の分離コード ファイルを開きます。

  2. コードを黄色で含めて分離コード ファイルを変更し、次のように表示されるようにします。

    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. Register.aspx.cs ファイルを保存します。 もう一度、 メソッドに関する警告を MigrateCart 無視します。

イベント ハンドラーで使用したコードは、 CreateUser_Click メソッドで LogIn 使用したコードと非常によく似ています。 ユーザーがサイトに登録またはログインすると、 メソッドの MigrateCart 呼び出しが行われます。

ショッピング カートの移行

ログインと登録のプロセスが更新されたので、 メソッドを使用してショッピング カートを移行するコードを MigrateCart 追加できます。

  1. ソリューション エクスプローラーで、Logic フォルダーを見つけて、ShoppingCartActions.cs クラス ファイルを開きます。

  2. ShoppingCartActions.cs ファイルの既存のコードに黄色で強調表示されたコードを追加して、ShoppingCartActions.cs ファイル内のコードが次のように表示されるようにします。

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

メソッドは MigrateCart 、既存の cartId を使用して、ユーザーのショッピング カートを検索します。 次に、コードはショッピング カートのすべてのアイテムをループ処理し、 プロパティ (スキーマで指定) をCartItemログインユーザー名に置き換えますCartId

データベース接続の更新

事前構築済みの Wingtip Toys サンプル アプリケーションを使用してこのチュートリアルに従っている場合は、既定のメンバーシップ データベースを再作成する必要があります。 既定の接続文字列を変更すると、次回アプリケーションを実行するとメンバーシップ データベースが作成されます。

  1. プロジェクトのルートにある Web.config ファイルを開きます。

  2. 既定の接続文字列を更新して、次のように表示されるようにします。

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

PayPal の統合

PayPal は、オンライン マーチャントによる支払いを受け入れる Web ベースの課金プラットフォームです。 このチュートリアルでは、PayPal の Express Checkout 機能をアプリケーションに統合する方法について説明します。 Express Checkout を使用すると、顧客は PayPal を使用して、ショッピング カートに追加したアイテムの支払いを行うことができます。

PayPal テスト アカウントを作成する

PayPal テスト環境を使用するには、開発者テスト アカウントを作成して確認する必要があります。 開発者テスト アカウントを使用して、購入者テスト アカウントと販売者テスト アカウントを作成します。 開発者テスト アカウントの資格情報を使用すると、Wingtip Toys サンプル アプリケーションから PayPal テスト環境にアクセスすることもできます。

  1. ブラウザーで、PayPal 開発者テスト サイトに移動します。
    https://developer.paypal.com

  2. PayPal 開発者アカウントをお持ちでない場合は、[サインアップ] をクリックし、 サインアップ手順に従って新しいアカウントを作成します。 既存の PayPal 開発者アカウントがある場合は、[ ログイン] をクリックしてサインインします。 このチュートリアルの後半で Wingtip Toys サンプル アプリケーションをテストするには、PayPal 開発者アカウントが必要です。

  3. PayPal 開発者アカウントにサインアップしたばかりの場合は、PayPal で PayPal 開発者アカウントの確認が必要になる場合があります。 PayPal がメール アカウントに送信した手順に従って、アカウントを確認できます。 PayPal 開発者アカウントを確認したら、PayPal 開発者テスト サイトに再度ログインします。

  4. PayPal 開発者アカウントを使用して PayPal 開発者サイトにログインしたら、PayPal 購入者テスト アカウントをまだ作成していない場合は作成する必要があります。 購入者テスト アカウントを作成するには、PayPal サイトで [ アプリケーション ] タブをクリックし、[ サンドボックス アカウント] をクリックします。
    [サンドボックス テスト アカウント] ページが表示されます。

    注意

    PayPal Developer サイトには、マーチャント テスト アカウントが既に用意されています。

    [アプリケーション] タブが強調表示されている [サンドボックス テスト アカウント] ページを示すスクリーンショット。

  5. [サンドボックス テスト アカウント] ページで、[ アカウントの作成] をクリックします。

  6. [ テスト アカウントの作成 ] ページで、任意の購入者テスト アカウントのメールとパスワードを選択します。

    注意

    このチュートリアルの最後に Wingtip Toys サンプル アプリケーションをテストするには、購入者のメール アドレスとパスワードが必要です。

    作成中のアカウントのフィールドを表示する [テスト アカウントの作成] ページのスクリーンショット。

  7. [アカウントの作成] ボタンをクリックして、購入者テスト アカウントを作成 します。
    [サンドボックス テスト アカウント] ページが表示されます。

    PayPal でのチェックアウトと支払い - PayPal アカウント

  8. [ サンドボックス テスト アカウント ] ページで、 ファシリテーター のメール アカウントをクリックします。
    プロファイル通知 のオプションが表示されます。

  9. [ プロファイル ] オプションを選択し、[ API 資格情報 ] をクリックして、マーチャント テスト アカウントの API 資格情報を表示します。

  10. TEST API 資格情報をメモ帳にコピーします。

Wingtip Toys サンプル アプリケーションから PayPal テスト環境に API 呼び出しを行うには、表示されたクラシック TEST API 資格情報 (ユーザー名、パスワード、署名) が必要です。 次の手順で資格情報を追加します。

PayPal クラスと API 資格情報を追加する

PayPal コードの大部分を 1 つのクラスに配置します。 このクラスには、PayPal との通信に使用されるメソッドが含まれています。 また、このクラスに PayPal 資格情報を追加します。

  1. Visual Studio 内の Wingtip Toys サンプル アプリケーションで、[ ロジック ] フォルダーを右クリックし、[ 追加 ] ->[新しい項目] を選択します。
    [新しい項目の追加] ダイアログ ボックスが表示されます。

  2. 左側の [インストール済み] ペインの [Visual C#] で、[コード] を選択します

  3. 中央のウィンドウで、[クラス] を選択 します。 この新しいクラスに PayPalFunctions.cs という名前を付けます

  4. [追加] をクリックします。
    新しいクラス ファイルがエディターに表示されます。

  5. 既定のコードを以下のコードに置き換えます。

    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. PayPal テスト環境に関数呼び出しを実行できるように、このチュートリアルで前に表示した Merchant API 資格情報 (ユーザー名、パスワード、署名) を追加します。

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

注意

このサンプル アプリケーションでは、単に資格情報を C# ファイル (.cs) に追加します。 ただし、実装されたソリューションでは、構成ファイルで資格情報を暗号化することを検討する必要があります。

NVPAPICaller クラスには、PayPal 機能の大部分が含まれています。 クラスのコードは、PayPal テスト環境からテスト購入を行うために必要なメソッドを提供します。 購入には、次の 3 つの PayPal 関数が使用されます。

  • SetExpressCheckout 関数
  • GetExpressCheckoutDetails 関数
  • DoExpressCheckoutPayment 関数

メソッドは ShortcutExpressCheckout 、ショッピング カートからテスト購入情報と製品の詳細を収集し、PayPal 関数を SetExpressCheckout 呼び出します。 メソッドは GetCheckoutDetails 、購入の詳細を確認し、テスト購入を行う前に GetExpressCheckoutDetails PayPal 関数を呼び出します。 メソッドは DoCheckoutPayment 、PayPal 関数を呼び出して、テスト環境からのテスト購入を DoExpressCheckoutPayment 完了します。 残りのコードでは、文字列のエンコード、文字列のデコード、配列の処理、資格情報の決定など、PayPal メソッドとプロセスがサポートされています。

注意

PayPal を使用すると、 PayPal の API 仕様に基づいてオプションの購入の詳細を含めることができます。 Wingtip Toys サンプル アプリケーションでコードを拡張することで、ローカライズの詳細、製品の説明、税、顧客サービス番号、その他の多くのオプション フィールドを含めることができます。

ShortcutExpressCheckout メソッドで指定されている戻り URL と取り消し URL ではポート番号が使用されることに注意してください。

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

Visual Web Developer が SSL を使用して Web プロジェクトを実行する場合、一般的にポート 44300 が Web サーバーに使用されます。 上記のように、ポート番号は 44300 です。 アプリケーションを実行すると、別のポート番号が表示される場合があります。 このチュートリアルの最後で Wingtip Toys サンプル アプリケーションを正常に実行できるように、コードでポート番号を正しく設定する必要があります。 このチュートリアルの次のセクションでは、ローカル ホスト ポート番号を取得し、PayPal クラスを更新する方法について説明します。

PayPal クラスの LocalHost ポート番号を更新する

Wingtip Toys サンプル アプリケーションは、PayPal テスト サイトに移動し、Wingtip Toys サンプル アプリケーションのローカル インスタンスに戻ることで製品を購入します。 PayPal が正しい URL に戻るには、前述の PayPal コードでローカルで実行されているサンプル アプリケーションのポート番号を指定する必要があります。

  1. ソリューション エクスプローラーでプロジェクト名 (WingtipToys) を右クリックし、[ プロパティ] を選択します

  2. 左側の列で、[ Web ] タブを選択します。

  3. [ プロジェクト URL] ボックスからポート番号を取得します。

  4. 必要に応じて、PayPalFunctions.cs ファイルの PayPal クラス (NVPAPICaller) の と cancelURL を更新returnURLして、Web アプリケーションのポート番号を使用します。

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

ここで、追加したコードは、ローカル Web アプリケーションの予想されるポートと一致します。 PayPal は、ローカル コンピューター上の正しい URL に戻すことができます。

PayPal チェックアウト ボタンを追加する

主要な PayPal 関数がサンプル アプリケーションに追加されたので、これらの関数を呼び出すために必要なマークアップとコードの追加を開始できます。 最初に、ユーザーがショッピング カート ページに表示するチェックアウト ボタンを追加する必要があります。

  1. ShoppingCart.aspx ファイルを開きます。

  2. ファイルの一番下までスクロールし、コメントを <!--Checkout Placeholder --> 見つけます。

  3. コメントをコントロールに ImageButton 置き換えて、マークアップを次のように置き換えます。

    <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. ShoppingCart.aspx.cs ファイルで、ファイルの末尾付近にあるUpdateBtn_Clickイベント ハンドラーの後に、イベント ハンドラーをCheckOutBtn_Click追加します。

    protected void CheckoutBtn_Click(object sender, ImageClickEventArgs e)
    {
        using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
        {
            Session["payment_amt"] = usersShoppingCart.GetTotal();
        }
        Response.Redirect("Checkout/CheckoutStart.aspx");
    }
    
  5. また、 ShoppingCart.aspx.cs ファイルで、 への参照を追加して CheckoutBtn、新しいイメージ ボタンが次のように参照されるようにします。

    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. 変更を ShoppingCart.aspx ファイルと ShoppingCart.aspx.cs ファイルの両方に保存します。

  7. メニューから [Debug-Build>WingtipToys] を選択します。
    プロジェクトは、新しく追加された ImageButton コントロールを使用して再構築されます。

購入の詳細を PayPal に送信する

ユーザーがショッピング カート ページ (ShoppingCart.aspx) の [チェックアウト] ボタンをクリックすると、購入プロセスが開始されます。 次のコードは、製品を購入するために必要な最初の PayPal 関数を呼び出します。

  1. Checkout フォルダーから CheckoutStart.aspx.cs という名前の分離コード ファイルを開きます。
    分離コード ファイルを必ず開きます。

  2. 既存のコードを次のコードに置き換えます。

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

アプリケーションのユーザーがショッピング カート ページの [チェックアウト ] ボタンをクリックすると、ブラウザーは CheckoutStart.aspx ページに移動します。 CheckoutStart.aspx ページが読み込まれると、 ShortcutExpressCheckout メソッドが呼び出されます。 この時点で、ユーザーは PayPal テスト Web サイトに転送されます。 PayPal サイトでは、ユーザーは PayPal の資格情報を入力し、購入の詳細を確認し、PayPal 契約に同意し、メソッドが完了した Wingtip Toys サンプル アプリケーションに ShortcutExpressCheckout 戻ります。 メソッドが ShortcutExpressCheckout 完了すると、 メソッドで指定された CheckoutReview.aspx ページにユーザーが ShortcutExpressCheckout リダイレクトされます。 これにより、ユーザーは Wingtip Toys サンプル アプリケーション内から注文の詳細を確認できます。

注文の詳細を確認する

PayPal から戻った後、Wingtip Toys サンプル アプリケーションの CheckoutReview.aspx ページに注文の詳細が表示されます。 このページでは、ユーザーは製品を購入する前に注文の詳細を確認できます。 CheckoutReview.aspx ページは、次のように作成する必要があります。

  1. Checkout フォルダーで、CheckoutReview.aspx という名前のページを開きます。

  2. 既存のマークアップを次のように置き換えます。

    <%@ 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. CheckoutReview.aspx.cs という名前の分離コード ページを開き、既存のコードを次のように置き換えます。

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

DetailsView コントロールは、PayPal から返された注文の詳細を表示するために使用されます。 また、上記のコードでは、注文の詳細が Wingtip Toys データベースに OrderDetail オブジェクトとして保存されます。 ユーザーが [ 注文の完了 ] ボタンをクリックすると、 CheckoutComplete.aspx ページにリダイレクトされます。

注意

ヒント

CheckoutReview.aspx ページのマークアップで、ページの下部付近にある DetailsView コントロール内の項目のスタイルを変更するためにタグが使用されていること<ItemStyle>に注意してください。 デザイン ビューでページを表示すると (Visual Studio の左下隅にある [デザイン] を選択し、DetailsView コントロールを選択し、スマート タグ (コントロールの右上にある矢印アイコン) を選択すると、DetailsView タスクを表示できます。

PayPal を使用したチェックアウトと支払い - フィールドの編集

[フィールドの 編集] を選択すると、[ フィールド ] ダイアログ ボックスが表示されます。 このダイアログ ボックスでは、DetailsView コントロールの ItemStyle などのビジュアル プロパティを簡単に制御できます。

PayPal を使用したチェックアウトと支払い - [フィールド] ダイアログ

購入の完了

CheckoutComplete.aspx ページは PayPal から購入します。 前述のように、アプリケーションが CheckoutComplete.aspx ページに移動する前に、ユーザーは [注文の完了] ボタンをクリックする必要があります。

  1. Checkout フォルダーで、CheckoutComplete.aspx という名前のページを開きます。

  2. 既存のマークアップを次のように置き換えます。

    <%@ 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. CheckoutComplete.aspx.cs という名前の分離コード ページを開き、既存のコードを次のように置き換えます。

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

CheckoutComplete.aspx ページが読み込まれるとDoCheckoutPayment、 メソッドが呼び出されます。 前述のように、 メソッドは DoCheckoutPayment PayPal テスト環境からの購入を完了します。 PayPal が注文の購入を完了すると、 CheckoutComplete.aspx ページに購入者への支払いトランザクション ID が表示されます。

購入の取り消しを処理する

ユーザーが購入を取り消す場合は、 CheckoutCancel.aspx ページに移動し、注文が取り消されたことを確認します。

  1. Checkout フォルダーでCheckoutCancel.aspx という名前のページを開きます。

  2. 既存のマークアップを次のように置き換えます。

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

購入エラーの処理

購入プロセス中のエラーは、 CheckoutError.aspx ページによって処理されます。 CheckoutStart.aspx ページ、CheckoutReview.aspx ページ、CheckoutComplete.aspx ページの分離コードは、エラーが発生した場合に CheckoutError.aspx ページにリダイレクトされます。

  1. Checkout フォルダーでCheckoutError.aspx という名前のページを開きます。

  2. 既存のマークアップを次のように置き換えます。

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

チェックアウト プロセス中にエラーが発生すると、 CheckoutError.aspx ページがエラーの詳細と共に表示されます。

アプリケーションの実行

アプリケーションを実行して、製品を購入する方法を確認します。 PayPal テスト環境で実行されることに注意してください。 実際のお金は交換されません。

  1. すべてのファイルが Visual Studio に保存されていることを確認します。

  2. Web ブラウザーを開き、 に移動します https://developer.paypal.com

  3. このチュートリアルで前に作成した PayPal 開発者アカウントでログインします。
    PayPal の開発者サンドボックスの場合は、高速チェックアウトをテストするために に https://developer.paypal.com ログインする必要があります。 これは PayPal のサンドボックス テストにのみ適用され、PayPal のライブ環境には適用されません。

  4. Visual Studio で F5 キーを押して Wingtip Toys サンプル アプリケーションを実行します。
    データベースの再構築後、ブラウザーが開き、 Default.aspx ページが表示されます。

  5. ショッピング カートに 3 つの異なる製品を追加するには、"Cars" などの製品カテゴリを選択し、各製品の横にある [ カートに追加 ] をクリックします。
    選択した製品がショッピング カートに表示されます。

  6. [ PayPal ] ボタンをクリックしてチェックアウトします。

    PayPalでのチェックアウトと支払い - カート

    チェックアウトするには、Wingtip Toys サンプル アプリケーションのユーザー アカウントが必要です。

  7. ページの右側にある Google リンクをクリックして、既存の gmail.com メール アカウントでログインします。
    gmail.com アカウントがない場合は、 www.gmail.com でテスト目的で作成できます。 [登録] をクリックして、標準のローカル アカウントを使用することもできます。

    PayPal でのチェックアウトと支払い - ログイン

  8. Gmail アカウントとパスワードでサインインします。

    PayPal でのチェックアウトと支払い - Gmail サインイン

  9. [ ログイン ] ボタンをクリックして、Gmail アカウントを Wingtip Toys サンプル アプリケーションのユーザー名に登録します。

    PayPal でのチェックアウトと支払い - アカウントの登録

  10. PayPal テスト サイトで、このチュートリアルで前に作成した 購入者 のメール アドレスとパスワードを追加し、[ ログイン ] ボタンをクリックします。

    PayPal でのチェックアウトと支払い - PayPal サインイン

  11. PayPal ポリシーに同意し、[同意して 続行 ] ボタンをクリックします。
    このページは、この PayPal アカウントを初めて使用したときにのみ表示されることに注意してください。 繰り返しになりますが、これはテスト アカウントであり、実際のお金は交換されません。

    PayPal でのチェックアウトと支払い - PayPal ポリシー

  12. PayPal テスト環境のレビュー ページで注文情報を確認し、[ 続行] をクリックします。

    PayPal でのチェックアウトと支払い - レビュー情報

  13. CheckoutReview.aspx ページで、注文金額を確認し、生成された配送先住所を表示します。 次に、[ 注文の完了 ] ボタンをクリックします。

    PayPal でのチェックアウトと支払い - 注文レビュー

  14. CheckoutComplete.aspx ページは、支払いトランザクション ID と共に表示されます。

    PayPal でのチェックアウトと支払い - チェックアウトの完了

データベースの確認

アプリケーションの実行後に Wingtip Toys サンプル アプリケーション データベースの更新されたデータを確認すると、アプリケーションが製品の購入を正常に記録していることがわかります。

Wingtiptoys.mdf データベース ファイルに含まれるデータは、このチュートリアル シリーズで前に行ったように、[データベース エクスプローラー] ウィンドウ (Visual Studio の [サーバー エクスプローラー] ウィンドウ) を使用して調べることができます。

  1. ブラウザー ウィンドウがまだ開いている場合は閉じます。

  2. Visual Studio で、ソリューション エクスプローラーの上部にある [すべてのファイルを表示] アイコンを選択して、App_Data フォルダーを展開できるようにします。

  3. App_Data フォルダーを展開します。
    フォルダーの [ すべてのファイルを表示 ] アイコンを選択する必要がある場合があります。

  4. Wingtiptoys.mdf データベース ファイルを右クリックし、[開く] を選択します。
    サーバー エクスプローラーが表示されます。

  5. [テーブル] フォルダーを展開します。

  6. Ordersテーブルを右クリックし、[テーブル データの表示] を選択します。
    Orders テーブルが表示されます。

  7. 成功したトランザクションを確認するには 、PaymentTransactionID 列を確認します。

    PayPal でのチェックアウトと支払い - データベースの確認

  8. Orders テーブル ウィンドウを閉じます。

  9. サーバー エクスプローラーで OrderDetails テーブルを右クリックし、[テーブル データの表示] を選択します。

  10. OrderIdOrderDetails テーブルの と Username の値を確認します。 これらの値は、Orders テーブルにOrderId含まれる と の値とUsername一致していることに注意してください。

  11. OrderDetails テーブル ウィンドウを閉じます。

  12. Wingtip Toys データベース ファイル (Wingtiptoys.mdf) を右クリックし、[接続を 閉じる] を選択します。

  13. [ソリューション エクスプローラー] ウィンドウが表示されない場合は、[サーバー エクスプローラー] ウィンドウの下部にある [ソリューション エクスプローラー] をクリックして、ソリューション エクスプローラーをもう一度表示します。

まとめ

このチュートリアルでは、注文と注文の詳細スキーマを追加して、製品の購入を追跡しました。 また、PayPal 機能を Wingtip Toys サンプル アプリケーションに統合しました。

その他のリソース

ASP.NET 構成の概要
メンバーシップ、OAuth、SQL Databaseを使用してセキュリティで保護された ASP.NET Web Forms アプリをAzure App Serviceにデプロイする
Microsoft Azure - 無料試用版

免責情報

このチュートリアルには、サンプル コードが含まれています。 このようなサンプル コードは、いかなる種類の保証もなく "現状のまま" 提供されます。 したがって、Microsoft はサンプル コードの正確性、整合性、または品質を保証しません。 お客様は、自己責任でサンプル コードを使用することに同意するものとします。 いかなる状況でも、Microsoft は、サンプル コード、サンプル コードのエラーや欠落、サンプル コードの使用によって生じたいかなる種類の損失または損害を含むがこれらに限定されないコンテンツに対して、いかなる方法でもお客様に責任を負いません。 お客様はここに通知され、お客様が投稿、送信、使用、または依存する資料によって生じた、またはそれらに起因するものを含むがこれらに限定されない、あらゆる種類の損失、損失、傷害または損害に対して、Microsoft に対して補償、保存、および無害な状態を維持することに同意します。ここに記載されているビューを含みますが、これらに限定されません。