PayPal Integration Part 2: PayPal REST API

Final product image
What You'll Be Creating

In this tutorial I am going to show you how you can take payments using the PayPal REST API and C#. All the libraries that they have for different languages such as Ruby, Node.js, Python, PHP are very similar, so all the concepts here apply to all the libraries.

Project Setup

To start, I have created an MVC project in Visual Studio 2015: File > New > Project, and select ASP.NET Application.

Setting up a Project

Select the ASP.NET 5 Web Application Template, which uses the new MVC 6. It is similar to MVC 5 if you are familiar with it.

ASPNET MVC5

As you can see in the photo below, I have added a few files and folders to the solution. The main two things to notice are:

  1. In References I have removed the target DNX Core 5.0, which is what would allow us to run this project in Mac OS X or Linux, but the PayPal library that we need hasn't been updated yet. 
  2. I have added the folder "Services", where I am going to wrap the logic for PayPal calls, so we can keep the controllers nice and short.
Solution Explorer

Install PayPal SDK using NuGet. Right click on the name of the solution and select Manage NuGet Packages, and then search for "PayPal" and install it.

Package Manager

Create a PayPal App

To integrate our application with PayPal, we need to navigate to PayPal Developers, and then under REST API apps, click on Create App.

PayPal Developer App Dashboard

Give your app a name and choose a sandbox developer account associated with the app. For testing purposes, we can then navigate to http://sandbox.paypal.com and log in with the sandbox login details to see the test PayPal account and transactions.

PayPal Developer App

After clicking on Create App, we see the confirmation screen with the Client ID and Secret tokens.

PayPal App Credentials

Copy the clientId and clientSecret tokens to appsettings.json, as you can see in the screenshot below:

Application Settings JSON

Testing Payments

PayPal provides a Sandbox environment for testing. You can create test buyer and seller accounts from there. When you sign up, you will have a Business account in the Sandbox that is tied to your developer account.

To create a new test account, log in to the Developer site, and then click the Dashboard tab and navigate to Sandbox > Accounts. Here you can see the list of test accounts if you have any:

PayPal Sandbox

If you haven't created your test accounts yet, go ahead and click on Create Account, on the top right, to create at least one test personal account and one test business account.

PayPal Test Account

After creating the test accounts, you can log in through www.sandbox.paypal.com with the test email address and password that you assigned to each account on the previous form. This is really useful to test that when you are purchasing something with your 'personal test account' the funds are being transferred to your 'test business account'. Now you're ready to start integrating with PayPal and test that the funds are moving from one account to another.

Single PayPal Payment

PayPal offers different methods of payment. You can use direct credit card payments, which means that your customers don't get to see the PayPal login page or summary—it all happens in your website. You need to be PCI compliant for this, and I recommend using Stripe, as you only need SSL using their JavaScript library. On the other hand, to take payments via PayPal payments, it takes three steps:

  1. Specify payment information to create a payment.
  2. Get payment approval, by redirecting your customer to PayPal to approve the transaction.
  3. Execute the payment to capture the funds after PayPal redirects your customer back to your website.

In my MVC project, in the Services folder, I have created the PayPalPaymentService class where I have added these methods:

There are a few parameters being passed in this call:

  • Intent: Three possible values: 'sale' for immediate payments, 'authorize' to authorize a payment to capture later, or 'order' to create an order. When you get the authorization for a payment to capture later, you have 3 days guaranteed, although you can attempt to capture the payment up to 29 days later.
  • Payer: Source of the funds for this payment, payment method being used—PayPal Wallet payment, Bank Direct Debit or Direct Credit card. 
  • Transactions: This is used to specify the amount for the payment, and optionally specify the items being paid for. You can also specify the subtotal, shipping and tax if needed.
  • Redirect URLs: Specify the URL to which PayPal will redirect your customers after a transaction, so you can update your database and display a confirmation message.

The previous functions can be used from your controller like this:

As you can see, I have created three actions:

  • CreatePayment: This is the action triggering the payment. It's making a call to PayPal to create the Payment, then is redirecting the user to PayPal to approve the transaction.
  • PaymentSuccessful: This is the action where PayPal redirects our customer back after a successful payment. At this point we can execute the payment to get the funds transferred to our merchant account.
  • PaymentCancelled: This action is where the user is redirected from PayPal if the user cancels the approval process. At this time you'll probably want to give the option to the customer to try again or get in touch with you.

Authorize a Payment to Capture Later

This scenario is very similar to the previous case. You might want to use this method if you are trying to take pre-orders for a product that isn't available yet. The steps to get this payment are:

  1. Authorize the payment: The 'intent' parameter for this call should be 'authorize'.
  2. Capture the payment: Bear in mind that authorizations are guaranteed for up to 3 days, although you can attempt to capture a payment for up to 29 days.

In order to implement this type of payment, I have only added one new method to the class PayPalPaymentService to capture the payment:

