.NetCore对接各大财务软件凭证API——金蝶系列(1)

哈喽,又和大家见面了,虽然看文章的小伙伴不多,但是我相信总有一天,自己写的这些文章或多或少会对其他人有些帮助,让他们在相关的业务开发下能少走些弯路,那我的目的就达到了,好了,今天就正式开始我们的系列了,今天要讲的是金蝶系列的API,大家都知道,金蝶的产品是比较多的,那么我们这次要讲解的就是金蝶云星空,或者叫K3Cloud。

首先,作为一名程序猿我们在拿到类似的接口对接需求,第一件是肯定是看相关文档,然后做接口分析,最后是封装接口,运用到我们的项目中去,所以对于我们来说,第一步就是寻找相关的开发文档,在这方面不得不承认,金蝶社区是个好地方。里面有关于产品的所有知识点和大家遇到的各种问题。废话不多说,文档哪里找,请看下面的步骤

一.K3Cloud接口地址以及财务环境的登录信息

我们在做.netCore对接财务系统时,要用到的几个参数有:账套号,用户名,密码,财务环境地址(支持外网访问)

这个信息你可以找你对接的客户要,最好是能要到外网登录的地址,因为这样省去你远程登录的麻烦,其次,账号的权限也很重要,该账号下必须能看到名为-- WebAPI的菜单,因为我们需要的接口信息包括后续的测试等都可以在这里处理。如下图所示

二.对接要用到的接口列表

既然将凭证API,那么我们需要用到的几个菜单在财务会计--总账下:主要有科目查询接口、凭证字查询接口、凭证新增接口

每个操作我们都可以通过在线测试WebAPI来验证我们的接口信息,查询接口的请求参数说明详见下图

1.唯一码的FormId

FormId为每个业务对象的表单Id,如科目对应的就是BD_Account,这里建议我们在开发时,可以提前将这些用到的表单ID统一设置为常量。参考以下代码片段,当然实际开发中我们可能用不到这么多,大家根据自己的情况进行合理的取舍。

