PayPal Permissions Integration
By: Rahul Monga

If your application provides a storefront or invoice system for its users, it is sometimes useful to use PayPal as a payment gateway for your users to get paid through.  In order to do this, you need to use the PayPal permissions API, which enables you to request and obtain permission from PayPal account holders.  After obtaining this permission, you can execute API operations for your users that have granted you permission.

For Ruby, PayPal has conveniently packaged this API into a gem:

 https://github.com/paypal/permissions-sdk-ruby

You can use this gem to redirect your user to the PayPal website, where they will authenticate with PayPal, and ultimately grant your application the requested permissions.

The following chart shows the logical flow of the permissions API:

Image00

  1. First make a call to the PayPal API with what permissions you want to request.
  2. Then redirect your user to the PayPal website where they can grant you these permissions.
  3. After permissions are granted, PayPal redirects you back to your application where you make the final call to the PayPal API to get and store access and secret tokens for said permissions.

To get started, you can follow instructions from the GitHub page to install the gem and run the rails generate which will create a paypal.yml file in your config/ directory.  This file is used to store your applications API credentials for your different environments.  A sample one is below:

 test: &default  
   # Mode can be 'live' or 'sandbox'  
   mode: sandbox  
   # Credentials for Classic APIs  
   app_id: APP-80W284485P519543T  
   username: <your user name here>  
   password: <your password here>  
   signature: <signature>   
   # # With Certificate  
   # cert_path: "config/cert_key.pem"  
   sandbox_email_address: Platform.sdk.seller@gmail.com  
 staging:  
   <<: *default  
 development:  
   <<: *default  
 production:  
   mode: live  
   app_id: <your production app id>  
   username: <your production username>  
   password: <your production password>   
   signature: <your production signature>

The necessary values can be found in your paypal developer account for your specific application.  You can then create an initializer like below:

 PayPal::SDK.load("config/paypal.yml", Rails.env)  
 PayPal::SDK.logger = Rails.logger  
 PAYPAL_PERMISSIONS_API = PayPal::SDK::Permissions::API.new

This will load the configurations from the file we just created earlier along with which environment you are in.  Then PAYPAL_PERMISSIONS_API can be used throughout your application whenever you need to the the PayPal API.  You will have to figure out what kind of permissions you want to request and store for your users. 

A full list of available permissions can be found here:

https://developer.paypal.com/docs/classic/permissions-service/integration-guide/PermissionsAbout/


To store what kinds of permission I needed from my users, I went ahead and made a constant.

 module PayPalConstants  
   PERMISSIONS = ['EXPRESS_CHECKOUT', 'MOBILE_CHECKOUT', 'DIRECT_PAYMENT']  
 end

We can now set up our routes.rb file for redirecting our user.

 resource :user do  
   member do  
     put :revoke_paypal  
     get :request_permission  
     get :grant_paypal  
   end  
 end

The revoke route will be used later to add an option for our user to revoke our PayPal permission.  First method we need to write in our controller is the request_permission action.  This action will call the API with what permissions we want to request from our user, and a callback url.  Then our action will redirect our user to the PayPal website to actually grant those permissions.

 def request_permission  
   begin  
     request_permissions = PAYPAL_PERMISSIONS_API.build_request_permissions({   
                           scope: PayPalConstants::PERMISSIONS,  
                           callback: grant_paypal_user_url(@user) })  
     response = PAYPAL_PERMISSIONS_API.request_permissions(request_permissions)  
     if response.success?  
       # Redirect url to grant permissions  
       redirect_to PAYPAL_PERMISSIONS_API.grant_permission_url(response)   
     else  
       response.error  
     end  
     rescue PayPal::SDK::Core::Exceptions::ServerError => e  
     flash[:error] = t('paypal.errors.service_unavailable')  
     redirect_to @user  
   end  
 end

When the user is done with their PayPal authentication, PayPal will redirect the user to whatever call back you specified. PayPal will also pass you params called request_token, and verification_code that you will use to build an access_token.  Once you build this token, you can use this to request the paypal_access_token and paypal_secret_token which you will save for your user.

 def grant_paypal  
   begin  
     request = PAYPAL_PERMISSIONS_API.build_get_access_token(token:params['request_token'],   
                                                             verifier: params['verification_code'])  
     response = PAYPAL_PERMISSIONS_API.get_access_token(request)  
     @user.update_attributes(paypal_access_token: response.token,   
                             paypal_secret_token: response.tokenSecret,   
                             paypal_correlation_id: response.responseEnvelope.correlationId,   
                             paypal_timestamp: response.responseEnvelope.timestamp)  
     redirect_to @user  
     rescue PayPal::SDK::Core::Exceptions::ServerError => e  
     flash[:error] = t('paypal.errors.service_unavailable')  
     @user  
   end  
 end

Note, I wrap the calls to the PayPal API in begin and rescue blocks.  This is because the sandbox version of the API is very inconsistent and will sometimes throw 503s.  But you will not see this type of inconsistency when running against the live production PayPal API.

After this grant_paypal action completes, your user record will have stored the access token and secret token needed to make PayPal API calls on your users' behalf.  The last part is to also include a way to let your users revoke the permissions they have given your application.  For this, you can include an action revoke_paypal which will make a call to the PayPal API to cancel the permissions.  You will pass in the user's paypal_access_token in the API call.

 def revoke_paypal  
   begin  
     response = PAYPAL_PERMISSIONS_API.cancel_permissions(token: @user.paypal_access_token)  
     @user.update_attributes(paypal_access_token: nil,   
                             paypal_secret_token: nil,   
                             paypal_correlation_id: response.responseEnvelope.correlationId,   
                             paypal_timestamp: response.responseEnvelope.timestamp)  
     redirect_to @user  
     rescue PayPal::SDK::Core::Exceptions::ServerError => e  
     flash[:error] = t('paypal.errors.service_unavailable')  
     redirect_to @user  
   end  
 end

SHARE:

Meet Rahul:
Rahul is a Senior Software Engineer at WeddingWire. Rahul is from Washington DC, has a Computer Science degree from University of Maryland, and is working on a Master's degree from Johns Hopkins. When he isn't building JEE or Rails web apps, Rahul likes to listen to music, travel, and watch Redskins games.