DingTalkService.cs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // 大名科技(天津)有限公司 版权所有
  2. //
  3. // 此源代码遵循位于源代码树根目录中的 LICENSE 文件的许可证
  4. //
  5. // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动
  6. //
  7. // 任何基于本项目二次开发而产生的一切法律纠纷和责任,均与作者无关
  8. using Admin.NET.Core.Integrations;
  9. namespace Admin.NET.Core.DingTalk;
  10. /// <summary>
  11. /// 钉钉服务
  12. /// </summary>
  13. [ApiDescriptionSettings(Order = 999)]
  14. public class DingTalkService : IDynamicApiController, IScoped
  15. {
  16. private readonly UserManager _userManager;
  17. private readonly IDingTalkApi _dingTalkApi;
  18. private readonly DingTalkOptions _dingTalkOptions;
  19. private readonly SqlSugarRepository<SysDingTalkUser> _sysDingTalkUserRepo;
  20. private readonly SqlSugarRepository<SysUser> _sysUserRep;
  21. private readonly IJsonSerializerProvider _jsonSerializer;
  22. public DingTalkService(
  23. UserManager userManager,
  24. IDingTalkApi dingTalkApi,
  25. IOptions<DingTalkOptions> dingTalkOptions,
  26. SqlSugarRepository<SysDingTalkUser> sysDingTalkUserRepo,
  27. SqlSugarRepository<SysUser> sysUserRep,
  28. IJsonSerializerProvider jsonSerializer
  29. )
  30. {
  31. _userManager = userManager;
  32. _dingTalkApi = dingTalkApi;
  33. _dingTalkOptions = dingTalkOptions.Value;
  34. _sysDingTalkUserRepo = sysDingTalkUserRepo;
  35. _sysUserRep = sysUserRep;
  36. _jsonSerializer = jsonSerializer;
  37. }
  38. /// <summary>
  39. /// 同步钉钉用户(后面可以做到job中)
  40. /// </summary>
  41. /// <returns></returns>
  42. [HttpGet]
  43. [DisplayName("同步钉钉用户")]
  44. public async Task SyncDingTalkUser()
  45. {
  46. // 获取token
  47. var param = new GetDingTalkTokenInput()
  48. {
  49. AppKey = _dingTalkOptions.ClientId,
  50. AppSecret = _dingTalkOptions.ClientSecret
  51. };
  52. var tokenRes = await _dingTalkApi.GetDingTalkToken(param);
  53. if (tokenRes.ErrCode != 0)
  54. {
  55. throw Oops.Oh(tokenRes.ErrMsg);
  56. }
  57. var offset = 0;
  58. while (offset >= 0)
  59. {
  60. // 获取用户id列表
  61. var userIdsRes = await _dingTalkApi.GetDingTalkCurrentEmployeesList(tokenRes.AccessToken, new GetDingTalkCurrentEmployeesListInput
  62. {
  63. StatusList = "2,3,5,-1",
  64. Size = 50,
  65. Offset = offset
  66. });
  67. if (!userIdsRes.Success)
  68. {
  69. throw Oops.Oh(userIdsRes.ErrMsg);
  70. }
  71. // 根据用户id获取花名册
  72. var rosterRes = await _dingTalkApi.GetDingTalkCurrentEmployeesRosterList(tokenRes.AccessToken, new GetDingTalkCurrentEmployeesRosterListInput()
  73. {
  74. UserIdList = string.Join(",", userIdsRes.Result.DataList),
  75. FieldFilterList = $"{DingTalkFieldConst.NameField},{DingTalkFieldConst.JobNumberField},{DingTalkFieldConst.MobileField}",
  76. AgentId = _dingTalkOptions.AgentId
  77. });
  78. if (!rosterRes.Success)
  79. {
  80. throw Oops.Oh(rosterRes.ErrMsg);
  81. }
  82. // 判断新增还是更新
  83. var userIds = rosterRes.Result.Select(res => res.UserId).ToList();
  84. var uDingTalkUser = await _sysDingTalkUserRepo.AsQueryable()
  85. .Where(u => userIds.Contains(u.DingTalkUserId))
  86. .ToListAsync();
  87. // 需要更新的用户id
  88. var uUserIds = uDingTalkUser.Select(u => u.DingTalkUserId);
  89. // 需要新增的用户id
  90. var iUserIds = userIds.Where(u => !uUserIds.Contains(u));
  91. #region 保存到钉钉用户表
  92. var iUser = rosterRes.Result
  93. .Where(res => iUserIds.Contains(res.UserId))
  94. .Select(res => new SysDingTalkUser
  95. {
  96. DingTalkUserId = res.UserId,
  97. Name = res.FieldDataList
  98. .Where(f => f.FieldCode == DingTalkFieldConst.NameField)
  99. .Select(f => f.FieldValueList.Select(v => v.Value).FirstOrDefault())
  100. .FirstOrDefault(),
  101. Mobile = res.FieldDataList
  102. .Where(f => f.FieldCode == DingTalkFieldConst.MobileField)
  103. .Select(f => f.FieldValueList.Select(v => v.Value).FirstOrDefault())
  104. .FirstOrDefault(),
  105. JobNumber = res.FieldDataList
  106. .Where(f => f.FieldCode == DingTalkFieldConst.JobNumberField)
  107. .Select(f => f.FieldValueList.Select(v => v.Value).FirstOrDefault())
  108. .FirstOrDefault(),
  109. }).ToList();
  110. if (iUser.Count > 0)
  111. {
  112. var iUserRes = await _sysDingTalkUserRepo.AsInsertable(iUser).ExecuteCommandAsync();
  113. if (iUserRes <= 0)
  114. {
  115. throw Oops.Oh("保存钉钉用户错误");
  116. }
  117. }
  118. #endregion
  119. #region 更新钉钉用户
  120. var uUser = rosterRes.Result
  121. .Where(res => uUserIds.Contains(res.UserId))
  122. .Select(res => new SysDingTalkUser
  123. {
  124. Id = uDingTalkUser.Where(d => d.DingTalkUserId == res.UserId).Select(d => d.Id).FirstOrDefault(),
  125. DingTalkUserId = res.UserId,
  126. Name = res.FieldDataList
  127. .Where(f => f.FieldCode == DingTalkFieldConst.NameField)
  128. .Select(f => f.FieldValueList.Select(v => v.Value).FirstOrDefault())
  129. .FirstOrDefault(),
  130. Mobile = res.FieldDataList
  131. .Where(f => f.FieldCode == DingTalkFieldConst.MobileField)
  132. .Select(f => f.FieldValueList.Select(v => v.Value).FirstOrDefault())
  133. .FirstOrDefault(),
  134. JobNumber = res.FieldDataList
  135. .Where(f => f.FieldCode == DingTalkFieldConst.JobNumberField)
  136. .Select(f => f.FieldValueList.Select(v => v.Value).FirstOrDefault())
  137. .FirstOrDefault(),
  138. }).ToList();
  139. if (uUser.Count > 0)
  140. {
  141. var uUserRes = await _sysDingTalkUserRepo.AsUpdateable(uUser)
  142. .UpdateColumns(d => new
  143. {
  144. d.DingTalkUserId,
  145. d.Name,
  146. d.Mobile,
  147. d.JobNumber,
  148. d.UpdateTime,
  149. d.UpdateUserName,
  150. d.UpdateUserId,
  151. }).ExecuteCommandAsync();
  152. if (uUserRes <= 0)
  153. {
  154. throw Oops.Oh("更新钉钉用户错误");
  155. }
  156. }
  157. #endregion
  158. // 保存分页游标
  159. if (userIdsRes.Result.NextCursor == null)
  160. {
  161. break;
  162. }
  163. offset = (int)userIdsRes.Result.NextCursor;
  164. }
  165. var sysUser = await _sysUserRep.AsQueryable().Select(x => new
  166. {
  167. x.Id,
  168. x.Account,
  169. x.Phone
  170. }).ToListAsync();
  171. var sysDingTalkUser = await _sysDingTalkUserRepo.AsQueryable()
  172. .Where(d => sysUser.Any(u => u.Account == d.JobNumber))
  173. .Select(x => new
  174. {
  175. x.Id,
  176. x.JobNumber,
  177. x.Mobile
  178. }).ToListAsync();
  179. // 更新钉钉用户中系统用户id
  180. var uSysDingTalkUser = sysDingTalkUser.Select(d => new SysDingTalkUser
  181. {
  182. Id = d.Id,
  183. SysUserId = sysUser.Where(u => u.Account == d.JobNumber).Select(u => u.Id).FirstOrDefault(),
  184. }).ToList();
  185. var uSysDingTalkUserRes = await _sysDingTalkUserRepo.AsUpdateable(uSysDingTalkUser)
  186. .UpdateColumns(d => new
  187. {
  188. d.SysUserId,
  189. d.UpdateTime,
  190. d.UpdateUserName,
  191. d.UpdateUserId,
  192. }).ExecuteCommandAsync();
  193. if (uSysDingTalkUserRes <= 0)
  194. {
  195. throw Oops.Oh("更新钉钉用户错误");
  196. }
  197. return;
  198. }
  199. /// <summary>
  200. /// 获取企业内部应用的access_token
  201. /// </summary>
  202. /// <param name="input"></param>
  203. /// <returns></returns>
  204. [HttpGet]
  205. [DisplayName("获取企业内部应用的access_token")]
  206. public async Task<GetDingTalkTokenOutput> GetDingTalkToken([FromQuery] GetDingTalkTokenInput input)
  207. {
  208. return await _dingTalkApi.GetDingTalkToken(input);
  209. }
  210. /// <summary>
  211. /// 获取在职员工列表
  212. /// </summary>
  213. /// <param name="access_token"></param>
  214. /// <param name="input"></param>
  215. /// <returns></returns>
  216. [HttpPost]
  217. [DisplayName("获取在职员工列表")]
  218. public async Task<DingTalkBaseResponse<GetDingTalkCurrentEmployeesListOutput>> GetDingTalkCurrentEmployeesList(string access_token, [Required] GetDingTalkCurrentEmployeesListInput input)
  219. {
  220. return await _dingTalkApi.GetDingTalkCurrentEmployeesList(access_token, input);
  221. }
  222. /// <summary>
  223. /// 获取员工花名册字段信息
  224. /// </summary>
  225. /// <param name="access_token"></param>
  226. /// <param name="input"></param>
  227. /// <returns></returns>
  228. [HttpPost]
  229. [DisplayName("获取员工花名册字段信息")]
  230. public async Task<DingTalkBaseResponse<List<DingTalkEmpRosterFieldVo>>> GetDingTalkCurrentEmployeesRosterList(string access_token, [Required] GetDingTalkCurrentEmployeesRosterListInput input)
  231. {
  232. return await _dingTalkApi.GetDingTalkCurrentEmployeesRosterList(access_token, input);
  233. }
  234. /// <summary>
  235. /// 发送钉钉互动卡片
  236. /// </summary>
  237. /// <param name="token"></param>
  238. /// <param name="input"></param>
  239. /// <returns></returns>
  240. [HttpPost]
  241. [DisplayName("给指定用户发送钉钉互动卡片")]
  242. public async Task<DingTalkSendInteractiveCardsOutput> DingTalkSendInteractiveCards(string token, DingTalkSendInteractiveCardsInput input)
  243. {
  244. return await _dingTalkApi.DingTalkSendInteractiveCards(token, input);
  245. }
  246. }