public class BillKeyConst
    {
        #region 财务会计 总账 

​        public const string 科目 = "BD_Account";

​        public const string 帐薄 = "BD_AccountBook";

​        public const string 会计日历 = "BD_ACCOUNTCALENDAR";

​        public const string 会计要素 = "BD_AccountGroup";

​        public const string 币别 = "BD_Currency";

​        public const string 费用项目 = "BD_Expense";

​        public const string 汇率 = "BD_Rate";

​        public const string 结算方式 = "BD_SETTLETYPE";

​        public const string 凭证字 = "BD_VOUCHERGROUP";

​        public const string 调整期间管理 = "GL_ADJUSTPERIOD";

​        public const string 自动转账 = "GL_AutoTransfer";

​        public const string 现金流量项目 = "GL_CashFlow";

​        public const string 附表项目指定 = "GL_CashIndirectItem";

​        public const string 智能转存 = "GL_DepositScheme";

​        public const string 期末调汇 = "GL_ExchangeScheme";

​        public const string 摘要库 = "GL_Explanation";

​        public const string 附表项目调整 = "GL_INDIRECTITEMADJUST";

​        public const string 帐薄隶属关系 = "GL_MultiBookMergeScheme";

​        public const string 结转损益 = "GL_PLScheme";

​        public const string T型账 = "GL_TACCOUNT";

​        public const string 凭证 = "GL_VOUCHER";

​        public const string 凭证摊销 = "GL_VoucherAmortize";

​        public const string 模式凭证 = "GL_VoucherModel";

​        public const string 凭证预提 = "GL_VoucherProvision";

​        public const string 会计核算体系 = "Org_AccountSystem";

​        #endregion

​        #region 财务会计 智能会计平台

​        public const string 业务凭证 = "BAS_BusinessVoucher";

​        public const string 凭证生成 = "Bas_MakeBizVchWizard";

​        public const string 分录类型 = "BAS_VchEntryType";

​        public const string 凭证模板 = "BAS_VchTemplate";

​        public const string 增值税发票单据 = "GL_AddedTaxBill";

​        public const string 增值税发票识别 = "GL_AddedTaxOcrResult";

​        public const string 凭证自动生成方案 = "GL_AutoBuildVoucherScheme";

​        public const string 扫描识别模板管理 = "GL_BillOcrTemplate";

​        public const string 对账方案 = "GL_CHECKSCHEME";

​        public const string 自定义单据识别 = "GL_OcrResultBase";

​        public const string 扫描仪注册登记 = "GL_ScannerSign";

​        public const string 银行回单_付款 = "GL_YHHDFK";

​        public const string 银行回单_收款 = "GL_YHHDSK";

​        #endregion

​        #region 供应链 采购单据

​        public const string SCM_警示灯方案 = "SCM_WarnScheme";

​        public const string BD_采购条款 = "BD_PURCLAUSE";

​        public const string BD_采购折扣表 = "BD_PurDiscount";

​        public const string PUR_评估等级 = "PUR_Assessment";

​        public const string PUR_采购评估指标 = "PUR_AssessmentIndex";

​        public const string PUR_采购评估方案 = "PUR_AssessmentPlans";

​        public const string PUR_货源清单 = "PUR_CATALOG";

​        public const string PUR_采购合同 = "PUR_Contract";

​        public const string PUR_采购合同变更单 = "PUR_ContractChange";

​        public const string PUR_期初采购退料单 = "PUR_InitMRS";

​        public const string PUR_退料申请单 = "PUR_MRAPP";

​        public const string PUR_采购退料单 = "PUR_MRB";

​        public const string PUR_采购调价表 = "PUR_PAT";

​        public const string PUR_采购定价变更单 = "PUR_POChange";

​        public const string PUR_采购定价新变更单 = "PUR_POXChange";

​        public const string PUR_采购价目表 = "PUR_PriceCategory";

​        public const string PUR_物权转移单 = "PUR_PropertyConvert";

​        public const string PUR_采购订单 = "PUR_PurchaseOrder";

​        public const string PUR_收料通知单 = "PUR_ReceiveBill";

​        public const string PUR_采购申请单 = "PUR_Requisition";

​        public const string PUR_供应商评分表 = "PUR_SupplierAsseementTb";

​        public const string PUR_消耗汇总表 = "PUR_VMIConsumeSum";

​        public const string STK_期初采购入库单 = "STK_InitInStock";

​        public const string STK_采购入库单 = "STK_InStock";

​        #endregion

​        #region 供应链 销售管理

​        public const string BD_云之家考勤设置 = "BD_AttendanceSetting";

​        public const string BD_轻应用自定义字段设置 = "BD_MobExtendFieldConfig";

​        public const string BD_销售折扣表 = "BD_SAL_DiscountList";

​        public const string BD_销售价目表 = "BD_SAL_PriceList";

​        public const string BD_销售条款 = "BD_SALCLAUSE";

​        public const string SAL_销售调价方案 = "SAL_ADJUSTPRICE";

​        public const string SAL_可发量查询 = "SAL_AvailableQuery";

​        public const string SAL_批量调价单 = "SAL_BATCHADJUSTPRICE";

​        public const string SAL_寄售结算单 = "SAL_ConsignmentSettle";

​        public const string SAL_客户物料对应表 = "SAL_CustMatMapping";

​        public const string SAL_发货通知单 = "SAL_DELIVERYNOTICE";

​        public const string SAL_期初销售出库单 = "SAL_INITOUTSTOCK";

​        public const string SAL_电子面单 = "SAL_KuaidiBill";

​        public const string SAL_销售物流信息 = "SAL_LogisticsInfo";

​        public const string SAL_销售出库单 = "SAL_OUTSTOCK";

​        public const string SAL_销售报价单 = "SAL_QUOTATION";

​        public const string SAL_退货通知单 = "SAL_RETURNNOTICE";

​        public const string SAL_销售退货单 = "SAL_RETURNSTOCK";

​        public const string SAL_销售订单 = "SAL_SaleOrder";

​        public const string SAL_销售订单变更单 = "SAL_SaleOrderChange";

​        public const string SAL_模拟报价单 = "Sal_SimulateQuotation";

​        public const string SAL_标准费率维护 = "Sal_StdExchangeRate";

​        public const string SAL_销售订单新变更单 = "SAL_XORDER";

​        public const string SAL_销售报价变更单 = "SAL_XQUOTATION";

​        #endregion

​        #region 供应链 信用管理

​        public const string CRE_信用检查规则 = "CRE_CheckRule";

​        public const string CRE_信用表更 = "CRE_CreditChange";

​        public const string CRE_信用总额特批 = "CRE_CreditSumPermit";

​        public const string CRE_信用档案 = "CRE_CustArchives";

​        public const string CRE_客户物料信用档案 = "CRE_CustMaterialArchive";

​        public const string CRE_信用评估模型 = "CRE_EvalModel";

​        public const string CRE_信用评估指标 = "CRE_EvaluateIndex";

​        public const string CRE_信用等级方案 = "CRE_Gade";

​        public const string CRE_信用评分表 = "CRE_ScoringTable";

​        public const string CRE_信用特批权限 = "CRE_SpecPermission";

​        public const string CRE_临时信用档案 = "CRE_TmpCustArchives";

​        #endregion

​        #region 供应链 库存管理

​        public const string BD_归档序列号 = "BD_ArchivedSerial";

​        public const string BD_批号主档 = "BD_BatchMainFile";

​        public const string BD_批号_序列号属性 = "BD_LotCodeItem";

​        public const string BD_批号_序列号编码规则 = "BD_LotCodeRule";

​        public const string BD_生产追溯序列号主档 = "BD_MTSerialMainFile";

​        public const string BD_序列号主档 = "BD_SerialMainFile";

​        public const string BD_仓库 = "BD_STOCK";

​        public const string BD_仓库最大最小安全库存 = "BD_StockAlert";

​        public const string BD_库存状态 = "BD_StockStatus";

​        public const string SP_简单生成入库单 = "SP_InStock";

​        public const string SP_简单生成退库单 = "SP_OUTSTOCK";

​        public const string SP_简单生成领料单 = "SP_PickMtrl";

​        public const string SP_简单生成退料单 = "SP_ReturnMtrl";

​        public const string STK_组装拆卸单 = "STK_AssembledApp";

​        public const string STK_周期盘点计划 = "STK_CycleCountPlan";

​        public const string BD_物料周期盘点表 = "STK_CycleCountTable";

​        public const string STK_即时库存 = "STK_Inventory";

​        public const string STK_初始库存 = "STK_InvInit";

​        public const string STK_库存锁库 = "STK_LockStock";

​        public const string STK_锁库日志 = "STK_LOCKSTOCKLOG";

​        public const string STK_批号调整单 = "STK_LOTADJUST";

​        public const string STK_ABC分配组 = "STK_MaterialABCGroup";

​        public const string STK_其他入库单 = "STK_MISCELLANEOUS";

​        public const string STK_其他出库单 = "STK_MisDelivery";

​        public const string STK_委托加工材料入库单 = "STK_OEMInStock";

​        public const string STK_委托加工材料退料单 = "STK_OEMInStockRETURN";

​        public const string STK_委托加工材料收料单 = "STK_OEMReceive";

​        public const string STK_出库申请单 = "STK_OutStockApply";

​        public const string STK_形态转换单 = "STK_StatusConvert";

​        public const string STK_库存状态转换 = "STK_StockConvert";

​        public const string STK_盘盈单 = "STK_StockCountGain";

​        public const string STK_物料盘点作业 = "STK_StockCountInput";

​        public const string STK_盘亏单 = "STK_StockCountLoss";

​        public const string STK_盘点方案 = "STK_StockCountScheme";

​        public const string STK_调拨申请单 = "STK_TRANSFERAPPLY";

​        public const string STK_直接调拨单 = "STK_TransferDirect";

​        public const string STK_分布式调入单 = "STK_TRANSFERIN";

​        public const string STK_分布式调出单 = "STK_TRANSFEROUT";

​        #endregion

​        #region 供应链  组织间结算

​        public const string IOS_应付结算清单_物料 = "IOS_APSettlement";

​        public const string IOS_应付结算清单_费用 = "IOS_APSettlementExp";

​        public const string IOS_应付结算清单_资产 = "IOS_APSettlementFA";

​        public const string IOS_应收结算清单_物料 = "IOS_ARSettlement";

​        public const string IOS_应收结算清单_费员 = "IOS_ARSettlementExp";

​        public const string IOS_应收结算清单_资产 = "IOS_ARSettlementFA";

​        public const string IOS_组织间结算价目表 = "IOS_PriceList";

​        public const string IOS_定时结算 = "IOS_ScheduleSettle";

​        public const string IOS_组织间结算关系 = "IOS_SettleRelation";

​        public const string IOS_跨组织业务类型 = "IOS_TransferBizType";

​        #endregion

​        #region 供应链 条码管理

​        public const string BD_异步生成数据 = "BD_AsyncBillScanData";

​        public const string BD_条码盘点清单 = "BD_BarcodeInventoryData";

​        public const string BD_条码属性 = "BD_BarCodeItem";

​        public const string BD_条码主档 = "BD_BarCodeMainFile";

​        public const string BD_条码打印 = "BD_BarCodePrint";

​        public const string BD_条码规则 = "BD_BarCodeRule";

​        public const string BD_条码扫描 = "BD_BarCodeScan";

​        public const string BD_条码拆分 = "UN_BarCodeSplit";

​        public const string BD_物料编码解析对应表 = "UN_MaterialMap";

​        public const string BD_条码拆箱表 = "UN_Packaging";

​        public const string BD_扫描配置 = "UN_SCAN";

​        public const string BD_扫描记录 = "UN_SCANRecordSet";

​        public const string BD_条码扫描任务 = "UN_SCANTASK";

​        public const string BD_条码扫描任务生成日志 = "UN_SCANTASKCREATELOG";

​        public const string BD_条码扫描任务方案 = "UN_SCANTASKSCHEME";

​        #endregion

​        #region 供应链 供应商管理

​        public const string SVM_企业公告 = "SVM_BusinessBulletin";

​        public const string SVM_比价单 = "SVM_ComparePrice";

​        public const string SVM_询价单 = "SVM_InquiryBill";

​        public const string SVM_报价单 = "SVM_QuoteBill";

​        public const string SVM_供应商角色 = "SVM_Role";

​        public const string SVM_供应商用户 = "SVM_SUPPLIERUSER";

​        #endregion

​        #region 供应链 供应商协同

​        public const string SCP_供应商协同条码打印 = "SCP_BarCodePrint";

​        public const string SCP_供应商协同条码扫描 = "SCP_BarCodeScan";

​        public const string SCP_企业公告 = "SCP_BusinessBulletin";

​        public const string SCP_询价单 = "SCP_InquiryBill";

​        public const string SCP_采购入库单 = "SCP_InStock";

​        public const string SCP_退料通知单 = "SCP_MRAPP";

​        public const string SCP_采购退料单 = "SCP_MRB";

​        public const string SCP_应付单 = "SCP_Payable";

​        public const string SCP_采购订单变更单 = "SCP_POChange";

​        public const string SCP_采购订单 = "SCP_PurchaseOrder";

​        public const string SCP_报价单 = "SCP_QuoteBill";

​        public const string SCP_送货通知单 = "SCP_ReceiveBill";

​        public const string SCP_供应商协同即时库存查询 = "SCP_STKInventory";

​        public const string SCP_供应商评估报告 = "SCP_SupplierAssResport";

​        public const string SCP_供应商注册资料 = "SCP_SupReg";

​        public const string SCP_供应商协同VMI消耗汇总表 = "SCP_VMIConsumeSum";

​        #endregion

​        #region 基础管理--基础资料

​        public const string 关键字_智能机器人 = "BAS_ROBOTKEYWORDS";

​        public const string 消息任务_智能机器人 = "BAS_ROBOTMSGTASK";

​        public const string 关键字服务_智能机器人 = "BAS_ROBOTSERVICE";

​        public const string 会计政策 = "BD_ACCTPOLICY";

​        public const string 辅助属性值组合 = "BD_AuxPtyValCom";

​        public const string 辅助属性值 = "BD_AuxPtyValue";

​        public const string 银行 = "BD_BANK";

​        public const string 联系对象 = "BD_ContactObject";

​        public const string 客户 = "BD_Customer";

​        public const string 客户_包含非交易客户 = "BD_Customer_All";

​        public const string 部门 = "BD_Department";

​        public const string 员工 = "BD_Empinfo";

​        public const string 快递100物流公司 = "BD_KD100LogisticsCom";

​        public const string 物料 = "BD_MATERIAL";

​        public const string 存货类别 = "BD_MATERIALCATEGORY";

​        public const string 存货模板 = "BD_MATERIALTEMPLATE";

​        public const string 物料单位换算 = "BD_MATERIALUNITCONVERT";

​        public const string 员工任岗信息 = "BD_NEWSTAFF";

​        public const string 业务员 = "BD_OPERATOR";

​        public const string 业务组 = "BD_OPERATORGROUPBILL";

​        public const string 付款条件 = "BD_PaymentCondition";

​        public const string 岗位汇报 = "BD_PostReport";

​        public const string 收款条件 = "BD_RecCondition";

​        public const string 供应商 = "BD_Supplier";

​        public const string 税组合 = "BD_TAXMIX";

​        public const string 税率 = "BD_TaxRate";

​        public const string 税务规则 = "BD_TAXRULE";

​        public const string 税收制度 = "BD_TAXSYSTEM";

​        public const string 税种 = "BD_TAXTYPE";

​        public const string 计量单位 = "BD_UNIT";

​        public const string 银行账号 = "CN_BANKACNT";

​        public const string 现金账号 = "CN_CASHACCOUNT";

​        public const string 内部账户 = "CN_INNERACCOUNT";

​        public const string 其他往来单位 = "FIN_OTHERS";

​        public const string 岗位信息 = "HR_ORG_HRPOST";

​        #endregion

​        #region 基础管理--组织管理

​        public const string 组织隶属关系 = "ORG_Affiliation";

​        public const string 分配执行情况 = "ORG_AutoAllocateLogInfo";

​        public const string 基础资料自动分配计划 = "ORG_AUTOALLOCATEPLAN";

​        public const string 基础资料控制策略 = "ORG_BaseDataControlPolicy";

​        public const string 组织业务关系 = "ORG_BizRelation";

​        public const string 组织变更检查规则 = "ORG_ChangeChkRule";

​        public const string 组织变更方案 = "ORG_ChangeSolution";

​        public const string 组织机构 = "ORG_Organizations";

​        public const string 组织形态 = "ORG_OrgBodyForm";

​        public const string 组织用户维护 = "Org_OrgUserRoleMap";

​        #endregion
​    }

