Hi guys! Nowadays, more often and often in different projects you have to handle and deal with different payment services, like Stripe, PayPal, Authorize.net, etc, to provide users with ability to purchase in your app, or make payouts to them.
Here we will speak about how to add PayPal payment system to the Spring Boot project and communicate with Angular 2 application.
So, first of all let’s talk how the PayPal actually works:
The payment procedure consists of three main parts:
- Payment Creation
- Payment Confirmation
- Payment Completion
Let’s discuss the option when we have Front-End part and Back-End part of the application. When you want to buy some item and you press the “Pay Now with PayPal” button -> One request is made to the server side. This request may contain all needed data for Payment Creation — item properties(amount, price, etc.), user details(token). The server side creates the payment object and sends it to PayPal, as a response it receives the “Created Payment” object. This object contains usefull data about the payment, like amount, total, tex, shipping, currency, and so on. What we use in this example is the “redirect url” — it is URL to the PayPal service, where you have to login to your account and confirma the purchase. Here is the place where the second part of payment procedure — “Payment Confirmation” starts. So, you need to confirm your purchase, and once it’s done, the PayPal will redirect you to the URL (as usual — URL to your Client app) that you specified as “return url” in the Payment object during first step(“Payment Creation”). After that, you will have to complete the payment by calling your server side again, and pass the Payment ID and Payer ID, that you got after Payment Confiramation. This is the third and the last step of the payment with PayPal.
So, let’s do some code!
In the Spring Boot project we will create a class called PayPalClient and will put the logic here. But before starting we will need clientId and clientSecret from the registered with PayPal. You get them by going to https://developer.paypal.com/, log in to your account(create one if you don’t have), and find button “Create App”.
Then set App Name, choose email address to use with it. And press “Create App”. On the next page you’ll have your clientId and clientSecret. And we are ready to go!
Add new dependency to your project:
<dependency> <groupId>com.paypal.sdk</groupId> <artifactId>rest-api-sdk</artifactId> <version>1.13.1</version> </dependency>
Create PayPalClient class, and define your clientId and clientSecret there:
String clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; String clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";public Map<String, Object> createPayment(String sum){ Map<String, Object> response = new HashMap<String, Object>(); Amount amount = new Amount(); amount.setCurrency("USD"); amount.setTotal(sum); Transaction transaction = new Transaction(); transaction.setAmount(amount); List<Transaction> transactions = new ArrayList<Transaction>(); transactions.add(transaction); Payer payer = new Payer(); payer.setPaymentMethod("paypal"); Payment payment = new Payment(); payment.setIntent("sale"); payment.setPayer(payer); payment.setTransactions(transactions); RedirectUrls redirectUrls = new RedirectUrls(); redirectUrls.setCancelUrl("https://localhost:4200/cancel"); redirectUrls.setReturnUrl("https://localhost:4200/"); payment.setRedirectUrls(redirectUrls); Payment createdPayment; try { String redirectUrl = ""; APIContext context = new APIContext(clientId, clientSecret, "sandbox"); createdPayment = payment.create(context); if(createdPayment!=null){ List<Links> links = createdPayment.getLinks(); for (Links link:links) { if(link.getRel().equals("approval_url")){ redirectUrl = link.getHref(); break; } } response.put("status", "success"); response.put("redirect_url", redirectUrl); } } catch (PayPalRESTException e) { System.out.println("Error happened during payment creation!"); } return response; }
And we need one RestController to handle requests from the Front-End application, we will call it PayPalController;
@RestController @RequestMapping(value = "/paypal") public class PayPalController { private final PayPalClient payPalClient; @Autowired PayPalController(PayPalClient payPalClient){ this.payPalClient = payPalClient; } @PostMapping(value = "/make/payment") public Map<String, Object> makePayment(@RequestParam("sum") String sum){ return payPalClient.createPayment(sum); } }
So, we have logic for Payment Creation. But we need still to add the methods that will compete tha payment once it will be confirmed by user. In the PayPalClient add another one method:
public Map<String, Object> completePayment(HttpServletRequest req){ Map<String, Object> response = new HashMap(); Payment payment = new Payment(); payment.setId(req.getParameter("paymentId")); PaymentExecution paymentExecution = new PaymentExecution(); paymentExecution.setPayerId(req.getParameter("PayerID")); try { APIContext context = new APIContext(clientId, clientSecret, "sandbox"); Payment createdPayment = payment.execute(context, paymentExecution); if(createdPayment!=null){ response.put("status", "success"); response.put("payment", createdPayment); } } catch (PayPalRESTException e) { System.err.println(e.getDetails()); } return response; }
And back to the PayPalController, need to add one more mapping for payment completion:
@PostMapping(value = "/complete/payment") public Map<String, Object> completePayment(HttpServletRequest request){ return payPalClient.completePayment(request); }
Ok! Our Back-End is ready to make payments. Let’s quickly create Front-End part. We need a simple UI and just two HTTP POST requests.
The one HTTP POST request will trigger payment creation on the server, and as the response of it we should receive redirect_url, that we will use to to be redirected to PayPal.
Here is the angular service method, that will make a request to the server. It contains just the payment amount that we should be charged.
makePayment(sum) { return this.http.post(this.url+'paypal/make/payment?sum='+sum, {}) .map((response: Response) => response.json()); }
Once this request is submitted to the server → it will trigger createPayment method. As a response we should receive a redirect_url property that we need to use to redirect our client.
After that, on the page that we was sent to we can log in to the PayPal account, and confirm the payment. Once it is confirmed → the PayPal will send us to the URL that we specified as a “returnUrl” in our createPayment method on the server side.
On confirmation Success we will be redirected to the home page. And after we are redirected back, we need to make another and the last request to complete the payment:
completePayment(paymentId, payerId) { return this.http.post(this.url + 'paypal/complete/payment?paymentId=' + paymentId + '&payerId=' + payerId , {}) .map((response: Response) => response.json()); }
In the URL returned from PayPal, in query parameters will be three properties:
- PaymentId
- PayerId
- Token
We will need only paymentId and payerId to be passed to the server side. With this information the payment will be executed and completed. And when you’ll log in to PayPal, you will see that the exact amount of money was charged from your account.
So, we are done. Let’s execute our programs.
On the home page(Angular) we have 3 items available. Each of the item has “PayPal Checkout” button → when user presses it, the request to createPayment is executed to the Back-End with the sum of the item.
After that server will send us a response with “redirectUrl”, that we immediately use to redirect user to the next page, where user has to login to his account and confirm the payment. We pressed on the first item with price 999$. And you see the payment with that amount is created on PayPal:
So, we clicked the continue, it is processing the payment, and in couple seconds redirects us to the https://localhost:4200, as it was specified as the “success return URL”. During returing PayPal sends query paramaters and appends them to the “success return URL”, so we need to get paymentId and payerId from it and pass in the completePayment method, that should be executed once we are redirected back after successfull payment confirmation.
Once the completePayment request executed and response from server received with success status — the payment is completed. You can go to https://www.sandbox.paypal.com/signin → log in to your account, and you will see all your sandbox transactions that are completed.
Conclusion
So, that was easy. If you need code samples — check out the sources on my GitHub.
As well you can find it on Oril Software GitHub.
Thank you!