金蝶K3 Cloud WebAPI接口说明书:异构系统对接与实战避坑指南
发布时间:2026/9/29 4:07:46来源:尧图网络
简介这份《K3 Cloud WebAPI接口说明书_V4.0》面向金蝶云星空K3 Cloud二次开发人员、云计算应用开发者及第三方系统集成工程师用于解决企业系统对接中接口调用、参数传递与错误处理等实际问题。文档围绕Kingdee.BOS.WebApi.FormService、ServicesStub、Client三个核心组件展开系统讲解WebAPI架构、技术规范与开发工具并逐一说明登录验证、查看表单数据、保存与批量保存、提交、审核、反审核、删除等接口的定义、参数与返回值同时给出接口调用失败、错误信息处理与性能优化的常见策略。资源包为1个docx文档约101KB共34页目录结构清晰便于按模块查阅。目前已有1162人学习下载适合需要快速上手金蝶云星空接口集成、对照官方规范排查问题的开发者参考。1. 异构系统对接 K3 Cloud这份 34 页的 WebAPI 说明书到底能省多少事做过金蝶 K/3Cloud 集成的都清楚最头疼的不是写代码而是找不到一份能直接照着调的接口文档。官方社区帖子散、SDK 示例少、字段标识全靠猜一个保存接口的表体更新逻辑能折腾一整天。这份《K3 Cloud WebAPI 接口说明书_V4.0》一共 34 页覆盖了从登录验证到分组保存共 15 个接口的完整参数说明和调用示例适用版本标注为 V5.0 及后续版本。它解决的核心问题是让异构系统OA、CRM、MES、WMS通过 HTTPJSON 的方式读写 K/3Cloud 的单据和基础资料不用装金蝶客户端不用引用一堆 DLL。适合谁正在做 ERP 集成开发的 .NET 工程师、需要对接金蝶云星空的第三方系统开发者以及被字段标识和参数格式反复折磨的一线实施。2. WebAPI 架构拆解三个 DLL 各管什么什么时候可以不引用2.1 组装件分工与部署位置说明书第 4 章把整个 WebAPI 框架拆成三个组装件这个划分直接决定了你的调用方式组装件职责部署位置是否必须拷贝到客户端Kingdee.BOS.WebApi.FormService.dll接口功能实现应用层服务器否Kingdee.BOS.WebApi.ServicesStub.dll接口定义、扩展接口、登录验证应用层服务器否Kingdee.BOS.WebApi.Client.dll客户端调用封装异构系统客户端C# 程序需要非 C# 不需要服务端两个 DLL 由 K/3Cloud 环境自带你不需要动。关键在第三个如果你的异构系统是 C# 写的引用Kingdee.BOS.WebApi.Client.dll后可以用ApiClient类登录、调用一行搞定如果是 Java、Python 或其他语言完全不需要这个 DLL直接用 HTTP 请求走.common.kdsvc后缀的通用接口就行。技术栈方面说明书明确写了 HTTPJSON、RESTful 风格、.NET Framework 4.0、C# 编写、开发工具 VS2012。这意味着接口本身对调用方语言没有限制只要你能发 POST 请求、能解析 JSON 就能用。2.2 两种调用方式的选型逻辑说明书在每个接口的调用参考里都给了两套示例这个设计很务实。选哪套取决于你的技术栈和部署环境SDK 辅助类方式适合 C# 项目代码量少登录状态由ApiClient实例维护。但有个硬约束Kingdee.BOS.WebApi.Client.dll必须拷贝到你的客户端环境而且版本要和服务端匹配。我一般会在项目里单独建一个 lib 目录放这个 DLL避免不同项目引用不同版本导致玄学问题。无引用组件方式适合非 C# 项目或者你不想在客户端部署金蝶 DLL 的场景。核心是自己实现一个 HttpClient 辅助类处理 Cookie 保持、请求体封装和响应解析。说明书第 7 到 9 页给出了完整的 C# 实现关键点有三个一是用静态CookieContainer保证登录后所有请求持有同一个会话二是请求体必须包含format、useragent、rid、parameters、timestamp、v六个字段三是响应如果以response_error:开头需要截掉前缀再解析。// 无引用组件方式的核心请求封装摘自说明书示例加注释说明 public string AsyncRequest() { HttpWebRequest httpRequest HttpWebRequest.Create(Url) as HttpWebRequest; httpRequest.Method POST; httpRequest.ContentType application/json; httpRequest.CookieContainer Cookie; // 静态变量保证会话不丢 httpRequest.Timeout 1000 * 60 * 10; // 10分钟大批量操作时别改小 using (Stream reqStream httpRequest.GetRequestStream()) { JObject jObj new JObject(); jObj.Add(format, 1); // 固定值 jObj.Add(useragent, ApiClient); // 固定值 jObj.Add(rid, Guid.NewGuid().ToString().GetHashCode().ToString()); // 请求唯一标识 jObj.Add(parameters, Content); // 业务参数数组的 JSON 序列化结果 jObj.Add(timestamp, DateTime.Now); jObj.Add(v, 1.0); // 接口版本 string sContent jObj.ToString(); var bytes UnicodeEncoding.UTF8.GetBytes(sContent); reqStream.Write(bytes, 0, bytes.Length); reqStream.Flush(); } // ... 读取响应并处理 response_error 前缀 }参数说明format和useragent是协议约定值不要改rid用哈希值即可主要用来排查日志parameters是实际业务参数的序列化数组每个接口不同timestamp和v按格式填就行。超时时间设了 10 分钟批量保存几百行分录时这个值很关键设短了直接超时翻车。3. 核心接口实战登录、查看、保存、提交、审核的完整调用链3.1 登录验证接口与 LoginResultType 返回值处理登录是所有接口的前置。服务地址格式为http://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc四个参数acctID账套 ID、username、password、lcid语言 ID中文 2052英文 1033繁体 3076。账套 ID 从管理中心数据库查select FDATACENTERID from T_BAS_DATACENTER。这个 SQL 说明书直接给了省得你去翻数据库字典。返回值里最关键的是LoginResultType说明书列了完整的枚举值返回值含义处理建议1登录成功正常执行业务-5需要表单处理管理员登录可能出现API 验证时可视为允许-3密码验证不通过强制必须处理不能跳过-2密码验证不通过可选根据业务决定是否放行-1登录失败检查网络和服务状态0用户或密码错误检查凭据-4登录警告记录日志-6云通行证未绑定需要绑定操作-7激活账号未激活说明书特别提醒-5的情况在 API 验证时也可认为是允许的具体根据实际情况定。我一般会在登录封装里把1和-5都当作成功处理但-5会额外记一条日志方便后续排查。// SDK 方式登录 ApiClient client new ApiClient(http://192.168.66.60/k3cloud/); string dbId 5756960b27b1aa; bool bLogin client.Login(dbId, demo, 888888, 2052); if (bLogin) { /* 登录成功client 实例可直接调后续接口 */ } // 无引用方式登录 HttpClient httpClient new HttpClient(); httpClient.Url http://192.168.66.60/k3cloud/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc; Listobject Parameters new Listobject(); Parameters.Add(558cbb01bfc79b); // 账套 Id Parameters.Add(Administrator); Parameters.Add(888888); Parameters.Add(2052); httpClient.Content JsonConvert.SerializeObject(Parameters); var iResult JObject.Parse(httpClient.AsyncRequest())[LoginResultType].Valueint(); if (iResult 1 || iResult -5) { /* 验证成功 */ }3.2 查看与保存接口的参数结构查看接口DynamicFormService.View需要两个参数formid表单标识如IV_SALESIC表示发票和dataJSON 字符串包含Number或Id以及可选的CreateOrgId。Id和Number任选一个CreateOrgId非必须。保存接口DynamicFormService.Save的参数结构复杂得多也是踩坑最多的地方。核心参数formid业务对象标识如SAL_OUTSTOCK销售出库单、BD_Currency币别data数据包 JSON包含Creator、NeedUpDateFields、IsDeleteEntry、NeedReturnFields、IsVerifyBaseDataField、IsEntryBatchFill、ModelModel里字段用元素标识识别单据头直接写子单据头用SubHeadEntity单据体用中括号数组// 保存销售出库单新增 string sFormId SAL_OUTSTOCK; string sContent {\Creator\:\\,\NeedUpDateFields\:[],\Model\:{ \FID\:\0\, \FStockOrgId\:{\FNumber\:\210\}, // 库存组织用编码 \FBillTypeID\:{\FNumber\:\XSCKD01_SYS\}, // 单据类型 \FBillNo\:\CSDGBC21002\, \FCustomerID\:{\FNumber\:\CUST0073\}, // 客户用编码 \SubHeadEntity\:{\FExchangeRate\:6.51}, // 子单据头汇率 \FEntity\:[ // 单据体数组 {\FEntryID\:\0\,\FMATERIALID\:{\FNumber\:\03.001\},\FStockID\:{\FNumber\:\CK002\},\FRealQty\:324,\FBaseUnitQty\:324}, {\FEntryID\:\0\,\FMATERIALID\:{\FNumber\:\03.001\},\FStockID\:{\FNumber\:\CK004\},\FRealQty\:220,\FBaseUnitQty\:220} ]}}; object[] saveInfo new object[] { sFormId, sContent }; var ret client.Executestring(Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save, saveInfo);关键参数说明FID为0表示新增FEntryID为0表示新增分录基础资料字段用{FNumber:编码}格式引用SubHeadEntity是子单据头不是所有单据都有FEntity是单据体的集合标识不同单据的单据体标识不同需要查对应表单的元数据。3.3 更新单据表体的主键逻辑说明书第 12 页专门用了一个例子讲更新场景这是最容易翻车的地方。更新内码为100017的单据要保留原有100024和100025两行新增两行删除其他分录string sFormId STK_MISCELLANEOUS; // 其他入库单 string sContent {\Creator\:\\,\NeedUpDateFields\:[],\Model\:{ \FID\:\100017\, // 更新必须填主键 \FEntity\:[ {\FEntryID\:\100024\}, // 只填主键 保留该行 {\FEntryID\:\100025\}, // 只填主键 保留该行 {\FMATERIALID\:{\FNumber\:\A.0060480933\},\FUnitID\:{\FNumber\:\03\},\FSTOCKID\:{\FNumber\:\PRTSH\},\FQty\:\200\,\FBASEQTY\:\200\,\FPlanAmount\:\132856\,\FBASEUNITID\:{\FNumber\:\03\},\FEntryNOTE\:\2015-7-29\,\FAmount\:\132856\,\FPRICE\:\664.28\}, {\FMATERIALID\:{\FNumber\:\A.0060480933\},\FUnitID\:{\FNumber\:\03\},\FSTOCKID\:{\FNumber\:\PRTSH\},\FQty\:\200\,\FBASEQTY\:\200\,\FPlanAmount\:\132856\,\FBASEUNITID\:{\FNumber\:\03\},\FEntryNOTE\:\2015-7-29\,\FAmount\:\132856\,\FPRICE\:\664.28\} ]}};逻辑很明确有FEntryID的视为更新没有的视为新增源单中有但请求里没出现的分录会被删除。说明书原文是“如果不填写将会删除源单的表体而没有主键的数据会视为新增有明细主键的视为更新”。这个规则如果不注意一次更新就能把客户的分录全删了血泪经验。3.4 提交、审核、反审核、删除的调用要点这四个接口的参数结构比保存简单核心就是formiddata包含Numbers或Ids数组// 提交 var submitRet client.Executestring(Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit, new object[] { SAL_OUTSTOCK, {\Numbers\:[\CSDGBC21002\]} }); // 审核 var auditRet client.Executestring(Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit, new object[] { SAL_OUTSTOCK, {\Numbers\:[\CSDGBC21002\]} }); // 反审核 var unauditRet client.Executestring(Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnAudit, new object[] { SAL_OUTSTOCK, {\Numbers\:[\CSDGBC21002\]} }); // 删除 var deleteRet client.Executestring(Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Delete, new object[] { SAL_OUTSTOCK, {\Numbers\:[\CSDGBC21002\]} });注意约束数据操作接口仅支持以基础资料编码、单据编号或表单主键去操作数据。多单关联查询需要二开接口实现标准接口不支持。4. 批量保存与查询接口数据量大时怎么不超时、不丢数据4.1 批量保存接口的参数与性能边界批量保存BatchSave和单条保存的参数结构基本一致区别在于data是一个数组可以一次提交多条单据。说明书第 13 页开始描述这个接口但实际使用时有几个性能边界需要自己把握单次批量提交的单据数量建议控制在 50 条以内每条单据的分录行数不超过 200 行。超过这个量级即使超时设了 10 分钟也可能出现部分成功部分失败的情况。更稳妥的做法是分批提交每批 20 到 30 条记录每批的返回结果失败的单独重试。// 批量保存data 是数组每个元素是一条单据的完整 JSON string sFormId SAL_OUTSTOCK; string sContent [{\Creator\:\\,\NeedUpDateFields\:[],\Model\:{...单据1...}}, {\Creator\:\\,\NeedUpDateFields\:[],\Model\:{...单据2...}}]; object[] saveInfo new object[] { sFormId, sContent }; var ret client.Executestring(Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BatchSave, saveInfo);返回参数里SuccessEntitys数组包含成功记录的Id、Number和DIndex原始数据行号Errors数组包含失败原因。拿到返回后一定要遍历Errors不能只看IsSuccess就完事。4.2 查询接口的字段选择与分页查询接口ExecuteBillQuery的参数结构和保存完全不同需要指定FormId、FieldKeys、FilterString、OrderString、TopRowCount、StartRow、Limitstring sFormId SAL_OUTSTOCK; string sContent {\FormId\:\SAL_OUTSTOCK\, \FieldKeys\:\FBillNo,FDate,FCustomerID.FName,FRealQty\, // 字段标识逗号分隔 \FilterString\:\FDate2024-01-01\, // 过滤条件 \OrderString\:\FDate DESC\, \TopRowCount\:0, // 0 表示不限制 \StartRow\:0, // 起始行 \Limit\:100}; // 每页条数 var ret client.Executestring(Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery, new object[] { sFormId, sContent });FieldKeys里引用基础资料字段用点号如FCustomerID.FName。Limit设太大响应会慢一般 100 到 500 比较合适配合StartRow做分页。TopRowCount和Limit同时存在时以较小的为准。4.3 自定义 WebAPI 接口的扩展方式说明书第 23 页开始讲自定义接口这是标准接口不够用时的出口。自定义接口需要继承Kingdee.BOS.WebApi.ServicesStub里的基类实现自己的业务逻辑然后部署到应用层服务器。调用方式和标准接口一样只是服务地址里的类名和方法名换成你自己的。常见做法是标准接口能覆盖的用标准接口覆盖不了的比如多单关联查询、复杂业务校验才写自定义接口。自定义接口的调试比标准接口麻烦建议先在 VS 里本地跑通再部署。5. 避坑与排查登录返回 -5、保存丢分录、查询超时的真实处理记录5.1 登录返回 -5 到底算不算成功现象用管理员账号调登录接口LoginResultType返回 -5后续接口调用正常。原因说明书第 6 页明确写了“管理员登陆可能出现返回 -5 的情况这种情况在 api 验证时也可认为是允许的”。-5 对应DealWithForm意思是需要表单处理通常是密码策略或首次登录提示。解决在登录封装里把1和-5都当作成功但 -5 额外记日志。如果业务要求严格可以在管理中心调整管理员账号的密码策略避免返回 -5。5.2 更新单据时表体分录被全部删除现象调保存接口更新一张已有单据只改了单据头字段结果表体所有分录都没了。原因更新时Model里没有传FEntity数组或者传了空数组。说明书第 11 页原文“更新单据时表体信息必须填写明细表体的主键如果不填写将会删除源单的表体”。解决更新单据前先调 View 接口拿到完整的表体数据把需要保留的分录主键填回去只填主键不填其他字段就表示保留。或者用NeedUpDateFields明确指定要更新的字段避免冗余字段覆盖源数据。5.3 批量保存部分成功部分失败现象批量提交 100 条单据返回IsSuccess为 false但SuccessEntitys里有 80 条成功记录。原因批量接口不是事务性的每条单据独立处理。失败的原因可能是基础资料编码不存在、必填字段缺失、单据编号重复等。解决遍历Errors数组按DIndex定位到原始数据行号逐条修正后重试。不要因为IsSuccess为 false 就全部重提会导致成功的单据重复创建。5.4 查询接口返回数据不完整现象查询销售出库单返回的记录数比预期少。原因Limit参数设了默认值或者FilterString里的日期格式不对。K/3Cloud 的日期过滤需要用yyyy-MM-dd格式不能用yyyy/MM/dd。解决显式设置Limit为需要的条数StartRow从 0 开始分页拉取。日期格式统一用yyyy-MM-dd。如果还是不对检查当前登录账号有没有对应单据的查看权限。5.5 非 C# 环境调用时 Cookie 丢失现象用 Python 或 Java 调登录接口成功但调后续接口返回未登录。原因登录接口返回的 Cookie 没有在后续请求中带上。K/3Cloud 的会话靠 Cookie 维持不是靠 Token。解决用requests.Session()Python或HttpClient的CookieContainerC#保持会话。每次请求都带上登录后拿到的 Cookie。如果中间隔了很长时间Cookie 可能过期需要重新登录。6. 从说明书到生产我封装 K3Cloud 客户端的几个习惯说明书给的是接口定义和示例但直接拿示例代码上生产还差一层封装。我一般会做三件事第一把登录逻辑单独抽成一个K3CloudClient类构造函数里完成登录后续所有接口调用都复用这个实例。登录失败时抛明确异常不要返回 bool 让调用方猜。第二给每个接口写一个方法参数用强类型对象而不是裸 JSON 字符串。比如SaveBill(string formId, object model)内部序列化调用方不用手拼 JSON。这样字段名写错了编译期就能发现不用等到运行时。第三所有接口调用统一加日志记录请求参数、响应结果、耗时。K/3Cloud 的报错信息有时候很模糊比如只返回“保存失败”不说什么字段的问题有日志才能定位。// 我常用的封装骨架 public class K3CloudClient { private ApiClient _client; private string _serverUrl; public K3CloudClient(string serverUrl, string acctId, string user, string pwd, int lcid 2052) { _serverUrl serverUrl; _client new ApiClient(serverUrl); if (!_client.Login(acctId, user, pwd, lcid)) throw new Exception($K3Cloud 登录失败: {user}{serverUrl}); } public string Save(string formId, object model) { var data new { Creator , NeedUpDateFields new string[] { }, Model model }; var json JsonConvert.SerializeObject(data); var sw Stopwatch.StartNew(); try { var ret _client.Executestring( Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save, new object[] { formId, json }); return ret; } finally { sw.Stop(); // 记录 formId、耗时、请求和响应 } } }验证封装是否可靠我一般会跑一个最小闭环登录 → 查一张已有单据 → 保存一张新单据 → 提交 → 审核 → 反审核 → 删除。每一步检查返回的ResponseStatus.IsSuccess和Errors全部通过才算封装没问题。这个闭环跑通一次后面接业务逻辑就踏实了。从那以后我每次对接新的 K/3Cloud 环境都强制先跑一遍这个最小闭环确认接口通、权限够、字段标识对再开始写业务代码。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网