View Code

2.查询字段集合

FieldKeys为要查询的字段Key集合,如我需要查询的字段有FName,FNumber等,详细的字段说明可以通过保存接口查看

那么我们只需要传入FName,FNumber即可。

3.返回结果的处理

返回的结果是个数组类型,所以我们无法直接通过.net序列化为对象,所以建议是直接序列化为JArry数组,然后进行取值。

三. .NetCore对接处理

3.1登录以及业务接口处理

有了以上的对接参数和简单的接口信息了解之后,我们就可以开始我们的API接口对接工作了,

首先,在社区一位大佬封装的WebAPI的基础上,我们来处理.netCore环境下的WebAPI接口,非常感谢大佬,我们可以看到封装的接口文件如下图所示:

常用的有Query、BatchSave类,如下图所示

Query操作

/// <summary>
    /// 执行查询操作。
    /// </summary>
    public class Query : FormOperation
    {
        #region 公共覆盖操作参数

        /// <summary>
        /// 操作的服务名称定义。
        /// </summary>
        public override string ServiceName
        {
            get
            {
                return "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery";
            }
        }//end property

        /// <summary>
        /// 操作的请求参数。
        /// </summary>
        public override string RequestParameters
        {
            get
            {
                var parametersArray = new object[]
                {
                    new
                    {
                        FormId = this.ObjectTypeId,
                        TopRowCount = this.TopRowCount,
                        Limit = this.PageRowCount == default(int) ? 2000 : this.PageRowCount,
                        StartRow = this.PageIndex,
                        FilterString = this.Filter,
                        OrderString = this.OrderBy,
                        FieldKeys = string.Join(",", this.FieldKeys)
                    }
                };

                return JsonConvert.SerializeObject(parametersArray);
            }
        }//end property

        #endregion

        #region 公共操作参数属性

        /// <summary>
        /// 读写最多允许查询的数量属性值。
        /// </summary>
        /// <remarks>
        /// 0或者不要此属性表示不限制。
        /// </remarks>
        public virtual int TopRowCount { get; set; }//end property

        /// <summary>
        /// 读写分页取数每页允许获取的数据属性值。
        /// </summary>
        /// <remarks>
        /// 最大不能超过2000。
        /// </remarks>
        public virtual int PageRowCount { get; set; }//end property

        /// <summary>
        /// 读写分页取数开始行索引属性值。
        /// </summary>
        /// <remarks>
        /// 从0开始,例如每页10行数据,第2页开始是10,第3页开始是20,以此类推,当不提供此属性,表示仅查询Limit中填写的数据量。
        /// </remarks>
        public virtual int PageIndex { get; set; }//end property

        /// <summary>
        /// 读写过滤条件属性值。
        /// </summary>
        public virtual string Filter { get; set; }//end property

        /// <summary>
        /// 读写排序条件属性值。
        /// </summary>
        public virtual string OrderBy { get; set; }//end property

        /// <summary>
        /// 读写表单返回数据字段的索引键属性值。
        /// </summary>
        public virtual List<string> FieldKeys { get; set; }//end property

        #endregion

        #region 公共方法

        /// <summary>
        /// 设置读写动态表单类型标识。
        /// </summary>
        /// <param name="objectTypeId">动态表单类型标识。</param>
        /// <returns>返回类本身实例对象。</returns>
        public virtual Query SetObjectTypeId(string objectTypeId)
        {
            return this.SetObjectTypeId<Query>(objectTypeId);
        }//end method

        /// <summary>
        /// 设置最多允许查询的单据数量。
        /// </summary>
        /// <param name="topRowCount">单据数量值。</param>
        /// <returns>返回类本身实例对象。</returns>
        public virtual Query SetTopRowCount(int topRowCount)
        {
            this.TopRowCount = topRowCount;
            return this;
        }//end method

        /// <summary>
        /// 设置分页取数每页允许获取的单据数量。
        /// </summary>
        /// <param name="pageRowCount">分页数量值。</param>
        /// <returns>返回类本身实例对象。</returns>
        public virtual Query SetPageRowCount(int pageRowCount)
        {
            this.PageRowCount = pageRowCount;
            return this;
        }//end method

        /// <summary>
        /// 设置分页取数开始行索引。
        /// </summary>
        /// <param name="pageIndex">索引值。</param>
        /// <returns>返回类本身实例对象。</returns>
        public virtual Query SetPageIndex(int pageIndex)
        {
            this.PageIndex = pageIndex;
            return this;
        }//end method

        /// <summary>
        /// 设置过滤条件。
        /// </summary>
        /// <param name="filter">过滤条件。</param>
        /// <returns>返回类本身实例对象。</returns>
        public virtual Query SetFilter(string filter)
        {
            this.Filter = filter;
            return this;
        }//end method

        /// <summary>
        /// 设置排序条件。
        /// </summary>
        /// <param name="orderBy">排序条件。</param>
        /// <returns>返回类本身实例对象。</returns>
        public virtual Query SetOrderBy(string orderBy)
        {
            this.OrderBy = orderBy;
            return this;
        }//end method

        /// <summary>
        /// 表单返回数据字段。
        /// </summary>
        /// <param name="fieldKey">字段索引键。</param>
        /// <returns>返回类本身实例对象。</returns>
        public virtual Query AddFieldKey(string fieldKey)
        {
            if (this.FieldKeys == null)
            {
                this.FieldKeys = new List<string>();
            }//end if

            this.FieldKeys.Add(fieldKey);
            return this;
        }//end method

        #endregion

    }//end class

