How to accept PayPal payments on Grails

How to accept PayPal payments
with Grails Application.







Introduction to Paypal payments plugin.

The Paypal payments plugin simplifies the integration of Paypal

with Grails applications.  Grails is a web framework for developing web applications and a

plugin is a module that can be easily installed to add specific

features to your application. Modules/Plugins are usually designed

to accomplish a specific task. 

Who should read this?


Anyone interested in how to integrate paypal with a Grails application. 

What you need

  1. A Paypal developer account with your API keys
  2. Grails paypal payments plugin
  3. Grails Application ( Version 2.x and above ) 
If you do not already have a Paypal developer account please visit https://developer.paypal.com/developer/accounts/ to get one. 

The paypal-payments plugin will provide the features required to interact with the Paypal API. You do not need to be a paypal payments guru to use Paypal. 

A Grails application is required. A demo app is just fine. 

Create a Paypal sandbox account.

After you have created your Paypal developer account, Create a REST API app on your Paypal user dashboard. The app will enable you to receive REST API credentials for testing and live transactions.

The test environment (Sandbox) will allow you to play around with most of the API features available. It is also a good way to test your application integration before moving over to a live environment.

Create your Grails Application.

I will assume that you already have your Grails application designed and ready to accept payments. A demo application will be sufficient for this exercise. A discussion on how to  create a Grails application is beyond the scope of this post. I will address it in future posts ;)


Integrate Grails paypal-payments plugin


You need to add the paypal payments plugin to your grails dependencies build.gradle (Grails 3.x) or BuildConfig.groovy file ( Grails 2.x). Inside your dependencies block add the following: 

compile 'org.grails.plugins:paypal-payments:0.1.0'

Obtain your client id and client secret from Paypal dashboard


Obtain the API keys for your sandbox account/app and add it to your grails config file [Config.groovy for grails 2.x and application.groovy for grails 3.x].

Here's what my config file looks like:

paypal.email="myname@mydomain.com"
paypal.clientId = 'your client id'
paypal.sandbox.clientId = 'your client id'
paypal.clientSecret = 'your client secret'
paypal.sandbox.clientSecret ='your client secret'
paypal.endpoint = "https://api.paypal.com"
paypal.sandbox.endpoint = "https://api.sandbox.paypal.com"


Notice that I added config for sandbox and live environment. The reason is that I want to be able to switch between both environments during app development.

Create a Grails controller and add required actions

Create a Grails controller. Personally, I called my own controller PaypalController. There is no need to create another controller if you already have one you want to use. 

To create a Grails controller, go to your app folder and type:

grails create-controller com.mypackage.Paypal

Inject PaypalService

The paypal payments make available, a PaypalService. The PaypalService provides methods for accomplishing common tasks with Paypal API.

Inject the service into your controller. 

Class PaypalController{    
    def paypalService
   ....
   ...
  
}


Add required actions

I like to complete the Paypal payments collection in 3 steps.  I think it normally takes three steps :)

Here are the steps:

1. Make approval request to paypal.
2. Approval - Customer approves the payment
3. Execution - Process response from Paypal in order to execute the payment.

Approval Step


For the approval step, you need to redirect the user/customer to the paypal website in order to approve the transaction. The approval usually involves the user entering payment information that will allow Paypal to proceed with the transaction.

To complete the approval step here's my action inside my PaypalController .


def approve(){      

    String clientId = grailsApplication.config.paypal.clientId
    String clientSecret = grailsApplication.config.paypal.clientSecret
    String endpoint = grailsApplication.config.paypal.endpoint
    Map sdkConfig = [:] 
    sdkConfig.put(Constants.CLIENT_ID,clientId)
    sdkConfig.put(Constants.CLIENT_SECRET,clientSecret)
    sdkConfig.put(Constants.ENDPOINT,endpoint)
    def accessToken = paypalService.getAccessToken(clientId,clientSecret,sdkConfig)
    def apiContext = paypalService.getAPIContext(accessToken,sdkConfig)

    def details = paypalService.createDetails(['subtotal':"12.50"])
    def amount = paypalService.createAmount(['currency':currencyCode,'total':"12.50",'details':details])

    def transaction = paypalService.createTransaction(['amount':amount,'description':"your description",details:details])
    def transactions = []
    transactions.add(transaction)

    def payer = paypalService.createPayer(['paymentMethod':'paypal'])
    def cancelUrl="http://mydomain/paypal/cancel";
    def returnUrl = "http://mydomain/paypal/execute";

    def redirectUrls = paypalService.createRedirectUrls(['cancelUrl':cancelUrl,'returnUrl':returnUrl])


    def payment
    try{
        // create the paypal payment
        payment = paypalService.createPayment(['payer':payer,'intent':'sale'
                ,'transactionList':transactions,'redirectUrls':redirectUrls
                ,'apiContext':apiContext])



    }
    catch(Exception ex){
        String msg = ex.getMessage()
        flash.message = "Could not complete the transaction because: ${msg? msg : ''}"  

        redirect controller:'paypal', action:"error"
        return
    }

    def approvalUrl = ""
    def retUrl = ""
    // retrieve links from returned paypal object
    payment?.links.each{ 
        if(it?.rel == 'approval_url'){
            approvalUrl = it.href
        }
        if(it?.rel == 'return_url'){
            retUrl = it.href

        }
    }


    redirect url:approvalUrl? approvalUrl:'/', method:'POST'

}


Approval

The customer will be redirected to the Paypal website for approval. After the customer approves or
cancels the payment, Paypal will either call the returnUrl or cancelUrl you provided depending on
what action the customer performs.

def execute(){

    String clientId = grailsApplication.config.paypal.clientId
    String clientSecret = grailsApplication.config.paypal.clientSecret
    String endpoint = grailsApplication.config.paypal.endpoint
    Map sdkConfig = [:] //= grailsApplication.config.paypal.sdkConfig//['mode':'live']
    //sdkConfig.put("grant-type","client_credentials")
    sdkConfig.put(Constants.CLIENT_ID,clientId)
    sdkConfig.put(Constants.CLIENT_SECRET,clientSecret)
    sdkConfig.put(Constants.ENDPOINT,endpoint)
    def accessToken = paypalService.getAccessToken(clientId,clientSecret,sdkConfig)
    def apiContext = paypalService.getAPIContext(accessToken,sdkConfig)
    //the paypal website will add params to the call to your app. Eg. PayerId, PaymentId
    // you will use the params to 'execute' the payment
    def paypalPayment = paypalService.createPaymentExecution(['paymentId':params.paymentId,'payerId':params?.PayerID],apiContext)

    JsonSlurper slurper = new JsonSlurper()
    def map = slurper.parseText(paypalPayment.toString())

    redirect(url:"to your url")
}

Normally, if the 'createPaymentExecution' call to paypalService is successful, you will receive the payment. You may also need to perform other actions like storing details of the transaction on your db, marking your customer invoice as 'paid', etc.

Paypal provides a dashboard that you can use to monitor all transactions.


The grails paypal-payments plugin provides other features that developers can combine in order to fulfill app requirements. eg. Payouts, etc. 

That's it. Easy as pie. Go ahead and explore. . . .

You may use the comments box to share your thoughts. 


Comments

Popular posts from this blog

Off-shoring, offshore outsourcing, near-shoring, co-shoring and information security cost: A comparative study

Fulani Marriages vs. Igbo Marriages