Then from the HomeController, I have added two new actions to show this type of payment:

  • AuthorizePayment is the action triggering the payment. It's very similar to the previous 'CreatePayment' function, but we are passing 'authorize' as the intent parameter in this case.
  • AuthorizeSuccessful is the action where your customer will be redirected after successfully approving the payment on PayPal. At this point I'm capturing the payment, but you could save the paymentId in your database and capture the payment when you need to.

In these code samples, for simplicity, I have hard-coded the payment variable values. In your real application, you will probably wrap them in methods that take all those values as variables so that everything can be set dynamically and reused.

Subscriptions

This is called "Billing Plans" in PayPal—you can create recurring payment plans, and subscribe your customers to a billing plan by creating a billing agreement. Using the PayPal REST API you can create, update or delete billing plans; this is something that you might use if you want to build an admin panel to manage these things for your business.

The steps to create recurring charges to your customers would be:

  1. Create a billing plan and activate it. After you create a Billing Plan, it's in a CREATED state. It needs to be activated by making a PATCH request.
  2. Create a billing agreement and execute it: The response to the call to Create a billing agreement includes the links to approval_url and execute_url. We need to get the approval for the billing agreement and then execute the billing agreement.

Billing Plans

Create a Billing Plan

Create a billing plan that defines the billing periods. This is a summary of the parameters that we need to pass to create a plan.

  • Name: Name of the billing plan.
  • Description: Description of the billing plan.
  • Type: Allowed values are 'FIXED' for a set number of recurring payments, or 'INFINITE' for a plan that recurs until it's manually cancelled.
  • Merchant Preferences: This is an object that specifies preferences such as setup fee, maximum fail attempts of a payment, return URL, cancel URL, notify URL, where PayPal will redirect the user after a payment.
  • Payment Definitions: Array of payment definitions for this plan. Normally this array would have one or two payment definitions. If we want to offer a free trial or a trial at a discounted price, then we set up two payment definitions. The first will be the definition for the trial period, and the second definition would be the regular payment. The properties for a Payment Definition are name, type (trial or regular), frequency (day, week, month, year), frequency interval (if we set the frequency to 'WEEK' and the frequency interval to '1', we are defining a weekly payment), amount to charge the customer, and cycles is the number of total payments. Charge Models is to specify the shipping cost and tax additional to the amount value for the plan.

This is a code snippet that shows how to create a Billing Plan:

A newly created billing plan is in a CREATED state. Activate it to the ACTIVE state, so your customers can subscribe to the plan. To activate the plan, we need to make a PATCH request:

As you can see, PayPal libraries are a direct wrapper over their REST API, which is good, but the API is also really complex compared to others like Stripe. For this reason, it's really a good option to wrap all PayPal communication in objects with clearer and simpler APIs for our applications. Here you can see what this code wrapped in multiple functions taking parameters looks like:

Update Billing Plan

You can update the information for an existing billing plan by making a 'PATCH' request. This is a function that wraps that call:

To update the Billing Plan description, we can call this function and pass the right parameters:

Delete a Billing Plan

Ideally, when you don't want to accept new customers to a Billing Plan, you'll want to update it to the 'INACTIVE' state. This is not going to affect to existing billing agreements on this plan. This can be done simply by calling the UpdateBillingPlan function:

Billing Agreements

Create a Billing Agreement

Once you have created one or more billing plans, you want to start getting customers signing up for your subscription plans. In order to do this, you need to collect your customer details and make a request to PayPal. To be able to test this functionality, I have added several actions to the HomeController:

  • Subscribe: This is the first action that is called. It's creating a test Billing Plan, and then a Billing Agreement (subscription) to that plan is created, and the user is redirected to PayPal to confirm the payment.
  • SubscribeSuccess: This action is the one used as 'Return URL' after a successful subscription. The agreement token identifier is passed in the query string, and we use this token to execute the billing agreement and make it active.
  • SubscribeCancel: This action is the one used as 'Cancel URL'. If for some reason the payment fails, or your customer cancels the payment on PayPal, the user is taken to this action, and you need to handle this. Maybe offer the option to try again.

As you can see in the previous code snippet, I have wrapped most of the functionality in several methods. The first one is "CreateBillingPlan" that was explained in the previous section. The second one is "CreateBillingAgreement" that is used to subscribe a user to a plan:

The third method is "ExecuteBillingAgreement". After a successful subscription approval, we use the token returned to activate the subscription:

Suspend a Billing Agreement

Use this method to suspend an agreement:

Reactivate a Billing Agreement

This one is really similar to the previous one:

Cancel a Billing Agreement

Use this function to cancel a plan:

Update a Billing Agreement

This option is very limited, and what I would expect from this call is the possibility to change the subscription plan, for upgrading or downgrading a customer. This is not supported in a single call as it is in Stripe. You need to handle this scenario by cancelling the current agreement and creating a new one for upgrades or downgrades. It's not ideal, but it might change in the future.

Conclusion

This is an overview of the most common functions that people use to integrate with PayPal. Their API is far bigger than the integration methods explained in this article—you can also issue refunds and partial refunds, and they have many different options for edge cases in the samples covered in this article. If you are interested in getting more details about any specific integration, please leave a suggestion in the comments.

Tags:

Comments

Related Articles