View Code

BatchSave操作,主要用于凭证的批量保存

/// <summary>
    /// 执行批量保存操作。
    /// </summary>
    public class BatchSave : Save
    {
        #region 公共覆盖操作参数

        /// <summary>
        /// 操作的服务名称定义。
        /// </summary>
        public override string ServiceName
        {
            get
            {
                return "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BatchSave";
            }
        }//end property

        /// <summary>
        /// 待保存的数据对象。
        /// </summary>
        public override string RequestParameters
        {
            get
            {
                var parametersArray = new object[]{
                    this.ObjectTypeId,
                    new
                    {
                        Creator = string.IsNullOrEmpty(this.Creator) ? "IT" : this.Creator ,
                        NeedUpDateFields = this.NeedUpdateFieldKeys,
                        NeedReturnFieldKeys=this.NeedReturnFieldKeys,
                        Model = this.Models,
                        IsEntryBatchFill=this.IsEntryBatchFill,
                        IsDeleteEntry = this.IsDeleteEntry,
                        SubSystemId = this.SubSystemId,
                        IsAutoSubmitAndAudit=this.IsAutoSubmitAndAudit,
                        IsVerifyBaseDataField = this.IsVerifyBaseDataField,
                        NumberSearch = (this.BDSetter == BaseDataSetter.Number),
                        BatchCount=this.BatchCount
                    }
                };

                return JsonConvert.SerializeObject(parametersArray);
            }
        }//end property

        #endregion

        #region 公共操作参数属性

        /// <summary>
        /// 读写待保存的数据对象。
        /// </summary>
        public override object Model
        {
            get
            {
                return this.Models == null ? null : this.Models.FirstOrDefault();
            }
            set
            {
                if (this.Models == null)
                {
                    this.Models = new List<object>();
                }//end if
                this.Models.Add(value);
            }
        }//end property

        /// <summary>
        /// 读写待保存的多个数据对象。
        /// </summary>
        public virtual List<object> Models { get; set; }//end property

        /// <summary>
        /// 是否批量填充分录。
        /// </summary>
        public virtual bool IsEntryBatchFill { get; set; }//end property

        public virtual bool IsAutoSubmitAndAudit { get; set; }
        public virtual int BatchCount { get; set; }

        #endregion

        #region 公共方法

        /// <summary>
        /// 添加待保存的数据对象。
        /// </summary>
        /// <param name="model">待保存的数据对象。</param>
        /// <returns>返回类本身实例对象。</returns>
        public virtual BatchSave AddModel(object model)
        {
            if (this.Models == null)
            {
                this.Models = new List<object>();
            }//end if
            this.Models.Add(model);
            return this;
        }//end method

        /// <summary>
        /// 设置待保存的数据对象,但无论执行多少次只会保留最后一次设置的数据对象。
        /// </summary>
        /// <param name="model">待保存的数据对象。</param>
        /// <returns>返回类本身实例对象。</returns>
        new public virtual BatchSave SetModel(object model)
        {
            return this.SetModel<BatchSave>(model);
        }//end method

        #endregion

    }//end class

