springboot实现支付宝支付
- 1. 获取应用id,应用私钥和支付宝公钥
- 2. 开始开发
- 3. 内网穿透
- 4. 测试支付功能
1. 获取应用id,应用私钥和支付宝公钥
进入支付宝控制台:https://open.alipay.com/develop/manage
找到沙箱
这里可以看到应用id
可以看到应用私钥
和支付宝公钥
,获取这三后就可以开始敲代码了
2. 开始开发
依赖:
<!--支付宝-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.34.0.ALL</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在resources/templates目录下创建一个pay.html文件,用于展示支付宝支付页面。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>支付宝支付</title>
</head>
<body onload="document.forms[0].submit();">
<div th:utext="${form}"></div>
</body>
</html>
创建同步通知页面
在resources/templates目录下创建一个return.html文件,用于展示同步通知结果。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>支付结果</title>
</head>
<body>
<h1 th:text="${message}"></h1>
</body>
</html>
# 支付宝支付参数配置
alipay:
# 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
appId: 111111111111111111
# 应用私钥,您的PKCS8格式RSA2私钥
privateKey: 11111111111111111
# 支付宝公钥
publicKey: 111111111111111111111111
# 支付宝网关
gatewayUrl: https://openapi.alipaydev.com/gateway.do
# 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
notifyUrl: http://花生壳地址:花生壳端口/api/alipay/notify
# 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
returnUrl: http://花生壳地址:花生壳端口/returnView.html
/**
* 支付配置类
*/
@Configuration
@ConfigurationProperties(prefix = "alipay")
@Data
public class PayAliConfig {
/**
* 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
*/
public String appId;
/**
* 应用私钥,您的PKCS8格式RSA2私钥
*/
public String privateKey;
/**
* 支付宝公钥
*/
public String publicKey;
/**
* 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
*/
public String notifyUrl;
/**
* 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
*/
public String returnUrl;
/**
* 支付宝网关
*/
public String gatewayUrl;
}
/**
* 初始化AlipayClient
* @version 1.0.0
* @date 2023/6/7
*/
@Component
public class AliPayClient {
@Autowired
private PayAliConfig payAliConfig;
@Bean
public AlipayClient AlipayClient() throws AlipayApiException {
AlipayConfig alipayConfig = new AlipayConfig();
//设置网关地址
alipayConfig.setServerUrl(payAliConfig.gatewayUrl);
//设置应用ID
alipayConfig.setAppId(payAliConfig.appId);
//设置应用私钥
alipayConfig.setPrivateKey(payAliConfig.privateKey);
//设置请求格式,固定值json
alipayConfig.setFormat(AlipayConstants.FORMAT_JSON);
//设置字符集
alipayConfig.setCharset(AlipayConstants.CHARSET_UTF8);
//设置支付宝公钥
alipayConfig.setAlipayPublicKey(payAliConfig.publicKey);
//设置签名类型
alipayConfig.setSignType(AlipayConstants.SIGN_TYPE_RSA2);
//构造client
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
return alipayClient;
}
}
/**
* @version 1.0.0
* @date 2023/6/6
*/
@RestController
@RequestMapping("/api/alipay")
@Api(tags = "网站支付宝支付")
@Slf4j
public class AlipayController {
@Autowired
private AliPayService alipayService;
/**
* 创建支付订单,返回支付页面
*/
@GetMapping("/pay")
@Timing(remark = "创建支付订单")
public ModelAndView pay(){
String outTradeNo= IdUtil.simpleUUID();
String subject="测试商品";
BigDecimal totalAmount = BigDecimal.valueOf(250);
PayRequest payRequest = new PayRequest();
payRequest.setOut_trade_no(outTradeNo);
payRequest.setSubject(subject);
payRequest.setTotal_amount(totalAmount);
payRequest.setBody("这是一个测试商品描述哦");
payRequest.setQr_pay_mode("2");
AlipayTradePagePayResponse response = alipayService.pay(payRequest);
if (response == null) {
return null;
}
log.info("响应:{}",response.getBody());
// 返回支付页面
ModelAndView modelAndView = new ModelAndView("pay");
modelAndView.addObject("form", response.getBody());
return modelAndView;
}
/**
* 处理支付宝异步通知
*/
@PostMapping("/notify")
@Timing(remark = "处理支付宝异步通知")
public void notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
boolean signVerified = alipayService.rsaCheckV1(request);
// 将请求参数转换为Map
if (signVerified) {
// 处理支付成功逻辑,更新订单状态等操作
response.getWriter().write("success"); // 告诉支付宝已经收到通知并处理成功
} else {
response.getWriter().write("failure"); // 告诉支付宝验签失败
}
}
}
/**
* @version 1.0.0
* @date 2023/6/7
*/
public interface AliPayService {
AlipayTradePagePayResponse pay(PayRequest payRequest);
boolean rsaCheckV1(HttpServletRequest request);
}
/**
* @version 1.0.0
* @date 2023/6/7
*/
@Service
@Slf4j
public class AliPayServiceImpl implements AliPayService {
@Autowired
private AlipayClient alipayClient;
@Autowired
private PayAliConfig payAliConfig;
@Override
public AlipayTradePagePayResponse pay(PayRequest payRequest) {
// 构造请求参数
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setReturnUrl(payAliConfig.getReturnUrl());
request.setNotifyUrl(payAliConfig.getNotifyUrl());
log.info("生成的字符串:{}", JSONUtil.toJsonStr(payRequest));
request.setBizContent(JSONUtil.toJsonStr(payRequest));
// request.setBizContent("{\"out_trade_no\":\"" + UUID.randomUUID().toString().replaceAll("-", "") + "\","
// + "\"total_amount\":\"0.01\","
// + "\"subject\":\"测试商品\","
// + "\"body\":\"测试商品详情\","
// + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
// 调用SDK生成表单
try {
return alipayClient.pageExecute(request);
} catch (AlipayApiException e) {
log.error("支付宝请求失败");
}
return null;
}
@Override
public boolean rsaCheckV1(HttpServletRequest request) {
boolean flag = false;
Map<String, String> params = new HashMap<>();
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String paramName = parameterNames.nextElement();
String paramValue = request.getParameter(paramName);
params.put(paramName, paramValue);
}
// 调用SDK验证签名
try {
flag =AlipaySignature.rsaCheckV1(params, payAliConfig.publicKey, AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);
} catch (AlipayApiException e) {
log.error("验签失败");
}
return flag;
}
}
3. 内网穿透
花生壳:https://hsk.oray.com/
下载安装配置一下就好了
4. 测试支付功能
启动Spring Boot应用,访问http://localhost:8889/api/alipay/pay,即可看到支付宝支付页面。输入支付密码后,会自动跳转到同步通知页面,并显示支付结果。
账号密码在沙箱账号
中看到