如何从零开始创建基于K3Cloud的个性化WebService
金蝶云社区-战斗车
战斗车
3人赞赏了该文章 1,963次浏览 未经作者许可,禁止转载编辑于2017年03月24日 18:31:43

虽然目前我们推荐使用WebAPI作为第三方集成首选工具,但鉴于有些终端仅支持WebService调用,并且大部分场景下标准的动态表单服务均无法满足。比如传递一个单号,料号,希望有一个服务接口,找出这个单号的采购订单直接生成采购入库单。这就需要客户化开发WebService来实现该接口功能。本贴基于类似需求作详细说明如何创建基于K3Cloud的个性化WebService,以下为.net示例:

一、创建一个工程,然后添加一个类,举例名为:CostomerWebService,按下面填写必要标签和继承基于:
using System.Web;
using System.Web.Services;

///


/// WMSWebService 的摘要说明
///

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class CostomerWebService: System.Web.Services.WebService
{

二、创建了这个工程并保存后,需要手工添加一个WebSerivce页面文件:CostomerWebService.asmx,并将该页面文件指向CostomerWebService.cs,如:<%@ WebService Language="C#" CodeBehind="CostomerWebService.cs" Class="CostomerWebService" %>,这一步很重要,将在下面第六步讲述利用这个页面文件如果对外提供服务,本贴示例代码前提就是第六步照做才生效。

三、至此只是创建了空的WebSerivce,现在我们需要在该服务中添加方法,以便实现具体的功能。既然我们的服务是基于K3Cloud的,因此很自然地是需要有个登录的方法,登录又需要数据中心,用户名,和密码这三项,首先是定义一个获取数据中心的接口:
///


/// 获取数据中心账套列表
///

///
[WebMethod(Description = "获取数据中心账套列表")]
[XmlInclude(typeof(ReturnInfo>))] //ReturnInfo和DataCenter返回值类型,可随意定义
public ReturnInfo> GetDataCenterList()
{
try
{
List dataList = Kingdee.BOS.ServiceHelper.DataCenterService.GetDataCentersFromMC("", Kingdee.BOS.Context.DataBaseCategory.Normal); //这句需引用Kingdee.BOS.ServiceHelper.dll组件
List centerList = new List();
foreach (Kingdee.BOS.DataCenterInfo.DataCenter item in dataList)
{
DataCenter center = new DataCenter();
center.Id = item.Id;
center.Name = item.Name;
center.Number = item.Number;
centerList.Add(center);
}
var returnInfo = new ReturnInfo>()
{
IsSuccess = true,
IsList = true
};
returnInfo.ReturnValue = centerList;
returnInfo.ListCount = centerList.Count;
return returnInfo;
}
catch (Exception ex)
{
return new ReturnInfo>() { IsSuccess = false, Message = ex.Message, ReturnValue = new List() };
}
}

附ReturnInfo和DataCenter类定义:
public class ReturnInfo
{
public ReturnInfo();

// Summary:
// 是否集合
public bool IsList { get; set; }
//
// Summary:
// 是否成功
public bool IsSuccess { get; set; }
//
// Summary:
// 集合数量
public int ListCount { get; set; }
//
// Summary:
// 提示信息
public string Message { get; set; }
//
// Summary:
// 返回值
public T ReturnValue { get; set; }
}

[Serializable]
public class DataCenter
{
public DataCenter();

// Summary:
// 数据中心内码
public string Id { get; set; }
//
// Summary:
// 数据中心名称
public string Name { get; set; }
//
// Summary:
// 数据中心编码
public string Number { get; set; }
}

三、获取了数据中心列表,就可以取其中一个数据中心ID,连同用户名密码作为登录参数进行登录,以下是登录接口:
///


/// 登录
///

/// 数据中心id
/// 用户名
/// 密码
///
[WebMethod(EnableSession = true, Description = "登录到金蝶K/3 Cloud系统")]
[XmlInclude(typeof(ReturnInfo))]
public ReturnInfo Login(string datacenterId, string userName, string password)
{
try
{
password = ConfidentialDataSecurityUtil.CipherText(password); //引用Kingdee.BOS.dll组件并using Kingdee.BOS.Util可调用
var result = WMSLoginServiceHelper.Login("", datacenterId, userName, password); //引用Kingdee.K3.SCM.WMS.ServiceFacade.WebService.dll组件并using Kingdee.K3.SCM.WMS.ServiceFacade.WebService可调用
if ((result.LoginResultType == Kingdee.BOS.Authentication.LoginResultType.Success || result.LoginResultType == BOS.Authentication.LoginResultType.Wanning)
&& result.Context != null)
{
var first = Guid.NewGuid();
Guid second = new Guid();
do
{
second = Guid.NewGuid();
} while (first == second);
string accToken = second.ToString();
GlobalCacheManager.TryAdd(accToken, new KDServiceSession(accToken)); //引用Kingdee.BOS.ServiceFacade.KDServiceFx.dll组件并using Kingdee.BOS.ServiceFacade.KDServiceFx

object kdsession;
GlobalCacheManager.TryGet(accToken, out kdsession); //引用Kingdee.BOS.ServiceFacade.KDServiceFx.dll组件并using Kingdee.BOS.ServiceFacade.KDServiceFx
KDServiceSession sn = kdsession as KDServiceSession;
sn.AppContext = result.Context;
return new ReturnInfo()
{
IsSuccess = true,
ReturnValue = new LoginResult()
{
AccessToken = accToken,
UserRealName = sn.UserName
},
};
}
return new ReturnInfo()
{
IsSuccess = false,
Message = result.Message,
ReturnValue = new LoginResult()
{
AccessToken = ""
},
};
}
catch (Exception ex)
{
return new ReturnInfo() { IsSuccess = false, Message = ex.Message, ReturnValue = new LoginResult() };
}
}

附LoginResult类定义:
[Serializable]
public class LoginResult
{
public LoginResult();

// Summary:
// 接入标识Guid:该标识非常重要,登录成功后,该标识将作为后续调用功能接口的首要参数
public string AccessToken { get; set; }
//
// Summary:
// 用户名
public string UserRealName { get; set; }
}

四、登录成功并获得接入标识accessToken后,就可以开发实现各类个性功能接口方法了,正常来说登录成功后不确定登录到了哪个组织,或者保留了默认组织,因此在指定登录的组织,首先是获取组织列表,然后才能指定登录组织:
首先获取组织列表:
///


/// 获取当前登录用户的组织列表
///

/// Login方法登录成功后返回的有效AccessToken
///
[WebMethod(Description = "获取当前登录用户的组织列表")]
[XmlInclude(typeof(ReturnInfo>))]
public ReturnInfo> GetOrganizationInfoList(string accToken)
{
try
{
object kdsession;
GlobalCacheManager.TryGet(accToken, out kdsession); //引用Kingdee.BOS.ServiceFacade.KDServiceFx.dll组件并using Kingdee.BOS.ServiceFacade.KDServiceFx
KDServiceSession sn = kdsession as KDServiceSession;
if (sn == null)
{
return new ReturnInfo>()
{
IsSuccess = false,
ReturnValue = new List(),
Message = "登录失效,请重新登录",
};
}
List infos = WMSAccountService.GetUserOrgs(sn.AppContext); //引用Kingdee.K3.SCM.WMS.ServiceFacade.ServicesStub.dll组件并using Kingdee.K3.SCM.WMS.ServiceFacade.ServicesStub可调用
var returnInfo = new ReturnInfo>()
{
IsSuccess = true,
IsList = true
};
returnInfo.ReturnValue = infos;
returnInfo.ListCount = infos.Count;
return returnInfo;
}
catch (Exception ex)
{
return new ReturnInfo>() { IsSuccess = false, Message = ex.Message, ReturnValue = new List() };
}
}

然后指定登录组织:
///


/// 根据组织ID设置当前组织
///

/// Login方法登录成功后返回的有效AccessToken
/// 组织id
///
[WebMethod(Description = "根据组织ID设置当前组织")]
[XmlInclude(typeof(ReturnInfo))]
public ReturnInfo ChangeOrganizationById(string accToken, string Id)
{
try
{
object kdsession;
GlobalCacheManager.TryGet(accToken, out kdsession); //引用Kingdee.BOS.ServiceFacade.KDServiceFx.dll组件并using Kingdee.BOS.ServiceFacade.KDServiceFx
KDServiceSession sn = kdsession as KDServiceSession;
if (sn == null)
{
return new ReturnInfo()
{
IsSuccess = false,
ReturnValue = false,
Message = "登录失效,请重新登录",
};
}
if (!Id.IsNullOrEmptyOrWhiteSpace())
{

}
bool isSuccess = WMSAccountService.ChangeCurrentOrganizationById(sn.AppContext, Convert.ToInt64(Id)); //引用Kingdee.K3.SCM.WMS.ServiceFacade.ServicesStub.dll组件并using Kingdee.K3.SCM.WMS.ServiceFacade.ServicesStub可调用
return new ReturnInfo()
{
IsSuccess = isSuccess,
ReturnValue = isSuccess
};
}
catch (Exception ex)
{
return new ReturnInfo() { IsSuccess = false, Message = ex.Message };
}
}

五、这时可以说是登录动作已经完成,再举个栗子说明一下具体业务功能如何做WebSerivce接口,如下:
///


/// 根据物料和批号获取序列号信息列表
///

/// Login方法登录成功后返回的有效AccessToken
/// 物料编码
/// 批号
///
[WebMethod(Description = "根据物料和批号获取序列号信息列表")]
[XmlInclude(typeof(ReturnInfo>))]
public ReturnInfo> GetSerialInfoList(string accToken, string materialNumber, string lotNumber)
{
try
{
object kdsession;
GlobalCacheManager.TryGet(accToken, out kdsession); //引用Kingdee.BOS.ServiceFacade.KDServiceFx.dll组件并using Kingdee.BOS.ServiceFacade.KDServiceFx
KDServiceSession sn = kdsession as KDServiceSession;
if (sn == null)
{
return new ReturnInfo>()
{
IsSuccess = false,
ReturnValue = new List(),
Message = "登录失效,请重新登录",
};
}

if (materialNumber.IsNullOrEmptyOrWhiteSpace())
{
return new ReturnInfo>() { IsSuccess = false, ReturnValue = new List(), Message = "物料代码不能为空" };
}
List infos = WMSBaseService.GetSerialInfoList(sn.AppContext, materialNumber, lotNumber); //这是具体业务代码,示例不关注里面逻辑
var returnInfo = new ReturnInfo>()
{
IsSuccess = true,
IsList = true
};
returnInfo.ReturnValue = infos;
if (infos.Count > 0)
{
returnInfo.ListCount = infos.Count;
}
return returnInfo;
}
catch (Exception ex)
{
return new ReturnInfo>() { IsSuccess = false, Message = ex.Message, ReturnValue = new List() };
}
}

六、更多的业务接口,就可在此基础上不断完善和加深,还有一点需注意的是,第二步提到的CostomerWebService.asmx该怎么用,最简单的用法就是:将该文件放置于K3Cloud站点目录下的services目录中,这样与K3Cloud共用站点,访问时只需要指明完整路径即可,如:http://192.168.1.123/k3cloud/services/CostomerWebService.asmx,具体IP应根据具体K3Cloud站点IP改变。

至此,一个简单的全个性化的WebService就搭建好了,用浏览器访问一下第六步的地址,即可以网页上模拟操作WebService的调用操作,在此基础上,就可以进行一序列的个性功能的WebService开发了。如有疑问,欢迎跟帖讨论。