View Code

然后我们来看APIException类,可以看到该异常处理类统一继承自Kingdee.BOS.WebAPi.Client.ServiceException.

所以我们要引用 Kingdee.BOS.WebApi.Client.dll

另外这里官网给的代码示例中有句话很值得重视:// 使用webapi引用组件Kingdee.BOS.WebApi.Client.dll

这个组件我们可以在金蝶的安装目录下找到,当你兴致勃勃的找到这个dll,并将它引用到你的.netCore的项目中时,编译运行你会发现有个ServiceException类在.netCore环境下不支持,因为它仅在.net Framework支持。

所以呢,我们的第一反应是这可咋办,别着急,我们总有办法解决,反编译应该是我们在开发过程中比较常见的解决问题的办法,所以当我们将上述的dll进行反编译以后,我们可以得到如下一堆文件

接着我们就可以来处理我们的接口了,按照示例代码中的一样,我们来实现登录接口

/// <summary>
/// 实现登录。
/// </summary>
/// <returns>返回API结果。</returns>
public virtual APIResponse<LoginResult> Login()
{
var result = APIClient.CreateAPIOperation<LoginByUserPassword>(_Config.URL)
.SetDBId(_Config.DBId)
.SetUserName(_Config.UserName)
.SetPassword(_Config.Password)
.ToKdAPIRequest()
.ToAPIResponse<LoginResult>();
return result;
}

