DEV Community

FaxriddinMaxmadiyorov
FaxriddinMaxmadiyorov

Posted on • Updated on

PayPal REST API

In this article, I will explain how to integrate the PayPal REST API. First of all, we should create a sandbox account on PayPal at developer.paypal.com.
Image description

Authentication
As written in the documentation, we have 2 options to authenticate our request to sandbox server:

get a bearer token:

curl -v -X POST "https://api-m.sandbox.paypal.com/v1/oauth2/token"\
 -u "CLIENT_ID:CLIENT_SECRET"\
 -H "Content-Type: application/x-www-form-urlencoded"\
 -d "grant_type=client_credentials"
Enter fullscreen mode Exit fullscreen mode

encryption of CLIENT_ID:CLIENT_SECRET in Base64

Base64.strict_encode64("#{PAYPAL_CLIENT_ID}:#{PAYPAL_CLIENT_SECRET}")
Enter fullscreen mode Exit fullscreen mode

We will get access_token in both ways. I will write business logic in active interactions.

We need to set 2 endpoints to proceed a payment with Paypal: 1) create order 2) execute order;

Order
We should create an order;

create_order.rb

request_path = BASE_URL + '/v2/checkout/orders'
HTTParty.post(request_path, headers: headers, body: your_body.to_json)
Enter fullscreen mode Exit fullscreen mode

There are two options for intent:

  1. AUTHORIZE
  2. CAPTURE

When you set the intent to "AUTHORIZE," PayPal authorizes the payment amount but doesn't capture the funds immediately. Instead, it places a hold on the funds, reserving them for capture at a later time. This is useful in scenarios where you need to verify the availability of funds or perform additional checks before completing the transaction.
Use Case: For example, if you operate an e-commerce platform, you might use the "AUTHORIZE" intent when a customer places an order. This allows you to verify the payment details and inventory availability before confirming the purchase and capturing the funds.

CAPTURE: With the "CAPTURE" intent, PayPal immediately captures the funds from the customer's account when the payment is made. This completes the transaction in real-time, and the funds are transferred to your account.
Use Case: In scenarios where you provide digital goods or instant services, using the "CAPTURE" intent ensures that payments are processed and funds are transferred immediately upon completion of the transaction.

If we create an order with "AUTHORIZE" intent, then we have to authorize (Authorize Order method, Orders API) the order then capture the order (Capture Authorized Payment, Payments API); If we create an order with "CAPTURE" intent, then we directly use Capture Payment for Order method (Orders API);

We will use "CAPTURE" intent here.

CAPTURE

request_path = BASE_URL + '/v2/checkout/orders/{id}/capture'
HTTParty.post(request_path, headers: headers, body: your_body.to_json)
Enter fullscreen mode Exit fullscreen mode

that is all.

Subscriptions

When we visit Netflix.com, we can see monthly plans; Every month, some money is withdrawn from our card. How can it happen by itself? Here comes webhooks. A webhook is an HTTP request triggered by an event in a source system and sent to a destination system. When money is withdrawn, PayPal sends a notification to our server. We need an endpoint to receive a POST request from Paypal and add it in "Add Webhook" section. It is not possible to set localhost url, if you want to test in your localhost, then you can use ngrok. We need to return a response with 200 status code if everything is ok, else failure. Otherwise it keeps sending a request to our server.
Image description

class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token, only: :checkout_webhook

  def checkout_webhook
    render plain: '', status: :ok
  end
end
Enter fullscreen mode Exit fullscreen mode

Product and Plan should be created for a Subscription.

create_product.rb

request_path = BASE_URL + '/v1/catalogs/products'
HTTParty.post(request_path, headers: headers, body: your_body.to_json)
Enter fullscreen mode Exit fullscreen mode

create_plan.rb

request_path = BASE_URL + '/v1/billing/plans'
HTTParty.post(request_path, headers: headers, body: your_body.to_json)
Enter fullscreen mode Exit fullscreen mode

create_subscription.rb

request_path = BASE_URL + '/v1/billing/subscriptions'
HTTParty.post(request_path, headers: headers, body: your_body.to_json)
Enter fullscreen mode Exit fullscreen mode

After subscription is created successfully, its status will be APPROVAL_PENDING. After clicking the button, the status will be active.

Top comments (1)

Collapse
 
smash311 profile image
Sokhib

Great article