Spring Boot 集成支付宝 SDK 实现支付功能(完整版)

现代电商系统中,在线支付模块是不可或缺的一部分。支付宝作为中国最大的第三方支付平台之一,提供了丰富的 SDK 和接口,支持多种支付场景和模式。本文将基于 Spring Boot 和支付宝 EasySDK,详细介绍如何开发一个功能完善的支付模块。


目录


一、前置准备

1. 环境搭建

确保以下环境已安装:

  • JDK 1.8 以上(推荐 11)
  • Spring Boot 2.x 项目框架
  • Maven 或 Gradle 用于构建项目
  • MySQL/PostgreSQL 数据库用于保存订单和支付记录

2. 支付宝开放平台配置

2.1 创建应用
  1. 登录 支付宝开放平台
  2. 在"我的应用"页面,点击"创建应用",填写基本信息。
  3. 获取 App ID
2.2 配置密钥
  1. 生成 RSA2 公私钥对(推荐使用支付宝提供的工具)。
  2. 将公钥上传到支付宝开放平台。
  3. 保存私钥到本地,并妥善管理。
2.3 配置回调地址
  1. 在支付宝开放平台的应用详情中,找到"接口加签和回调配置"。
  2. 配置异步通知回调地址和同步通知(页面跳转)地址。
2.4 测试环境
  • 使用支付宝沙箱环境测试支付流程:沙箱环境入口
  • 通过沙箱测试账号完成支付测试。

二、支付模块功能设计

模块架构

├── config          # 支付宝配置类
├── controller      # API 控制器
├── service         # 支付核心业务逻辑
├── util            # 工具类(如签名验证、日志等)
└── repository      # 数据库操作

功能划分

  1. 支付接口:发起支付请求,生成支付页面链接。
  2. 支付状态查询:根据订单号实时查询支付状态。
  3. 异步通知处理:接收支付宝异步通知并验证签名。
  4. 退款接口:支持全额或部分退款。
  5. 账单下载:获取支付宝对账单,便于对账。
  6. 邮件通知:支付完成后发送确认邮件。

三、支付模块核心功能实现

1. 支付宝配置类

创建一个 AlipayConfig 类,集中管理支付宝相关配置:

java 复制代码
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AlipayConfig {
    private String appId;
    private String privateKey;
    private String publicKey;
    private String notifyUrl;
    private String returnUrl;
    private String gatewayUrl = "https://openapi.alipay.com/gateway.do"; // 正式环境
}

application.yml 中添加支付宝配置:

yaml 复制代码
alipay:
  app-id: "your_app_id"
  private-key: "your_private_key"
  public-key: "your_alipay_public_key"
  notify-url: "https://yourdomain.com/pay/callback"
  return-url: "https://yourdomain.com/pay/success"

2. 支付接口开发

支付接口用于生成支付页面链接。实现如下:

java 复制代码
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/pay")
public class PayController {

    @Autowired
    private AlipayConfig alipayConfig;

    @GetMapping("/create")
    public String createPayment(@RequestParam String orderId, @RequestParam Double amount) {
        try {
            Factory.setOptions(Factory.createOptions()
                .setAppId(alipayConfig.getAppId())
                .setPrivateKey(alipayConfig.getPrivateKey())
                .setAlipayPublicKey(alipayConfig.getPublicKey())
                .setNotifyUrl(alipayConfig.getNotifyUrl())
                .setReturnUrl(alipayConfig.getReturnUrl()));

            AlipayTradePagePayResponse response = Factory.Payment.Page().pay(
                "商品标题",  // 商品标题
                orderId,     // 商户订单号
                String.valueOf(amount), // 金额
                alipayConfig.getReturnUrl()
            );
            return response.getBody(); // 返回支付页面
        } catch (Exception e) {
            throw new RuntimeException("支付接口调用失败", e);
        }
    }
}

3. 支付状态查询

