用c#和ASP实现PayPal智能按钮的客户端/服务器。网络核心

源代码

学习成果

  • 如何建立PayPal商业账户。
  • 如何为沙箱获取API凭据——即客户端ID和秘密。
  • 如何获取实时的API凭证——例如客户端ID和Secret。
  • 数据存储中的字段。
  • 服务器端代码。

先决条件

  • 您已经为您的电子商务网站注册了一个URL,例如,www.delaneys.space。
  • 网站使用SSL证书进行保护。
  • 您的客户可以注册和登录到您的网站在一个安全的方式使用OAuth或一些过度安全的方法。
  • 你的网站有一个后台数据存储,你知道如何维护它。
  • 你对Visual Studio很熟悉。

用下面的行标题创建一个电子表格:

1仪表板url https://www.paypal.com/mep/dashboard2开发者仪表板url https://developer.paypal.com/developer/applications3沙箱细节 4 url www.sandbox.paypal.com/5 app名称6业务7用户名……@business.example.com8密码,9客户端id10的秘密,11个人(顾客)12个用户名…@personal.example.com13个密码,14个生活细节 ,15个用户名info@……16个密码,17 app名称18客户id19个秘密,

创建一个PayPal业务帐户

要创建一个PayPal商业账户,你不需要拥有自己的企业或商业银行账户。不过,你应该采取措施,把你的个人金融交易与电子商务网站的交易分开。因此,我建议使用一个单独的个人银行账户连接到你的PayPal业务账户。

      导航到www.PayPal.com。点击注册,即使你已经有一个个人贝宝帐户。记住永远不要把工作和娱乐混为一谈。 选择业务帐户并单击Next。完成简短的问卷 对于“我想主要接受付款”的问题,选择“On my website”。选择问题“May annual volume is:”的答案。
Image 2
    提供一个电子邮件地址并单击Continue。 这可以是任何有效的电子邮件地址,但你可能想使用“info@youre-commerce.com”。 提供密码并单击Continue。 确认电子邮件将发送到所提供的地址。 更新你的电子表格。 15个用户名info@……16个密码, 完成业务联系细节页面,点击同意和创建帐户。 他们会要求你的联系人姓名,企业名称,电话号码和企业地址。 选择业务类型 从个人、独资、合伙、私人公司、上市公司、非营利组织、政府实体、信托投资和家庭的列表中选择。 添加个人信息。 包括你的姓名、出生日期和地址。 单击Submit。 您现在已经建立了您的PayPal业务帐户。您将看到一个仪表板显示。

获取API凭证——即客户端ID和秘密

    进入开发人员控制面板: 2开发者仪表板url https://developer.paypal.com/developer/applications 沙箱选项将被预先选中。我们先来设置它。 单击“创建应用”。创建一个沙箱应用名称并存储在电子表格中。 17 app名称 再次单击Create App。 更新以下电子表格: 6业务7用户名…@business.example.com , 9客户端id10的秘密, 现在让我们获取密码。 点击沙箱|帐户按钮或(developer.paypal.com/developer/accounts/)。 您应该看到两个电子邮件地址表示一个企业帐户和个人帐户。 点击业务账户的…按钮,选择查看/编辑账户。 在电子表格中记录系统生成的密码。 8密码, 单击Close。点击个人帐户的…按钮,选择查看/编辑帐户。 在电子表格中记录用户名和密码。 11个人(顾客)12个用户名……@personal.example.com 13密码 |0>>>>;

为Live获取API凭据

    点击我的应用程序&凭证(developer.paypal.com/developer/applications/)。单击Live按钮。 单击Create App。 在电子表格中记录应用程序名称。 17 app名称 点击创建App(再次)。 在电子表格中记录客户ID和secret。 18客户id19个秘密,

要向数据存储添加哪些字段

      选择一个数据存储,比如SQL Servers。你需要一个篮子,项目和发票模型/核心类。将以下蓝色突出显示的字段添加到您的发票表中。这些字段将被贝宝使用。
Image 6
    注意,FirstName、LastName和Email存储在用户表中,但是也复制在Invoice表中。这是因为来自客户PayPal账户的数据可能与用户表中的数据不同。 由您决定如何在数据存储中包括蓝色字段。

