钉钉作为一个热门的办公软件,很多公司都在用。我个人还是偏爱企业微信,但无奈要做一个与钉钉对接系统的中间件,就将这次钉钉开发的笔记写一下吧。首先钉钉的接口有新旧2种接口,但都是互通的;所以别害怕。接口接入首先要获得SDK,SDK从Java、Node.js、PHP、Go、C#和Python都有还有小例子,总体来说还是比较齐全(大厂一般都会提供,某度除外)。C# dotnet add packageCloud.SDK.Dingtalk 就可以安装了。
安装成功了就是进入第一关,获得AccessToken,这个基本就是入门的钥匙了。我这里写了2个方法,第一种方法比较简单,就是用旧接口,通过GET直接获得;
public static OapiGettokenResponse GetAccessToken(string Appkey, string Appsecret)
{
DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
OapiGettokenRequest request = new OapiGettokenRequest();
request.Appkey = Appkey;//Appkey
request.Appsecret = Appsecret;//Appsecret
request.SetHttpMethod("GET");
OapiGettokenResponse response = client.Execute(request);
if (response.Errcode == 0)
{
return response;
}
else
{
return null;
}
}
由于这个AccessToken都有时效性,所以我发现了第二种方法,但我没试。。。
private static readonly long agentId =1;
private static readonly string appkey = "******";
private static readonly string appsecret = "******";
private static string _accessToken = "";
private static DateTime _accessTokenTime = DateTime.Now.AddMinutes(-1);
public static string GetAccessToken()
{
//没有AccessToken或者AccessToken过期,则重新获取
if (string.IsNullOrEmpty(_accessToken) || _accessTokenTime < DateTime.Now)
{
var client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
var req = new OapiGettokenRequest { Appkey = appkey, Appsecret = appsecret };
req.SetHttpMethod("Get");
var execute = client.Execute(req);
if (execute.Errcode == 0)
{
_accessToken = execute.AccessToken;
_accessTokenTime = DateTime.Now.AddHours(1);
}
}
return _accessToken;
}
我比较喜欢简单^_^,ok.获得了AccessToken我们就进行数据的捞取了,我们这里看看怎么捞取钉钉的人员吧。钉钉没有直接人员获得只能通过部门进行递归获得,至于如何递归,这个咱也会略提。
/// <summary>
/// 取得所有部门编号
/// </summary>
/// <returns></returns>
public static List<long> GetDepartIds(long DeptId, string accesstoken)
{
var client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsubid");
var req = new OapiV2DepartmentListsubidRequest { DeptId = DeptId };
var res = client.Execute(req, accesstoken);
if (res.Errcode == 0) return res.Result.DeptIdList;
return new List<long>();
}
/// <summary>
/// 取得部门详细资料,返回JSON
/// </summary>
/// <param name="accesstoken"></param>
/// <returns></returns>
public static void GetDepartSub(long DeptId,string accesstoken)
{
var client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
var req = new OapiV2DepartmentListsubidRequest { DeptId = DeptId };
var res = client.Execute(req,accesstoken);
JSON=res.Body;
}
/// <summary>
/// 取得部门下用户列表(仅用户Id)
/// </summary>
/// <param name="depid"></param>
/// <returns></returns>
public static List<string> GetDepartUserIds(long depid, string accesstoken)
{
var client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid");
var req = new OapiUserListidRequest { DeptId = depid };
var res = client.Execute(req,accesstoken);
if (res.Errcode == 0)
{
if (res.Result == null) return new List<string>();
if (res.Result.UseridList == null) return new List<string>();
return res.Result.UseridList;
}
return new List<string>();
}
/// <summary>
/// 根据用户UserId取得用户信息
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static string GetUserInfoByUserId(string userId, string accesstoken)
{
var client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
var req = new OapiV2UserGetRequest();
req.Userid = userId;
req.Language = "zh_CN";
var res = client.Execute(req, accesstoken);
if (res.Errcode == 0)
{
return res.Result.Userid+"|"+res.Result.Unionid+"|"+ res.Result.Name+"|"+ res.Result.Mobile;
} else {
return "";
}
}
/// <summary>
/// 获取用户详细资料
/// </summary>
/// <param name="Userid"></param>
/// <param name="accesstoken"></param>
/// <returns></returns>
public static OapiUserGetResponse Getuserinfo(string Userid,string accesstoken)
{
IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
OapiUserGetRequest request = new OapiUserGetRequest();
request.Userid = Userid;
request.SetHttpMethod("GET");
OapiUserGetResponse response = client.Execute(request, accesstoken);
if (response.Errcode == 0)
{
return response;
}
else
{
LogHelper.WriteLog(response.ErrMsg);
return null;
}
}
以上旧API,但可以调出数据。如何能进行递归获取?好吧,下面就是递归的部分思路
var Departinfo = DING_SDK.GetDepartIds(469151981,accesstoken.AccessToken);
foreach (var departid in Departinfo) {
var Duserinfo_A = DING_SDK.GetDepartUserIds(departid, accesstoken.AccessToken);
if (Duserinfo_A.Count > 0) {
foreach (var item in Duserinfo_A)
{
var Userinff = DING_SDK.GetUserInfoByUserId(item.ToString(), accesstoken.AccessToken);
}
}
};
最后给一下新接口的调用。
/**
* 使用 Token 初始化账号Client
* @return Client
* @throws Exception
*/
public static AlibabaCloud.SDK.Dingtalktodo_1_0.Client CreateClient()
{
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config();
config.Protocol = "https";
config.RegionId = "central";
return new AlibabaCloud.SDK.Dingtalktodo_1_0.Client(config);
}
public static void NEW_SDK(string accesstoken, string unionId) {
AlibabaCloud.SDK.Dingtalktodo_1_0.Client client = CreateClient();
AlibabaCloud.SDK.Dingtalktodo_1_0.Models.QueryOrgTodoTasksHeaders queryOrgTodoTasksHeaders = new AlibabaCloud.SDK.Dingtalktodo_1_0.Models.QueryOrgTodoTasksHeaders();
queryOrgTodoTasksHeaders.XAcsDingtalkAccessToken = accesstoken;
AlibabaCloud.SDK.Dingtalktodo_1_0.Models.QueryOrgTodoTasksRequest queryOrgTodoTasksRequest = new AlibabaCloud.SDK.Dingtalktodo_1_0.Models.QueryOrgTodoTasksRequest
{
NextToken = "0",
//IsDone = true,
};
try
{
var bbb=client.QueryOrgTodoTasksWithOptions(unionId, queryOrgTodoTasksRequest, queryOrgTodoTasksHeaders, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
}
catch (TeaException err)
{
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
catch (Exception _err)
{
TeaException err = new TeaException(new Dictionary<string, object>
{
{ "message", _err.Message }
});
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
public static void Add_SDK(string accesstoken, string unionId)
{
AlibabaCloud.SDK.Dingtalktodo_1_0.Client client = CreateClient();
AlibabaCloud.SDK.Dingtalktodo_1_0.Models.CreateTodoTaskHeaders createTodoTaskHeaders = new AlibabaCloud.SDK.Dingtalktodo_1_0.Models.CreateTodoTaskHeaders();
createTodoTaskHeaders.XAcsDingtalkAccessToken = accesstoken;
AlibabaCloud.SDK.Dingtalktodo_1_0.Models.CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs notifyConfigs = new AlibabaCloud.SDK.Dingtalktodo_1_0.Models.CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs
{
DingNotify = "1",
};
AlibabaCloud.SDK.Dingtalktodo_1_0.Models.CreateTodoTaskRequest.CreateTodoTaskRequestDetailUrl detailUrl = new AlibabaCloud.SDK.Dingtalktodo_1_0.Models.CreateTodoTaskRequest.CreateTodoTaskRequestDetailUrl
{
AppUrl = "https://www.dingtalk.com",
PcUrl = "https://www.dingtalk.com",
};
AlibabaCloud.SDK.Dingtalktodo_1_0.Models.CreateTodoTaskRequest createTodoTaskRequest = new AlibabaCloud.SDK.Dingtalktodo_1_0.Models.CreateTodoTaskRequest
{
SourceId = "isv_disgtalkTodo1",
Subject = "接入钉钉待办",
CreatorId = unionId,
Description = "应用可以调用该接口发起一个钉钉待办任务,该待办事项会出现在钉钉客户端“待办”页面,需要注意的是,通过开放接口发起的待办,目前仅支持直接跳转ISV应用详情页(ISV在调该接口时需传入自身应用详情页链接)。",
DueTime = 1617675000000,
ExecutorIds = new List<string>
{
unionId
},
ParticipantIds = new List<string>
{
unionId
},
DetailUrl = detailUrl,
IsOnlyShowExecutor = true,
Priority = 20,
NotifyConfigs = notifyConfigs,
};
try
{
client.CreateTodoTaskWithOptions(unionId, createTodoTaskRequest, createTodoTaskHeaders, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
}
catch (TeaException err)
{
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
catch (Exception _err)
{
TeaException err = new TeaException(new Dictionary<string, object>
{
{ "message", _err.Message }
});
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
public static AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Client ACreateClient()
{
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config();
config.Protocol = "https";
config.RegionId = "central";
return new AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Client(config);
}
public static void Get_SDK(string accesstoken) {
AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Client client = ACreateClient();
AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Models.QueryTodoStatisticalDataHeaders queryTodoStatisticalDataHeaders = new AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Models.QueryTodoStatisticalDataHeaders();
queryTodoStatisticalDataHeaders.XAcsDingtalkAccessToken = accesstoken;
AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Models.QueryTodoStatisticalDataRequest queryTodoStatisticalDataRequest = new AlibabaCloud.SDK.Dingtalkdatacenter_1_0.Models.QueryTodoStatisticalDataRequest
{
StatDate = "20210403",
};
try
{
var ccc=client.QueryTodoStatisticalDataWithOptions(queryTodoStatisticalDataRequest, queryTodoStatisticalDataHeaders, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
}
catch (TeaException err)
{
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
catch (Exception _err)
{
TeaException err = new TeaException(new Dictionary<string, object>
{
{ "message", _err.Message }
});
if (!AlibabaCloud.TeaUtil.Common.Empty(err.Code) && !AlibabaCloud.TeaUtil.Common.Empty(err.Message))
{
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
}
}
最后做个总结吧,钉钉经过这么多年的积累和背靠阿里团队在接入方便还是比较好的,但是可能软件迭代的比较勤,估有些功能还没有一个十分好的开发,例如我们这次做的待办事项,只能通过接口写入的数据来获取而非接口写入的就不可以。估计是因为新旧数据的问题,但没有去详研。。毕竟对钉钉个人还是有点小抵触的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。