用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:”的答案。
- 提供一个电子邮件地址并单击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。你需要一个篮子,项目和发票模型/核心类。将以下蓝色突出显示的字段添加到您的发票表中。这些字段将被贝宝使用。
- 注意,FirstName、LastName和Email存储在用户表中,但是也复制在Invoice表中。这是因为来自客户PayPal账户的数据可能与用户表中的数据不同。 由您决定如何在数据存储中包括蓝色字段。
服务器端代码
- Create an ASP.NET Core 3.x MVC application using Visual Studio.
- 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.ConfigureServicesor choose an option from the next step.
-
-
Update
Startup.ConfigureServicesto callAddNewtonsoftJson.Hide Copy Codeservices.AddMvc() .AddNewtonsoftJson();
OR
Hide Copy Codeservices.AddMvc() .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver()); - Create a folder called
PayPalin your ASP.NET Core project. - Create a class
PayPalClientin the folder, with the code below.
Remember to use the sandbox and live client Ids and secrets to populate the highlighted string content.Hide Shrink
ggimggg0 Copy Codeusing 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(); } } }
- Create a class
SmartButtonHttpResponsein the folder, with code.Hide Copy Codeusing 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; } } }
-
Create a class
OrderBuilderin the folder, with code.Hide Copy Codeusing 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; } } }
-
Create a controller class in the
Controllersfolder calledCheckoutController. Add the following code.Hide Shrink
ggimggg1 Copy Codeusing 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(); } } }
-
Create a
Checkoutfolder in theViewsfolder and add a view calledindex.cshtmlAdd the following code to create the PayPal smart button to the view.
Hide Shrink
ggimggg2 Copy Code<!-- 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¤cy=@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.
-
Add the following JavaScript function:
Hide Copy Codefunction httpGet(url) { var xmlHttp = new XMLHttpRequest(); xmlHttp.open("GET", url, false); xmlHttp.send(null); return xmlHttp.responseText; }
-
Create a folder called
Valueswithin thePayPalfolder. -
Add a class called
CheckoutPaymentIntent.cs, within theValuesfolder.
Add the following code.Hide Shrink
ggimggg3 Copy Codeusing 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"; } }
-
Add a class called
CurrencyCode.cs, within theValuesfolder.
Add the following code.Hide Copy Codeusing 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.
-
Add a class called
LandingPage.cs, within theValuesfolder.
Add the following code.Hide Shrink
ggimggg4 Copy Codeusing 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"; } }
-
Add a class called
ShippingPreference.cs, within theValuesfolder.
Add the following code.Hide Shrink
ggimggg5 Copy Codenamespace 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"; } }
-
Add a class called
UserAction.cs, within theValuesfolder.
Add the following code.Hide Shrink
ggimggg6 Copy Codeusing 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"; } }
-
Create a folder called
Itemwithin thePayPal\Valuesfolder. -
Add a class called
Category.cs, within theValuesfolder.
Add the following code.Hide Shrink
ggimggg7 Copy Codeusing 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"; } }
- The final step is to write code to handle what happens when the following code is called:
api/paypal/checkout/order/createapi/paypal/checkout/order/approved/{orderId}api/paypal/checkout/order/complete/{orderId}api/paypal/checkout/order/cancel/{orderId}api/paypal/checkout/order/error/{orderId}/{error}
- Good Luck.
本文转载于:http://www.diyabc.com/frontweb/news16489.html本文转载于:http://www.diyabc.com/frontweb/news16914.html

浙公网安备 33010602011771号