引言:为什么选择Spring AI及MCP协议对接支付宝

大家好,我是小冬瓜。在数字化时代,支付渠道对接是每个订单系统的核心痛点。传统开发中,调用支付宝API需要繁琐的签名、参数校验和错误处理,耗时耗力。想象一下,如果对接支付渠道像和AI助手对话一样简单,会怎样?Spring AI结合MCP(Model Context Protocol)让这一切成为现实!传统支付对接的复杂性(如手动处理支付宝API的签名、回调验证等)与企业对快速上线的需求矛盾。通过Spring AI Agent和支付宝MCP,开发者可以像调用自然语言接口一样完成支付功能,降低开发门槛,提升效率。 本文将带你实战Spring AI与支付宝MCP,学习如何用Spring AI构建智能Agent,通过MCP协议无缝对接支付宝,打造智能订单系统,让支付对接如丝般顺滑。

技术背景:Spring AI、MCP和Agent的核心概念

Spring AI:Spring AI是Spring官方推出的AI开发框架,支持大模型集成(如DeepSeek、Claude)和MCP协议,提供统一的API接口,简化AI与外部工具的交互。

MCP协议:MCP(Model Context Protocol)是由Anthropic提出的标准化协议,类似“AI世界的USB接口”,让大模型通过统一接口调用外部服务(如支付宝支付API)。它解决了数据孤岛和重复开发问题。

Spring AI Agent的作用:Agent是大模型的“智能代理”,通过MCP协议,Spring AI Agent可以自动调用支付宝服务,完成支付、查询、退款等操作,无需手动编码复杂逻辑。

实战场景:基于Spring AI的订单系统对接支付宝

业务场景:设计一个电商订单系统,用户下单通过支付宝支付后,系统自动验证支付状态并更新订单。

演示效果

agent-order演示

系统模块:

  • order-agent: Spring AI Agent,负责解析用户意图,调用MCP Client发起支付请求。

  • mcp-server-order:自定义MCP Server,负责本地订单业务逻辑

  • mcp-server-alipay:支付宝MCP服务,支付渠道

实现步骤:手把手带你对接支付宝MCP

准备工作: 申请支付宝开放平台参数

  • 登录支付宝开放平台创建网页/移动应用,完成相关配置并上线。开通手机网站支付或者电脑网站支付产品

  • 调用MCP服务还需要在支付宝开放平台申请MCP场景受限密钥

  • 我是个人开发者,没有商户资质,申请使用的沙箱环境参数。

  • 将获取的参数在Modalscope中配置为MCP sse服务。(在springai中使用stdio方式调用支付宝mcp服务会有些问题,对参数限制也比较死,这里踩了好多坑,最后配置为sse服务才调通)

依赖配置,在pom.xml中引入Spring AI、MCP相关依赖。

mcp-server-order/pom.xml

   <dependencies>
    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
  </dependencies>

order-agent/pom.xml

    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

mcp-server-order具体代码

application.yml

spring:
  ai:
    mcp:
      server:
        name: mcp-server-order
        version: 0.0.1
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/demodb?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: xgourd
    password: xgourd123
#sse方式需要启动web
server:
  port: 8081
# stdio方式需要加一下配置项禁用web     
#  main:
#    banner-mode: off
#    web-application-type: none
#logging:
#  pattern:
#    console: ''

MCP Server工具类

/**
 * @author 任海东
 * @since 2025年7月10日
 */
@Service
@Slf4j
@AllArgsConstructor
public class OrderService {
​
  private final OrderRepository orderRepository;
​
  @AllArgsConstructor
  @Getter
  enum State {
    /**
     * 等待支付中
     */
    WAITING("0"),
    /**
     * 已取消
     */
    CANCEL("1"),
    /**
     * 已支付
     */
    PAYED("2"),
    /**
     * 已退款
     */
    REFUND("3"),
    /**
     * 已超时
     */
    TIMEOUT("4");
​
    private final String code;
  }
​
  /**
   * 模拟某软件商品三种套餐及价格
   */
  private static final Map<String, BigDecimal> PKGS = Map.of("1", BigDecimal.valueOf(9.9), "2",
      BigDecimal.valueOf(29.9), "3", BigDecimal.valueOf(99.9));
​
  @Tool(description = "根据客户购买的套餐,本地生成一笔待支付订单")
  public Order createOrder(@ToolParam(description = "客户手机号") final String phoneNo,
      @ToolParam(description = "购买套餐的数字编号") final String pkgNo) {
    return orderRepository.save(new Order().setOrderNo(System.currentTimeMillis() + "").setProductNo(pkgNo)
        .setOrderAmount(PKGS.get(pkgNo)).setCustomerId(phoneNo).setCreateTime(new Date())
        .setOrderStatus(State.WAITING.getCode()));
  }
​
  @Tool(description = "完成本地订单,更新本地订单状态为已支付, 并记录支付宝交易号")
  public void complete(@ToolParam(description = "本地订单号,即商户订单号") final String orderNo,
      @ToolParam(description = "支付宝订单号") final String alipayTradeNo) {
    final Order order = orderRepository.findByOrderNo(orderNo).orElseThrow();
    orderRepository.save(
        order.setOrderStatus(State.PAYED.getCode()).setAlipayTradeNo(alipayTradeNo).setUpdateTime(new Date()));
  }
​
  @Tool(description = "取消本地订单,更新本地订单状态为已取消")
  public void cancel(final String orderNo) {
    final Order order = orderRepository.findByOrderNo(orderNo).orElseThrow();
    orderRepository.save(order.setOrderStatus(State.CANCEL.getCode()).setUpdateTime(new Date()));
  }
​
  @Tool(description = "发生退款,更新本地订单状态为已退款")
  public void refund(final String orderNo) {
    final Order order = orderRepository.findByOrderNo(orderNo).orElseThrow();
    orderRepository.save(order.setOrderStatus(State.REFUND.getCode()).setUpdateTime(new Date()));
  }
}