View Code

_config.Url---对应我们的金蝶财务环境的登录地址

_config.DBid--对应我们要操作的账套号---怎么查看到这个账套号是多少呢?还记得我们上面说的那个WebAPI菜单嘛,没错就是那里。我们随便点开一个菜单,比如我这里以科目为例,我们选中科目后,点击在线测试WebAPI按钮,就能找到我们所需的各自参数了。

_config.UserName --登录的用户名

_config.Password -- 登录的用户名的密码

这四个参数就对应我们登录接口的四个参数。

要注意的一点是我们在调用我们的业务接口时,必须先调用登录接口以实现登录操作。不然无法操作我们的业务接口。

/// <summary>
        /// 查询人民币币别编码
        /// </summary>
        /// <returns></returns>
        public string QueryCurrency()
        {
            this.Login();
            var result = APIClient.CreateAPIOperation<Query>(_Config.URL)
                .SetObjectTypeId(BillKeyConst.币别)
                .AddFieldKey("FNumber")
                .AddFieldKey("FName")
                .SetFilter("FName like '%人民币%'")
                .ToAPIRequest<KdAPIRequest>().Execute<JArray>();
            if (result.Count > 0)
            {
                return result[0][0].ToString();
            }
            else
            {
                return "";
            }
        }

如我们上图所示的查询人民币的名称和编码。当然这只是查询单个实体,当我们查询所有的数据时,就可能会用到分页查询,因为金蝶的查询接口默认一次查询2000条数据,所以当总数量超过2000时,我们就需要用到分页查询了。

