A guide to integrating Paypal with Spring Boot application.

In this article, I am going to integrate Paypal with Java Spring Boot application. Please note I am using PayPal Checkout with Smart Payment Button https://developer.paypal.com/docs/checkout/ which is the preferred method since February 2019. You have to generate client id and secret from the PayPal developer site as well.

I am using Spring MVC. So first I am sharing view code

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Handy Opinion</title>
<script src="https://www.paypal.com/sdk/js?client-id=Here give your id"></script>
</head>
<body>

  <div id="paypal-button-container"></div>

  <script>
  paypal.Buttons({
	    createOrder: function(data, actions) {
	      // Set up the transaction
	    	return fetch('http://localhost:8080/api/v1/order', {
	    	    method: 'post',
	    	    body: JSON.stringify(
	    	    	  {
	    	    		    "amount": 10,
	    	    		    "buyerId": 505,
	    	    		    "name" : "test",
	    	    		    "email": "bilal@asd",
	    	    		    "orderId": "1DU40159BF1571222",
	    	    		    "packageId": 4,
	    	    		    "quantity": 50,
	    	    		    "supplierId": 505
	    	    		  }
	    	    		),
	    	    headers: {
	    	      'content-type': 'application/json'
	    	    }
	    	  }).then(function(res) {
	    	    return res.json();
	    	  }).then(function(data) {
	    	    return data.orderID; // Use the same key name for order ID on the client and server
	    	  });
	    },
	    onApprove: function(data, actions) {
	        // Capture the funds from the transaction
			  return fetch('http://localhost:8080/api/v1/approve', {
				  method: 'post',
				  headers: {
			      'content-type': 'application/json'
			    },
			    body: JSON.stringify({
			      orderId: data.orderID,
			      amount: 10,
			      buyerId: 505,
			      email: "bilal@asd",
			      productId: 1,
			      quantity: 50,
			      packageId: 4,
			      supplierId: 505
			    })
			  }).then(function(res) {
			    return res.json();
			  }).then(function(details) {
			    alert('Transaction approved by ' + details.orderID);
			})
	      }
	  }).render('#paypal-button-container');
  </script>
</body>
</html>

I am going to explain some important points here. You have to include below PayPal library script in head. Please generate your PayPal id and secret from the PayPal developer web site.

<script src="https://www.paypal.com/sdk/js?client-id=Here give your id"></script>

After that create a div. This is div where the checkout button will render.

 <div id="paypal-button-container"></div>

In the end, you can see a javascript function paypal.Buttons. There are two functions that we define the first one (createOrder) is called once we click the checkout button and the second one (onApprove) is called once payment done on PayPal and control come back to our application. We capture the order here and insert it into a database. We have two api’s call here.

  1. /api/v1/order this initiate an order
  2. /api/v1/approve this finishes the order and put order in database

Here I am sharing controllers and service methods. But before make sure to add below dependency in pom.xml

		<dependency>
		    <groupId>com.paypal.sdk</groupId>
		    <artifactId>checkout-sdk</artifactId>
		    <version>1.0.1</version>
		</dependency>

After that, we need to define a spring component for Paypal Client.

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.paypal.core.PayPalEnvironment;
import com.paypal.core.PayPalHttpClient;

@Component
public class PayPalClient {
	/**
	   *Set up the PayPal Java SDK environment with PayPal access credentials.  
	   *This sample uses SandboxEnvironment. In production, use LiveEnvironment.
	   */
	private String clientId;
	private String secretId;	
	

	  /**
	   *Method to get client object
	   *
	   *@return PayPalHttpClient client
	   */
	public PayPalHttpClient client() {
//		PayPalEnvironment environment = new PayPalEnvironment.Live(clientId,secretId);
		PayPalEnvironment environment = new PayPalEnvironment.Sandbox(clientId,secretId);
		  /**
		   *PayPal HTTP client instance with environment that has access
		   *credentials context. Use to invoke PayPal APIs.
		   */
		PayPalHttpClient client = new PayPalHttpClient(environment);
		client.setConnectTimeout((int) TimeUnit.SECONDS.toMillis(900));
		return client;
	}

	@Value("${paypal.client.id}")
	public void setClientId(String clientId) {
		this.clientId = clientId;
	}

	@Value("${paypal.secret.id}")
	public void setSecretId(String secretId) {
		this.secretId = secretId;
	}
	
}

Please note PayPalEnvironment.Sandbox(clientId,secretId) change this to Live while going live. The second point is the client id and secret are stored in the properties file. We will use this class to call PayPal API from our server.

