├── .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 |
9 | 10 |
11 | 12 | -------------------------------------------------------------------------------- /src/main/resources/templates/success.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Insert title here 6 | 7 | 8 |

Payment Success

9 | 10 | --------------------------------------------------------------------------------