public string QueryBasicInfoByPageList(string typeId, string FieldName, string Filter, int pageIndex)
        {
            this.Login();
            var result = APIClient.CreateAPIOperation<Query>(_Config.URL)
                .SetObjectTypeId(typeId)
                .AddFieldKey(FieldName)
                .SetFilter(Filter)
                .SetPageIndex(pageIndex)
                .ToAPIRequest<KdAPIRequest>().Execute<string>();
            return result;
        }

只需要在原有的基础上,增加pageIndex-页码参数即可,不过要注意的是每次查询的起始页码是不一样的,这样才能通过循环来得到我们需要的列表数据。

3.2 凭证保存接口

/// <summary>
        /// 批量保存单据实体
        /// </summary>
        /// <param name="typeId"></param>
        /// <param name="models"></param>
        /// <returns></returns>
        public string BatchSave(string typeId, List<object> models)
        {
            this.Login();
            var client = APIClient.CreateAPIOperation<BatchSave>(_Config.URL);
            client.SetObjectTypeId(typeId);
            client.Models = models;
            return client.ToAPIRequest<KdAPIRequest>().Execute<string>();
        }

View Code

凭证批量保存接口,所以当我们在外部构造好凭证实体后,就可直接通过该接口来处理凭证的保存工作。凭证保存实体如下CloudSaveVoucherModel

