Spring Boot 集成金蝶 API 演示

✨ Spring Boot 集成金蝶 API 演示:登录 / 注销 + Cookie 保存

本文将通过 Spring Boot 完整实现一套金蝶接口集成模型,包括:

  • ✅ 普通登录
  • ✅ AppSecret 登录
  • ✅ 注销
  • ✅ Cookie 保存与复用

项目结构

src/
├── controller/
│   └── KingdeeController.java         // API 接口
├── service/
│   ├── KingdeeService.java            // 登录/注销逻辑
├── component/
│   └── KingdeeSessionManager.java     // Cookie 管理
├── resources/
│   └── static/pages/kingdee.html      // 前端测试页

✨ 1. Cookie 保存组件 KingdeeSessionManager

package org.example.component;

import org.springframework.stereotype.Component;

import java.util.List;

/**
 * ==================================================
 * This class KingdeeSessionManager is responsible for [功能描述].
 *
 * @author Darker
 * @version 1.0
 * ==================================================
 */

@Component
public class KingdeeSessionManager {

    private String cookie;

    public void saveFromHeaders(List<String> cookies) {
        if (cookies != null && !cookies.isEmpty()) {
            // 可扩展支持多个 Cookie,但这里我们只取第一个
            this.cookie = cookies.get(0);
        }
    }

    public String getCookie() {
        return this.cookie;
    }

    public boolean hasCookie() {
        return cookie != null && !cookie.isEmpty();
    }

    public void clear() {
        this.cookie = null;
    }
}

✨ 2. 金蝶服务层 KingdeeService

package org.example.service;

import org.example.component.KingdeeSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * ==================================================
 * This class KingdeeService is responsible for 金蝶 API 服务.
 *
 * @author Darker
 * @version 2.0
 * ==================================================
 */
@Service
public class KingdeeService {

    private static final String BASE_URL = "https://your.kingdee.server/K3Cloud";

    @Autowired
    private KingdeeSessionManager sessionManager;

    private ResponseEntity<String> postWithOptionalCookie(String url, Map<String, Object> payload, boolean withCookie) {
        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        if (withCookie && sessionManager.hasCookie()) {
            headers.add("Cookie", sessionManager.getCookie());
        }

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(payload, headers);
        return restTemplate.postForEntity(url, request, String.class);
    }

    /**
     * 普通登录
     */
    public String login() {
        String url = BASE_URL + "/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc";

        Map<String, Object> payload = new HashMap<>();
        payload.put("parameters", new Object[]{
                "你的数据中心 ID", "你的用户名", "你的密码", 2052
        });

        ResponseEntity<String> response = postWithOptionalCookie(url, payload, false);

        // 记录 Cookie
        sessionManager.saveFromHeaders(response.getHeaders().get(HttpHeaders.SET_COOKIE));
        return response.getBody();
    }

    /**
     * AppSecret 登录
     */
    public String loginByAppSecret() {
        String url = BASE_URL + "/Kingdee.BOS.WebApi.ServicesStub.AuthService.LoginByAppSecret.common.kdsvc";

        Map<String, Object> payload = new HashMap<>();
        payload.put("parameters", new Object[]{
                "你的数据中心 ID",                             // 数据中心 ID
                "你的用户名",                                  // 用户名
                "你的 AppID",    							  // AppID
                "你的 AppSecret",           				  // AppSecret
                2052
        });

        ResponseEntity<String> response = postWithOptionalCookie(url, payload, false);
        sessionManager.saveFromHeaders(response.getHeaders().get(HttpHeaders.SET_COOKIE));
        return response.getBody();
    }

    /**
     * 注销:需要携带 Cookie
     */
    public String logout() {
        String url = BASE_URL + "/Kingdee.BOS.WebApi.ServicesStub.AuthService.Logout.common.kdsvc";

        Map<String, Object> payload = new HashMap<>();
        payload.put("parameters", new Object[]{});

        ResponseEntity<String> response = postWithOptionalCookie(url, payload, true);

        // 如果注销成功(返回 true),则清除本地 cookie
        if ("true".equalsIgnoreCase(response.getBody().trim())) {
            sessionManager.clear();
        }

        return response.getBody();
    }
}

✨ 3. Controller 接口 KingdeeController

package org.example.controller;

import org.example.service.KingdeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.util.UriComponentsBuilder;

/**
 * ==================================================
 * This class KingdeeController is responsible for [功能描述].
 *
 * @author Darker
 * @version 1.0
 * ==================================================
 */

@RestController
@RequestMapping("/kingdee")
public class KingdeeController {
    @Autowired
    private KingdeeService kingdeeService;

    @GetMapping("/login")
    public ResponseEntity<?> login() {
        try {
            String result = kingdeeService.login();
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().body("登录失败:" + e.getMessage());
        }
    }

    @GetMapping("/logout")
    public ResponseEntity<?> logout() {
        try {
            String result = kingdeeService.logout();
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().body("注销失败:" + e.getMessage());
        }
    }

    @GetMapping("/login-app-secret")
    public ResponseEntity<?> loginByAppSecret() {
        try {
            String result = kingdeeService.loginByAppSecret();
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().body("AppSecret 登录失败:" + e.getMessage());
        }
    }
}

✨ 4. 前端测试页 kingdee.html

DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>金蝶 API 测试title>
  <script>
    async function callApi(endpoint) {
      const res = await fetch(`/kingdee/${endpoint}`);
      const text = await res.text();
      document.getElementById('result').innerText = `[${endpoint}]:\n` + text;
    }
  script>
head>
<body>
  <h2>金蝶 API 测试h2>
  <button onclick="callApi('login')">普通登录button>
  <button onclick="callApi('login-app-secret')">AppSecret 登录button>
  <button onclick="callApi('logout')">注销button>
  <pre id="result">pre>
body>
html>

⚠️ Cookie 保存说明

  • 登录成功后,金蝶服务器会通过 Set-Cookie 头返回一个会话ID
  • 后续操作(注销 / 探量 / 单据传递)必须附带 Cookie
  • 本文中通过 KingdeeSessionManager 自动管理 Cookie,无需手动处理

金蝶 API 官方开发文档

官方开放平台:

  • 【K3Cloud Web API】总览:https://open.kingdee.com
  • 登录接口说明:https://open.kingdee.com/doc/view?doc_id=1055
  • App ID / Secret 说明:https://open.kingdee.com/doc/view?doc_id=1297
  • 提交单据示例:https://open.kingdee.com/doc/view?doc_id=1061

扩展方向

  • ✉ 增加 callKingdeeService(String serviceName, Object[] parameters) 通用调用方法
  • ✔ 支持查询单据 / 提交审核 / 操作单据
  • 将登录状态持久化到 Redis

你可能感兴趣的:(前端开发,后端开发,个人经验,spring,boot,后端,java)