Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot + MyBatis 集成支付宝支付流程

核心流程
  1. 商户系统生成订单
  2. 调用支付宝创建预支付订单
  3. 用户跳转支付宝完成支付
  4. 支付宝异步通知支付结果
  5. 商户处理支付结果更新订单状态
  6. 支付宝同步跳转回商户页面

代码实现示例(电脑网站支付)

1. 添加依赖
xml 复制代码
<!-- pom.xml -->
<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- MyBatis & MySQL -->
    <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>
    </dependency>
    
    <!-- 支付宝SDK -->
    <dependency>
        <groupId>com.alipay.sdk</groupId>
        <artifactId>alipay-sdk-java</artifactId>
        <version>4.35.0.ALL</version>
    </dependency>
    
    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>
2. 支付宝配置类
java 复制代码
@Configuration
public class AlipayConfig {

    @Value("${alipay.app_id}")
    private String appId;
    
    @Value("${alipay.merchant_private_key}")
    private String merchantPrivateKey;
    
    @Value("${alipay.alipay_public_key}")
    private String alipayPublicKey;
    
    @Value("${alipay.notify_url}")
    private String notifyUrl;
    
    @Value("${alipay.return_url}")
    private String returnUrl;
    
    @Value("${alipay.gateway_url}")
    private String gatewayUrl;
    
    @Value("${alipay.sign_type}")
    private String signType;
    
    @Value("${alipay.charset}")
    private String charset;

    @Bean
    public AlipayClient alipayClient() {
        return new DefaultAlipayClient(
            gatewayUrl,
            appId,
            merchantPrivateKey,
            "json",
            charset,
            alipayPublicKey,
            signType
        );
    }
}
3. 实体类和Mapper
java 复制代码
// 订单实体
@Data
public class Order {
    private Long id;
    private String orderNo;   // 商户订单号
    private BigDecimal amount;// 支付金额
    private Integer status;   // 0-待支付, 1-已支付
    private LocalDateTime createTime;
}

// MyBatis Mapper
@Mapper
public interface OrderMapper {
    @Insert("INSERT INTO orders(order_no, amount, status, create_time) " +
            "VALUES(#{orderNo}, #{amount}, 0, NOW())")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    void insert(Order order);
    
    @Update("UPDATE orders SET status = #{status} WHERE order_no = #{orderNo}")
    void updateStatus(@Param("orderNo") String orderNo, @Param("status") int status);
}
4. 支付服务类
java 复制代码
@Service
public class PayService {

    @Autowired private AlipayClient alipayClient;
    @Autowired private OrderMapper orderMapper;
    @Value("${alipay.return_url}") private String returnUrl;
    @Value("${alipay.notify_url}") private String notifyUrl;

    // 创建支付订单
    public String createPayOrder(Order order) throws AlipayApiException {
        orderMapper.insert(order); // 保存订单到数据库
        
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setReturnUrl(returnUrl);
        request.setNotifyUrl(notifyUrl);
        
        // 构造业务参数
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", order.getOrderNo());
        bizContent.put("total_amount", order.getAmount());
        bizContent.put("subject", "商品支付");
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY"); // 电脑网站支付
        
        request.setBizContent(bizContent.toString());
        
        return alipayClient.pageExecute(request).getBody();
    }

    // 处理异步通知
    public boolean handleNotify(Map<String, String> params) throws AlipayApiException {
        // 1. 验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(
                params,
                alipayPublicKey,  // 注入支付宝公钥
                charset,
                signType
        );
        
        if (!signVerified) return false;

        // 2. 验证交易状态
        String tradeStatus = params.get("trade_status");
        if (!"TRADE_SUCCESS".equals(tradeStatus)) return false;

        // 3. 更新订单状态
        String orderNo = params.get("out_trade_no");
        orderMapper.updateStatus(orderNo, 1); // 更新为已支付
        
        return true;
    }
}
5. 控制器
java 复制代码
@RestController
@RequestMapping("/pay")
public class PayController {

    @Autowired private PayService payService;

