一.官网文档:https://opendocs.alipay.com/common/02kkv7
二.开发流程:
三.预期效果展示:
在开始之前我们要清楚的知道我们要达到的最后效果:
- 前端点击支付跳转到支付宝界面
- 支付宝界面展示付款二维码
- 用户手机端支付
- 完成支付,支付宝回调开发者指定的url。
四.沙箱环境准备:
4.1注册入驻支付宝开放平台
登录支付宝开放平台,支付宝登陆平台,找到开发接入入驻为开发者。
4.2配置沙箱环境
账号: 注意:沙箱不能注册账号!!!
支付参数:
点击查看:获取应用私钥和支付宝公钥
五.SpringBoot 整合支付宝沙箱
5.1项目结构:
5.2 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>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lianchun</groupId>
<artifactId>springboot_demo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_demo1</name>
<description>springboot_demo1</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</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>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
5.3 对应的配置类
package com.lianchun.springboot_demo1.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.lianchun.springboot_demo1.pojo.AliPayBean;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @author 陈佳乐
*/
@Data
@Configuration
//@PropertySource("classpath:application.yaml")
public class Alipay {
/**
* 日志对象
*/
private static final Logger logger = LoggerFactory.getLogger(Alipay.class);
private final String format = "json";
/**
* appId
*/
@Value("${app.appId}")
private String appId;
/**
* 商户私钥
*/
@Value("${app.privateKey}")
private String privateKey;
/**
* 支付宝公钥
*/
@Value("${app.publicKey}")
private String publicKey;
/**
* 服务器异步通知页面路径,需要公网能访问到
*/
@Value("${app.notifyUrl}")
private String notifyUrl;
/**
* 服务器同步通知页面路径,需要公网能访问到
*/
@Value("${app.returnUrl}")
private String returnUrl;
/**
* 签名方式
*/
@Value("${app.signType}")
private String signType;
/**
* 字符编码格式
*/
@Value("${app.charset}")
private String charset;
/**
* 支付宝网关
*/
@Value("${app.gatewayUrl}")
private String gatewayUrl;
public String pay(AliPayBean aliPayBean) throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
gatewayUrl, appId, privateKey, format, charset, publicKey, signType);
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(returnUrl);
alipayRequest.setNotifyUrl(notifyUrl);
alipayRequest.setBizContent(JSON.toJSONString(aliPayBean));
logger.info("封装请求支付宝付款参数为:{}", JSON.toJSONString(alipayRequest));
String result = alipayClient.pageExecute(alipayRequest).getBody();
logger.info("请求支付宝付款返回参数为:{}", result);
System.out.println(result);
return result;
}
/**
* 查询订单是否成功
*
* @param id
* @return
*/
public String query(String id) throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
gatewayUrl, appId, privateKey, format, charset, publicKey, signType);
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
JSONObject bizContent = new JSONObject();
//订单id
bizContent.put("out_trade_no", id);
request.setBizContent(bizContent.toString());
AlipayTradeQueryResponse response = null;
//和上面方法一样,定义变量存放响应的数据
String from = null;
try {
response = alipayClient.execute(request);
//获取响应的数据
from = response.getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
if (response.isSuccess()) {
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}
//返回数据
return from;
}
}
OrderController
package com.lianchun.springboot_demo1.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.lianchun.springboot_demo1.config.Alipay;
import com.lianchun.springboot_demo1.pojo.AliPayBean;
import com.lianchun.springboot_demo1.service.PayService;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @author 陈佳乐
*/
@Controller
@RequestMapping("/ali")
public class OrderController {
/**
* 日志对象
*/
private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
@Autowired
private PayService payService;
@Autowired
private Alipay alipay;
@RequestMapping("/pay")
@ResponseBody
public String alipay(String outTradeNo, String subject, String totalAmount, String body) throws AlipayApiException {
logger.info("商户订单号为{},订单名称为{},付款金额为{},商品描述{}", outTradeNo, subject, totalAmount, body);
AliPayBean alipayBean = new AliPayBean();
alipayBean.setOut_trade_no(outTradeNo);
alipayBean.setSubject(subject);
alipayBean.setTotal_amount(totalAmount);
alipayBean.setBody(body);
return payService.aliPay(alipayBean);
}
@RequestMapping(value = "/index")
public String payCoin() {
return "index";
}
/**
* 支付成功以后跳转的页面
*
* @return
*/
@GetMapping("/return")
//传入商品的编号
public String returnNotice(String out_trade_no, Model model) throws AlipayApiException {
System.out.println(out_trade_no);
String query = alipay.query(out_trade_no);
model.addAttribute("form", query);
return "query";
}
/*
* @author: limaorong
* @date: 2022/12/29 21:40
* @return:
#异步返回地址必须是公网
app.notifyUrl: http://r48qbv.natappfree.cc/ali/callBack
* @decription:
**/
@PostMapping("/callBack")
@ResponseBody
public Map<String, String> alipayNotify(HttpServletRequest request) throws Exception {
// 获取支付宝的请求信息
Map<String, String> map = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
if (requestParams.isEmpty()) {
return map;
}
// 将 Map<String,String[]> 转为 Map<String,String>
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
map.put(name, valueStr);
}
// 验签
boolean signVerified = AlipaySignature.rsaCheckV1(map, alipay.getPublicKey(), alipay.getCharset(),
alipay.getSignType());
// 验签通过
if (signVerified) {
//异步通知成功执行写入订单表的操做
//支付成功后进行操作
System.out.println(map);
System.out.println("支付成功");
}
//支付失败的操做
return map;
}
}
AliPayBean
package com.lianchun.springboot_demo1.pojo;
import lombok.Data;
/**
* 支付宝支付实体,以下实体参数参考阿里官方给的那个demo,
* @author 陈佳乐
*/
@Data
public class AliPayBean {
/**
* 商户订单号
*/
private String out_trade_no;
/**
* 订单名称
*/
private String subject;
/**
* 付款金额
*/
private String total_amount;
/**
* 商品描述
*/
private String body;
/**
* 超时时间参数
*/
private String timeout_express = "60m";
/**
* 产品编号
*/
private String product_code = "FAST_INSTANT_TRADE_PAY";
}
PayService
package com.lianchun.springboot_demo1.service;
import com.alipay.api.AlipayApiException;
import com.lianchun.springboot_demo1.pojo.AliPayBean;
/**
* @author 陈佳乐
*/
public interface PayService {
String aliPay(AliPayBean aliPayBean) throws AlipayApiException;
}
PayServiceImpl
package com.lianchun.springboot_demo1.service.impl;
import com.alipay.api.AlipayApiException;
import com.lianchun.springboot_demo1.config.Alipay;
import com.lianchun.springboot_demo1.pojo.AliPayBean;
import com.lianchun.springboot_demo1.service.PayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 支付服务接口
* @author 陈佳乐
*/
@Service
public class PayServiceImpl implements PayService {
/**日志对象*/
private static final Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);
@Autowired
private Alipay alipay;
@Override
public String aliPay(AliPayBean aliPayBean) throws AlipayApiException {
logger.info("调用支付服务接口...");
return alipay.pay(aliPayBean);
}
/**
* 支付宝异步请求逻辑
*/
}
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>$Title$</title>
</head>
<body>
<form action="/ali/pay" method="post">
订单号:<input type="text" name="outTradeNo" required><br/>
订单名称:<input type="text" name="subject" required><br/>
付款金额:<input type="text" name="totalAmount" required><br/>
商品描述:<input type="text" name="body"><br/>
<input type="submit" value="下单"> <input type="reset" value="重置">
</form>
</body>
</html>
query.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div th:text="${form}"></div>
</body>
</html>
application.yaml
spring:
thymeleaf:
cache: false
encoding: UTF-8
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/alipay?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: root
output:
ansi:
enabled: always
#mybatis配置
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
#pagehelper分页插件
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
server.port: 9090
#支付宝沙盒 账号ahmfkg9284@sandbox.com 111111
alipay: iwuxpv9095@sandbox.com
# APPID 登录支付宝会生成
app.appId: 9021000137637932
# 应用私钥 生成密钥器生成
app.privateKey: MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQD0K+08Udh1nj/CtO5P5wgU23txZc+zX/IuiD9cFXffjFSF4qm1SyMSvLp7PMkaG39IMsXewofKSiPWWzbODR1evP+n5JArC1uEuGhxQjkanV0dUvbwHlGSt/WiNW1D5FNqf5MQ20hD5UICelkfgzXYWbIHLpJK7hHkE12Dg5ZuFez+Iz7d+V2u34snPzreVaKMNu3f0up5cvPQTqrUvGh4wEvtaeVHn89ZKhzrOmxm8Jhn/ot+xysi0w250eAdW5ZzIoSSsKe/7frQsFoYIDGoviVMSWjCUgQ6toNphAcrJN6Yq5FyghKx2Ddr+73G9oSdDwV+e/A3ruzvWIBdize9AgMBAAECggEBAIm8UbnqDWnj1+HUwG3wTF2/pbXFEdIEuI/JKbyfG5zOA0v3HXZ4KRPDxIoKMwL4KeenRHkxUPoqsmaT06mOOlgb0zd5Nl4hrQGEKN5i1eWOiV0mVMgEwk06WmSjMLzQisGTr3kdyXkLVR4iuC2PjYs6pbNpcPq1qv/2cJTkYLI9r/0E703RXnc8B3uEn/rzEEdsytRdbQe6xcXug6Oyt1OfE+a/ZPi+wO+BDv6093VmwmT4PNMh1SrAr+i/BLFLxJE6z2LtT/0zNVakD86jz8b9E+g20c3XhQOaX+fAo64JYs4N0RZMKSkhDeTNmQ7WxQtyVTg+fGl3sCiDAAwTvSECgYEA+zC4TQhXS0cR98w4N1TrQe6guno/Komk+XQyATxXYFqE/OiBB1KRmIC2GDy54s27XwP4zYKTVTVv3B/wDMkHVrXpfOQruEOrW85Ae0M7jMWw3uas8c55rNtAnO84ZtWAFp9nExG2QfZ374x0kll+la+L7xdZIKIc4gWhtMmBuKkCgYEA+NjNclMMiZp7TEwXDErmG1LMm0X/p6odloc1nX8PwrIHtX4OOlM7zw5XZuH7Ebxl2BRZYV1NpFsovplpaJNjq9kQgJUNX7QwmWpW88Kbizmsl78bsULRvHH9CF+TeWYqZQ0Pn1iN1DoXDwBck57wnHlAFEz59t5XeBDhERhSTvUCgYEAzmhpebtZ6By9cg8ZPraEHwiUgMeFclHrA6TslkFcV2vqjdwMctTxmQxjFaWI5gtCZcBgyZb7tHAVvB9uZUMnyaPv+lWQa3kHrYfdSqyjmXi1b2TERmrxZw4/mPWmNjJIb86Kp4vNZYS/Z1PWUpBByYSYC173OS6dZ0lTaLiQ5QkCgYEAw0BpQxDCv51ErULuuqhyEHJRNGwiAo5KFPgWK3OtDBjgT5mO1FjGjtoz3ffmJa5rQrYEw46QAyu7toFs4a7z/7ybZCiPi844a8eyXiUOIpmoQJCky9sf8fqGjXFgp1pwXUV4QpEbB7Bks1KXUQTeygehLcyQPRGMFBs6XU12F5kCgYEAx2C2Un1ZjpTB95nBLJGZJ2OSO+XDHj6bsBWmTdftO3eIxYFpvIa3zdo0KCM2P696sr0uVYCPkumX9bbvN6S29SiHJ3LG0uRzekhejQ/c3N3nWejIrnyt5+NjVTLPHz73rOt/l24icZ4KvDIt/L4sLjh6u+RgU8lVM1bjvlWvH1Y=
# 支付宝公钥 RSA2密钥(推荐) 配置好并启动会生成
app.publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnoG2pJdwQcaszrfnijYr2O87HiAnXjN+/+iSvnrihG5uR0v3Lh/EY+gGb3H2q2udmrobGm73VNdttLB7KJWbXIYaufsN2RmbdzouKG6OSx4Wcsfx4Mr3+VdlOkbBHltw4gBP0Si0kA76nD5Phdzn77miBawrPCr9siQNZLHh87NMMjY59Dm4dyV/ukIYG1XpUviIshzbAKDMJAfDOZqU+lUlVph9v+aG860oCAeP0TL3mum58VeWdaq5cE4iN3GIYa6DmTy9jJZ6eRtUIjX1fqgYf9hidT01g287ZOgE4OJpGsMSMf41O2zqKSzSVBRk3lcxPBej1Lftnmy+dJRbWQIDAQAB
#异步返回地址必须是公网 http://r48qbv.natappfree.cc/ali/callBack
app.notifyUrl: http://r48qbv.natappfree.cc/ali/callBack
#支付成功返回
app.returnUrl: http://localhost:9090/ali/return
app.signType: RSA2
app.charset: utf-8
# 支付宝网关
#app.gatewayUrl: https://openapi.alipaydev.com/gateway.do
app.gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do