工具注册

  @Bean
  public ToolCallbackProvider dataTool(final OrderService orderService) {
    return MethodToolCallbackProvider.builder().toolObjects(orderService).build();
  }

Agent具体代码

application.yml

spring:
  application:
    name: order-agent
  ai:
    dashscope:
      api-key: ${DASHSCOPE_API_KEY}
      chat:
        options:
          model: deepseek-v3
    mcp:
      client:
#        stdio:
#          servers-configuration: classpath:mcp-servers.json
        sse:
          connections:
            ali:
              url: https://mcp.api-inference.modelscope.net
              sse-endpoint: /cb8d2f1aad9341/sse
            order:
              url: http://localhost:8081
        toolcallback:
          enabled: false
logging:
  level:
    '[io.modelcontextprotocol.client]': debug
    '[io.modelcontextprotocol.spec]': debug

入口代码

/**
 * @author 任海东
 * @since 2025年7月10日
 */
@SpringBootApplication
@RestController
@Slf4j
public class AgentApplication {
​
  private final ChatClient chatClient;
​
  /**
   * @param args
   */
  public static void main(final String[] args) {
    SpringApplication.run(AgentApplication.class, args);
  }
​
  /**
   * 初始化chatClient
   *
   * @param mcpClients
   * @param builder
   */
  public AgentApplication(final List<McpSyncClient> mcpClients, final ChatClient.Builder builder) {
    this.chatClient = builder.defaultToolCallbacks(new SyncMcpToolCallbackProvider(mcpClients)).build();
  }
​
  /**
   * 客户下单
   *
   * @param phone    客户手机号
   * @param pkgNo    选择的套餐
   * @param response
   */
  @PostMapping("/buy")
  public void buy(@RequestParam final String phone, @RequestParam final String plan,
      final HttpServletResponse response) {
    final String prompt = """
        请根据用户输入信息: 手机号: %s, 套餐号: %s
        1. 生成一笔本地订单;
        2. 将订单号、订单金额、订单主题<套餐n:选择的套餐对应的名称>[1-基础套餐、2-专业套餐、3-尊享套餐]作为参数生成支付宝订单,将支付链接<https://xxx>返回;
        3. 输出格式:key为url的可解析的json字符串,eg: {"url":"https://xxx"}
        4. 请注意url的提取末尾不含括号,输出json字符串末尾不含"]";
        """.formatted(phone, plan);
    final String resp = chatClient.prompt(prompt).call().content().replace("```json", "").replace("```", "");
    log.info("生成订单响应: {}", resp);
    final String url = JSON.parseObject(resp).getString("url");
    log.info("支付链接: {}", url);
    try {
      response.sendRedirect(url);
    } catch (final IOException e) {
      log.error("重定向失败", e);
      try {
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "重定向失败");
      } catch (final IOException ioException) {
        log.error("发送错误响应失败", ioException);
      }
    }
  }
​
  /**
   *
   * @param params
   * @return
   */
  @GetMapping("/callback")
  public String callback(@RequestParam final Map<String, String> params) {
    log.info("订单回调: {}", params);
    // 这里最好还有验签逻辑,回调更新
    final String prompt = """
        根据回调参数: %s,完成本地订单
        1. 将本地订单状态更新为已支付,并记录支付宝交易号;
        2. 请注意本地订单号是out_trade_no, 支付宝交易号是trade_no
        """.formatted(JSON.toJSONString(params));
    return chatClient.prompt(prompt).call().content();
  }
​
}

结论:开始你的Spring AI支付之旅

总结:通过Spring AI Agent和支付宝MCP,支付对接从繁琐的API调用变为自然语言般的简单交互,极大降低了开发难度。

行动号召:立即尝试Spring AI,用MCP对接支付宝,打造属于你的智能订单系统!

资源推荐

Spring AI官方文档:Spring AI

MCP协议介绍:MCP 简介 - MCP 中文文档

支付宝开放平台:支付宝开放平台

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