Now, I am sharing Controller methods. Please note only important code is given, details are not given.

//This is controller	  
//2. Set up your server to receive a call from the client
	  
	@PostMapping(value = "/api/v1/order",consumes = MediaType.APPLICATION_JSON_VALUE)
	  public PaypalResponse createOrder(@RequestBody PaypalRequest paypalRequest) throws IOException {

		OrdersCreateRequest request = new OrdersCreateRequest();
	    request.prefer("return=representation");
	    request.requestBody(buildRequestBody(paymentDto.getData().getDiscountedPrice().toString()));
	    //3. Call PayPal to set up a transaction
	    HttpResponse<Order> response = paypalClient.client().execute(request);
	     PaypalResponse paypalResponse = new PaypalResponse();
	    if (response.statusCode() == 201) {
	    	paypalResponse.setOrderID(response.result().id());
	    }

	     return paypalResponse;
	  }

	@PostMapping("/api/v1/approve")
	public PaypalResponse approveOrder(@RequestBody PaypalRequest paypalRequest) throws IOException {
		PaypalResponse res = new PaypalResponse();
		OrdersGetRequest request = new OrdersGetRequest(paypalRequest.getOrderId());

	    //3. Call PayPal to get the transaction
	    HttpResponse<Order> response = paypalClient.client().execute(request);
	    //4. Save the transaction in your database. Implement logic to save transaction to your database for future reference.
	    if(response.statusCode() == HttpStatus.SC_OK){
	    	response = paypalService.captureOrder(paypalRequest, true);
		    if(response.statusCode() == HttpStatus.SC_CREATED) {
		    	//System.out.println(new JSONObject(new Json().serialize(response.result())).toString(4));
			    res.setOrderID(response.result().id());
		    } 
		    return res;
	    }else {
	    	return res;
	    }
	}

	  private OrderRequest buildRequestBody(String amount ) {
	    OrderRequest orderRequest = new OrderRequest();
	    orderRequest.checkoutPaymentIntent(capture);

	    ApplicationContext applicationContext = new ApplicationContext().brandName(brandName).landingPage(landingPage);
	    orderRequest.applicationContext(applicationContext);

	    List<PurchaseUnitRequest> purchaseUnitRequests = new ArrayList<PurchaseUnitRequest>();
	    PurchaseUnitRequest purchaseUnitRequest = new PurchaseUnitRequest().referenceId(referenceId)
	        .description(description).customId(customId).softDescriptor(descriptor)
	        .amountWithBreakdown(new AmountWithBreakdown().currencyCode("EUR").value(amount));
	    purchaseUnitRequests.add(purchaseUnitRequest);
	    orderRequest.purchaseUnits(purchaseUnitRequests);
	    return orderRequest;
	  }

Here I am sharing service methods. Please note this method is transactional as this will insert records in the database.

	@Transactional
	public HttpResponse<Order> captureOrder(PaypalRequest paypalRequest, boolean debug) throws IOException{
		OrdersCaptureRequest request = new OrdersCaptureRequest(paypalRequest.getOrderId());
	    request.requestBody(buildRequestBody());
	    // Call PayPal to capture an order
	    HttpResponse<Order> response = paypalClient.client().execute(request);
	    // Save the capture ID to your database. Implement logic to save capture to your database for future reference.
	    if(response.statusCode() == HttpStatus.SC_CREATED) {
	    	OrderDTO orderDTO = new OrderDTO();
	    	for (PurchaseUnit purchaseUnit : response.result().purchaseUnits()) {
		    	  purchaseUnit.amountWithBreakdown();
		        for (Capture capture : purchaseUnit.payments().captures()) {
		          orderDTO.setAmount(Double.parseDouble(capture.amount().value()));
		          orderDTO.setOrderId(capture.id());
				  //Here you can insert order into database
		        }
		      }
		    }
	    	return response;
	    }  
	    
	
	  /**
	   *Creating empty body for capture request.
	   *You can set the payment source if required.
	   *
	   *@return OrderRequest request with empty body
	   */
	  private OrderRequest buildRequestBody() {
	    return new OrderRequest();
	  }

That is it. You may go to PayPal developer examples for further details.

https://developer.paypal.com/docs/checkout/reference/server-integration/setup-sdk/

https://developer.paypal.com/docs/checkout/reference/server-integration/capture-transaction/

Please share this post:
Distinguished Engineer Java, PHP, Spring, Mysql
Posts created 11

Ask a Question

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

%d bloggers like this: