QiYeWeChatApiService.cs 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567
  1. using OASystem.Domain.Dtos.QiYeWeChat;
  2. using OASystem.Domain.ViewModels.QiYeWeChat;
  3. using System.Diagnostics;
  4. using System.Text.Json;
  5. namespace OASystem.API.OAMethodLib.QiYeWeChatAPI
  6. {
  7. /// <summary>
  8. /// 聚合Api 服务
  9. /// </summary>
  10. public class QiYeWeChatApiService : IQiYeWeChatApiService
  11. {
  12. private readonly HttpClient _httpClient;
  13. private readonly string CorpId = "wwe978bef5495a0728"; //企业Id
  14. private readonly string PersonnelAssistant_AgentId = "3010011"; //人事助手Id
  15. private readonly string PersonnelAssistant_Corpsecret = "ig--IJd6TxWDMJ1wT4e-RDRcRX12v5GjB359DNATwJ4"; //人事助手凭证密钥
  16. private readonly string PunchCard_AgentId = "3010185"; //打卡Id
  17. private readonly string PunchCard_Corpsecret = "Xhrl37GOqlAjsu0VzUSJECaJdjzkDXQLbvrzRsZQb8M"; //打卡凭证密钥
  18. private readonly string Email_AgentId = "1000004"; //E-Mail Id
  19. private readonly string Email_Corpsecret = "NA1zbJM15GmgjPYwDOqz59dIo1Wnug-MbU107MeUemc"; //E-Mail 凭证密钥
  20. private readonly string AddressBook_Corpsecret = "Y1tnjh7j-BvbqAytAoXZPUbmDR6dqLTL6mXtc6PZ7fo"; //通讯录同步 凭证密钥
  21. private readonly string Approve_AgentId = "3010040"; //审批 Id
  22. private readonly string Approve_Corpsecret = "k_Jo69Jw9Hqg_in-Rypbs30PNbxOYa1t4e-dxYuT-kw"; //审批 凭证密钥
  23. private readonly string GroupStatus_AgentId = "1000008"; //OA通知 Id
  24. private readonly string GroupStatus_Corpsecret = "7J_ST3jTPzbZpFwl7ttToTVufjEx6O2wuApvKHxt2Ak"; //OA通知Secret
  25. private readonly DateTime _1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0);
  26. private readonly JobPostRepository _jobPostRep;
  27. /// <summary>
  28. /// 初始化
  29. /// </summary>
  30. /// <param name="clientFactory"></param>
  31. /// <param name="jobPostRep"></param>
  32. public QiYeWeChatApiService(IHttpClientFactory clientFactory, JobPostRepository jobPostRep)
  33. {
  34. _httpClient = clientFactory.CreateClient("PublicQiYeWeChatApi"); ;
  35. _jobPostRep = jobPostRep;
  36. }
  37. /// <summary>
  38. /// 获取access_token
  39. /// </summary>
  40. /// <param name="applicationType">
  41. /// 1:人事助手
  42. /// 2:打卡
  43. /// 3:邮件
  44. /// 4:通讯录同步
  45. /// 5:审批
  46. /// 6:团组状态通知
  47. /// </param>
  48. /// <returns></returns>
  49. private async Task<Access_TokenView> GetTokenAsync(int applicationType)
  50. {
  51. Access_TokenView tokenResult = new Access_TokenView();
  52. Access_Token_Request access_Token = new Access_Token_Request();
  53. string cacheName = string.Empty;
  54. if (applicationType == 1)
  55. {
  56. access_Token.corpsecret = PersonnelAssistant_Corpsecret; //人事助手
  57. cacheName = "PersonnelAssistant_Access_Token";
  58. }
  59. else if (applicationType == 2)
  60. {
  61. access_Token.corpsecret = PunchCard_Corpsecret; //打卡
  62. cacheName = "PunchCard_Access_Token";
  63. }
  64. else if (applicationType == 3)
  65. {
  66. access_Token.corpsecret = Email_Corpsecret; //E-Mail
  67. cacheName = "Enail_Access_Token";
  68. }
  69. else if (applicationType == 4) //通讯录同步
  70. {
  71. access_Token.corpsecret = AddressBook_Corpsecret;
  72. cacheName = "AddressBook_Access_Token";
  73. }
  74. else if (applicationType == 5) //审批
  75. {
  76. access_Token.corpsecret = Approve_Corpsecret;
  77. cacheName = "Approve_Access_Token";
  78. }
  79. else if (applicationType == 6) //团组状态通知
  80. {
  81. access_Token.corpsecret = GroupStatus_Corpsecret;
  82. cacheName = "GroupStatus_Access_Token";
  83. }
  84. else
  85. {
  86. tokenResult.errmsg = "未识别应用类型Id!";
  87. return tokenResult;
  88. }
  89. string access_token = await RedisRepository.RedisFactory
  90. .CreateRedisRepository()
  91. .StringGetAsync<string>(cacheName);//string 取
  92. if (string.IsNullOrEmpty(access_token))
  93. {
  94. string access_token_url = string.Format(@"/cgi-bin/gettoken?corpid={0}&corpsecret={1}", access_Token.corpid, access_Token.corpsecret);
  95. var access_tokenReq = await _httpClient.GetAsync(access_token_url);
  96. if (access_tokenReq.IsSuccessStatusCode)
  97. {
  98. var stringResponse = await access_tokenReq.Content.ReadAsStringAsync();
  99. tokenResult = System.Text.Json.JsonSerializer.Deserialize<Access_TokenView>(stringResponse,
  100. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  101. if (tokenResult.errcode == 0)
  102. {
  103. TimeSpan ts = DateTime.Now.AddMinutes(118) - DateTime.Now; //设置redis 过期时间 118分钟
  104. await RedisRepository
  105. .RedisFactory
  106. .CreateRedisRepository()
  107. .StringSetAsync<string>(cacheName, tokenResult.access_token, ts);//string 存
  108. }
  109. }
  110. else
  111. {
  112. tokenResult.errmsg = "企业微信Token未获取到!";
  113. }
  114. }
  115. else
  116. {
  117. tokenResult.errcode = 0;
  118. tokenResult.access_token = access_token;
  119. }
  120. return tokenResult;
  121. }
  122. #region 添加员工
  123. /// <summary>
  124. /// 获取成员ID列表
  125. /// </summary>
  126. /// <returns></returns>
  127. public async Task<UserIdListView> GetUserIdListAsync()
  128. {
  129. UserIdListView userIdListView = new UserIdListView();
  130. Access_TokenView access_Token = await GetTokenAsync(4);
  131. if (access_Token.errcode != 0)
  132. {
  133. userIdListView.errcode = access_Token.errcode;
  134. userIdListView.errmsg = access_Token.errmsg;
  135. return userIdListView;
  136. }
  137. string url = string.Format("/cgi-bin/user/list_id?access_token={0}&debug=1", access_Token.access_token);
  138. var jsonData = new
  139. {
  140. access_token = access_Token.access_token, //调用接口凭证
  141. };
  142. var json = System.Text.Json.JsonSerializer.Serialize(jsonData);
  143. var content = new StringContent(json, Encoding.UTF8, "application/json");
  144. var create_Req = await _httpClient.PostAsync(url, content);
  145. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  146. userIdListView = System.Text.Json.JsonSerializer.Deserialize<UserIdListView>(stringResponse,
  147. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  148. return userIdListView;
  149. }
  150. /// <summary>
  151. /// 获取成员信息
  152. /// </summary>
  153. /// <returns></returns>
  154. public async Task<QYWX_UserInfosView> GetUserInfosAsync()
  155. {
  156. QYWX_UserInfosView infoViews = new QYWX_UserInfosView();
  157. //获取员工useridList
  158. UserIdListView useridView = await GetUserIdListAsync();
  159. if (useridView.errcode != 0)
  160. {
  161. infoViews.errcode = useridView.errcode;
  162. infoViews.errmsg = useridView.errmsg;
  163. return infoViews;
  164. }
  165. Access_TokenView access_Token = await GetTokenAsync(4);
  166. if (access_Token.errcode != 0)
  167. {
  168. infoViews.errcode = access_Token.errcode;
  169. infoViews.errmsg = access_Token.errmsg;
  170. return infoViews;
  171. }
  172. List<QYWX_UserInfo> items = new List<QYWX_UserInfo>();
  173. string urlTitle = string.Format("/cgi-bin/user/get?access_token={0}", access_Token.access_token);
  174. foreach (var item in useridView.dept_user)
  175. {
  176. if (!string.IsNullOrEmpty(item.userid))
  177. {
  178. QYWX_UserInfoView _UserInfoView = new QYWX_UserInfoView();
  179. string url = string.Format("{0}&userid={1}", urlTitle, item.userid);
  180. var create_Req = await _httpClient.GetAsync(url);
  181. if (create_Req.IsSuccessStatusCode)
  182. {
  183. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  184. _UserInfoView = System.Text.Json.JsonSerializer.Deserialize<QYWX_UserInfoView>(stringResponse,
  185. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  186. if (_UserInfoView.errcode == 0)
  187. {
  188. items.Add(new QYWX_UserInfo()
  189. {
  190. userid = _UserInfoView.QYWX_User.userid,
  191. name = _UserInfoView.QYWX_User.name,
  192. mobile = _UserInfoView.QYWX_User.mobile,
  193. position = _UserInfoView.QYWX_User.position,
  194. email = _UserInfoView.QYWX_User.email,
  195. biz_mail = _UserInfoView.QYWX_User.biz_mail,
  196. });
  197. }
  198. }
  199. }
  200. }
  201. infoViews.errcode = 0;
  202. infoViews.errmsg = "操作成功!";
  203. infoViews.QYWX_Users = items;
  204. return infoViews;
  205. }
  206. /// <summary>
  207. /// 获取部门列表
  208. /// </summary>
  209. /// <param name="access_token"></param>
  210. /// <returns></returns>
  211. private async Task<DepartmentListView> GetDepartmentAsync(string access_token)
  212. {
  213. DepartmentListView result = new DepartmentListView();
  214. string dep_url = string.Format("/cgi-bin/department/list?access_token={0}&debug=1", access_token);
  215. var depReq = await _httpClient.GetAsync(dep_url);
  216. if (depReq.IsSuccessStatusCode)
  217. {
  218. var stringResponse = await depReq.Content.ReadAsStringAsync();
  219. result = System.Text.Json.JsonSerializer.Deserialize<DepartmentListView>(stringResponse,
  220. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  221. }
  222. else
  223. {
  224. result.errcode = -1;
  225. result.errmsg = "企业微信部门列表未获取到!";
  226. }
  227. return result;
  228. }
  229. /// <summary>
  230. /// 创建员工
  231. /// </summary>
  232. /// <param name="create_Request"></param>
  233. /// <returns></returns>
  234. public async Task<ResponseBase> CreateAsync(Create_Request create_Request)
  235. {
  236. ResponseBase responseBase = new ResponseBase();
  237. #region 职位
  238. string depName = string.Empty,
  239. jobName = string.Empty;
  240. List<Sys_JobPostI> jobs = await _jobPostRep.QueryJobPost(string.Empty);
  241. Sys_JobPostI jobPost = jobs.Where(it => it.IsDel == 0 && it.Id == Convert.ToInt32(create_Request.position)).FirstOrDefault();
  242. if (jobPost != null)
  243. {
  244. depName = jobPost.DepName;
  245. jobName = jobPost.JobName;
  246. }
  247. create_Request.position = jobName;
  248. if (string.IsNullOrEmpty(create_Request.biz_mail))
  249. {
  250. create_Request.biz_mail = string.Format("{0}@pan-american-intl.com", create_Request.userid);
  251. }
  252. #endregion
  253. Access_TokenView access_Token = new Access_TokenView();
  254. access_Token = await GetTokenAsync(4);
  255. if (access_Token.errcode == 0)
  256. {
  257. create_Request.access_token = access_Token.access_token;
  258. #region 处理部门
  259. Access_TokenView dep_Access_Token = await GetTokenAsync(1);
  260. if (dep_Access_Token.errcode != 0)
  261. {
  262. responseBase.errcode = dep_Access_Token.errcode;
  263. responseBase.errmsg = dep_Access_Token.errmsg;
  264. }
  265. DepartmentListView depData = await GetDepartmentAsync(dep_Access_Token.access_token);
  266. if (depData.errcode == 0)
  267. {
  268. var depData1 = depData.department.Where(x => x.name == depName).FirstOrDefault();
  269. if (depData1 != null)
  270. {
  271. create_Request.department = new List<long> { depData1.id };
  272. }
  273. else
  274. {
  275. responseBase.errcode = -1;
  276. responseBase.errmsg = "未在企业微信上找到OA内设置的部门";
  277. return responseBase;
  278. }
  279. }
  280. else
  281. {
  282. responseBase.errcode = depData.errcode;
  283. responseBase.errmsg = depData.errmsg;
  284. return responseBase;
  285. }
  286. #endregion
  287. create_Request.access_token = access_Token.access_token;
  288. string create_url = string.Format("/cgi-bin/user/create?access_token={0}", create_Request.access_token);
  289. var json = System.Text.Json.JsonSerializer.Serialize(create_Request);
  290. var content = new StringContent(json, Encoding.UTF8, "application/json");
  291. var create_Req = await _httpClient.PostAsync(create_url, content);
  292. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  293. responseBase = System.Text.Json.JsonSerializer.Deserialize<ResponseBase>(stringResponse,
  294. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  295. }
  296. else
  297. {
  298. responseBase.errcode = access_Token.errcode;
  299. responseBase.errmsg = access_Token.errmsg;
  300. }
  301. return responseBase;
  302. }
  303. #endregion
  304. #region 打卡
  305. /// <summary>
  306. /// 获取企业所有打卡规则
  307. /// </summary>
  308. /// <returns></returns>
  309. public async Task<CorpCheckInRuleView> GetCheckIn_CorpCheckInOptionAsync()
  310. {
  311. CorpCheckInRuleView corpCheckInRuleView = new CorpCheckInRuleView();
  312. //获取打卡数据 token
  313. Access_TokenView access_Token = await GetTokenAsync(2);
  314. if (access_Token.errcode != 0)
  315. {
  316. corpCheckInRuleView.errcode = access_Token.errcode;
  317. corpCheckInRuleView.errmsg = string.Format("【企业微信】【获取月打卡数据】【Token】【Msg】{0}", access_Token.errmsg);
  318. return corpCheckInRuleView;
  319. }
  320. string url = string.Format("/cgi-bin/checkin/getcorpcheckinoption?access_token={0}", access_Token.access_token);
  321. var content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
  322. var create_Req = await _httpClient.PostAsync(url, content);
  323. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  324. corpCheckInRuleView = System.Text.Json.JsonSerializer.Deserialize<CorpCheckInRuleView>(stringResponse,
  325. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  326. return corpCheckInRuleView;
  327. }
  328. /// <summary>
  329. /// 获取月打卡记录数据
  330. /// </summary>
  331. /// <param name="startDt"></param>
  332. /// <param name="endDt"></param>
  333. /// <returns></returns>
  334. public async Task<CheckInView> GetCheckin_MonthDataAsync1(DateTime startDt, DateTime endDt)
  335. {
  336. CheckInView checkInView = new CheckInView();
  337. //获取员工Id
  338. UserIdListView userIdListView = await GetUserIdListAsync();
  339. if (userIdListView.errcode != 0)
  340. {
  341. checkInView.errcode = userIdListView.errcode;
  342. checkInView.errmsg = string.Format("【企业微信】【获取员工IdList】【Msg】{0}", userIdListView.errmsg);
  343. return checkInView;
  344. }
  345. if (userIdListView.dept_user == null || userIdListView.dept_user.Count <= 0)
  346. {
  347. checkInView.errmsg = string.Format("【企业微信】【获取员工IdList】【Msg】未查出员工Id");
  348. return checkInView;
  349. }
  350. //获取打卡数据 token
  351. Access_TokenView access_Token = await GetTokenAsync(2);
  352. if (access_Token.errcode != 0)
  353. {
  354. checkInView.errcode = access_Token.errcode;
  355. checkInView.errmsg = string.Format("【企业微信】【获取月打卡数据】【Token】【Msg】{0}", access_Token.errmsg);
  356. return checkInView;
  357. }
  358. string url = string.Format("/cgi-bin/checkin/getcheckin_monthdata?access_token={0}", access_Token.access_token);
  359. Checkin_MonthData_Request checkInReq = new Checkin_MonthData_Request();
  360. checkInReq.access_token = access_Token.access_token;
  361. checkInReq.starttime = (uint)(startDt - _1970).TotalSeconds;
  362. checkInReq.endtime = (uint)(endDt - _1970).TotalSeconds;
  363. checkInReq.useridlist = userIdListView.dept_user.Select(it => it.userid).ToList();
  364. var json = System.Text.Json.JsonSerializer.Serialize(checkInReq);
  365. var content = new StringContent(json, Encoding.UTF8, "application/json");
  366. var create_Req = await _httpClient.PostAsync(url, content);
  367. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  368. checkInView = System.Text.Json.JsonSerializer.Deserialize<CheckInView>(stringResponse,
  369. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  370. return checkInView;
  371. }
  372. /// <summary>
  373. /// 获取月打卡记录数据
  374. /// </summary>
  375. /// <param name="startDt"></param>
  376. /// <param name="endDt"></param>
  377. /// <returns></returns>
  378. public async Task<CheckInView> GetCheckin_MonthDataAsync(DateTime startDt, DateTime endDt)
  379. {
  380. CheckInView checkInView = new CheckInView();
  381. //获取员工Id
  382. UserIdListView userIdListView = await GetUserIdListAsync();
  383. if (userIdListView.errcode != 0)
  384. {
  385. checkInView.errcode = userIdListView.errcode;
  386. checkInView.errmsg = string.Format("【企业微信】【获取员工IdList】【Msg】{0}", userIdListView.errmsg);
  387. return checkInView;
  388. }
  389. if (userIdListView.dept_user == null || userIdListView.dept_user.Count <= 0)
  390. {
  391. checkInView.errmsg = string.Format("【企业微信】【获取员工IdList】【Msg】未查出员工Id");
  392. return checkInView;
  393. }
  394. //获取打卡数据 token
  395. Access_TokenView access_Token = await GetTokenAsync(2);
  396. if (access_Token.errcode != 0)
  397. {
  398. checkInView.errcode = access_Token.errcode;
  399. checkInView.errmsg = string.Format("【企业微信】【获取月打卡数据】【Token】【Msg】{0}", access_Token.errmsg);
  400. return checkInView;
  401. }
  402. #region 处理超31天的月报表数据
  403. string url = string.Format("/cgi-bin/checkin/getcheckin_monthdata?access_token={0}", access_Token.access_token);
  404. Checkin_MonthData_Request checkInReq = new Checkin_MonthData_Request();
  405. checkInReq.access_token = access_Token.access_token;
  406. checkInReq.useridlist = userIdListView.dept_user.Select(it => it.userid).ToList();
  407. uint starttimeOne, endtimeOne, starttimeTwo, endtimeTwo;
  408. int days = (int)(endDt - startDt).TotalDays;
  409. if (days > 32)
  410. {
  411. starttimeOne = (uint)((startDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000);
  412. endtimeOne = (uint)((startDt.AddDays(31).ToUniversalTime().Ticks - 621355968000000000) / 10000000);
  413. starttimeTwo = (uint)((startDt.AddDays(32).ToUniversalTime().Ticks - 621355968000000000) / 10000000);
  414. endtimeTwo = (uint)((endDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000);
  415. checkInReq.starttime = starttimeOne;
  416. checkInReq.endtime = endtimeOne;
  417. CheckInView checkInViewOne = new CheckInView();
  418. var jsonOne = System.Text.Json.JsonSerializer.Serialize(checkInReq);
  419. var contentOne = new StringContent(jsonOne, Encoding.UTF8, "application/json");
  420. var create_ReqOne = await _httpClient.PostAsync(url, contentOne);
  421. var stringResponseOne = await create_ReqOne.Content.ReadAsStringAsync();
  422. checkInViewOne = System.Text.Json.JsonSerializer.Deserialize<CheckInView>(stringResponseOne,
  423. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  424. if (checkInViewOne.errcode != 0)
  425. {
  426. return checkInViewOne;
  427. }
  428. checkInReq.starttime = starttimeTwo;
  429. checkInReq.endtime = endtimeTwo;
  430. CheckInView checkInViewTwo = new CheckInView();
  431. var jsonTwo = System.Text.Json.JsonSerializer.Serialize(checkInReq);
  432. var contentTwo = new StringContent(jsonTwo, Encoding.UTF8, "application/json");
  433. var create_ReqTwo = await _httpClient.PostAsync(url, contentTwo);
  434. var stringResponseTwo = await create_ReqTwo.Content.ReadAsStringAsync();
  435. checkInViewTwo = System.Text.Json.JsonSerializer.Deserialize<CheckInView>(stringResponseTwo,
  436. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  437. if (checkInViewTwo.errcode != 0)
  438. {
  439. return checkInViewTwo;
  440. }
  441. #region 整合月报表数据
  442. foreach (var item_one in checkInViewOne.datas)
  443. {
  444. foreach (var item_two in checkInViewTwo.datas)
  445. {
  446. if (item_one.base_info.acctid.Equals(item_two.base_info.acctid))
  447. {
  448. #region summary_info 汇总信息整合
  449. item_one.summary_info.work_days += item_two.summary_info.work_days; //应打卡天数
  450. item_one.summary_info.regular_days += item_two.summary_info.regular_days; //正常天数
  451. item_one.summary_info.except_days += item_two.summary_info.except_days; //异常天数
  452. item_one.summary_info.regular_work_sec += item_two.summary_info.regular_work_sec; //实际工作时长,为统计周期每日实际工作时长之和
  453. item_one.summary_info.standard_work_sec += item_two.summary_info.standard_work_sec; //标准工作时长,为统计周期每日标准工作时长之和
  454. #endregion
  455. #region exception_infos 异常状态统计信息 整合
  456. item_one.exception_infos.AddRange(item_two.exception_infos);
  457. #endregion
  458. #region sp_items 假勤统计信息整合
  459. item_one.sp_items.AddRange(item_two.sp_items);
  460. #endregion
  461. #region overwork_info 加班情况 整合
  462. item_one.overwork_info.workday_over_sec += item_two.overwork_info.workday_over_sec; //工作日加班时长
  463. item_one.overwork_info.holidays_over_sec += item_two.overwork_info.holidays_over_sec; //节假日加班时长
  464. item_one.overwork_info.restdays_over_sec += item_two.overwork_info.restdays_over_sec; //休息日加班时长
  465. #endregion
  466. break;
  467. }
  468. }
  469. }
  470. #endregion
  471. checkInView = checkInViewOne;
  472. }
  473. else
  474. {
  475. checkInReq.starttime = (uint)((startDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000);
  476. checkInReq.endtime = (uint)((endDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000);
  477. var json = System.Text.Json.JsonSerializer.Serialize(checkInReq);
  478. var content = new StringContent(json, Encoding.UTF8, "application/json");
  479. var create_Req = await _httpClient.PostAsync(url, content);
  480. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  481. checkInView = System.Text.Json.JsonSerializer.Deserialize<CheckInView>(stringResponse,
  482. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  483. }
  484. #endregion
  485. return checkInView;
  486. }
  487. /// <summary>
  488. /// 获取月打卡数据(redis缓存)
  489. /// </summary>
  490. /// <param name="startDt"></param>
  491. /// <param name="endDt"></param>
  492. /// <returns></returns>
  493. public async Task<CheckInView> GetCheckin_MonthDataRedisAsync(DateTime startDt, DateTime endDt)
  494. {
  495. CheckInView checkInView = new CheckInView();
  496. string checkInDatastring = await RedisRepository.RedisFactory
  497. .CreateRedisRepository()
  498. .StringGetAsync<string>("Checkin_MonthData");//List<T> 取
  499. if (!string.IsNullOrEmpty(checkInDatastring))
  500. {
  501. checkInView = JsonConvert.DeserializeObject<CheckInView>(checkInDatastring);
  502. return checkInView;
  503. }
  504. //获取员工Id
  505. UserIdListView userIdListView = await GetUserIdListAsync();
  506. if (userIdListView.errcode != 0)
  507. {
  508. checkInView.errcode = userIdListView.errcode;
  509. checkInView.errmsg = string.Format("【企业微信】【获取员工IdList】【Msg】{0}", userIdListView.errmsg);
  510. return checkInView;
  511. }
  512. if (userIdListView.dept_user == null || userIdListView.dept_user.Count <= 0)
  513. {
  514. checkInView.errmsg = string.Format("【企业微信】【获取员工IdList】【Msg】未查出员工Id");
  515. return checkInView;
  516. }
  517. //获取月打卡数据 token
  518. Access_TokenView access_Token = await GetTokenAsync(2);
  519. if (access_Token.errcode != 0)
  520. {
  521. checkInView.errcode = access_Token.errcode;
  522. checkInView.errmsg = string.Format("【企业微信】【获取月打卡数据】【Token】【Msg】{0}", access_Token.errmsg);
  523. return checkInView;
  524. }
  525. string url = string.Format("/cgi-bin/checkin/getcheckin_monthdata?access_token={0}", access_Token.access_token);
  526. Checkin_MonthData_Request checkInReq = new Checkin_MonthData_Request();
  527. checkInReq.access_token = access_Token.access_token;
  528. checkInReq.starttime = (uint)(startDt - _1970).TotalSeconds;
  529. checkInReq.endtime = (uint)(endDt - _1970).TotalSeconds;
  530. checkInReq.useridlist = userIdListView.dept_user.Select(it => it.userid).ToList();
  531. var json = System.Text.Json.JsonSerializer.Serialize(checkInReq);
  532. var content = new StringContent(json, Encoding.UTF8, "application/json");
  533. var create_Req = await _httpClient.PostAsync(url, content);
  534. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  535. checkInView = System.Text.Json.JsonSerializer.Deserialize<CheckInView>(stringResponse,
  536. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  537. if (checkInView.errcode == 0)
  538. {
  539. TimeSpan ts = DateTime.Now.AddMinutes(60) - DateTime.Now; //设置redis 过期时间 60分钟
  540. await RedisRepository
  541. .RedisFactory
  542. .CreateRedisRepository()
  543. .StringSetAsync<string>("Checkin_MonthData", JsonConvert.SerializeObject(checkInView), ts);//List<T> 存
  544. }
  545. return checkInView;
  546. }
  547. /// <summary>
  548. /// 获取打卡记录数据
  549. /// </summary>
  550. /// <param name="useridlist">需要获取打卡记录的用户列表</param>
  551. /// <param name="opencheckindatatype">打卡类型。1:上下班打卡;2:外出打卡;3:全部打卡</param>
  552. /// <param name="startDt">获取打卡记录的开始时间。Unix时间戳</param>
  553. /// <param name="endDt">获取打卡记录的结束时间。Unix时间戳</param>
  554. /// <returns></returns>
  555. public async Task<CheckInDataView> GetCheckinDataAsync(List<string> useridlist, int opencheckindatatype, DateTime startDt, DateTime endDt)
  556. {
  557. CheckInDataView checkInDataView = new CheckInDataView();
  558. //参数处理
  559. if (useridlist.Count <= 0)
  560. {
  561. checkInDataView.errmsg = "请填写企业微信用户id,可为多个!";
  562. return checkInDataView;
  563. }
  564. if (useridlist.Count > 100)
  565. {
  566. checkInDataView.errmsg = "用户列表不超过100个。若用户超过100个,请分批获取!";
  567. return checkInDataView;
  568. }
  569. //获取打卡数据 token
  570. Access_TokenView access_Token = await GetTokenAsync(2);
  571. if (access_Token.errcode != 0)
  572. {
  573. checkInDataView.errcode = access_Token.errcode;
  574. checkInDataView.errmsg = string.Format("【企业微信】【获取打卡数据】【Token】【Msg】{0}", access_Token.errmsg);
  575. return checkInDataView;
  576. }
  577. string url = string.Format("/cgi-bin/checkin/getcheckindata?access_token={0}", access_Token.access_token);
  578. DateTime centerDt = startDt.AddDays(30);
  579. long startTs = (long)(startDt - _1970).TotalSeconds;
  580. long centerTs = (long)(centerDt - _1970).TotalSeconds;
  581. long endTs = (long)(endDt - _1970).TotalSeconds;
  582. CheckInData_Request checkInData_Req = new CheckInData_Request()
  583. {
  584. access_token = access_Token.access_token,
  585. opencheckindatatype = opencheckindatatype,
  586. useridlist = useridlist,
  587. starttime = startTs,
  588. endtime = centerTs
  589. };
  590. var json = System.Text.Json.JsonSerializer.Serialize(checkInData_Req);
  591. var content = new StringContent(json, Encoding.UTF8, "application/json");
  592. var create_Req = await _httpClient.PostAsync(url, content);
  593. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  594. checkInDataView = System.Text.Json.JsonSerializer.Deserialize<CheckInDataView>(stringResponse,
  595. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  596. if (centerDt < endDt)
  597. {
  598. checkInData_Req.starttime = centerTs;
  599. checkInData_Req.endtime = endTs;
  600. var json1 = System.Text.Json.JsonSerializer.Serialize(checkInData_Req);
  601. var content1 = new StringContent(json1, Encoding.UTF8, "application/json");
  602. var create_Req1 = await _httpClient.PostAsync(url, content1);
  603. var stringResponse1 = await create_Req1.Content.ReadAsStringAsync();
  604. CheckInDataView checkInDataView1 = System.Text.Json.JsonSerializer.Deserialize<CheckInDataView>(stringResponse1,
  605. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  606. if (checkInDataView1.errcode != 0)
  607. {
  608. return checkInDataView1;
  609. }
  610. checkInDataView.checkindata.AddRange(checkInDataView1.checkindata);
  611. return checkInDataView;
  612. }
  613. return checkInDataView;
  614. }
  615. /// <summary>
  616. /// 获取打卡日报数据
  617. /// </summary>
  618. /// <param name="useridlist"></param>
  619. /// <param name="startDt"></param>
  620. /// <param name="endDt"></param>
  621. /// <returns></returns>
  622. public async Task<CheckInDayDataView> GetCheckInDayDataAsync1(List<string> useridlist, DateTime startDt, DateTime endDt)
  623. {
  624. CheckInDayDataView checkInDayDataView = new CheckInDayDataView();
  625. //参数处理
  626. if (useridlist.Count <= 0)
  627. {
  628. checkInDayDataView.errmsg = "请填写企业微信用户id,可为多个!";
  629. return checkInDayDataView;
  630. }
  631. //获取打卡数据 token
  632. Access_TokenView access_Token = await GetTokenAsync(2);
  633. if (access_Token.errcode != 0)
  634. {
  635. checkInDayDataView.errcode = access_Token.errcode;
  636. checkInDayDataView.errmsg = string.Format("【企业微信】【获取打卡日报数据】【Token】【Msg】{0}", access_Token.errmsg);
  637. return checkInDayDataView;
  638. }
  639. string url = string.Format("/cgi-bin/checkin/getcheckin_daydata?access_token={0}&debug=1", access_Token.access_token);
  640. long startTs = (startDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  641. long endTs = (endDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  642. var checkInData_Req = new
  643. {
  644. access_token = access_Token.access_token,
  645. useridlist = useridlist,
  646. starttime = startTs,
  647. endtime = endTs
  648. };
  649. var json = System.Text.Json.JsonSerializer.Serialize(checkInData_Req);
  650. var content = new StringContent(json, Encoding.UTF8, "application/json");
  651. var create_Req = await _httpClient.PostAsync(url, content);
  652. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  653. checkInDayDataView = System.Text.Json.JsonSerializer.Deserialize<CheckInDayDataView>(stringResponse,
  654. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  655. return checkInDayDataView;
  656. }
  657. /// <summary>
  658. /// 获取打卡日报数据
  659. /// </summary>
  660. /// <param name="useridlist"></param>
  661. /// <param name="startDt"></param>
  662. /// <param name="endDt"></param>
  663. /// <returns></returns>
  664. public async Task<CheckInDayDataView> GetCheckInDayDataAsync(List<string> useridlist, DateTime startDt, DateTime endDt)
  665. {
  666. CheckInDayDataView checkInDayDataView = new CheckInDayDataView();
  667. //参数处理
  668. if (useridlist.Count <= 0)
  669. {
  670. checkInDayDataView.errmsg = "请填写企业微信用户id,可为多个!";
  671. return checkInDayDataView;
  672. }
  673. //获取打卡数据 token
  674. Access_TokenView access_Token = await GetTokenAsync(2);
  675. if (access_Token.errcode != 0)
  676. {
  677. checkInDayDataView.errcode = access_Token.errcode;
  678. checkInDayDataView.errmsg = string.Format("【企业微信】【获取打卡日报数据】【Token】【Msg】{0}", access_Token.errmsg);
  679. return checkInDayDataView;
  680. }
  681. string url = string.Format("/cgi-bin/checkin/getcheckin_daydata?access_token={0}&debug=1", access_Token.access_token);
  682. int days = (int)(endDt - startDt).TotalDays;
  683. if (days > 31)
  684. {
  685. long startTs_One = (startDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  686. long endTs_One = (startDt.AddDays(31).ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  687. long startTs_Two = (startDt.AddDays(31).ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  688. long endTs_Two = (endDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  689. var checkInData_ReqOne = new
  690. {
  691. access_token = access_Token.access_token,
  692. useridlist = useridlist,
  693. starttime = startTs_One,
  694. endtime = endTs_One
  695. };
  696. var jsonOne = System.Text.Json.JsonSerializer.Serialize(checkInData_ReqOne);
  697. var contentOne = new StringContent(jsonOne, Encoding.UTF8, "application/json");
  698. var create_ReqOne = await _httpClient.PostAsync(url, contentOne);
  699. var stringResponseOne = await create_ReqOne.Content.ReadAsStringAsync();
  700. CheckInDayDataView checkInDayDataViewOne = System.Text.Json.JsonSerializer.Deserialize<CheckInDayDataView>(stringResponseOne,
  701. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  702. if (checkInDayDataViewOne.errcode != 0)
  703. {
  704. return checkInDayDataViewOne;
  705. }
  706. var checkInData_ReqTwo = new
  707. {
  708. access_token = access_Token.access_token,
  709. useridlist = useridlist,
  710. starttime = startTs_Two,
  711. endtime = endTs_Two
  712. };
  713. var jsonTwo = System.Text.Json.JsonSerializer.Serialize(checkInData_ReqTwo);
  714. var contentTwo = new StringContent(jsonTwo, Encoding.UTF8, "application/json");
  715. var create_ReqTwo = await _httpClient.PostAsync(url, contentTwo);
  716. var stringResponseTwo = await create_ReqTwo.Content.ReadAsStringAsync();
  717. CheckInDayDataView checkInDayDataViewTwo = System.Text.Json.JsonSerializer.Deserialize<CheckInDayDataView>(stringResponseTwo,
  718. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  719. if (checkInDayDataViewTwo.errcode != 0)
  720. {
  721. return checkInDayDataViewTwo;
  722. }
  723. checkInDayDataViewOne.datas.AddRange(checkInDayDataViewTwo.datas);
  724. return checkInDayDataViewOne;
  725. }
  726. else
  727. {
  728. long startTs = (startDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  729. long endTs = (endDt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  730. var checkInData_Req = new
  731. {
  732. access_token = access_Token.access_token,
  733. useridlist = useridlist,
  734. starttime = startTs,
  735. endtime = endTs
  736. };
  737. var json = System.Text.Json.JsonSerializer.Serialize(checkInData_Req);
  738. var content = new StringContent(json, Encoding.UTF8, "application/json");
  739. var create_Req = await _httpClient.PostAsync(url, content);
  740. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  741. checkInDayDataView = System.Text.Json.JsonSerializer.Deserialize<CheckInDayDataView>(stringResponse,
  742. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  743. }
  744. return checkInDayDataView;
  745. }
  746. #endregion
  747. #region 审批
  748. /// <summary>
  749. /// 获取审批数据(旧)
  750. /// </summary>
  751. /// <param name="startDt"></param>
  752. /// <param name="endDt"></param>
  753. /// <returns></returns>
  754. public async Task<ApprovalDataView> GetApprovalDataAsync(DateTime startDt, DateTime endDt)
  755. {
  756. ApprovalDataView approvalDataView = new ApprovalDataView();
  757. //获取审批数据 token
  758. Access_TokenView access_Token = await GetTokenAsync(5);
  759. if (access_Token.errcode != 0)
  760. {
  761. approvalDataView.errcode = access_Token.errcode;
  762. approvalDataView.errmsg = string.Format("【企业微信】【获取审批数据】【Token】【Msg】{0}", access_Token.errmsg);
  763. return approvalDataView;
  764. }
  765. string url = string.Format("/cgi-bin/corp/getapprovaldata?access_token={0}", access_Token.access_token);
  766. ApprovalData_Request approvalDataReq = new ApprovalData_Request();
  767. approvalDataReq.access_token = access_Token.access_token;
  768. approvalDataReq.starttime = (uint)(startDt - _1970).TotalSeconds;
  769. approvalDataReq.endtime = (uint)(endDt - _1970).TotalSeconds;
  770. var json = System.Text.Json.JsonSerializer.Serialize(approvalDataReq);
  771. var content = new StringContent(json, Encoding.UTF8, "application/json");
  772. var create_Req = await _httpClient.PostAsync(url, content);
  773. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  774. approvalDataView = System.Text.Json.JsonSerializer.Deserialize<ApprovalDataView>(stringResponse,
  775. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  776. List<Sp_Info> sp_datas = new List<Sp_Info>();
  777. sp_datas.AddRange(approvalDataView.data);
  778. int index = 0;
  779. //多次访问审批接口
  780. if (approvalDataView.total >= 100)
  781. {
  782. approvalDataView.total -= 100;
  783. int forTotal = approvalDataView.total % 100 == 0 ? approvalDataView.total / 100 : approvalDataView.total / 100 + 1;
  784. long? next_spnum = approvalDataView.next_spnum;
  785. approvalDataReq.next_spnum = next_spnum;
  786. for (int i = 0; i < forTotal; i++)
  787. {
  788. index++;
  789. var for_json = System.Text.Json.JsonSerializer.Serialize(approvalDataReq);
  790. var for_content = new StringContent(for_json, Encoding.UTF8, "application/json");
  791. var for_create_Req = await _httpClient.PostAsync(url, for_content);
  792. var for_stringResponse = await for_create_Req.Content.ReadAsStringAsync();
  793. ApprovalDataView for_approvalDataView = System.Text.Json.JsonSerializer.Deserialize<ApprovalDataView>(for_stringResponse,
  794. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  795. approvalDataReq.next_spnum = for_approvalDataView.next_spnum; //重新定义游标
  796. sp_datas.AddRange(for_approvalDataView.data); //追加数据
  797. }
  798. approvalDataView.total += 100;
  799. }
  800. approvalDataView.data = sp_datas;
  801. return approvalDataView;
  802. }
  803. /// <summary>
  804. /// 获取审批数据(旧)(redis缓存)
  805. /// </summary>
  806. /// <param name="startDt"></param>
  807. /// <param name="endDt"></param>
  808. /// <returns></returns>
  809. public async Task<List<Sp_Info>> GetApprovalDatasAsync(DateTime startDt, DateTime endDt)
  810. {
  811. List<Sp_Info> sp_Infos = new List<Sp_Info>();
  812. //获取所有打卡补卡,审批 数据 前后范围增加10天
  813. DateTime sp_startDt = startDt.AddDays(-10);
  814. DateTime sp_centerDt = sp_startDt.AddDays(30);
  815. DateTime sp_endDt = endDt.AddDays(10);
  816. ApprovalDataView approvalData_1 = await GetApprovalDataAsync(sp_startDt, sp_centerDt); //时间段内所有 审批数据
  817. ApprovalDataView approvalData_2 = await GetApprovalDataAsync(sp_centerDt, sp_endDt); //时间段内所有 审批数据
  818. if (approvalData_1.errcode != 0)
  819. {
  820. Log.Error("企业微信 获取 " + sp_startDt + " - " + sp_centerDt + " 内审批 Msg:" + approvalData_1.errmsg);
  821. return sp_Infos;
  822. }
  823. sp_Infos.AddRange(approvalData_1.data);
  824. if (approvalData_2.errcode != 0)
  825. {
  826. Log.Error("企业微信 获取 " + sp_centerDt + " - " + sp_endDt + " 内审批 Msg:" + approvalData_2.errmsg);
  827. return sp_Infos;
  828. }
  829. sp_Infos.AddRange(approvalData_2.data);
  830. sp_Infos = sp_Infos.Where(it => it.sp_status == 2).ToList(); //存储已审核的数据
  831. return sp_Infos;
  832. }
  833. /// <summary>
  834. /// 获取审批数据(旧)(redis缓存)
  835. /// </summary>
  836. /// <param name="startDt"></param>
  837. /// <param name="endDt"></param>
  838. /// <returns></returns>
  839. public async Task<List<Sp_Info>> GetApprovalDatasRedisAsync(DateTime startDt, DateTime endDt)
  840. {
  841. List<Sp_Info> sp_Infos = new List<Sp_Info>();
  842. //获取所有打卡补卡,审批 数据 前后范围增加10天
  843. DateTime sp_startDt = startDt.AddDays(-10);
  844. DateTime sp_centerDt = sp_startDt.AddDays(30);
  845. DateTime sp_endDt = endDt.AddDays(10);
  846. string redisName = "ApprovalData" + sp_startDt.ToString("yyyyMMdd") + "-" + sp_endDt.ToString("yyyyMMdd");
  847. string sp_InfosString = string.Empty;
  848. //sp_InfosString = await RedisRepository.RedisFactory
  849. // .CreateRedisRepository()
  850. // .StringGetAsync<string>(redisName);//string 取
  851. if (string.IsNullOrEmpty(sp_InfosString))
  852. {
  853. ApprovalDataView approvalData_1 = await GetApprovalDataAsync(sp_startDt, sp_centerDt); //时间段内所有 审批数据
  854. ApprovalDataView approvalData_2 = await GetApprovalDataAsync(sp_centerDt, sp_endDt); //时间段内所有 审批数据
  855. if (approvalData_1.errcode != 0)
  856. {
  857. Log.Error("企业微信 获取 " + sp_startDt + " - " + sp_centerDt + " 内审批 Msg:" + approvalData_1.errmsg);
  858. return sp_Infos;
  859. }
  860. sp_Infos.AddRange(approvalData_1.data);
  861. if (approvalData_2.errcode != 0)
  862. {
  863. Log.Error("企业微信 获取 " + sp_centerDt + " - " + sp_endDt + " 内审批 Msg:" + approvalData_2.errmsg);
  864. return sp_Infos;
  865. }
  866. sp_Infos.AddRange(approvalData_2.data);
  867. sp_Infos = sp_Infos.Where(it => it.sp_status == 2).ToList(); //存储已审核的数据
  868. TimeSpan ts = DateTime.Now.AddMinutes(60) - DateTime.Now; //设置redis 过期时间 60分钟
  869. await RedisRepository
  870. .RedisFactory
  871. .CreateRedisRepository()
  872. .StringSetAsync<string>(redisName, JsonConvert.SerializeObject(sp_Infos), ts);//string 存
  873. }
  874. else
  875. {
  876. sp_Infos = JsonConvert.DeserializeObject<List<Sp_Info>>(sp_InfosString);
  877. }
  878. return sp_Infos;
  879. }
  880. /// <summary>
  881. /// 批量获取审批单号
  882. /// </summary>
  883. /// <param name="startDt"></param>
  884. /// <param name="endDt"></param>
  885. /// <param name="creator">
  886. /// 申请人
  887. /// </param>
  888. /// <param name="sp_status">
  889. /// sp_status-审批单状态(1-审批中;2-已通过;3-已驳回;4-已撤销;6-通过后撤销;7-已删除;10-已支付)
  890. /// </param>
  891. /// <param name="record_type">
  892. /// record_type == 0 ALL 有值 请填写对应值
  893. /// record_type - 审批单类型属性,1-请假;2-打卡补卡;3-出差;4-外出;5-加班; 6- 调班;7-会议室预定;8-退款审批;9-红包报销审批
  894. /// </param>
  895. /// <returns></returns>
  896. private async Task<ApprovalInfoView> GetApprovalInfoAsync(DateTime startDt, DateTime endDt, string creator, int sp_status, int record_type)
  897. {
  898. Stopwatch sw = new Stopwatch();
  899. sw.Start();
  900. ApprovalInfoView approvalInfoView = new ApprovalInfoView();
  901. //获取所有打卡补卡,审批 数据 向前增加30天 向后范围增加15天
  902. DateTime sp_startDt = startDt.AddDays(-30);
  903. DateTime sp_endDt = endDt.AddDays(15);
  904. //获取审批数据 token
  905. Access_TokenView access_Token = await GetTokenAsync(5);
  906. if (access_Token.errcode != 0)
  907. {
  908. approvalInfoView.errcode = access_Token.errcode;
  909. approvalInfoView.errmsg = string.Format("【企业微信】【批量获取审批单号】【Token】【Msg】{0}", access_Token.errmsg);
  910. return approvalInfoView;
  911. }
  912. string url = string.Format("/cgi-bin/oa/getapprovalinfo?access_token={0}", access_Token.access_token);
  913. List<Dic> filters = new List<Dic> {
  914. new Dic() { key = "creator", value = creator }, //筛选条件 申请人
  915. new Dic() { key = "sp_status", value = sp_status.ToString() }, //筛选条件 审核状态 2 已同意
  916. };
  917. if (record_type != 0)
  918. {
  919. filters.Add(new Dic() { key = "record_type", value = record_type.ToString() }); //筛选条件 审批单类型 请假 1
  920. }
  921. int days = (sp_endDt - sp_startDt).Days;
  922. decimal runCount = days % 30;
  923. int runCount1 = 0;
  924. if (runCount == 0) runCount1 = (int)(days % 30.00M);
  925. else runCount1 = (int)Math.Ceiling(days / 30.00M);
  926. List<string> sp_no_lists = new List<string>();
  927. for (int i = 0; i < runCount1; i++)
  928. {
  929. DateTime for_sp_startDt = sp_startDt;
  930. DateTime for_sp_endDt = sp_startDt.AddDays(30);
  931. sp_startDt = sp_startDt.AddDays(30);
  932. if (for_sp_endDt >= sp_endDt)
  933. {
  934. for_sp_endDt = sp_endDt;
  935. }
  936. ApprovalInfo_Request approvalInfoReq = new ApprovalInfo_Request()
  937. {
  938. access_token = access_Token.access_token,
  939. starttime = (uint)ConvertToTimeSpan(for_sp_startDt),
  940. endtime = (uint)ConvertToTimeSpan(for_sp_endDt),
  941. filters = filters.ToList(),
  942. };
  943. var json = System.Text.Json.JsonSerializer.Serialize(approvalInfoReq);
  944. var content = new StringContent(json, Encoding.UTF8, "application/json");
  945. var create_Req = await _httpClient.PostAsync(url, content);
  946. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  947. ApprovalInfoView approvalInfoView1 = System.Text.Json.JsonSerializer.Deserialize<ApprovalInfoView>(stringResponse,
  948. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  949. #region 分页调用 new_next_cursor != null
  950. string new_cursor = approvalInfoView1.new_next_cursor;
  951. while (!string.IsNullOrEmpty(new_cursor))
  952. {
  953. approvalInfoReq.new_cursor = new_cursor;
  954. var json1 = System.Text.Json.JsonSerializer.Serialize(approvalInfoReq);
  955. var content1 = new StringContent(json, Encoding.UTF8, "application/json");
  956. var create_Req1 = await _httpClient.PostAsync(url, content1);
  957. var stringResponse1 = await create_Req1.Content.ReadAsStringAsync();
  958. ApprovalInfoView approvalInfoView11 = System.Text.Json.JsonSerializer.Deserialize<ApprovalInfoView>(stringResponse1,
  959. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  960. if (approvalInfoView11.errcode != 0)
  961. {
  962. return approvalInfoView1;
  963. }
  964. new_cursor = approvalInfoView11.new_next_cursor;
  965. if (approvalInfoView11.sp_no_list.Count > 0 || approvalInfoView11.sp_no_list != null)
  966. {
  967. sp_no_lists.AddRange(approvalInfoView1.sp_no_list);
  968. }
  969. }
  970. #endregion
  971. if (approvalInfoView1.errcode != 0)
  972. {
  973. return approvalInfoView1;
  974. }
  975. if (approvalInfoView1.sp_no_list.Count > 0 || approvalInfoView1.sp_no_list != null)
  976. {
  977. sp_no_lists.AddRange(approvalInfoView1.sp_no_list);
  978. }
  979. }
  980. approvalInfoView.errcode = 0;
  981. if (sp_no_lists.Count > 0)
  982. {
  983. sp_no_lists = sp_no_lists.Distinct().ToList();
  984. }
  985. approvalInfoView.sp_no_list = sp_no_lists;
  986. sw.Stop();
  987. approvalInfoView.errmsg = approvalInfoView.errmsg + " 耗时:" + sw.Elapsed.TotalMilliseconds + "ms";
  988. return approvalInfoView;
  989. }
  990. /// <summary>
  991. /// 获取审批申请详情
  992. /// </summary>
  993. /// <param name="sp_no"></param>
  994. /// <returns></returns>
  995. public async Task<ApprovalDetailView> GetApprovalDetailAsync(string sp_no)
  996. {
  997. ApprovalDetailView ApprovalDetailView = new ApprovalDetailView();
  998. if (string.IsNullOrEmpty(sp_no))
  999. {
  1000. return ApprovalDetailView;
  1001. }
  1002. //获取审批数据 token
  1003. Access_TokenView access_Token = await GetTokenAsync(5);
  1004. if (access_Token.errcode != 0)
  1005. {
  1006. ApprovalDetailView.errcode = access_Token.errcode;
  1007. ApprovalDetailView.errmsg = string.Format("【企业微信】【审批申请详情】【Token】【Msg】{0}", access_Token.errmsg);
  1008. return ApprovalDetailView;
  1009. }
  1010. string url = string.Format("/cgi-bin/oa/getapprovaldetail?access_token={0}", access_Token.access_token);
  1011. ApprovalDetail_Request approvalDetail_Req = new ApprovalDetail_Request()
  1012. {
  1013. access_token = access_Token.access_token,
  1014. sp_no = sp_no,
  1015. };
  1016. var json = System.Text.Json.JsonSerializer.Serialize(approvalDetail_Req);
  1017. var content = new StringContent(json, Encoding.UTF8, "application/json");
  1018. var create_Req = await _httpClient.PostAsync(url, content);
  1019. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  1020. ApprovalDetailView = System.Text.Json.JsonSerializer.Deserialize<ApprovalDetailView>(stringResponse,
  1021. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  1022. return ApprovalDetailView;
  1023. }
  1024. /// <summary>
  1025. /// 批量获取审批详情
  1026. /// </summary>
  1027. /// <param name="startDt"></param>
  1028. /// <param name="endDt"></param>
  1029. /// <param name="creator">
  1030. /// 申请人
  1031. /// </param>
  1032. /// <param name="sp_status">
  1033. /// sp_status-审批单状态(1-审批中;2-已通过;3-已驳回;4-已撤销;6-通过后撤销;7-已删除;10-已支付)
  1034. /// </param>
  1035. /// <param name="record_type">
  1036. /// record_type - 审批单类型属性,1-请假;2-打卡补卡;3-出差;4-外出;5-加班; 6- 调班;7-会议室预定;8-退款审批;9-红包报销审批
  1037. /// </param>
  1038. /// <returns></returns>
  1039. public async Task<List<Sp_Detail>> GetApprovalDetailsAsync(DateTime startDt, DateTime endDt, string creator, int sp_status, int record_type)
  1040. {
  1041. Stopwatch sw = new Stopwatch();
  1042. sw.Start();
  1043. List<Sp_Detail> details = new List<Sp_Detail>();
  1044. if (string.IsNullOrEmpty(creator))
  1045. {
  1046. return details;
  1047. }
  1048. ApprovalInfoView approvalInfoView = new ApprovalInfoView();
  1049. approvalInfoView = await GetApprovalInfoAsync(startDt, endDt, creator, sp_status, record_type);
  1050. if (approvalInfoView.errcode != 0)
  1051. {
  1052. return details;
  1053. }
  1054. //循环查询详情
  1055. foreach (var item in approvalInfoView.sp_no_list)
  1056. {
  1057. ApprovalDetailView approvalDetailView = new ApprovalDetailView();
  1058. approvalDetailView = await GetApprovalDetailAsync(item);
  1059. if (approvalDetailView.errcode != 0)
  1060. {
  1061. Log.Error("【GetApprovalDetailsAsync】 record_type:" + record_type + " ErrorMsg:" + approvalDetailView.errmsg);
  1062. break;
  1063. }
  1064. details.Add(approvalDetailView.info);
  1065. }
  1066. sw.Stop();
  1067. double hs = sw.Elapsed.TotalMilliseconds;
  1068. return details;
  1069. }
  1070. /// <summary>
  1071. /// 获取审批模板详情
  1072. /// </summary>
  1073. /// <param name="template_id">模板Id</param>
  1074. /// <returns></returns>
  1075. public async Task<TemplateDetailView> GetTemplateDetailAsync(string template_id)
  1076. {
  1077. TemplateDetailView templateDetailView = new TemplateDetailView();
  1078. if (string.IsNullOrEmpty(template_id))
  1079. {
  1080. templateDetailView.errmsg = "template_id为空!";
  1081. return templateDetailView;
  1082. }
  1083. //获取审批数据 token
  1084. Access_TokenView access_Token = await GetTokenAsync(5);
  1085. if (access_Token.errcode != 0)
  1086. {
  1087. templateDetailView.errcode = access_Token.errcode;
  1088. templateDetailView.errmsg = string.Format("【企业微信】【审批申请详情】【Token】【Msg】{0}", access_Token.errmsg);
  1089. return templateDetailView;
  1090. }
  1091. string url = string.Format("/cgi-bin/oa/gettemplatedetail?access_token={0}", access_Token.access_token);
  1092. var approvalDetail_Req = new
  1093. {
  1094. access_token = access_Token.access_token,
  1095. template_id = template_id,
  1096. };
  1097. var json = System.Text.Json.JsonSerializer.Serialize(approvalDetail_Req);
  1098. var content = new StringContent(json, Encoding.UTF8, "application/json");
  1099. var create_Req = await _httpClient.PostAsync(url, content);
  1100. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  1101. templateDetailView = System.Text.Json.JsonSerializer.Deserialize<TemplateDetailView>(stringResponse,
  1102. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  1103. return templateDetailView;
  1104. }
  1105. #endregion
  1106. #region hook机器人
  1107. /// <summary>
  1108. /// 发送团组信息给财务群
  1109. /// </summary>
  1110. /// <param name="msg"></param>
  1111. /// <returns></returns>
  1112. /// <exception cref="NotImplementedException"></exception>
  1113. public async Task<ResponseBase> RobotSendMsg_GroupInfo(string msg)
  1114. {
  1115. string key = "b4fe152f-a97a-48b1-830f-ab447f6d2f5f";
  1116. string url = string.Format("/cgi-bin/webhook/send?key={0}", key);
  1117. RobotSendMsg_GroupInfo_Content contentStr = new RobotSendMsg_GroupInfo_Content() { content = msg };
  1118. RobotSendMsg_GroupInfo_Param reqJson = new RobotSendMsg_GroupInfo_Param()
  1119. {
  1120. msgtype = "markdown",
  1121. markdown = contentStr
  1122. };
  1123. var json = System.Text.Json.JsonSerializer.Serialize(reqJson);
  1124. var content = new StringContent(json, Encoding.UTF8, "application/json");
  1125. var create_Req = await _httpClient.PostAsync(url, content);
  1126. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  1127. ResponseBase sendMsgView = System.Text.Json.JsonSerializer.Deserialize<ResponseBase>(stringResponse,
  1128. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  1129. return sendMsgView;
  1130. }
  1131. #endregion
  1132. #region 团组状态通知
  1133. /// <summary>
  1134. /// 获取部门成员
  1135. /// </summary>
  1136. /// <param name="departmentId"></param>
  1137. /// <returns></returns>
  1138. public async Task<GroupStatus_UserSimplelistView> GroupStatus_GetUserList(int departmentId = 8402038)
  1139. {
  1140. GroupStatus_UserSimplelistView result = new GroupStatus_UserSimplelistView();
  1141. Access_TokenView access_Token = await GetTokenAsync(6);
  1142. if (access_Token.errcode != 0)
  1143. {
  1144. result.errcode = access_Token.errcode;
  1145. result.errmsg = string.Format("【企业微信】【团组状态通知】【Token】【Msg】{0}", access_Token.errmsg);
  1146. return result;
  1147. }
  1148. string url = string.Format("/cgi-bin/user/simplelist?access_token={0}&department_id={1}", access_Token.access_token, departmentId);
  1149. var simplelist_Req = await _httpClient.GetAsync(url);
  1150. if (simplelist_Req.IsSuccessStatusCode)
  1151. {
  1152. var stringResponse = await simplelist_Req.Content.ReadAsStringAsync();
  1153. result = System.Text.Json.JsonSerializer.Deserialize<GroupStatus_UserSimplelistView>(stringResponse,
  1154. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  1155. }
  1156. else
  1157. {
  1158. result.errcode = -1;
  1159. result.errmsg = "企业微信部门列表未获取到!";
  1160. }
  1161. return result;
  1162. }
  1163. /// <summary>
  1164. /// 创建群聊
  1165. /// </summary>
  1166. /// <param name="chatName"></param>
  1167. /// <param name="owner"></param>
  1168. /// <param name="userList"></param>
  1169. /// <param name="chatId"></param>
  1170. /// <returns></returns>
  1171. public async Task<GroupStatus_CreateChatView> GroupStatus_CreateChat(string chatName, string owner, List<string> userList, string chatId)
  1172. {
  1173. GroupStatus_CreateChatView result = new GroupStatus_CreateChatView();
  1174. Access_TokenView access_Token = await GetTokenAsync(6);
  1175. if (access_Token.errcode != 0)
  1176. {
  1177. result.errcode = access_Token.errcode;
  1178. result.errmsg = string.Format("【企业微信】【团组状态通知】【Token】【Msg】{0}", access_Token.errmsg);
  1179. return result;
  1180. }
  1181. GroupStatus_CreateChat reqJson = new GroupStatus_CreateChat()
  1182. {
  1183. chatid = chatId,
  1184. name = chatName,
  1185. owner = owner,
  1186. userlist = userList
  1187. };
  1188. string url = string.Format("/cgi-bin/appchat/create?access_token={0}&debug=1", access_Token.access_token);
  1189. var json = System.Text.Json.JsonSerializer.Serialize(reqJson);
  1190. var content = new StringContent(json, Encoding.UTF8, "application/json");
  1191. var create_Req = await _httpClient.PostAsync(url, content);
  1192. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  1193. result = System.Text.Json.JsonSerializer.Deserialize<GroupStatus_CreateChatView>(stringResponse,
  1194. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  1195. return result;
  1196. }
  1197. /// <summary>
  1198. /// 向群聊发送信息
  1199. /// </summary>
  1200. /// <param name="chatId"></param>
  1201. /// <param name="msgContent"></param>
  1202. /// <param name="msgType"></param>
  1203. /// <returns></returns>
  1204. /// <exception cref="NotImplementedException"></exception>
  1205. public async Task<ResponseBase> GroupStatus_SendChatMsg_Markdown(string chatId, string msgContent, string msgType = "markdown")
  1206. {
  1207. ResponseBase result = new ResponseBase();
  1208. Access_TokenView access_Token = await GetTokenAsync(6);
  1209. if (access_Token.errcode != 0)
  1210. {
  1211. result.errcode = access_Token.errcode;
  1212. result.errmsg = string.Format("【企业微信】【团组状态通知】【Token】【Msg】{0}", access_Token.errmsg);
  1213. return result;
  1214. }
  1215. RobotSendMsg_GroupInfo_Content markdown = new RobotSendMsg_GroupInfo_Content() { content = msgContent };
  1216. GroupStatus_AppChatSend_Markdown reqJson = new GroupStatus_AppChatSend_Markdown()
  1217. {
  1218. chatid = chatId,
  1219. msgtype = msgType,
  1220. markdown = markdown
  1221. };
  1222. string url = string.Format("/cgi-bin/appchat/send?access_token={0}", access_Token.access_token);
  1223. var json = System.Text.Json.JsonSerializer.Serialize(reqJson);
  1224. var content = new StringContent(json, Encoding.UTF8, "application/json");
  1225. var create_Req = await _httpClient.PostAsync(url, content);
  1226. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  1227. result = System.Text.Json.JsonSerializer.Deserialize<ResponseBase>(stringResponse,
  1228. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  1229. return result;
  1230. }
  1231. /// <summary>
  1232. /// 向用户发送Markdown信息
  1233. /// </summary>
  1234. /// <param name="toUser"></param>
  1235. /// <param name="msgContent"></param>
  1236. /// <param name="msgType"></param>
  1237. /// <returns></returns>
  1238. /// <exception cref="NotImplementedException"></exception>
  1239. public async Task<GroupStatus_SendMessageView> GroupStatus_SendMessage_ToUser_Markdown(List<string> toUser, string msgContent, string msgType = "markdown")
  1240. {
  1241. GroupStatus_SendMessageView result = new GroupStatus_SendMessageView();
  1242. Access_TokenView access_Token = await GetTokenAsync(6);
  1243. if (access_Token.errcode != 0)
  1244. {
  1245. result.errcode = access_Token.errcode;
  1246. result.errmsg = string.Format("【企业微信】【团组状态通知】【Token】【Msg】{0}", access_Token.errmsg);
  1247. return result;
  1248. }
  1249. RobotSendMsg_GroupInfo_Content markdown = new RobotSendMsg_GroupInfo_Content() { content = msgContent };
  1250. string userIds = "";
  1251. toUser.ForEach(s => userIds += s + "|");
  1252. userIds = userIds.TrimEnd('|');
  1253. GroupStatus_AppSend_Markdown reqJson = new GroupStatus_AppSend_Markdown()
  1254. {
  1255. markdown = markdown,
  1256. touser = userIds
  1257. };
  1258. string url = string.Format("/cgi-bin/message/send?access_token={0}&debug=1", access_Token.access_token);
  1259. var json = System.Text.Json.JsonSerializer.Serialize(reqJson);
  1260. var content = new StringContent(json, Encoding.UTF8, "application/json");
  1261. var create_Req = await _httpClient.PostAsync(url, content);
  1262. var stringResponse = await create_Req.Content.ReadAsStringAsync();
  1263. result = System.Text.Json.JsonSerializer.Deserialize<GroupStatus_SendMessageView>(stringResponse,
  1264. new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
  1265. return result;
  1266. }
  1267. #endregion
  1268. public long ConvertToTimeSpan(DateTime dt)
  1269. {
  1270. return (dt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
  1271. }
  1272. }
  1273. }