public class CloudSaveVoucherModel
    {
        public string FVoucherID { get; set; }
        public FVoucherNumber FAccountBookID { get; set; }
        public string FDate { get; set; }
        public FVoucherNumber FVoucherGroupID { get; set; }
        public string FVoucherGroupNo { get; set; }
        public string FIsAdjustVoucher { get; set; }
        public string FDocumentStatus { get; set; }
        public string FYear { get; set; }
        public FVoucherNumber FSourceBillKey { get; set; }
        public string FPeriod { get; set; }
        public string FImportVersion { get; set; }
        public Fentity[] FEntity { get; set; }
    }
    public class FVoucherNumber
    {
        public string FNumber { get; set; }
    }
    public class Fentity
    {
        public string FEntryID { get; set; }
        public string FExplanation { get; set; }
        public FVoucherNumber FAccountID { get; set; }
        public Fdetailid FDetailID { get; set; }
        public FVoucherNumber FCurrencyID { get; set; }
        public FVoucherNumber FExchangerateType { get; set; }
        public string FExchangeRate { get; set; }
        public FVoucherNumber FUnitId { get; set; }
        public string FPrice { get; set; }
        public string FQty { get; set; }
        public decimal FAmountFor { get; set; }
        public decimal FDebit { get; set; }
        public decimal FCredit { get; set; }
        public FVoucherNumber FSettleTypeID { get; set; }
        public string FSettleNo { get; set; }
        public string FExportentryID { get; set; }
    }
    public class Fdetailid
    {
        /// <summary>
        /// 费用项目
        /// </summary>
        public FVoucherNumber FDetailID__Fflex9 { get; set; }
        /// <summary>
        /// 供应商
        /// </summary>
        public FVoucherNumber FDetailID__Fflex4 { get; set; }
        public FVoucherNumber FDetailID__Fflex5 { get; set; }
        /// <summary>
        /// 客户
        /// </summary>
        public FVoucherNumber FDetailID__Fflex6 { get; set; }
        /// <summary>
        /// 员工
        /// </summary>
        public FVoucherNumber FDetailID__Fflex7 { get; set; }
        /// <summary>
        /// 物料
        /// </summary>
        public FVoucherNumber FDetailID__Fflex8 { get; set; }
        /// <summary>
        /// 资产类别
        /// </summary>
        public FVoucherNumber FDetailID__Fflex10 { get; set; }
        /// <summary>
        /// 组织机构
        /// </summary>
        public FVoucherNumber FDetailID__Fflex11 { get; set; }
        /// <summary>
        /// 物料分组
        /// </summary>
        public FVoucherNumber FDETAILID__FF100005 { get; set; }
        public FVoucherNumber FDetailID__Fflex12 { get; set; }
        public FVoucherNumber FDetailID__Fflex13 { get; set; }
    }

通过前面的BatchSave类,我们可以看到有个属性叫做NeedReturnFieldKeys -- 意为需要返回的字段,等于是在执行成功保存操作后,金蝶可以直接将我们需要返回的字段返回回来,传递形式还是和查询的FieldsKey格式一样,但是在实际的开发过程中我发现其实即便你传了NeedReturnFieldKeys,但是在返回值中并没有正常返回。我曾经在论坛里找个该问题,发现有小伙伴也遇到同样的问题。但是都没有得到解决,因为我在实际的逻辑中还需要得到类似总金额,凭证日期,凭证号等字段,所以没办法只能通过查询接口再执行一次查询操作了,当然不涉及后续的业务处理的话,可以不用执行该步骤的。

ps:当你执行批量保存操作时,如果一次操作的JSon数据量过大时,接口提示操作超时,所以在实际开发中建议可以分批次进行保存操作。

四.结语

相对来说,K3Cloud的接口文档还是比较全面的,所以当时在实际开发的时候,并没有遇到很多坑,只是在API封装的过程中,如上述说到的.netCore环境不支持的情况,这样的话通过反编译来处理问题也是一个不错的办法。后续我们还会在处理用友的一个产品时同样使用反编译来处理问题。

以上就是自己在实际生产过程中处理K3CloudAPI接口时的一些想法和思路。比如金蝶社区,论坛是不错的选择。同样QQ群也是一个沟通交流的途径。比如上面说到的批量保存时JSon串过大导致接口操作超时的问题,就是通过群里一个小伙伴的提醒,改变了思路通过分批传递的方法来解决问题的。我想说的是在开发过程中我们会遇到各种各样的问题,但是通过解决这些问题我们就能得到锻炼和成长,这就是我们的财富。说实话在之前我从没接触过这些知识点和业务范围,但是这不是也是一种成长的方式嘛。希望可以给在开发对接此产品的小伙伴一点帮助,一点支持就够了。

附上本文中的示例代码:K3Cloud接口 或者微信搜索【程序员贝塔】回复 "金蝶"即可获取文章中的源代码

(0)

相关推荐