CoreAPIHttpService.cs 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055
  1. using Microsoft.Extensions.Configuration;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Dynamic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Http;
  9. using System.Net.Http.Json;
  10. using System.Text;
  11. using System.Text.Json;
  12. using System.Threading.Tasks;
  13. using System.Web;
  14. using TEAMModelOS.Models;
  15. using TEAMModelOS.SDK.DI;
  16. using TEAMModelOS.SDK.Extension;
  17. using TEAMModelOS.SDK.Models;
  18. using TEAMModelOS.SDK.Models.Cosmos.BI;
  19. using TEAMModelOS.SDK.Models.Service;
  20. using static TEAMModelOS.SDK.CoreAPIHttpService;
  21. namespace TEAMModelOS.SDK
  22. {
  23. public class CoreAPIHttpServiceOptions
  24. {
  25. public string location { get; set; }
  26. public string coreUrl { get; set; }
  27. public string bbUrl { get; set; }
  28. public string clientID { get; set; }
  29. public string clientSecret { get; set; }
  30. }
  31. public class CoreAPIHttpService
  32. {
  33. //private readonly IWebHostEnvironment _environment;
  34. public bool check=true;
  35. private SnowflakeId _snowflakeId;
  36. private readonly HttpClient _httpClient;
  37. public readonly CoreAPIHttpServiceOptions options;
  38. //private readonly IConfiguration _configuration;
  39. // private readonly DI.DingDing _dingDing;
  40. //public readonly Option _option;
  41. public CoreAPIHttpService(HttpClient httpClient, IConfiguration _configuration , SnowflakeId snowflakeId)
  42. {
  43. _httpClient = httpClient;
  44. string location = _configuration.GetValue<string>("Option:Location");
  45. string url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  46. string bburl = _configuration.GetValue<string>("HaBookAuth:CoreBBAPI");
  47. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  48. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  49. options = new CoreAPIHttpServiceOptions
  50. {
  51. location=location,
  52. coreUrl=url,
  53. bbUrl=bburl,
  54. clientID=clientID,
  55. clientSecret=clientSecret
  56. };
  57. //_environment = environment;
  58. _snowflakeId = snowflakeId;
  59. //_option = option?.Value;
  60. //_configuration = configuration;
  61. //_dingDing = dingDing;
  62. }
  63. public class CoreAPIToken {
  64. public string id_token { get; set; }
  65. public string access_token { get; set; }
  66. public string expires_in { get; set; }
  67. public string token_type { get; set; }
  68. }
  69. public async Task<(HttpStatusCode code,string msg )> AdminChange(AdminChange data, string location, IConfiguration _configuration, DI.DingDing _dingDing)
  70. {
  71. /**
  72. IES5 管理员变更 调用BB的webhook接口和数据格式。
  73. https://bb.teammodel.cn/ies5/admin-change
  74. {
  75. "school": "hbcn",
  76. "lang":"zh-cn",
  77. "adminType":"master",
  78. "adminAdd": [
  79. "1535418750"
  80. ],
  81. "adminRmv": [
  82. "1595321354"
  83. ]
  84. }
  85. adminType: 主管理员 ,master 次要管理员,minor
  86. lang 语系"zh-cn" ,zh-tw", "en-us"
  87. **/
  88. try
  89. {
  90. string url = _configuration.GetValue<string>("HaBookAuth:CoreBBAPI") + "/ies5/admin-change";
  91. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  92. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  93. if (location.Contains("China"))
  94. {
  95. location = "China";
  96. }
  97. else if (location.Contains("Global"))
  98. {
  99. location = "Global";
  100. }
  101. var client = _httpClient;
  102. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  103. if (client.DefaultRequestHeaders.Contains("Authorization"))
  104. {
  105. client.DefaultRequestHeaders.Remove("Authorization");
  106. }
  107. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  108. HttpResponseMessage responseMessage = await client.PostAsJsonAsync(url, data);
  109. if (responseMessage.Content != null)
  110. {
  111. string content = await responseMessage.Content.ReadAsStringAsync();
  112. if (!string.IsNullOrWhiteSpace(content))
  113. {
  114. return (responseMessage.StatusCode, content);
  115. }
  116. else
  117. {
  118. return (responseMessage.StatusCode, null);
  119. }
  120. }
  121. else
  122. {
  123. return (responseMessage.StatusCode, null);
  124. }
  125. }
  126. catch (Exception ex)
  127. {
  128. await _dingDing.SendBotMsg($"{location},管理员或管理权限变更通知BB处理相关通知异常\n{data.ToJsonString()}{ex.Message},\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  129. return (HttpStatusCode.InternalServerError, null);
  130. }
  131. }
  132. public async Task<(HttpStatusCode code , CoreAPIToken token )> GetCoreAPIoAuth2Token(Dictionary<string,object> data, string location, IConfiguration _configuration, DI.DingDing _dingDing) {
  133. try
  134. {
  135. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  136. //coreUrl = "https://api2-rc.teammodel.cn";
  137. url = $"{url}/oauth2/token";
  138. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  139. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  140. if (location.Contains("China"))
  141. {
  142. location = "China";
  143. }
  144. else if (location.Contains("Global"))
  145. {
  146. location = "Global";
  147. }
  148. var client = _httpClient ;
  149. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  150. if (client.DefaultRequestHeaders.Contains("Authorization"))
  151. {
  152. client.DefaultRequestHeaders.Remove("Authorization");
  153. }
  154. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  155. HttpResponseMessage responseMessage = await client.PostAsJsonAsync(url, data);
  156. if (responseMessage.Content != null)
  157. {
  158. string content = await responseMessage.Content.ReadAsStringAsync();
  159. if (!string.IsNullOrWhiteSpace(content))
  160. {
  161. CoreAPIToken coreAPI = content.ToObject<CoreAPIToken>();
  162. return (responseMessage.StatusCode, coreAPI);
  163. }
  164. else
  165. {
  166. return (responseMessage.StatusCode, null);
  167. }
  168. }
  169. else
  170. {
  171. return (responseMessage.StatusCode, null);
  172. }
  173. }
  174. catch (Exception ex)
  175. {
  176. await _dingDing.SendBotMsg($"{location}验证码发送异常:\n{ex.Message}\n{ex.StackTrace}", DI.GroupNames.醍摩豆服務運維群組);
  177. return (HttpStatusCode.InternalServerError, null);
  178. }
  179. }
  180. /// <summary>
  181. /// 撤销通知
  182. /// </summary>
  183. /// <param name="indexNums"></param>
  184. /// <param name="location"></param>
  185. /// <param name="_configuration"></param>
  186. public async void CancelNotify(string indexNums, string location, IConfiguration _configuration)
  187. {
  188. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  189. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  190. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  191. if (location.Contains("China"))
  192. {
  193. location = "China";
  194. }
  195. else if (location.Contains("Global"))
  196. {
  197. location = "Global";
  198. }
  199. var client = _httpClient;
  200. var token =await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  201. if (client.DefaultRequestHeaders.Contains("Authorization"))
  202. {
  203. client.DefaultRequestHeaders.Remove("Authorization");
  204. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  205. }
  206. else
  207. {
  208. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  209. }
  210. HttpResponseMessage responseMessage = await _httpClient.PostAsJsonAsync($"{url}/service/DelNotify", new { indexNums= new List<string> { indexNums } });
  211. if (responseMessage.StatusCode == HttpStatusCode.OK)
  212. {
  213. string content = await responseMessage.Content.ReadAsStringAsync();
  214. }
  215. else
  216. {
  217. }
  218. }
  219. /*
  220. hubName string Optional 指定要傳送到哪個訊息中樞,若沒給則不傳送端外通知,只會發送端內通知。(目前只有"hita"及"hita5"能使用)
  221. sender string Optional 發送訊息的來源端
  222. tags string array Required 接收對象或手機註冊的tag,ID或服務等...
  223. title string Optional 標題,會"直接"顯示於端外通知的title位置
  224. body string Optional 正文,會"直接"顯示於端外通知的body位置
  225. eventId string Optional 事件ID
  226. eventName string Optional 事件名稱
  227. data string Optional 額外資料
  228. 'request_school': vm.$t('notice.type1'), // 管理员收到他人申请加入的通知
  229. 'invite_school': vm.$t('notice.type2'), // 你收到学校邀请你的通知
  230. 'remove_school': vm.$t('notice.type3'), // 学校将你移除的通知
  231. 'request-join_school': vm.$t('notice.type1'), // 学校同意你的加入请求
  232. 'invite-join_school': vm.$t('notice.type2'), // 某人已同意你对他的邀请
  233. 'coedit_syllabus': vm.$t('notice.type4'), // 邀请课纲共编的通知
  234. 'share_syllabus': vm.$t('notice.type4'), // 个人课纲分享的通知
  235. 'transfer-admin_school': vm.$t('notice.type5'), // 管理员转移的通知
  236. 'scoring-arb_school': vm.$t('notice.type6'), // 仲裁卷阅卷任务分配通知
  237. 'scoring-err_school': vm.$t('notice.type6'), // 异常卷阅卷任务分配通知
  238. 'scoring-mark_school': vm.$t('notice.type6'), // 普通阅卷任务分配通知
  239. 'scan-join_groupList': vm.$t('notice.type7'), // 扫码加入名单通知
  240. 'scan-join_school': vm.$t('notice.type7'), // 扫码加入学校通知
  241. 'submitanswer_homework': vm.$t('notice.type8'), // 作业提交通知
  242. 'expire_lessonRecord': vm.$t('notice.type9'), // 课例过期通知
  243. */
  244. /// <summary>
  245. ///
  246. /// 發送端內外通知
  247. ///
  248. /// id: 教师id,name 教师名称,code 语系
  249. /// </summary>
  250. /// <param name="toTeachers"></param>
  251. /// <param name="notifyCode"></param>
  252. /// <param name="replaceData"></param>
  253. /// <param name="location"></param>
  254. /// <param name="_configuration"></param>
  255. /// <param name="_dingDing"></param>
  256. /// <returns></returns>
  257. public void PushNotify(List<IdNameCode> toTeachers , string notifyCode,string notifyType,Dictionary<string, object> replaceData,
  258. string location, IConfiguration _configuration, DI.DingDing _dingDing,string rootPath) {
  259. /*
  260. * IES5_Management shift-assist_school DelBeforeCopyAbility-mark_start copyAbility-mark_finish copyAbility-mark_start
  261. * transfer-admin_school invite-join_school invite_school request_school request-join_school remove_school scan-join_school
  262. * IES5_Course submitanswer_homework scan-join_groupList expire-school_lessonRecord
  263. * IES5_Task scoring-mark_school scoring-arb_school scoring-err_school
  264. * IES5_Contect coedit_syllabus share_syllabus
  265. {
  266. "hubName":"hita5",
  267. "sender":"ies5",
  268. "tags":["1595321354_IES5_Management"]
  269. "title":"",
  270. "body":"",
  271. "eventId":"",
  272. "eventName":"",
  273. "data":""action":{"type":"click\link","tokenbindtype":1,"url":"http://xxxx"}"
  274. }
  275. {
  276. "action":[ //陣列, 可以包含多個按鈕
  277. {
  278. "type":"click", //按鈕
  279. "label":"Ok", //按鈕的字
  280. "url":"https://www.teammodel.net?code=", // POST API
  281. "tokenbindtype":1 //附掛 code token到 utl 後面
  282. }
  283. ]
  284. }
  285. {
  286. "action": [
  287. {
  288. "type": "click",
  289. "label": "\\u67e5\\u770b",
  290. "url": "https:\\/\\/sokrates.teammodel.org\\/exhibition\\/tbavideo\\/check-with-habook\\/?to=aHR0cHM6Ly9zb2tyYXRlcy50ZWFtbW9kZWwub3JnL2V4aGliaXRpb24vdGJhdmlkZW8jL2NvbnRlbnQvMTM5MzU\\/Z3JvdXBJZHM9MTQxJmNoYW5uZWxJZD0xMzA=&ticket=",
  291. "tokenbindtype": 1
  292. }
  293. ]
  294. }
  295. */
  296. try
  297. {
  298. string lang = location.Contains("China") ? "zh-cn" : "en-us";
  299. toTeachers.FindAll(x => string.IsNullOrWhiteSpace(x.code) || (!x.code.Equals("zh-cn") && !x.code.Equals("zh-tw") && !x.code.Equals("en-us"))).ForEach(x => { x.code = lang; });
  300. var groups = toTeachers.GroupBy(x => x.code).Select(x => new { x.Key, list = x.ToList() });
  301. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  302. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  303. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  304. string site = location;
  305. if (location.Contains("China"))
  306. {
  307. location = "China";
  308. }
  309. else if (location.Contains("Global"))
  310. {
  311. location = "Global";
  312. }
  313. replaceData.Add("notifyCode", notifyCode);
  314. replaceData.Add("location", site);
  315. if (replaceData.ContainsKey("schoolId"))
  316. {
  317. replaceData.Add("scope", "school");
  318. }
  319. else { replaceData.Add("scope", "private"); }
  320. var client = _httpClient;
  321. var token = CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location).Result;
  322. if (client.DefaultRequestHeaders.Contains("Authorization"))
  323. {
  324. client.DefaultRequestHeaders.Remove("Authorization");
  325. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  326. }
  327. else
  328. {
  329. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  330. }
  331. foreach (var group in groups)
  332. {
  333. string path =Path.Combine(rootPath, $"Lang/{group.Key}.json");
  334. var sampleJson = File.ReadAllBytes(path).AsSpan();
  335. Utf8JsonReader reader = new Utf8JsonReader(sampleJson);
  336. if (JsonDocument.TryParseValue(ref reader, out JsonDocument jsonDoc) && jsonDoc.RootElement.TryGetProperty(notifyCode, out JsonElement json))
  337. {
  338. List<string> msgs = json.ToObject<List<string>>();
  339. List<dynamic> actions = new List<dynamic>();
  340. if (msgs.IsNotEmpty())
  341. {
  342. dynamic action = new ExpandoObject();
  343. //处理action
  344. string urlAction = "";
  345. if (notifyCode.Equals("request_school") || notifyCode.Equals("invite_school")|| notifyCode.Equals("invoice-notify")) {
  346. if (site.Equals("Global")) {
  347. urlAction = "https://www.teammodel.net/core/process-notify";
  348. }
  349. if (site.Equals("Global-Test")|| site.Equals("Global-Dep"))
  350. {
  351. urlAction = "https://test.teammodel.net/core/process-notify";
  352. }
  353. if (site.Equals("China"))
  354. {
  355. urlAction = "https://www.teammodel.cn/core/process-notify";
  356. }
  357. if (site.Equals("China-Test")|| site.Equals("China-Dep"))
  358. {
  359. urlAction = "https://test.teammodel.cn/core/process-notify";
  360. }
  361. string dataJson = replaceData.ToJsonString();
  362. //byte[] byts = Encoding.Unicode.GetBytes(replaceData.ToJsonString());
  363. //var rdata=Convert.ToBase64String(byts);
  364. //byte[] bs= Convert.FromBase64String(rdata);
  365. //string data1 = Encoding.Unicode.GetString(bs);
  366. dataJson = HttpUtility.UrlEncode(dataJson, Encoding.UTF8);
  367. urlAction = $"{urlAction}?notifyCode={notifyCode}&data={dataJson}";
  368. if (msgs.Count == 3)
  369. {
  370. if (msgs[2].Contains("{link}"))
  371. {
  372. string urlA = $"{replaceData["link"]}";
  373. actions.Add(new { type = "link", label = msgs[2].Replace("{link}",""), url = urlA });
  374. }
  375. else {
  376. string urlA = $"{urlAction}&notifyEvent=1&ticket=";
  377. actions.Add(new { type = "click", label = msgs[2], url = urlA, tokenbindtype = 1 });
  378. }
  379. }
  380. if (msgs.Count == 4) {
  381. string urlA = $"{urlAction}&notifyEvent=1&ticket=";
  382. string urlB = $"{urlAction}&notifyEvent=2&ticket=";
  383. actions.Add(new { type = "click", label = msgs[2], url = urlA, tokenbindtype = 1 });
  384. actions.Add(new { type = "click", label = msgs[3], url = urlB, tokenbindtype = 1 });
  385. }
  386. }
  387. var tags = group.list.Select(x => $"{x.id}_{notifyType}");
  388. string data = new { value = replaceData }.ToJsonString();
  389. if (actions.Any()) {
  390. data=new { value = replaceData ,action=actions}.ToJsonString();
  391. }
  392. NotifyData notifyData = new NotifyData
  393. {
  394. hubName = "hita5",
  395. sender = "IES",
  396. tags = tags.ToList(),
  397. title = msgs[0],
  398. eventId = $"{notifyCode}-{_snowflakeId.NextId()}",
  399. eventName = $"{msgs[0]}",
  400. data = data
  401. };
  402. if (msgs.Count == 1)
  403. {
  404. notifyData.body = msgs[0];
  405. }
  406. else
  407. {
  408. replaceData.Keys.ToList().ForEach(x => {
  409. msgs[1] = msgs[1].Replace("{" + x + "}", $"{replaceData[x]}");
  410. });
  411. notifyData.body = msgs[1];
  412. }
  413. string result = "";
  414. try {
  415. HttpResponseMessage responseMessage = _httpClient.PostAsJsonAsync($"{url}/service/PushNotify", notifyData).Result;
  416. if (responseMessage.StatusCode == HttpStatusCode.OK)
  417. {
  418. string content = responseMessage.Content.ReadAsStringAsync().Result;
  419. result = content;
  420. }
  421. else
  422. {
  423. result = $"{responseMessage.StatusCode},推送返回的状态码。";
  424. }
  425. } catch (Exception exm) {
  426. _= _dingDing.SendBotMsg($"{location}站点发送消息异常,{exm.Message}\n{exm.StackTrace}:\n{url}/service/PushNotify \nheader: {token.AccessToken} \nresult:{result}\n params:{notifyData.ToJsonString()}", GroupNames.成都开发測試群組);
  427. }
  428. // _dingDing.SendBotMsg($"{location}站点发送消息:\n{url}/service/PushNotify \nheader: {token.AccessToken} \nresult:{result}\n params:{notifyData.ToJsonString()}", GroupNames.成都开发測試群組).GetAwaiter().GetResult();
  429. }
  430. }
  431. }
  432. } catch (Exception ex) {
  433. _ = _dingDing.SendBotMsg($"{location},通知V2发送异常\n{ex.Message}\n{ex.StackTrace}\n{replaceData.ToJsonString()}\n{toTeachers.ToJsonString()}\n{notifyCode}", GroupNames.醍摩豆服務運維群組);
  434. }
  435. }
  436. /// <summary>
  437. /// BI发送端外通知消息
  438. /// </summary>
  439. /// <param name="bINotice"></param>
  440. /// <param name="notifyCode"></param>
  441. /// <param name="notifyType"></param>
  442. /// <param name="replaceData"></param>
  443. /// <param name="location"></param>
  444. /// <param name="_configuration"></param>
  445. /// <param name="_dingDing"></param>
  446. public void BIPushNotify(BINotice bINotice, Dictionary<string, object> replaceData, string location, IConfiguration _configuration, DingDing _dingDing)
  447. {
  448. try
  449. {
  450. string notifyCode = "";
  451. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  452. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  453. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  454. string site = location;
  455. string sendSite = "";
  456. //处理action
  457. string urlAction = "";
  458. List<dynamic> actions = new List<dynamic>();
  459. if (site.Equals("Global"))
  460. {
  461. sendSite = "Global";
  462. urlAction = "https://bi-rc.teammodel.net/core/process-notify";
  463. }
  464. if (site.Equals("Global-Test") || site.Equals("Global-Dep"))
  465. {
  466. sendSite = "Global";
  467. urlAction = "https://bi-rc.teammodel.net/core/process-notify";
  468. }
  469. if (site.Equals("China"))
  470. {
  471. sendSite = "China";
  472. urlAction = "https://bi.teammodel.cn/core/process-notify";
  473. }
  474. if (site.Equals("China-Test") || site.Equals("China-Dep"))
  475. {
  476. sendSite = "China";
  477. urlAction = "https://bitest.teammodel.cn/core/process-notify";
  478. //urlAction = "https://localhost:5001/core/process-notify";
  479. }
  480. if (!string.IsNullOrEmpty($"{bINotice.jumpUrl}"))
  481. {
  482. urlAction = bINotice.jumpUrl;
  483. }
  484. if (!string.IsNullOrEmpty($"{bINotice.callbackName}") && !string.IsNullOrEmpty($"{bINotice.refuseName}"))
  485. {
  486. notifyCode = "notify_agree";
  487. }
  488. else if (!string.IsNullOrEmpty($"{bINotice.callbackName}") && string.IsNullOrEmpty($"{bINotice.refuseName}"))
  489. {
  490. notifyCode = "notify_see";
  491. }
  492. else
  493. {
  494. notifyCode = "notify_default";
  495. }
  496. replaceData.Add("noticeId", bINotice.id);
  497. replaceData.Add("notifyCode", notifyCode);
  498. replaceData.Add("location", site);
  499. byte[] byts = Encoding.Unicode.GetBytes(replaceData.ToJsonString());
  500. var rdata = Convert.ToBase64String(byts);
  501. byte[] bs = Convert.FromBase64String(rdata);
  502. string data1 = Encoding.Unicode.GetString(bs);
  503. rdata = HttpUtility.UrlEncode(rdata, Encoding.UTF8);
  504. urlAction = $"{urlAction}?notifyCode={bINotice.createId}&data={rdata}";
  505. if (!string.IsNullOrEmpty($"{bINotice.callbackName}")&& !string.IsNullOrEmpty($"{bINotice.refuseName}"))
  506. {
  507. //string id_token = "eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJsb2NhbGhvc3Q6NTAwMSIsInN1YiI6IjE2MzYwMTY0OTkiLCJhenAiOnRydWUsImV4cCI6IjE2NzU3NTYyOTciLCJuYW1lIjoi5b2t56S8IiwicGljdHVyZSI6bnVsbCwicm9sZXMiOlsiYWRtaW4iXSwicGVybWlzc2lvbnMiOlsiYXJlYWRhdGEtcmVhZCIsImFyZWFkYXRhLXVwZCIsInNjaG9vbGRhdGEtcmVhZCIsInNjaG9vbGRhdGEtdXBkIiwiY2hpbmEtcmVhZCIsImdsb2JhbC1yZWFkIl0sImRkc3ViIjoiMTYzMjk5MzA5MjMxNjc0NDEiLCJkZG5hbWUiOiLlva3npLwiLCJkZHBpY3R1cmUiOiIiLCJzY29wZSI6ImFzc2lzdCIsIndlYnNpdGUiOiJDaGluYSJ9.J_MCukBvxB9N0voo7uh9o2wK_3g8w-Dw7zbK95GanT4";
  508. //string urlA = $"{urlAction}&notifyEvent=1&token={id_token}&ticket=";
  509. string urlA = $"{urlAction}&notifyEvent=1&ticket=";
  510. string urlB = $"{urlAction}&notifyEvent=2&ticket=";
  511. actions.Add(new { type = "click", label = bINotice.callbackName, url = urlA, tokenbindtype = 1 });
  512. actions.Add(new { type = "click", label = bINotice.refuseName, url = urlB, tokenbindtype = 1 });
  513. }
  514. else if (!string.IsNullOrEmpty($"{bINotice.callbackName}") && string.IsNullOrEmpty($"{ bINotice.refuseName}"))
  515. {
  516. string urlA = $"{urlAction}&notifyEvent=1&ticket=";
  517. actions.Add(new { type = "click", label = bINotice.callbackName, url = urlA, tokenbindtype = 1 });
  518. }
  519. var client = _httpClient;
  520. var token = CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, sendSite).Result;
  521. if (client.DefaultRequestHeaders.Contains("Authorization"))
  522. {
  523. client.DefaultRequestHeaders.Remove("Authorization");
  524. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  525. }
  526. else
  527. {
  528. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  529. }
  530. string data = new { notice = bINotice, value = replaceData }.ToJsonString();
  531. if (actions.Any())
  532. {
  533. data = new { value = replaceData, action = actions }.ToJsonString();
  534. }
  535. NotifyData notifyData = new()
  536. {
  537. hubName = string.Join(",", bINotice.crowd.types),
  538. sender = bINotice.source,
  539. tags = bINotice.crowdIds,
  540. title = bINotice.theme,
  541. body = bINotice.content,
  542. eventId = $"BI-send",
  543. eventName = $"BI_SendNotice",
  544. data = data
  545. };
  546. string result = "";
  547. HttpResponseMessage responseMessage = _httpClient.PostAsJsonAsync($"{url}/service/PushNotify", notifyData).Result;
  548. if (responseMessage.StatusCode == HttpStatusCode.OK)
  549. {
  550. string content = responseMessage.Content.ReadAsStringAsync().Result;
  551. result = content;
  552. }
  553. else
  554. result = $"{responseMessage.StatusCode},推送返回的状态码。";
  555. }
  556. catch (Exception ex)
  557. {
  558. _ = _dingDing.SendBotMsg($"{location},BI通知V2发送异常\n{ex.Message}\n{ex.StackTrace}\n{replaceData.ToJsonString()}\n{bINotice.ToJsonString()}", GroupNames.成都开发測試群組);
  559. }
  560. }
  561. /// <summary>
  562. /// 每日课程消息发送
  563. /// </summary>
  564. /// <param name="notifyData"></param>
  565. /// <param name="replaceData"></param>
  566. /// <param name="location"></param>
  567. /// <param name="_configuration"></param>
  568. /// <param name="_dingDing"></param>
  569. public void CoursePushNotify(NotifyData notifyData, Dictionary<string, object> replaceData, string location, IConfiguration _configuration, DingDing _dingDing)
  570. {
  571. try
  572. {
  573. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  574. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  575. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  576. string site = location;
  577. string sendSite = "";
  578. //处理action
  579. string urlAction = "";
  580. List<dynamic> actions = new List<dynamic>();
  581. if (site.Equals("Global"))
  582. {
  583. sendSite = "Global";
  584. urlAction = "https://www.teammodel.net/core/process-notify";
  585. }
  586. if (site.Equals("Global-Test") || site.Equals("Global-Dep"))
  587. {
  588. sendSite = "Global";
  589. urlAction = "https://test.teammodel.net/core/process-notify";
  590. }
  591. if (site.Equals("China"))
  592. {
  593. sendSite = "China";
  594. urlAction = "https://www.teammodel.cn/core/process-notify";
  595. }
  596. if (site.Equals("China-Test") || site.Equals("China-Dep"))
  597. {
  598. sendSite = "China";
  599. urlAction = "https://test.teammodel.cn/core/process-notify";
  600. }
  601. var client = _httpClient;
  602. var token = CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, sendSite).Result;
  603. if (client.DefaultRequestHeaders.Contains("Authorization"))
  604. {
  605. client.DefaultRequestHeaders.Remove("Authorization");
  606. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  607. }
  608. else
  609. {
  610. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  611. }
  612. string data = new { value = replaceData }.ToJsonString();
  613. if (actions.Any())
  614. {
  615. data = new { value = replaceData, action = actions }.ToJsonString();
  616. }
  617. string result = "";
  618. HttpResponseMessage responseMessage = _httpClient.PostAsJsonAsync($"{url}/service/PushNotify", notifyData).Result;
  619. if (responseMessage.StatusCode == HttpStatusCode.OK)
  620. {
  621. string content = responseMessage.Content.ReadAsStringAsync().Result;
  622. result = content;
  623. }
  624. else
  625. result = $"{responseMessage.StatusCode},推送返回的状态码。";
  626. }
  627. catch (Exception ex)
  628. {
  629. _ = _dingDing.SendBotMsg($"{location},BI通知V2发送异常\n{ex.Message}\n{ex.StackTrace}\n{replaceData.ToJsonString()}\n{notifyData.ToJsonString()}", GroupNames.成都开发測試群組);
  630. }
  631. }
  632. public class NotifyData {
  633. public string hubName { get; set; }
  634. public string sender { get; set; }
  635. public List<string> tags { get; set; } = new List<string>();
  636. public string title { get; set; }
  637. public string body { get; set; }
  638. public string eventId { get; set; }
  639. public string eventName { get; set; }
  640. public string data { get; set; }
  641. }
  642. public async Task<(HttpStatusCode code, string content)> Auth2Login(string pin_code,string account, string location, IConfiguration _configuration, DI.DingDing _dingDing)
  643. {
  644. try
  645. {
  646. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  647. //url = "https://api2-rc.teammodel.cn";
  648. url = $"{url}/oauth2/login";
  649. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  650. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  651. if (location.Contains("China"))
  652. {
  653. location = "China";
  654. }
  655. else if (location.Contains("Global"))
  656. {
  657. location = "Global";
  658. }
  659. var client = _httpClient;
  660. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  661. if (client.DefaultRequestHeaders.Contains("Authorization"))
  662. {
  663. client.DefaultRequestHeaders.Remove("Authorization");
  664. }
  665. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  666. var data = new Dictionary<string, string>
  667. {
  668. { "pin_code", pin_code },
  669. { "account", account },
  670. { "grant_type", "create" },
  671. { "client_id", clientID },
  672. { "nonce", "habook" },
  673. { "name", "User" },
  674. };
  675. HttpResponseMessage responseMessage = await client.PostAsJsonAsync(url, data);
  676. if (responseMessage.Content != null)
  677. {
  678. string content = await responseMessage.Content.ReadAsStringAsync();
  679. if (!string.IsNullOrWhiteSpace(content))
  680. {
  681. return (responseMessage.StatusCode, content);
  682. }
  683. else
  684. {
  685. return (responseMessage.StatusCode, null);
  686. }
  687. }
  688. else
  689. {
  690. return (responseMessage.StatusCode, null);
  691. }
  692. }
  693. catch (Exception ex)
  694. {
  695. await _dingDing.SendBotMsg($"{location}短信登录验证异常:\n{ex.Message}\n{ex.StackTrace}", DI.GroupNames.醍摩豆服務運維群組);
  696. return (HttpStatusCode.InternalServerError, null);
  697. }
  698. }
  699. /// <summary>
  700. /// 发送短信验证码
  701. /// </summary>
  702. /// <param name="clientID"></param>
  703. /// <param name="clientSecret"></param>
  704. /// <param name="location"></param>
  705. /// <param name="url"></param>
  706. /// <param name="data"></param>
  707. /// <returns></returns>
  708. public async Task<(HttpStatusCode code ,string content)> SendSmsPin(Dictionary<string, object> data, string location, IConfiguration _configuration, DI.DingDing _dingDing)
  709. {
  710. try {
  711. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  712. //url = "https://api2-rc.teammodel.cn";
  713. url = $"{url}/service/sandsms/pin";
  714. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  715. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  716. if (location.Contains("China"))
  717. {
  718. location = "China";
  719. }
  720. else if (location.Contains("Global"))
  721. {
  722. location = "Global";
  723. }
  724. var client = _httpClient;
  725. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  726. if (client.DefaultRequestHeaders.Contains("Authorization"))
  727. {
  728. client.DefaultRequestHeaders.Remove("Authorization");
  729. }
  730. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  731. HttpResponseMessage responseMessage = await client.PostAsJsonAsync(url, data);
  732. if (responseMessage.Content != null)
  733. {
  734. string content = await responseMessage.Content.ReadAsStringAsync();
  735. if (!string.IsNullOrWhiteSpace(content))
  736. {
  737. return (responseMessage.StatusCode, content);
  738. }
  739. else {
  740. return (responseMessage.StatusCode, null);
  741. }
  742. }
  743. else {
  744. return (responseMessage.StatusCode, null);
  745. }
  746. } catch (Exception ex) {
  747. await _dingDing.SendBotMsg($"{location}验证码发送异常:\n{ex.Message}\n{ex.StackTrace}", DI.GroupNames.醍摩豆服務運維群組);
  748. return (HttpStatusCode.InternalServerError,null);
  749. }
  750. }
  751. /// <summary>
  752. /// 隐式登录
  753. /// </summary>
  754. /// <param name="clientID"></param>
  755. /// <param name="clientSecret"></param>
  756. /// <param name="location"></param>
  757. /// <param name="url"></param>
  758. /// <param name="data"></param>
  759. /// <returns></returns>
  760. public async Task<TmdidImplicit> Implicit( Dictionary<string,string> data,string location, IConfiguration _configuration)
  761. {
  762. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  763. //url = "https://api2-rc.teammodel.cn";
  764. url = $"{url}/oauth2/implicit";
  765. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  766. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  767. if (location.Contains("China"))
  768. {
  769. location = "China";
  770. }
  771. else if (location.Contains("Global"))
  772. {
  773. location = "Global";
  774. }
  775. var client = _httpClient;
  776. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  777. if (client.DefaultRequestHeaders.Contains("Authorization"))
  778. {
  779. client.DefaultRequestHeaders.Remove("Authorization");
  780. }
  781. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  782. HttpResponseMessage responseMessage = await client.PostAsJsonAsync(url, data);
  783. if (responseMessage.StatusCode == HttpStatusCode.OK)
  784. {
  785. string content=await responseMessage.Content.ReadAsStringAsync();
  786. if (!string.IsNullOrEmpty(content))
  787. {
  788. TmdidImplicit tmdidImplicit = content.ToObject<TmdidImplicit>();
  789. return tmdidImplicit;
  790. }
  791. else
  792. {
  793. return null;
  794. }
  795. }
  796. else if (responseMessage.StatusCode == HttpStatusCode.Unauthorized)
  797. {
  798. return null;
  799. }
  800. else
  801. {
  802. return null;
  803. }
  804. }
  805. /// <summary>
  806. /// 获取多个用户信息
  807. /// </summary>
  808. /// <param name="clientID"></param>
  809. /// <param name="clientSecret"></param>
  810. /// <param name="location"></param>
  811. /// <param name="url"></param>
  812. /// <param name="data"></param>
  813. /// <returns></returns>
  814. public async Task<string> GetUserInfos(StringContent scontent, string name = "Default") {
  815. var clientID = options.clientID;
  816. var clientSecret = options.clientSecret;
  817. var location = options.location;
  818. var url = options.coreUrl;
  819. if (location.Contains("China"))
  820. { url =string.IsNullOrWhiteSpace(url)? "https://api2.teammodel.cn":url;
  821. location = "China";
  822. }
  823. else if (location.Contains("Global"))
  824. {
  825. url = string.IsNullOrWhiteSpace(url) ? "https://api2.teammodel.net" : url;
  826. location = "Global";
  827. }
  828. url = $"{url}/oauth2/getuserinfos";
  829. var client = _httpClient;
  830. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  831. if (client.DefaultRequestHeaders.Contains("Authorization"))
  832. {
  833. client.DefaultRequestHeaders.Remove("Authorization");
  834. }
  835. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  836. HttpResponseMessage responseMessage = await client.PostAsync(url, scontent);
  837. if (responseMessage.StatusCode == HttpStatusCode.OK)
  838. {
  839. string content = await responseMessage.Content.ReadAsStringAsync();
  840. if (!string.IsNullOrEmpty(content))
  841. {
  842. return content;
  843. }
  844. else
  845. {
  846. return null;
  847. }
  848. }
  849. else if (responseMessage.StatusCode == HttpStatusCode.Unauthorized)
  850. {
  851. return null;
  852. }
  853. else
  854. {
  855. return null;
  856. }
  857. }
  858. public async Task SendMail(Dictionary<string, object> data, string location, IConfiguration _configuration)
  859. {
  860. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  861. //url = "https://api2-rc.teammodel.cn";
  862. url = $"{url}/service/sendmail";
  863. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  864. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  865. if (location.Contains("China"))
  866. {
  867. location = "China";
  868. }
  869. else if (location.Contains("Global"))
  870. {
  871. location = "Global";
  872. }
  873. var client = _httpClient;
  874. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  875. if (client.DefaultRequestHeaders.Contains("Authorization"))
  876. {
  877. client.DefaultRequestHeaders.Remove("Authorization");
  878. }
  879. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  880. HttpResponseMessage responseMessage = await client.PostAsJsonAsync(url, data);
  881. }
  882. /// <summary>
  883. /// 获取单个用户信息
  884. /// </summary>
  885. /// <param name="clientID"></param>
  886. /// <param name="clientSecret"></param>
  887. /// <param name="location"></param>
  888. /// <param name="url"></param>
  889. /// <param name="data"></param>
  890. /// <returns></returns>
  891. public async Task<CoreUser> GetUserInfo(Dictionary<string, string> data, string location, IConfiguration _configuration)
  892. {
  893. var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
  894. //url = "https://api2-rc.teammodel.cn";
  895. url = $"{url}/oauth2/getuserinfo";
  896. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  897. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  898. if (location.Contains("China"))
  899. {
  900. location = "China";
  901. }
  902. else if (location.Contains("Global"))
  903. {
  904. location = "Global";
  905. }
  906. var client = _httpClient;
  907. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  908. if (client.DefaultRequestHeaders.Contains("Authorization"))
  909. {
  910. client.DefaultRequestHeaders.Remove("Authorization");
  911. }
  912. client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
  913. HttpResponseMessage responseMessage = await client.PostAsJsonAsync(url, data);
  914. if (responseMessage.StatusCode == HttpStatusCode.OK)
  915. {
  916. string content = await responseMessage.Content.ReadAsStringAsync();
  917. if (!string.IsNullOrEmpty(content))
  918. {
  919. CoreUserInfo coreUserInfo = content.ToObject<CoreUserInfo>();
  920. if (coreUserInfo != null && !string.IsNullOrWhiteSpace(coreUserInfo.id))
  921. {
  922. bool isActivate = !string.IsNullOrWhiteSpace(coreUserInfo.password) || !string.IsNullOrWhiteSpace(coreUserInfo.passwordOld);
  923. CoreUser coreUser = new CoreUser
  924. {
  925. isActivate = isActivate,
  926. id = coreUserInfo.id,
  927. vid = coreUserInfo.vid,
  928. mail = coreUserInfo.mail,
  929. mobile = coreUserInfo.mobile,
  930. name = coreUserInfo.name,
  931. picture = coreUserInfo.picture,
  932. habook = coreUserInfo.habook,
  933. wechat = coreUserInfo.wechat,
  934. facebook = coreUserInfo.facebook,
  935. google = coreUserInfo.google,
  936. ding = coreUserInfo.ding,
  937. apple = coreUserInfo.apple,
  938. };
  939. return coreUser;
  940. }
  941. else
  942. {
  943. return null;
  944. }
  945. }
  946. else {
  947. return null;
  948. }
  949. }
  950. else if (responseMessage.StatusCode == HttpStatusCode.Unauthorized)
  951. {
  952. return null;
  953. }
  954. else
  955. {
  956. return null;
  957. }
  958. }
  959. }
  960. public class TmdidImplicit
  961. {
  962. public string id_token { get; set; }
  963. public string access_token { get; set; }
  964. public string expires_in { get; set; }
  965. public string token_type { get; set; }
  966. }
  967. public class CoreUser
  968. {
  969. public string searchKey { get; set; }
  970. public string id { get; set; }
  971. public string vid { get; set; }
  972. public string mail { get; set; }
  973. public string mobile { get; set; }
  974. public string name { get; set; }
  975. public string picture { get; set; }
  976. public string habook { get; set; }
  977. public string wechat { get; set; }
  978. public string facebook { get; set; }
  979. public string google { get; set; }
  980. public string ding { get; set; }
  981. public string apple { get; set; }
  982. public bool isActivate { get; set; }
  983. }
  984. public class CoreUserInfo : CoreUser
  985. {
  986. public string area { get; set; }
  987. public string country { get; set; }
  988. public string type { get; set; }
  989. public string password { get; set; }
  990. public string salt { get; set; }
  991. public string passwordOld { get; set; }
  992. public string saltOld { get; set; }
  993. }
  994. }