服务器端代码

  1. Create an ASP.NET Core 3.x MVC application using Visual Studio.
  2. Go to NuGet package manager and add the following packages:
    • PayPalCheckoutSdk, package version 1.0.3. I used the latest version at the time of writing.

      PayPalCheckoutSdk is merely a class library. There is no logic contained within the library. The classes are decorated with attributes to aid the serialisation into JSON.

    • PayPalHttp v1.0.0.

    • Microsoft.AspNetCore.Mvc.NewtonsoftJson. With the release of ASP.NET Core 3.0 Microsoft broke their implementation of JSON serialisation. Search for "ASP.NET Core: Blank Json {} Return After Upgrading to 3.0" to find out what to add to Startup.ConfigureServices or choose an option from the next step.

  3. Update Startup.ConfigureServices to call AddNewtonsoftJson.

    services.AddMvc()
            .AddNewtonsoftJson();

    OR

    services.AddMvc()
            .AddNewtonsoftJson(options =>
                               options.SerializerSettings.ContractResolver =
                               new CamelCasePropertyNamesContractResolver());

     

  4. Create a folder called PayPal in your ASP.NET Core project.
  5. Create a class PayPalClient in the folder, with the code below.
    Remember to use the sandbox and live client Ids and secrets to populate the highlighted string content.
    using System;
    using PayPalCheckoutSdk.Core;
    
    using System.IO;
    using System.Text;
    using System.Runtime.Serialization.Json;
    
    namespace PayPal
    {
        public class PayPalClient
        {
            // Place these static properties into a settings area.
            public static string SandboxClientId { get; set; } = "<alert>{PayPal SANDBOX Client Id}</alert>";
            public static string SandboxClientSecret { get; set; } = "<alert>{PayPal SANDBOX Client Secret}</alert>";
    
            public static string LiveClientId { get; set; } = "<alert>{PayPal LIVE Client Id}</alert>";
            public static string LiveClientSecret { get; set; } = "<alert>{PayPal LIVE Client Secret}</alert>";
    
            ///<summary>
            /// Set up PayPal environment with sandbox credentials.
            /// In production, use LiveEnvironment.
            ///</summary>
            public static PayPalEnvironment Environment()
            {
    #if DEBUG
                // You may want to create a UAT (user exceptance tester) role and check for this:
                // "if(_unitOfWork.IsUATTester(GetUserId())" instead of fcomiler directives.
                return new SandboxEnvironment(<alert>SandboxClientId</alert>,
                                              <alert>SandboxClientSecret</alert>);
    #else
                return new LiveEnvironment(<alert>LiveClientId</alert>, 
                                           <alert>LiveClientSecret</alert>);
    #endif
            }
    
            ///<summary>
            /// Returns PayPalHttpClient instance to invoke PayPal APIs.
            ///</summary>
            public static PayPalCheckoutSdk.Core.PayPalHttpClient Client()
            {
                return new PayPalHttpClient(Environment());
            }
    
            public static PayPalCheckoutSdk.Core.PayPalHttpClient Client(string refreshToken)
            {
                return new PayPalHttpClient(Environment(), refreshToken);
            }
    
            
            ///<summary>
            /// Use this method to serialize Object to a JSON string.
            ///</summary>
            public static String ObjectToJSONString(Object serializableObject)
            {
                MemoryStream memoryStream = new MemoryStream();
                var writer = JsonReaderWriterFactory.CreateJsonWriter(memoryStream,
                                                                      Encoding.UTF8,
                                                                      true,
                                                                      true,
                                                                      "  ");
    
                var ser = new DataContractJsonSerializer(serializableObject.GetType(),
                                                         new DataContractJsonSerializerSettings 
                                                         {
                                                             UseSimpleDictionaryFormat = true 
                                                         });
    
                ser.WriteObject(writer,
                                serializableObject);
    
                memoryStream.Position = 0;
                StreamReader sr = new StreamReader(memoryStream);
    
                return sr.ReadToEnd();
            }
        }
    }
  6. Create a class SmartButtonHttpResponse in the folder, with code.
    using System.Net;
    using System.Net.Http.Headers;
    
    namespace PayPal
    {
        public class SmartButtonHttpResponse
        {
            readonly PayPalCheckoutSdk.Orders.Order _result;
            public SmartButtonHttpResponse(PayPalHttp.HttpResponse httpResponse)
            {
                Headers = httpResponse.Headers;
                StatusCode = httpResponse.StatusCode;
                _result = httpResponse.Result<PayPalCheckoutSdk.Orders.Order>();
            }
    
            public HttpHeaders Headers { get; }
            public HttpStatusCode StatusCode { get; }
    
            public PayPalCheckoutSdk.Orders.Order Result()
            {
                return _result;
            }
    
            public string orderID { get; set; }
        }
    }
  7. Create a class OrderBuilder in the folder, with code.

    using PayPalCheckoutSdk.Orders;
    using System.Collections.Generic;
    
    namespace PayPal
    {
        public static class OrderBuilder
        {
            /// <summary>
            /// Use classes from the PayPalCheckoutSdk to build an OrderRequest
            /// </summary>
            /// <returns></returns>
            public static OrderRequest Build()
            {
                OrderRequest orderRequest = new OrderRequest();
                
                // Add code to fill out the order request properties
                <alert>// See the attached source code for a more detailed example.</alert> 
    
                return orderRequest;
            }
        }
    }
  8. Create a controller class in the Controllers folder called CheckoutController. Add the following code.

    using Microsoft.AspNetCore.Mvc;
    using System.Threading.Tasks;
    
    using PayPalCheckoutSdk.Orders;
    
    namespace Test.Controllers
    {
        public class CheckoutController : Controller
        {
            /// <summary>
            /// Action to display the cart form for the SERVER side intergration
            /// </summary>
            /// <returns></returns>
            public IActionResult Index()
            {
    #if DEBUG
                // You may want to create a UAT (user exceptance tester) role and check for this:
                // "if(_unitOfWork.IsUATTester(GetUserId())"
                // Company SANDBOX Client Id. To go live replace this with the live ID.
                ViewBag.ClientId = <alert>PayPal.PayPalClient.SandboxClientId</alert>; // Get from a data store or stettings
    #else
                // Company LIVE Client Id. To go live replace this with the live ID.
                ViewBag.ClientId = <alert>PayPal.PayPalClient.LiveClientId</alert>; // Get from a data store or stettings
    #endif
    
                ViewBag.CurrencyCode = "GBP"; // Get from a data store
                ViewBag.CurrencySign = "£";   // Get from a data store
    
                return View();
            }
    
            /// <summary>
            /// This action is called when the user clicks on the PayPal button.
            /// </summary>
            /// <returns></returns>
            [Route("api/paypal/checkout/order/create")]
            public async Task<PayPal.SmartButtonHttpResponse> Create()
            {
                var request = new PayPalCheckoutSdk.Orders.OrdersCreateRequest();
    
                request.Prefer("return=representation");
                request.RequestBody(PayPal.OrderBuilder.Build());
                
                // Call PayPal to set up a transaction
                var response = await PayPal.PayPalClient.Client().Execute(request);
                
                // Create a response, with an order id.
                var result = response.Result<PayPalCheckoutSdk.Orders.Order>();
                var payPalHttpResponse = new PayPal.SmartButtonHttpResponse(response)
                {
                    orderID = result.Id
                };
                return payPalHttpResponse;
            }
    
    
            /// <summary>
            /// This action is called once the PayPal transaction is approved
            /// </summary>
            /// <paramname="orderId"></param>
            /// <returns></returns>
            [Route("api/paypal/checkout/order/approved/{orderId}")]
            public IActionResult Approved(string orderId)
            {
                return Ok();
            }
    
    
            /// <summary>
            /// This action is called once the PayPal transaction is complete
            /// </summary>
            /// <paramname="orderId"></param>
            /// <returns></returns>
            [Route("api/paypal/checkout/order/complete/{orderId}")]
            public IActionResult Complete(string orderId)
            {
                // 1. Update the database.
                // 2. Complete the order process. Create and send invoices etc.
                // 3. Complete the shipping process.
                return Ok();
            }
    
    
            /// <summary>
            /// This action is called once the PayPal transaction is complete
            /// </summary>
            /// <paramname="orderId"></param>
            /// <returns></returns>
            [Route("api/paypal/checkout/order/cancel/{orderId}")]
            public IActionResult Cancel(string orderId)
            {
                // 1. Remove the orderId from the database.
                return Ok();
            }
    
    
            /// <summary>
            /// This action is called once the PayPal transaction is complete
            /// </summary>
            /// <paramname="orderId"></param>
            /// <returns></returns>
            [Route("api/paypal/checkout/order/error/{orderId}/{error}")]
            public IActionResult Error(string orderId,
                                       string error)
            {
                // Log the error.
                // Notify the user.
                return NoContent();
            }
        }
    }
  9. Create a Checkout folder in the Views folder and add a view called index.cshtml

    Add the following code to create the PayPal smart button to the view.

    <!-- Set up a container element for the PayPal smart button -->
    <divid="paypal-button-container"></div>
    
    <!-- Include the PayPal JavaScript SDK -->
    <scriptsrc="https://www.paypal.com/sdk/js?client-id=@ViewBag.ClientId&currency=@ViewBag.CurrencyCode"></script>
    
    <script>
    
        // This is stored just in case the user cancels the other 
        // or there is an error in the other process.
        var orderId;
        // Render the PayPal smart button into #paypal-button-container
        paypal.Buttons({
    
            // Set up the transaction
            createOrder: function (data, actions) {
                orderId = data.orderID;
                return fetch('/api/paypal/checkout/order/create/', {
                    method: 'post'
                }).then(function (res) {
                    return res.json();
                }).then(function (data) {
                    return data.orderID;
                });
            },
    
            // Finalise the transaction
            onApprove: function (data, actions) {
                return fetch('/api/paypal/checkout/order/approved/' + data.orderID, {
                    method: 'post'
                }).then(function (res) {
                    return actions.order.capture();
                }).then(function (details) {
    
                    // (Preferred) Notify the server that the transaction id complete and have a option to display an order completed screen.
                    window.location.replace('/api/paypal/checkout/order/complete/' + data.orderID + '/@ViewBag.CurrencyCode');
                    
                    // OR
                    // Notify the server that the transaction id complete
                    //httpGet('/api/paypal/checkout/order/complete/' + data.orderID);
    
                    // Show a success message to the buyer
                    alert('Transaction completed by ' + details.payer.name.given_name + '!');
                });
            },
    
            // Buyer cancelled the payment
            onCancel: function (data, actions) {
                httpGet('/api/paypal/checkout/order/cancel/' + data.orderID);
            },
    
            // An error occurred during the transaction
            onError: function (err) {
                httpGet('/api/paypal/checkout/order/error/' + orderId + '/' + encodeURIComponent(err));
            }
    
        }).render('#paypal-button-container');
    </script>

    Apart from the URLs, this code is the same for all solutions.

  10. Add the following JavaScript function:

    function httpGet(url) {
        var xmlHttp = new XMLHttpRequest();
        xmlHttp.open("GET", url, false);
        xmlHttp.send(null);
        return xmlHttp.responseText;
    }
  11. Create a folder called Values within the PayPal folder.

  12. Add a class called CheckoutPaymentIntent.cs, within the Values folder.
    Add the following code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace PayPal.Values
    {
        /// <summary>
        /// The intent to either capture payment immediately or
        /// authorize a payment for an order after order creation.
        /// </summary>
        public static class CheckoutPaymentIntent
        {
    
            /// <summary>
            /// The merchant intends to capture payment immediately after the customer makes a payment.
            /// </summary>
            public static string CAPTURE { get; private set; } = "CAPTURE";
    
            /// <summary>
            /// The merchant intends to authorize a payment and
            /// place funds on hold after the customer makes a payment.
            /// Authorized payments are guaranteed for up to three days but
            /// are available to capture for up to 29 days.
            /// After the three-day honor period, the original authorized payment expires
            /// and you must re-authorize the payment.
            /// You must make a separate request to capture payments on demand.
            /// This intent is not supported when you have more than one `purchase_unit` within your order.
            /// </summary>
            public static string AUTHORIZE { get; private set; } = "AUTHORIZE";
        }
    }
  13. Add a class called CurrencyCode.cs, within the Values folder.
    Add the following code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace PayPal.Values
    {
        public static class CurrencyCode
        {
    
            /// <summary>
            /// Great British Pounds
            /// </summary>
            public static string GBP { get; private set; } = "GBP";
    
            /// <summary>
            /// US Dolars
            /// </summary>
            public static string USD { get; private set; } = "USD";
    
            /// <summary>
            /// Euros
            /// </summary>
            public static string EUR { get; private set; } = "EUR";
        }
    }

    Add additional currencies, as required.

  14. Add a class called LandingPage.cs, within the Values folder.
    Add the following code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace PayPal.Values
    {
        /// <summary>
        /// The type of landing page to show on the PayPal site for customer checkout.
        /// Default: NO_PREFERENCE.
        /// Source: https://developer.paypal.com/docs/api/orders/v2/
        /// </summary>
        public class LandingPage
        {
            /// <summary>
            /// When the customer clicks PayPal Checkout, the customer is redirected to a page to log in to PayPal and approve the payment.
            /// </summary>
            public static string LOGIN { get; private set; } = "LOGIN";
    
            /// <summary>
            /// When the customer clicks PayPal Checkout, 
            /// the customer is redirected to a page to enter credit or 
            /// debit card and other relevant billing information required to complete the purchase.
            /// </summary>
            public static string BILLING { get; private set; } = "BILLING";
    
            /// <summary>
            /// When the customer clicks PayPal Checkout,
            /// the customer is redirected to either a page to log in to PayPal and
            /// approve the payment or to a page to enter credit or
            /// debit card and other relevant billing information
            /// required to complete the purchase, depending on their previous interaction with PayPal.
            /// </summary>
            public static string NO_PREFERENCE { get; private set; } = "NO_PREFERENCE";
        }
    }
  15. Add a class called ShippingPreference.cs, within the Values folder.
    Add the following code.

    namespace PayPal.Values
    {
        /// <summary>
        /// The shipping preference:
        ///    /// * Displays the shipping address to the customer.
        /// * Enables the customer to choose an address on the PayPal site.
        /// * Restricts the customer from changing the address during the payment-approval process.
        ///    /// Default: GET_FROM_FILE.
        /// Source: https://developer.paypal.com/docs/api/orders/v2/
        /// </summary>
        public static class ShippingPreference
        {
            /// <summary>
            /// Use the customer-provided shipping address on the PayPal site.
            /// </summary>
            public static string GET_FROM_FILE { get; private set; } = "GET_FROM_FILE";
    
            /// <summary>
            /// Redact the shipping address from the PayPal site. Recommended for digital goods.
            /// </summary>
            public static string NO_SHIPPING { get; private set; } = "NO_SHIPPING";
    
            /// <summary>
            /// Use the merchant-provided address. The customer cannot change this address on the PayPal site.
            /// </summary>
            public static string SET_PROVIDED_ADDRESS { get; private set; } = "SET_PROVIDED_ADDRESS";
        }
    }
  16. Add a class called UserAction.cs, within the Values folder.
    Add the following code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace PayPal.Values
    {
        /// <summary>
        /// Configures a Continue or Pay Now checkout flow.
        /// Source: https://developer.paypal.com/docs/api/orders/v2/
        /// </summary>
        public static class UserAction
        {
    
            /// <summary>
            /// After you redirect the customer to the PayPal payment page,
            /// a Continue button appears. Use this option when the final amount is not known
            /// when the checkout flow is initiated and you want to redirect
            /// the customer to the merchant page without processing the payment.
            /// </summary>
            public static string CONTINUE { get; private set; } = "CONTINUE";
    
            /// <summary>
            /// After you redirect the customer to the PayPal payment page,
            /// a Pay Now button appears.
            /// Use this option when the final amount is known when the checkout is initiated
            /// and you want to process the payment immediately when the customer clicks Pay Now.
            /// </summary>
            public static string PAY_NOW { get; private set; } = "PAY_NOW";
        }
    }
  17. Create a folder called Item within the PayPal\Values folder.

  18. Add a class called Category.cs, within the Values folder.
    Add the following code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace PayPal.Values.Item
    {
        /// <summary>
        /// The item category type.
        /// </summary>
        public static class Category
        {
    
            /// <summary>
            /// Goods that are stored, delivered, and
            /// used in their electronic format.
            /// This value is not currently supported for API callers that leverage the
            /// [PayPal for Commerce Platform](https://www.paypal.com/us/webapps/mpp/commerce-platform) product.
            /// </summary>
            public static string DIGITAL_GOODS { get; private set; } = "DIGITAL_GOODS";
    
            /// <summary>
            /// A tangible item that can be shipped with proof of delivery.
            /// </summary>
            public static string PHYSICAL_GOODS { get; private set; } = "PHYSICAL_GOODS";
        }
    }
  19. The final step is to write code to handle what happens when the following code is called:
    • api/paypal/checkout/order/create
    • api/paypal/checkout/order/approved/{orderId}
    • api/paypal/checkout/order/complete/{orderId}
    • api/paypal/checkout/order/cancel/{orderId}
    • api/paypal/checkout/order/error/{orderId}/{error}
  20. Good Luck.

本文转载于:http://www.diyabc.com/frontweb/news14859.html

posted @ 2020-08-12 04:28  Dincat  阅读(275)  评论(0编辑  收藏  举报