Download Source Code
GitHub Repository
Learning Outcomes
- How to setup a PayPal Business account.
- How to get API Credentials for Sandbox – i.e. Client ID and Secret.
- How to get API Credentials for Live – i.e. Client ID and Secret.
- What fields to in your data store.
- Server-Side Code.
Prerequisites
- You have registered a URL for your e-commerce website for example www.delaneys.space.
- The website is secured with an SSL certificate.
- Your customer can sign up and sign in to your website in a secure manner using OAuth or some over secure method.
- Your website has a backend datastore and you know how to maintain it.
- You are familiar with Visual Studio.
Create a spreadsheet with the following row heading:
1 | Dashboard URL | https://www.paypal.com/mep/dashboard |
2 | Developer Dashboard URL | https://developer.paypal.com/developer/applications |
3 | SandBox Details |
|
4 | URL | www.sandbox.paypal.com/ |
5 | App Name | |
6 | Business | |
7 | Username | …@business.example.com |
8 | Password | |
9 | Client ID | |
10 | Secret | |
11 | Personal (Customer) | |
12 | Username | ...@personal.example.com |
13 | Password | |
14 | Live Details |
|
15 | Username | info@... |
16 | Password | |
17 | App Name | |
18 | Client ID | |
19 | Secret |
Creating a PayPal Business Account
To creating a PayPal Business Account, you do not have to own a business or have a business bank account. Having said that you should put in place practices that separate your personal financial transactions with the transactions from your e-commerce website. Therefore, I suggest using a separate personal bank account to link to your PayPal 'business' account.
- Navigate to www.PayPal.com.
-
Click Sign Up, even if you already have a personal PayPal account. Remember never mix business with pleasure.
- Select Business Account and click Next.
-
Complete the short questionnaire
- Select "On my website" for the question "I want to mainly accept payments:".
Select an answer for the question "May annual volume is:".
Provide an email address and click Continue.
This can be any valid email address, but you may want to use 'info@your e-commerce.com'.
Provide a password and click Continue.
A confirmation email will be sent to the address provided.
Update your spreadsheet.
15 Username info@... 16 Password Complete the business contact details page and click Agree and Create Account.
They will require your contact name, a business name, telephone number and business address.
Select a business type
Select from a list of Individual, Sole owner, Partnership, Private company, Public company, Not-for-profit organisation, Government entity, Trust – Investment and Family.
Add personal details.
This includes your name, date of birth and address.
Click Submit.
You have now set up your PayPal Business Account. You should be presented with a dashboard display.
Get API Credentials – i.e. Client ID and Secret
Go to the developer dashboard:
2 Developer Dashboard URL https://developer.paypal.com/developer/applications The Sandbox option will be pre-selected. So, let's set that up first.
- Click Create App.
Create a sandbox app name and store in your spreadsheet.
17 App Name Click Create App, again.
Update the following on your spreadsheet:
6 Business 7 Username …@business.example.com 9 Client ID 10 Secret Now let's get the password.
Click the SANDBOX | Accounts button or (developer.paypal.com/developer/accounts/).
You should see two email addresses representing a business and personal account.
Click the … button of the Business account and select View/Edit Account.
Record the System Generated Password in your spreadsheet.
8 Password - Click Close.
Click the … button of the Personal account and select View/Edit Account.
Record the username and password in your spreadsheet.
11 Personal (Customer) 12 Username ...@personal.example.com 13 Password
Get API Credentials for Live
- Click My Apps & Credentials (developer.paypal.com/developer/applications/).
Click the Live button.
Click Create App.
Record the app name in your spreadsheet.
17 App Name Click Create App (again).
Record the client ID and secret in your spreadsheet.
18 Client ID 19 Secret
What fields to add to your data store
- Choose a data store such as SQL Servers.
You will require a
Basket
,Item
andInvoice
Model/Core classes. Add the following blue highlighted fields to your invoice table. These fields will be used by PayPal.Note that the
FirstName
,LastName
andEmail
are stored in theUser
table, but are also duplicated in theInvoice
table. This is because the data from the customer's PayPal account may be different from the data on theUser
table.It is up to you to decide how to include the blue fields in your data store.
Server-Side Code
- 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.ConfigureServices
or choose an option from the next step.
Update
Startup.ConfigureServices
to callAddNewtonsoftJson
.services.AddMvc()
.AddNewtonsoftJson();Create a Folder called
PayPal
in your ASP.NET Core project.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; } = "{PayPal SANDBOX Client Id} "; public static string SandboxClientSecret { get; set; } = "{PayPal SANDBOX Client Secret} "; public static string LiveClientId { get; set; } = "{PayPal LIVE Client Id} "; public static string LiveClientSecret { get; set; } = "{PayPal LIVE Client Secret} ";/// public static PayPalEnvironment Environment() { #if DEBUG/// Set up PayPal environment with sandbox credentials. /// In production, use LiveEnvironment. /// // 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(SandboxClientId ,SandboxClientSecret ); #else return new LiveEnvironment(LiveClientId ,LiveClientSecret ); #endif }/// public static PayPalCheckoutSdk.Core.PayPalHttpClient Client() { return new PayPalHttpClient(Environment()); } public static PayPalCheckoutSdk.Core.PayPalHttpClient Client(string refreshToken) { return new PayPalHttpClient(Environment(), refreshToken); }/// Returns PayPalHttpClient instance to invoke PayPal APIs. /// /// 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(); } } }/// Use this method to serialize Object to a JSON string. /// 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
(); } public HttpHeaders Headers { get; } public HttpStatusCode StatusCode { get; } public PayPalCheckoutSdk.Orders.Order Result() { return _result; } public string orderID { get; set; } } } Create a class
OrderBuilder
in the folder, with code.using PayPalCheckoutSdk.Orders; using System.Collections.Generic; namespace PayPal { public static class OrderBuilder {
public static OrderRequest Build() { OrderRequest orderRequest = new OrderRequest();/// ////// Use classes from the PayPalCheckoutSdk to build an OrderRequest /// // Add code to fill out the order request properties // See the attached source code for a more detailed example. return orderRequest; } } }Create a controller class in the
Controllers
folder calledCheckoutController
. Add the following code.using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; using PayPalCheckoutSdk.Orders; namespace Test.Controllers { public class CheckoutController : Controller {
public IActionResult Index() { #if DEBUG/// ////// Action to display the cart form for the SERVER side intergration /// // 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 =PayPal.PayPalClient.SandboxClientId ;// Get from a data store or stettings #else// Company LIVE Client Id. To go live replace this with the live ID. ViewBag.ClientId =PayPal.PayPalClient.LiveClientId ;// 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(); } [Route("api/paypal/checkout/order/create")] public async Task/// ////// This action is called when the user clicks on the PayPal button. /// 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(); var payPalHttpResponse = new PayPal.SmartButtonHttpResponse(response) { orderID = result.Id }; return payPalHttpResponse; } [Route("api/paypal/checkout/order/approved/{orderId}")] public IActionResult Approved(string orderId) { return Ok(); }/// /// ////// This action is called once the PayPal transaction is approved /// [Route("api/paypal/checkout/order/complete/{orderId}")] public IActionResult Complete(string orderId) {/// /// ////// This action is called once the PayPal transaction is complete /// // 1. Update the database. // 2. Complete the order process. Create and send invoices etc. // 3. Complete the shipping process. return Ok(); } [Route("api/paypal/checkout/order/cancel/{orderId}")] public IActionResult Cancel(string orderId) {/// /// ////// This action is called once the PayPal transaction is complete /// // 1. Remove the orderId from the database. return Ok(); } [Route("api/paypal/checkout/order/error/{orderId}/{error}")] public IActionResult Error(string orderId, string error) {/// /// ////// This action is called once the PayPal transaction is complete /// // Log the error. // Notify the user. return NoContent(); } } }Create a
Checkout
folder in theViews
folder and add a view calledindex.cshtml
Add the following code to create the PayPal smart button to the view.
Apart from the URLs, this code is the same for all solutions.
Add the following JavaScript function:
function httpGet(url) { var xmlHttp = new XMLHttpRequest(); xmlHttp.open("GET", url, false); xmlHttp.send(null); return xmlHttp.responseText; }
Create a folder called
Values
within thePayPal
folder.-
Add a class called
CheckoutPaymentIntent.cs
, within theValues
folder.
Add the following code.using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace PayPal.Values {
/// public static class CheckoutPaymentIntent {/// The intent to either capture payment immediately or /// authorize a payment for an order after order creation. /// /// public static string CAPTURE { get; private set; } = "CAPTURE";/// The merchant intends to capture payment immediately after the customer makes a payment. /// /// public static string AUTHORIZE { get; private set; } = "AUTHORIZE"; } }/// 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. /// -
Add a class called
CurrencyCode.cs
, within theValues
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 {
/// public static string GBP { get; private set; } = "GBP";/// Great British Pounds /// /// public static string USD { get; private set; } = "USD";/// US Dolars /// /// public static string EUR { get; private set; } = "EUR"; } }/// Euros /// Add additional currencies, as required.
-
Add a class called
LandingPage.cs
, within theValues
folder.
Add the following code.using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace PayPal.Values {
/// public class LandingPage {/// 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/ /// /// public static string LOGIN { get; private set; } = "LOGIN";/// When the customer clicks PayPal Checkout, the customer is redirected to a page to log in to PayPal and approve the payment. /// /// public static string BILLING { get; private set; } = "BILLING";/// 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. /// /// public static string NO_PREFERENCE { get; private set; } = "NO_PREFERENCE"; } }/// 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. /// -
Add a class called
ShippingPreference.cs
, within theValues
folder.
Add the following code.namespace PayPal.Values {
/// public static class ShippingPreference {/// 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/ /// /// public static string GET_FROM_FILE { get; private set; } = "GET_FROM_FILE";/// Use the customer-provided shipping address on the PayPal site. /// /// public static string NO_SHIPPING { get; private set; } = "NO_SHIPPING";/// Redact the shipping address from the PayPal site. Recommended for digital goods. /// /// public static string SET_PROVIDED_ADDRESS { get; private set; } = "SET_PROVIDED_ADDRESS"; } }/// Use the merchant-provided address. The customer cannot change this address on the PayPal site. /// -
Add a class called
UserAction.cs
, within theValues
folder.
Add the following code.using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace PayPal.Values {
/// public static class UserAction {/// Configures a Continue or Pay Now checkout flow. /// Source: https://developer.paypal.com/docs/api/orders/v2/ /// /// public static string CONTINUE { get; private set; } = "CONTINUE";/// 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. /// /// public static string PAY_NOW { get; private set; } = "PAY_NOW"; } }/// 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. /// Create a folder called
Item
within thePayPal\Values
folder.-
Add a class called
Category.cs
, within theValues
folder.
Add the following code.using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace PayPal.Values.Item {
/// public static class Category {/// The item category type. /// /// public static string DIGITAL_GOODS { get; private set; } = "DIGITAL_GOODS";/// 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. /// /// public static string PHYSICAL_GOODS { get; private set; } = "PHYSICAL_GOODS"; } }/// A tangible item that can be shipped with proof of delivery. /// - The final step is to write code to handle what happens when the following code are 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}
Good Luck.
OR
services.AddMvc() .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());