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 的支付宝支付模块,包括支付、退款、查询、分账和账单下载功能。在生产环境中,建议对系统的安全性和稳定性进行全面优化。通过本文,您可以快速集成支付宝支付模块并进行扩展开发。

相关推荐
空の鱼3 小时前
java开发,IDEA转战VSCODE配置(mac)
java·vscode
!!!5254 小时前
日志技术-LogBack入门程序&Log配置文件&日志级别
spring boot
P7进阶路4 小时前
Tomcat异常日志中文乱码怎么解决
java·tomcat·firefox
Ai 编码助手5 小时前
在 Go 语言中如何高效地处理集合
开发语言·后端·golang
小丁爱养花5 小时前
Spring MVC:HTTP 请求的参数传递2.0
java·后端·spring
CodeClimb5 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
等一场春雨5 小时前
Java设计模式 九 桥接模式 (Bridge Pattern)
java·设计模式·桥接模式
Channing Lewis5 小时前
什么是 Flask 的蓝图(Blueprint)
后端·python·flask
带刺的坐椅5 小时前
[Java] Solon 框架的三大核心组件之一插件扩展体系
java·ioc·solon·plugin·aop·handler
不惑_6 小时前
深度学习 · 手撕 DeepLearning4J ,用Java实现手写数字识别 (附UI效果展示)
java·深度学习·ui