    // 创建支付订单
    @PostMapping("/create")
    public String createOrder(@RequestParam BigDecimal amount) 
        throws AlipayApiException {
        
        Order order = new Order();
        order.setOrderNo(UUID.randomUUID().toString().replace("-", ""));
        order.setAmount(amount);
        
        return payService.createPayOrder(order); // 返回支付页面表单
    }

    // 支付宝异步通知(需公网可访问)
    @PostMapping("/notify")
    public String alipayNotify(HttpServletRequest request) 
        throws UnsupportedEncodingException, AlipayApiException {
        
        Map<String, String> params = parseRequestParams(request);
        boolean success = payService.handleNotify(params);
        return success ? "success" : "failure"; // 通知支付宝处理结果
    }

    // 支付宝同步跳转
    @GetMapping("/return")
    public String alipayReturn(HttpServletRequest request) {
        // 简单展示支付结果(实际需要验签和状态检查)
        return "支付完成!订单号:" + request.getParameter("out_trade_no");
    }

    // 解析请求参数
    private Map<String, String> parseRequestParams(HttpServletRequest request) {
        // 转换参数Map(参考支付宝示例代码)
    }
}
6. 配置文件
properties 复制代码
# application.properties
# 支付宝配置
alipay.app_id=2021000123456789
alipay.merchant_private_key=MIIEvQIBADANB...
alipay.alipay_public_key=MIIBIjANBgkq...
alipay.notify_url=http://your-domain.com/pay/notify
alipay.return_url=http://your-domain.com/pay/return
alipay.gateway_url=https://openapi.alipay.com/gateway.do
alipay.sign_type=RSA2
alipay.charset=UTF-8

# MySQL配置
spring.datasource.url=jdbc:mysql://localhost:3306/alipay_demo
spring.datasource.username=root
spring.datasource.password=123456

关键流程说明

  1. 生成商户订单

    • 生成唯一订单号(推荐雪花算法)
    • 保存订单到数据库(状态=待支付)
  2. 调用支付宝接口

    • 使用 AlipayTradePagePayRequest 构建请求
    • 关键参数:订单号、金额、支付标题、回调地址
  3. 接收异步通知

    • 必须验证签名(防止伪造请求)
    • 检查 trade_status 是否为 TRADE_SUCCESS
    • 更新订单状态(注意处理幂等性)
  4. 安全注意事项

    • 支付金额需与订单金额比对(防止金额篡改)
    • 敏感操作记录日志
    • 异步通知处理需要保证幂等性
  5. 扩展功能

    • 订单超时关闭:定时任务扫描未支付订单
    • 支付结果查询:通过 trade_no 调用支付宝查询接口
    • 退款功能:使用 AlipayTradeRefundRequest

提示:实际开发中需要:

  1. 替换为正式支付宝账户
  2. 配置公网可访问的域名
  3. 添加完整的错误处理
  4. 实现参数解析工具方法
  5. 添加数据库事务管理
相关推荐
lang201509282 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
刘一说4 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
提笔了无痕4 小时前
什么是Redis的缓存问题,以及如何解决
数据库·redis·后端·缓存·mybatis
lang201509285 小时前
Spring Boot缓存机制全解析
spring boot·后端·缓存
摇滚侠5 小时前
Spring Boot 3零基础教程,WEB 开发 默认页签图标 Favicon 笔记29
java·spring boot·笔记
lang201509285 小时前
Spring Boot SQL数据库全攻略
数据库·spring boot·sql
是梦终空7 小时前
计算机毕业设计241—基于Java+Springboot+vue的爱心公益服务系统(源代码+数据库+11000字文档)
java·spring boot·vue·毕业设计·课程设计·毕业论文·爱心公益系统
泉城老铁10 小时前
springboot 对接发送钉钉消息,消息内容带图片
前端·spring boot·后端
qq_124987075310 小时前
基于Spring Boot的高校实习实践管理系统(源码+论文+部署+安装)
java·spring boot·后端·毕业设计
韩宁羽10 小时前
SpringBoot开发双11商品服务系统[完结19章]
spring boot