1.环境准备
注册paypal账号
注册paypal开发者账号
创建两个测试用户
创建应用,生成用于测试的clientID 和 密钥
2.代码集成
springboot环境
pom引进paypal-sdk的jar包
注册paypal账号
在浏览器输入链接: https://www.paypal.com. 跳转到如下界面,点击右上角的注册
注册paypal开发者账号
在浏览器输入链接: https://developer.paypal.com,点击右上角的“Log into Dashboard”,用上一步创建好的账号登录
创建两个测试用户
登录成功后,在左边的导航栏中点击 Sandbox 下的 Accounts
点击右上角的“Create Account”,创建测试用户(商户账户和个人账户)
用测试账号登录查看,登录测试网址(跟开发网址不是同一个):链接: https://www.sandbox.paypal.com 在这里登陆测试账户
创建APP
创建app目的 个人账户消费的目标是商户账号 点击create app
选择商户账号(商户为创建的商户并非登录的商户)
测试环境为sanbox 线上以后需要在live创建app(商户为当前登录用户)
点击刚刚创建好的App“TestApp”,注意看到”ClientID“ 和”Secret“(Secret如果没显示,点击下面的show就会看到,点击后show变为hide)
开始代码
引入依赖pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--paypal-->
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>rest-api-sdk</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>checkout-sdk</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Swagger 接口文档 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties配置
#端口号
server.port= 8088
#html地址
spring.thymeleaf.prefix=classpath:/templates/
# 沙盒模式测试sanbox 线上模式改成live
# paypal.client.app和paypal.client.secret请查看app配置
paypal.mode=sandbox
paypal.client.app=AYxj25IuPg4rAQbUmOZCSIEdmji***********VPWo74dqVUnW1q0_WUoVJr4MIeS95PKnYSNJd5W9KT
paypal.client.secret=EKcdUZKpu5XPEQiFFh85kFAe************6iLyhh4xm42tqBCCVKApqJ8QdVcd8XUxYY-0WD8i
Controller层
package com.example.demo.controller;
import com.example.demo.model.PaymentModel;
import com.example.demo.service.PaymentService;
import com.example.demo.until.URLUtils;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payment;
import com.paypal.base.rest.PayPalRESTException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* @program:
* @description:
* @author:
* @create:
**/
@Controller
public class PaymentController {
/**
* 成功页面
*/
public static final String PAYPAL_SUCCESS_URL = "pay/success";
/**
* 取消页面
*/
public static final String PAYPAL_CANCEL_URL = "pay/cancel";
@Resource
private PaymentService paymentService;
@GetMapping("/paypal")
public String index(){
return "index";
}
@PostMapping("/pay")
public String payment(HttpServletRequest request){
//获取取消页面
String cancelUrl = URLUtils.getBaseURl(request) + "/" + PAYPAL_CANCEL_URL;
//获取成功页面
String successUrl = URLUtils.getBaseURl(request) + "/" + PAYPAL_SUCCESS_URL;
Payment payment = null;
PaymentModel paymentModel = new PaymentModel();
//金额
paymentModel.setAmount("10");
//金额类型
paymentModel.setCurrency("USD");
//充值描述
paymentModel.setDescription("payment description");
try {
payment = paymentService.createPayment(paymentModel, cancelUrl, successUrl);
} catch (PayPalRESTException e) {
e.printStackTrace();
}
for(Links links : payment.getLinks()){
if(links.getRel().equals("approval_url")){
//客户付款登陆地址
return "redirect:" + links.getHref();
}
}
return "redirect:/";
}
/**
* 取消页面
* @return
*/
@GetMapping(value = PAYPAL_CANCEL_URL)
public String cancelPay(){
return "cancel";
}
/**
* 执行支付
* @param paymentId
* @param payerId
* @return
*/
@GetMapping(value = PAYPAL_SUCCESS_URL)
public String successPay(@RequestParam("paymentId") String paymentId, @RequestParam("PayerID") String payerId){
Payment payment = null;
try {
payment = paymentService.executePayment(paymentId, payerId);
} catch (PayPalRESTException e) {
e.printStackTrace();
}
if(payment.getState().equals("approved")){
return "success";
}
return "redirect:/";
}
}
service层
package com.example.demo.service;
import com.example.demo.model.PaymentModel;
import com.paypal.api.payments.Payment;
import com.paypal.base.rest.PayPalRESTException;
/**
* @program:
* @description:
* @author:
* @create:
**/
public interface PaymentService {
/**
* 创建支付
* @param paymentModel
* @param cancelUrl
* @param successUrl
* @return
* @throws PayPalRESTException
*/
Payment createPayment(PaymentModel paymentModel, String cancelUrl, String successUrl) throws PayPalRESTException;
/**
* 执行支付
* @param paymentId
* @param payerId
* @return
* @throws PayPalRESTException
*/
Payment executePayment(String paymentId, String payerId) throws PayPalRESTException;
}
Impl层
package com.example.demo.impl;
import com.example.demo.config.PaypalPaymentIntent;
import com.example.demo.config.PaypalPaymentMethod;
import com.example.demo.model.PaymentModel;
import com.example.demo.service.PaymentService;
import com.paypal.api.payments.*;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.PayPalRESTException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @program:
* @description:
* @author:
* @create:
**/
@Service
public class PaymentServiceImpl implements PaymentService {
private final APIContext apiContext;
private final String USD = "USD";
@Autowired
public PaymentServiceImpl(APIContext apiContext) {
this.apiContext = apiContext;
}
@Override
public Payment createPayment(PaymentModel paymentModel , String cancelUrl, String successUrl) throws PayPalRESTException {
//订单金额 以及金额类型 默认为USD
Amount amount = new Amount();
if(null!=paymentModel.getCurrency()){
amount.setCurrency(paymentModel.getCurrency());
}else{
amount.setCurrency(USD);
}
amount.setTotal(paymentModel.getAmount());
List<Transaction> transactions = new ArrayList<>();
Transaction transaction = new Transaction();
transaction.setDescription(paymentModel.getDescription());
transaction.setAmount(amount);
transactions.add(transaction);
/**
* 支付信息
*/
Payer payer = new Payer();
payer.setPaymentMethod(PaypalPaymentMethod.paypal.toString());
Payment payment = new Payment();
payment.setIntent(PaypalPaymentIntent.sale.toString());
payment.setPayer(payer);
payment.setTransactions(transactions);
/**
* 回调地址
*/
RedirectUrls redirectUrls = new RedirectUrls();
redirectUrls.setCancelUrl(cancelUrl);
redirectUrls.setReturnUrl(successUrl);
payment.setRedirectUrls(redirectUrls);
return payment.create(apiContext);
}
@Override
public Payment executePayment(String paymentId, String payerId) throws PayPalRESTException {
Payment payment = new Payment();
payment.setId(paymentId);
PaymentExecution paymentExecute = new PaymentExecution();
paymentExecute.setPayerId(payerId);
return payment.execute(apiContext, paymentExecute);
}
}
config类
package com.example.demo.config;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.OAuthTokenCredential;
import com.paypal.base.rest.PayPalRESTException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @program:
* @description:
* @author:
* @create:
**/
@Configuration
public class PaypalConfig {
@Value("${paypal.client.app}")
private String clientId;
@Value("${paypal.client.secret}")
private String clientSecret;
@Value("${paypal.mode}")
private String mode;
@Bean
public Map<String, String> paypalSdkConfig(){
Map<String, String> sdkConfig = new HashMap<>();
sdkConfig.put("mode", mode);
return sdkConfig;
}
@Bean
public OAuthTokenCredential authTokenCredential(){
return new OAuthTokenCredential(clientId, clientSecret, paypalSdkConfig());
}
@Bean
public APIContext apiContext() throws PayPalRESTException {
APIContext apiContext = new APIContext(authTokenCredential().getAccessToken());
apiContext.setConfigurationMap(paypalSdkConfig());
return apiContext;
}
}
package com.example.demo.config;
/**
* @program:
* @description:
* @author:
* @create:
**/
public enum PaypalPaymentIntent {
sale, authorize, order
}
package com.example.demo.config;
/**
* @program:
* @description:
* @author:
* @create:
**/
public enum PaypalPaymentMethod {
credit_card, paypal
}
spingboot启动类
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @program:
* @description:
* @author:
* @create:
**/
@EnableAutoConfiguration
@Configuration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
paypal图标 paypal.jsp
成功 取消 登录界面html
index.html
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form method="post" th:action="@{/pay}">
<button type="submit"><img src="images/paypal.jpg" width="100px;" height="30px;"/>button>
form>
body>
html>
success.html
<html>
<head>
<meta charset="UTF-8" />
<title>Insert title heretitle>
head>
<body>
<h1>Payment Successh1>
body>
html>
cancel.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>Canceled by userh1>
body>
html>
启动登录
登录账号(之前注册的个人账号Test-P)
到链接: https://www.sandbox.paypal.com. 登录测试账号看看余额有没有变化
实际开发中 可以参照本博客V2版本链接: https://blog.csdn.net/m0_37693638/article/details/111152268.