├── .classpath
├── .gitignore
├── .project
├── README.md
├── pom.xml
└── src
└── main
├── java
└── com
│ └── masasdani
│ └── paypal
│ ├── Application.java
│ ├── config
│ ├── PaypalConfig.java
│ ├── PaypalPaymentIntent.java
│ └── PaypalPaymentMethod.java
│ ├── controller
│ └── PaymentController.java
│ ├── service
│ └── PaypalService.java
│ └── util
│ └── URLUtils.java
└── resources
├── application.properties
└── templates
├── cancel.html
├── index.html
└── success.html
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .DS_Store
3 | .settings
4 | target
5 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | paypal-springboot
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.common.project.facet.core.builder
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.m2e.core.maven2Builder
20 |
21 |
22 |
23 |
24 | org.springframework.ide.eclipse.core.springbuilder
25 |
26 |
27 |
28 |
29 |
30 | org.springframework.ide.eclipse.core.springnature
31 | org.eclipse.jdt.core.javanature
32 | org.eclipse.m2e.core.maven2Nature
33 | org.eclipse.wst.common.project.facet.core.nature
34 |
35 |
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Paypal REST API Payment using Spring Boot
2 | =========================================
3 | This is sample project how to implement paypal rest api to spring boot web application,
4 | if you see pom.xml it will show you that it's using spring boot 1.3.0 starter web, using thymeleaf as template engine, and Paypal Java SDK.
5 |
6 | Prerequisites:
7 | ==============
8 | * Java JDK-1.7 or higher
9 | * Apache Maven 3 or higher
10 | * Please refer http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html for any help in Maven.
11 |
12 | Usage
13 | =====
14 | to run this sample, please at first crete paypal account and register your apps to http://developer.paypal.com, get your app configuration and then change paypal configuration in src/main/resource/application.properties of your project
15 |
16 |
17 | paypal.mode=sandbox
18 | paypal.client.app=xxxxxxxxxxxxxxxxxxYOUR_CLIENT_IDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
19 | paypal.client.secret=xxxxxxxxxxxxxxxxxxYOUR_CLIENT_SECRETxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
20 |
21 |
22 | Then run it using maven :
23 |
24 |
25 | mvn spring-boot:run
26 |
27 |
28 | Test in your browser :
29 |
30 |
31 | http://localhost:8080
32 |
33 |
34 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.masasdani
4 | paypal-springboot
5 | 0.0.1-SNAPSHOT
6 | paypal-springboot
7 |
8 |
9 |
10 | spring-milestones
11 | Spring Milestones
12 | http://repo.spring.io/libs-milestone
13 |
14 |
15 | jcenter-snapshots
16 | jcenter
17 | https://jcenter.bintray.com/
18 |
19 |
20 |
21 |
22 |
23 | spring-milestones
24 | Spring Milestones
25 | http://repo.spring.io/libs-milestone
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-parent
32 | 1.3.0.RELEASE
33 |
34 |
35 |
36 | UTF-8
37 | 1.8
38 |
39 |
40 |
41 |
42 | org.springframework.boot
43 | spring-boot-starter-web
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-thymeleaf
48 |
49 |
50 | com.paypal.sdk
51 | rest-api-sdk
52 | 1.4.2
53 |
54 |
55 |
56 |
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-compiler-plugin
61 |
62 | ${java.version}
63 | ${java.version}
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/src/main/java/com/masasdani/paypal/Application.java:
--------------------------------------------------------------------------------
1 | package com.masasdani.paypal;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
5 | import org.springframework.context.annotation.ComponentScan;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | @EnableAutoConfiguration
9 | @Configuration
10 | @ComponentScan
11 | public class Application {
12 |
13 | public static void main(String[] args) {
14 | SpringApplication.run(Application.class, args);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/main/java/com/masasdani/paypal/config/PaypalConfig.java:
--------------------------------------------------------------------------------
1 | package com.masasdani.paypal.config;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | import com.paypal.base.rest.APIContext;
11 | import com.paypal.base.rest.OAuthTokenCredential;
12 | import com.paypal.base.rest.PayPalRESTException;
13 |
14 | @Configuration
15 | public class PaypalConfig {
16 |
17 | @Value("${paypal.client.app}")
18 | private String clientId;
19 | @Value("${paypal.client.secret}")
20 | private String clientSecret;
21 | @Value("${paypal.mode}")
22 | private String mode;
23 |
24 | @Bean
25 | public Map paypalSdkConfig(){
26 | Map sdkConfig = new HashMap<>();
27 | sdkConfig.put("mode", mode);
28 | return sdkConfig;
29 | }
30 |
31 | @Bean
32 | public OAuthTokenCredential authTokenCredential(){
33 | return new OAuthTokenCredential(clientId, clientSecret, paypalSdkConfig());
34 | }
35 |
36 | @Bean
37 | public APIContext apiContext() throws PayPalRESTException{
38 | APIContext apiContext = new APIContext(authTokenCredential().getAccessToken());
39 | apiContext.setConfigurationMap(paypalSdkConfig());
40 | return apiContext;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/masasdani/paypal/config/PaypalPaymentIntent.java:
--------------------------------------------------------------------------------
1 | package com.masasdani.paypal.config;
2 |
3 | public enum PaypalPaymentIntent {
4 |
5 | sale, authorize, order
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/masasdani/paypal/config/PaypalPaymentMethod.java:
--------------------------------------------------------------------------------
1 | package com.masasdani.paypal.config;
2 |
3 | public enum PaypalPaymentMethod {
4 |
5 | credit_card, paypal
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/masasdani/paypal/controller/PaymentController.java:
--------------------------------------------------------------------------------
1 | package com.masasdani.paypal.controller;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RequestMethod;
11 | import org.springframework.web.bind.annotation.RequestParam;
12 |
13 | import com.masasdani.paypal.config.PaypalPaymentIntent;
14 | import com.masasdani.paypal.config.PaypalPaymentMethod;
15 | import com.masasdani.paypal.service.PaypalService;
16 | import com.masasdani.paypal.util.URLUtils;
17 | import com.paypal.api.payments.Links;
18 | import com.paypal.api.payments.Payment;
19 | import com.paypal.base.rest.PayPalRESTException;
20 |
21 | @Controller
22 | @RequestMapping("/")
23 | public class PaymentController {
24 |
25 | public static final String PAYPAL_SUCCESS_URL = "pay/success";
26 | public static final String PAYPAL_CANCEL_URL = "pay/cancel";
27 |
28 | private Logger log = LoggerFactory.getLogger(getClass());
29 |
30 | @Autowired
31 | private PaypalService paypalService;
32 |
33 | @RequestMapping(method = RequestMethod.GET)
34 | public String index(){
35 | return "index";
36 | }
37 |
38 | @RequestMapping(method = RequestMethod.POST, value = "pay")
39 | public String pay(HttpServletRequest request){
40 | String cancelUrl = URLUtils.getBaseURl(request) + "/" + PAYPAL_CANCEL_URL;
41 | String successUrl = URLUtils.getBaseURl(request) + "/" + PAYPAL_SUCCESS_URL;
42 | try {
43 | Payment payment = paypalService.createPayment(
44 | 4.00,
45 | "USD",
46 | PaypalPaymentMethod.paypal,
47 | PaypalPaymentIntent.sale,
48 | "payment description",
49 | cancelUrl,
50 | successUrl);
51 | for(Links links : payment.getLinks()){
52 | if(links.getRel().equals("approval_url")){
53 | return "redirect:" + links.getHref();
54 | }
55 | }
56 | } catch (PayPalRESTException e) {
57 | log.error(e.getMessage());
58 | }
59 | return "redirect:/";
60 | }
61 |
62 | @RequestMapping(method = RequestMethod.GET, value = PAYPAL_CANCEL_URL)
63 | public String cancelPay(){
64 | return "cancel";
65 | }
66 |
67 | @RequestMapping(method = RequestMethod.GET, value = PAYPAL_SUCCESS_URL)
68 | public String successPay(@RequestParam("paymentId") String paymentId, @RequestParam("PayerID") String payerId){
69 | try {
70 | Payment payment = paypalService.executePayment(paymentId, payerId);
71 | if(payment.getState().equals("approved")){
72 | return "success";
73 | }
74 | } catch (PayPalRESTException e) {
75 | log.error(e.getMessage());
76 | }
77 | return "redirect:/";
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/com/masasdani/paypal/service/PaypalService.java:
--------------------------------------------------------------------------------
1 | package com.masasdani.paypal.service;
2 |
3 | import java.math.BigDecimal;
4 | import java.math.RoundingMode;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.stereotype.Service;
10 |
11 | import com.masasdani.paypal.config.PaypalPaymentIntent;
12 | import com.masasdani.paypal.config.PaypalPaymentMethod;
13 | import com.paypal.api.payments.Amount;
14 | import com.paypal.api.payments.Payer;
15 | import com.paypal.api.payments.Payment;
16 | import com.paypal.api.payments.PaymentExecution;
17 | import com.paypal.api.payments.RedirectUrls;
18 | import com.paypal.api.payments.Transaction;
19 | import com.paypal.base.rest.APIContext;
20 | import com.paypal.base.rest.PayPalRESTException;
21 |
22 | @Service
23 | public class PaypalService {
24 |
25 | @Autowired
26 | private APIContext apiContext;
27 |
28 | public Payment createPayment(
29 | Double total,
30 | String currency,
31 | PaypalPaymentMethod method,
32 | PaypalPaymentIntent intent,
33 | String description,
34 | String cancelUrl,
35 | String successUrl) throws PayPalRESTException{
36 | Amount amount = new Amount();
37 | amount.setCurrency(currency);
38 | total = new BigDecimal(total).setScale(2, RoundingMode.HALF_UP).doubleValue();
39 | amount.setTotal(String.format("%.2f", total));
40 |
41 | Transaction transaction = new Transaction();
42 | transaction.setDescription(description);
43 | transaction.setAmount(amount);
44 |
45 | List transactions = new ArrayList<>();
46 | transactions.add(transaction);
47 |
48 | Payer payer = new Payer();
49 | payer.setPaymentMethod(method.toString());
50 |
51 | Payment payment = new Payment();
52 | payment.setIntent(intent.toString());
53 | payment.setPayer(payer);
54 | payment.setTransactions(transactions);
55 | RedirectUrls redirectUrls = new RedirectUrls();
56 | redirectUrls.setCancelUrl(cancelUrl);
57 | redirectUrls.setReturnUrl(successUrl);
58 | payment.setRedirectUrls(redirectUrls);
59 |
60 | return payment.create(apiContext);
61 | }
62 |
63 | public Payment executePayment(String paymentId, String payerId) throws PayPalRESTException{
64 | Payment payment = new Payment();
65 | payment.setId(paymentId);
66 | PaymentExecution paymentExecute = new PaymentExecution();
67 | paymentExecute.setPayerId(payerId);
68 | return payment.execute(apiContext, paymentExecute);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/masasdani/paypal/util/URLUtils.java:
--------------------------------------------------------------------------------
1 | package com.masasdani.paypal.util;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 |
5 | public class URLUtils {
6 |
7 | public static String getBaseURl(HttpServletRequest request) {
8 | String scheme = request.getScheme();
9 | String serverName = request.getServerName();
10 | int serverPort = request.getServerPort();
11 | String contextPath = request.getContextPath();
12 | StringBuffer url = new StringBuffer();
13 | url.append(scheme).append("://").append(serverName);
14 | if ((serverPort != 80) && (serverPort != 443)) {
15 | url.append(":").append(serverPort);
16 | }
17 | url.append(contextPath);
18 | if(url.toString().endsWith("/")){
19 | url.append("/");
20 | }
21 | return url.toString();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port: 8080
2 | spring.thymeleaf.cache=false
3 |
4 | paypal.mode=sandbox
5 | paypal.client.app=xxxxxxxxxxxxxxxxxxYOUR_CLIENT_IDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
6 | paypal.client.secret=xxxxxxxxxxxxxxxxxxYOUR_CLIENT_SECRETxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--------------------------------------------------------------------------------
/src/main/resources/templates/cancel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Insert title here
6 |
7 |
8 | Canceled by user
9 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Insert title here
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/resources/templates/success.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Insert title here
6 |
7 |
8 | Payment Success
9 |
10 |
--------------------------------------------------------------------------------