java 复制代码
@GetMapping("/status/{orderId}")
public String queryStatus(@PathVariable String orderId) {
    try {
        return Factory.Payment.Common().query(orderId).getHttpBody();
    } catch (Exception e) {
        return "查询失败:" + e.getMessage();
    }
}

4. 异步通知处理

java 复制代码
@PostMapping("/callback")
public String handleCallback(HttpServletRequest request) {
    Map<String, String> params = new HashMap<>();
    request.getParameterMap().forEach((key, values) -> params.put(key, values[0]));
    try {
        boolean verified = Factory.Payment.Common().verifyNotify(params);
        if (verified) {
            // 处理订单逻辑
            String orderId = params.get("out_trade_no");
            String tradeStatus = params.get("trade_status");
            if ("TRADE_SUCCESS".equals(tradeStatus)) {
                // 更新订单状态为已支付
            }
            return "success";
        } else {
            return "failure";
        }
    } catch (Exception e) {
        return "failure";
    }
}

5. 退款接口

实现部分退款功能:

java 复制代码
@PostMapping("/refund")
public String refund(@RequestParam String orderId, @RequestParam Double refundAmount) {
    try {
        return Factory.Payment.Common().refund(orderId, String.valueOf(refundAmount)).getHttpBody();
    } catch (Exception e) {
        return "退款失败:" + e.getMessage();
    }
}

6. 账单下载

获取支付宝对账单:

java 复制代码
@GetMapping("/download-bill")
public String downloadBill(@RequestParam String billDate) {
    try {
        return Factory.Payment.Common().downloadBill(billDate).getHttpBody();
    } catch (Exception e) {
        return "下载失败:" + e.getMessage();
    }
}

四、安全性优化与异常处理

  1. 签名验证:验证回调中的签名,确保数据未被篡改。
  2. HTTPS 配置:强制使用 HTTPS,保护用户数据。
  3. 日志监控:记录支付相关日志,方便问题排查。

五、高级扩展

1. 支付分账

  • 支持平台将支付款项分账到多个子商户。
  • 示例接口:
java 复制代码
@PostMapping("/split")
public String splitPayment(@RequestParam String orderId, @RequestBody List<Map<String, String>> receivers) {
    try {
        return Factory.Payment.Common().createSplit(orderId, receivers).getHttpBody();
    } catch (Exception e) {
        return "分账失败:" + e.getMessage();
    }
}

2. 多商户支持

  • 使用多套密钥和配置管理多个商户。
  • 动态加载商户配置。

3. 国际支付

  • 支持外币支付,通过支付宝国际支付接口完成。

六、测试与部署

1. 沙箱环境测试

  • 使用沙箱账号完成支付、退款、回调等流程测试。

2. 部署注意事项

  • 配置防火墙和 DDOS 保护。
  • 确保密钥和配置文件安全。

七、总结

本文完整实现了基于 Spring Boot 的支付宝支付模块,包括支付、退款、查询、分账和账单下载功能。在生产环境中,建议对系统的安全性和稳定性进行全面优化。通过本文,您可以快速集成支付宝支付模块并进行扩展开发。

相关推荐
yuanbenshidiaos30 分钟前
c++---------数据类型
java·jvm·c++
向宇it34 分钟前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
Lojarro1 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
莫名其妙小饼干1 小时前
网上球鞋竞拍系统|Java|SSM|VUE| 前后端分离
java·开发语言·maven·mssql
isolusion1 小时前
Springboot的创建方式
java·spring boot·后端
Yvemil72 小时前
《开启微服务之旅:Spring Boot Web开发举例》(一)
前端·spring boot·微服务
zjw_rp2 小时前
Spring-AOP
java·后端·spring·spring-aop
Oneforlove_twoforjob2 小时前
【Java基础面试题033】Java泛型的作用是什么?
java·开发语言
TodoCoder2 小时前
【编程思想】CopyOnWrite是如何解决高并发场景中的读写瓶颈?
java·后端·面试
向宇it2 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