You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1332 lines
56 KiB

  1. using log4net;
  2. using CounsellorBL.Helper;
  3. using MonumentDefine;
  4. using Newtonsoft.Json;
  5. using Newtonsoft.Json.Linq;
  6. using OT.COM.ArsenalDB;
  7. using SoldierData.EnterprizeV4;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Net.Http;
  12. using static CounsellorBL.GROUP.ConstDefinition.GrpBLWording;
  13. using static MonumentDefine.Enums;
  14. using System.Text;
  15. namespace CounsellorBL.GROUP.Helper
  16. {
  17. /// <summary>
  18. /// 類別名稱:Mailer
  19. /// 類別說明:
  20. /// 起始作者:
  21. /// 起始日期:
  22. /// 最新修改人:
  23. /// 最新修改日:
  24. /// </summary>
  25. public class FbHelper : DBService
  26. {
  27. private static ILog _inst = null;
  28. private static ILog Logger
  29. {
  30. get
  31. {
  32. if (_inst == null)
  33. {
  34. _inst = LogManager.GetLogger(typeof(FbHelper));
  35. }
  36. return _inst;
  37. }
  38. }
  39. public override string MainTable => null;
  40. #region 類別
  41. /// <summary>
  42. /// Fb留言資料
  43. /// </summary>
  44. private class FbCommentData
  45. {
  46. public List<data> data { get; set; }
  47. public JObject paging { get; set; }
  48. }
  49. private class data
  50. {
  51. public DateTime created_time { get; set; }
  52. public from from { get; set; }
  53. public string message { get; set; }
  54. public string id { get; set; }
  55. public parent parent { get; set; }
  56. public int comment_count { get; set; }
  57. }
  58. private class from
  59. {
  60. public string name { get; set; }
  61. public string id { get; set; }
  62. public Picture picture { get; set; }
  63. public class Picture
  64. {
  65. public PictureData data { get; set; }
  66. public class PictureData
  67. {
  68. public string url { get; set; }
  69. }
  70. }
  71. }
  72. private class parent
  73. {
  74. public string id { get; set; }
  75. }
  76. /// <summary>
  77. /// Fb 延長token
  78. /// </summary>
  79. private class FbToken
  80. {
  81. public string access_token { get; set; }
  82. public string type { get; set; }
  83. }
  84. /// <summary>
  85. /// Fb token 驗證
  86. /// </summary>
  87. public class FbTokenVerification
  88. {
  89. public VerificationContent data { get; set; }
  90. }
  91. public class VerificationContent
  92. {
  93. public string app_id { get; set; }
  94. public string type { get; set; }
  95. public int data_access_expires_at { get; set; }
  96. //public error error { get; set; }
  97. public int expires_at { get; set; }
  98. public bool is_valid { get; set; }
  99. public string user_id { get; set; }
  100. }
  101. private class error
  102. {
  103. public int code { get; set; }
  104. public string message { get; set; }
  105. public int subcode { get; set; }
  106. }
  107. /// <summary>
  108. /// FB API get token response information
  109. /// </summary>
  110. public class FbGetTokenEntity
  111. {
  112. public string access_token { get; set; }
  113. public string token_type { get; set; }
  114. public string expires_in { get; set; }
  115. }
  116. public class FbGroupEntity
  117. {
  118. public string name { get; set; }
  119. public string id { get; set; }
  120. public string privacy { get; set; }
  121. }
  122. APIURLHelper ApiUrlHelper = new APIURLHelper();
  123. /// <summary>
  124. /// fb 貼文
  125. /// </summary>
  126. public class FbGetPost
  127. {
  128. public List<FbGetPostdata> data { get; set; }
  129. public JObject paging { get; set; }
  130. }
  131. public class FbGetPostdata
  132. {
  133. public string id { get; set; }
  134. public string message { get; set; }
  135. public string full_picture { get; set; }
  136. public string source { get; set; }
  137. public DateTime updated_time { get; set; }
  138. public DateTime created_time { get; set; }
  139. }
  140. public class PushPost
  141. {
  142. public string id { get; set; }
  143. }
  144. #endregion
  145. public enum CommentStatus
  146. {
  147. /// <summary>
  148. /// 無問題 (綠)
  149. /// </summary>
  150. OK = 1,
  151. /// <summary>
  152. /// 有問題【無數量】【無分店】【無產品】【數字有更新】 (紅)
  153. /// </summary>
  154. InvalidFormat = 2,
  155. /// <summary>
  156. /// 會員無登入系統 (橘)
  157. /// </summary>
  158. UnknownMember = 3,
  159. /// <summary>
  160. /// 黑名單或其他回覆的留言 (黑)
  161. /// </summary>
  162. Duplicate = 4,
  163. /// <summary>
  164. /// 已轉成訂單,不顯示其中
  165. /// </summary>
  166. TransferOrder = 9
  167. }
  168. class CommentModel
  169. {
  170. public string uid { get; set; }
  171. public string group_user_id { get; set; }
  172. public string comment { get; set; }
  173. public DateTime comment_time { get; set; }
  174. }
  175. #region FbAPI
  176. // 針對應用程式 可以使用{應用程式ID}|{應用程式密鑰}
  177. /// <summary>
  178. /// 上傳貼文的POST
  179. /// </summary>
  180. /// <param name="authorizationToken"></param>
  181. /// <param name="message"></param>
  182. /// <param name="path">圖片路徑</param>
  183. public string CallFbPostPushAPI(string authorizationToken, string message, string groupId, List<string> path, out string o_sPostFBID)
  184. {
  185. string sMsg = null;
  186. string sPostFBID = null;
  187. Logger.Info($"CallFbPostPushAPI start groupId={groupId}");
  188. if(path != null)
  189. {
  190. path.ForEach(p => {
  191. Logger.Info($"CallFbPostPushAPI path={p}");
  192. });
  193. }
  194. try
  195. {
  196. do
  197. {
  198. // 送出資料
  199. string uri = string.Format("https://graph.facebook.com/v8.0/{0}/feed", groupId);
  200. var lsData = new List<APIHelper.DataContent>()
  201. {
  202. new APIHelper.DataContent { Key = "access_token" , Type = typeof(StringContent) , Content = authorizationToken },
  203. new APIHelper.DataContent { Key = "message", Type = typeof(StringContent), Content = message },
  204. new APIHelper.DataContent { Key = "published", Type = typeof(StringContent), Content = "false" }
  205. };
  206. Logger.Info($"CallFbPostPushAPI f2 uri={uri}");
  207. if (path != null && path.Any())
  208. {
  209. int i = 0;
  210. path.ForEach(x =>
  211. {
  212. if (x != null)
  213. {
  214. lsData.Add(new APIHelper.DataContent { Key = $"attached_media[{i}]", Type = typeof(StringContent), Content = "{\"media_fbid\":" + x + "}" });
  215. }
  216. i++;
  217. });
  218. }
  219. Logger.Info($"CallFbPostPushAPI f3 uri={uri}");
  220. sMsg = APIHelper.BasePost(uri, null, lsData, out HttpResponseMessage responseMessage);
  221. if (sMsg != null)
  222. {
  223. Logger.Error(sMsg);
  224. break;
  225. }
  226. Logger.Info($"CallFbPostPushAPI responseMessage.IsSuccessStatusCode = {responseMessage.IsSuccessStatusCode}");
  227. if (responseMessage.IsSuccessStatusCode)
  228. {
  229. var fb_error = GetFbApiError(responseMessage);
  230. if (!string.IsNullOrWhiteSpace(fb_error))
  231. {
  232. sMsg = fb_error;
  233. Logger.Error($"CallFbPostPushAPI f7");
  234. Logger.Error($"CallFbPostPushAPI sMsg={sMsg}");
  235. break;
  236. }
  237. Logger.Info($"CallFbPostPushAPI f6");
  238. string sContent = responseMessage.Content.ReadAsStringAsync().Result;
  239. Logger.Info($"CallFbPostPushAPI f6 sContent={sContent}");
  240. sPostFBID = JsonConvert.DeserializeObject<PushPost>(sContent).id;
  241. Logger.Info($"CallFbPostPushAPI f6 sPostFBID={sPostFBID}");
  242. }
  243. else
  244. {
  245. Logger.Error($"CallFbPostPushAPI f7");
  246. sMsg = JsonConvert.SerializeObject(responseMessage);
  247. Logger.Error($"CallFbPostPushAPI sMsg={sMsg}");
  248. break;
  249. }
  250. }
  251. while (false);
  252. }
  253. catch (Exception ex)
  254. {
  255. sMsg = ex.Message;
  256. Logger.Error($"Exception={sMsg}");
  257. }
  258. o_sPostFBID = sPostFBID;
  259. Logger.Info($"CallFbPostPushAPI end groupId={groupId}");
  260. return sMsg;
  261. }
  262. /// <summary>
  263. /// 上傳圖片的POST
  264. /// </summary>
  265. /// <param name="authorizationToken"></param>
  266. /// <param name="message"></param>
  267. /// <param name="path">圖片路徑</param>
  268. public string CallFbPicturePushAPI(string authorizationToken, string groupId, string path, out string o_sPicID)
  269. {
  270. string sMsg = null;
  271. string sPicID = null;
  272. Logger.Info($"CallFbPicturePushAPI start groupId={groupId} path={path}");
  273. try
  274. {
  275. do
  276. {
  277. // 送出資料
  278. //string uri = string.Format("https://graph.facebook.com/v7.0/{0}/photos", groupId);
  279. //Logger.Info($"CallFbPicturePushAPI uri = {uri}");
  280. //var lsData = new List<APIHelper.DataContent>()
  281. //{
  282. // new APIHelper.DataContent { Key = "access_token" , Type = typeof(StringContent) , Content = authorizationToken },
  283. // new APIHelper.DataContent { Key = "url", Type = typeof(StringContent), Content = path },
  284. // new APIHelper.DataContent { Key = "published", Type = typeof(StringContent), Content = "false" },
  285. // new APIHelper.DataContent { Key = "attempt", Type = typeof(StringContent), Content = "3" }
  286. //};
  287. // 送出資料
  288. string uri = string.Format("https://graph.facebook.com/v7.0/{0}/photos?access_token={1}", groupId, authorizationToken);
  289. Logger.Info($"CallFbPicturePushAPI uri = {uri}");
  290. var lsData = new List<APIHelper.DataContent>()
  291. {
  292. //new APIHelper.DataContent { Key = "access_token" , Type = typeof(StringContent) , Content = authorizationToken },
  293. new APIHelper.DataContent { Key = "url", Type = typeof(StringContent), Content = path },
  294. new APIHelper.DataContent { Key = "published", Type = typeof(StringContent), Content = "false" },
  295. new APIHelper.DataContent { Key = "attempt", Type = typeof(StringContent), Content = "3" },
  296. new APIHelper.DataContent { Key = "suppress_http_code", Type = typeof(StringContent), Content = "1" },
  297. new APIHelper.DataContent { Key = "format", Type = typeof(StringContent), Content = "json" },
  298. new APIHelper.DataContent { Key = "pretty", Type = typeof(StringContent), Content = "0" },
  299. //new APIHelper.DataContent { Key = "debug", Type = typeof(StringContent), Content = "all" },
  300. new APIHelper.DataContent { Key = "transport", Type = typeof(StringContent), Content = "cors" },
  301. };
  302. sMsg = APIHelper.BasePost(uri, null, lsData, out HttpResponseMessage responseMessage);
  303. if (sMsg != null)
  304. {
  305. Logger.Error($"CallFbPicturePushAPI uri = {uri} sMsg={sMsg}");
  306. break;
  307. }
  308. if (responseMessage.IsSuccessStatusCode)
  309. {
  310. var fb_error = GetFbApiError(responseMessage);
  311. if (!string.IsNullOrWhiteSpace(fb_error))
  312. {
  313. sMsg = fb_error;
  314. Logger.Error($"CallFbPicturePushAPI f7");
  315. Logger.Error($"CallFbPicturePushAPI sMsg={sMsg}");
  316. break;
  317. }
  318. string sContent = responseMessage.Content.ReadAsStringAsync().Result;
  319. Logger.Info($"CallFbPicturePushAPI sContent={sContent}");
  320. sPicID = JsonConvert.DeserializeObject<PushPost>(sContent).id;
  321. Logger.Info($"CallFbPicturePushAPI sPicID={sPicID}");
  322. }
  323. else
  324. {
  325. Logger.Error($"CallFbPicturePushAPI f7");
  326. sMsg = JsonConvert.SerializeObject(responseMessage);
  327. Logger.Error($"CallFbPicturePushAPI sMsg={sMsg}");
  328. break;
  329. }
  330. }
  331. while (false);
  332. }
  333. catch (Exception ex)
  334. {
  335. sMsg = ex.Message;
  336. Logger.Error($"CallFbPicturePushAPI exception={sMsg}");
  337. }
  338. o_sPicID = sPicID;
  339. Logger.Info($"CallFbPicturePushAPI end groupId={groupId} path={path} sResult={sPicID}");
  340. return sMsg;
  341. }
  342. /// <summary>
  343. /// 貼文的Get(抓貼文、圖片、影片)
  344. /// </summary>
  345. /// <param name="authorizationToken"></param>
  346. /// <param name="message"></param>
  347. /// <param name="path">圖片路徑</param>
  348. public bool CallFbPostGetAPI(string authorizationToken, string groupId)
  349. {
  350. // 送出資料 取1000筆資料
  351. string uri = string.Format("https://graph.facebook.com/v7.0/{0}/feed?fields=full_picture,message,source,updated_time,created_time&limit=1000&", groupId);
  352. var dicData = new Dictionary<string, string>()
  353. {
  354. { "access_token", authorizationToken }
  355. };
  356. APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage);
  357. if (responseMessage.IsSuccessStatusCode)
  358. {
  359. GetFbPostData(JsonConvert.DeserializeObject<FbGetPost>(responseMessage.Content.ReadAsStringAsync().Result));
  360. }
  361. return responseMessage.IsSuccessStatusCode;
  362. }
  363. /// <summary>
  364. /// 貼文的Get(抓貼文、圖片、影片)
  365. /// </summary>
  366. /// <param name="authorizationToken"></param>
  367. /// <param name="message"></param>
  368. /// <param name="path">圖片路徑</param>
  369. public FbGetPost CallFbPostGetDataAPI(string authorizationToken, string groupId, int grabDate_ = 0)
  370. {
  371. if (grabDate_ == 0 || grabDate_ > 30)
  372. grabDate_ = 30;// 30日為預設天數
  373. // 送出資料 撈取30天內之文章 並重複取至無資料
  374. string uri = string.Format("https://graph.facebook.com/v7.0/{0}/feed?fields=full_picture,message,source,updated_time,created_time&limit=25&since={1}&",
  375. groupId,
  376. DateTime.Now.AddDays(-grabDate_).ToString("yyyy-MM-dd")
  377. );
  378. FbGetPost rawResult = null;
  379. FbGetPost result = new FbGetPost() { data = new List<FbGetPostdata>(), paging = new JObject() };
  380. bool isOver = false;
  381. var dicData = new Dictionary<string, string>()
  382. {
  383. { "access_token", authorizationToken }
  384. };
  385. while (!isOver)
  386. {
  387. APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage);
  388. if (responseMessage.IsSuccessStatusCode)
  389. {
  390. rawResult = JsonConvert.DeserializeObject<FbGetPost>(responseMessage.Content.ReadAsStringAsync().Result);
  391. result.data.AddRange(rawResult.data);
  392. uri = rawResult.paging != null ? rawResult.paging["next"].ToString() : null;
  393. if (rawResult.data.Count == 0)
  394. {
  395. isOver = true;
  396. }
  397. }
  398. else
  399. {
  400. isOver = true;
  401. }
  402. }
  403. return result;
  404. }
  405. /// <summary>
  406. /// 貼文的Get(抓單篇貼文)
  407. /// </summary>
  408. /// <param name="authorizationToken"></param>
  409. /// <param name="message"></param>
  410. /// <param name="path">圖片路徑</param>
  411. public FbGetPostdata CallSingleFbPostGetDataAPI(string authorizationToken, string postId)
  412. {
  413. string uri = string.Format("https://graph.facebook.com/v7.0/{0}?fields=created_time&", postId);
  414. FbGetPost result = new FbGetPost() { data = new List<FbGetPostdata>(), paging = new JObject() };
  415. var dicData = new Dictionary<string, string>()
  416. {
  417. { "access_token", authorizationToken }
  418. };
  419. FbGetPostdata rawResult = null;
  420. APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage);
  421. if (responseMessage.IsSuccessStatusCode)
  422. {
  423. rawResult = JsonConvert.DeserializeObject<FbGetPostdata>(responseMessage.Content.ReadAsStringAsync().Result);
  424. }
  425. return rawResult;
  426. }
  427. /// <summary>
  428. /// 取回留言的Get
  429. /// </summary>
  430. /// <param name="authorizationToken"></param>
  431. /// <param name="message"></param>
  432. /// <param name="path">圖片路徑</param>
  433. public bool CallFbCommentGetAPI(string articleId, string authorizationToken, string postId, out List<tb_grp_comment> comments)
  434. {
  435. // 送出資料
  436. string uri = string.Format("https://graph.facebook.com/v7.0/{0}/comments?filter=stream&fields={1}&access_token={2}&limit={3}", postId, "id,created_time,from{name,id,picture},message,parent,comment_count", authorizationToken, "150");
  437. FbCommentData rawResult = null;
  438. FbCommentData result = new FbCommentData() { data = new List<data>(), paging = new JObject() };
  439. bool isOver = false;
  440. while (!isOver)
  441. {
  442. APIHelper.BaseGet(uri, null, new Dictionary<string, string>(), out HttpResponseMessage responseMessage);
  443. if (responseMessage.IsSuccessStatusCode)
  444. {
  445. var fb_error = GetFbApiError(responseMessage);
  446. if (!string.IsNullOrWhiteSpace(fb_error))
  447. {
  448. Logger.Error($"{nameof(CallFbCommentGetAPI)} FB API response error message: {fb_error} ");
  449. }
  450. rawResult = JsonConvert.DeserializeObject<FbCommentData>(responseMessage.Content.ReadAsStringAsync().Result);
  451. result.data.AddRange(rawResult.data);
  452. uri = rawResult.paging != null && rawResult.paging.ContainsKey("next") ? rawResult.paging["next"].ToString() : null;
  453. if (rawResult.data.Count == 0 || uri == null)
  454. {
  455. isOver = true;
  456. }
  457. }
  458. else
  459. {
  460. var error = $"{nameof(CallFbCommentGetAPI)} Error, ReasonPhrase:{responseMessage.ReasonPhrase} hrmResult.Headers.WwwAuthenticate:{responseMessage.Headers.WwwAuthenticate} ";
  461. Logger.Error(error);
  462. isOver = true;
  463. }
  464. }
  465. if (result.data.Count > 0)
  466. {
  467. string sMsg = GetFCommentsData(articleId, result, postId, out comments);
  468. // 儲存出錯
  469. if (sMsg != null)
  470. {
  471. comments = null;
  472. }
  473. }
  474. else
  475. {
  476. comments = null;
  477. }
  478. return true;
  479. }
  480. /// <summary>
  481. /// 延長token
  482. /// </summary>
  483. /// <param name="authorizationToken"></param>
  484. /// <param name="message"></param>
  485. /// <param name="path">圖片路徑</param>
  486. public bool CallFbLongTokenGetAPI(string authorizationToken, string client_id, string client_secret)
  487. {
  488. // 送出資料
  489. string uri = "https://graph.facebook.com/oauth/access_token?";
  490. var dicData = new Dictionary<string, string>()
  491. {
  492. { "grant_type", "fb_exchange_token" },
  493. { "client_id", client_id },
  494. { "client_secret", client_secret },
  495. { "fb_exchange_token", authorizationToken },
  496. };
  497. APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage);
  498. if (responseMessage.IsSuccessStatusCode)
  499. {
  500. var responseData = JsonConvert.DeserializeObject<FbToken>(responseMessage.Content.ReadAsStringAsync().Result);
  501. }
  502. return responseMessage.IsSuccessStatusCode;
  503. }
  504. /// <summary>
  505. /// 驗證token, 可改用 Function FbApiCheckToken
  506. /// </summary>
  507. /// <param name="authorizationToken"></param>
  508. /// <param name="message"></param>
  509. /// <param name="path">圖片路徑</param>
  510. public string CallFbCheckTokenGetAPI(string authorizationToken, string client_id, string client_secret, out int status)
  511. {
  512. // 送出資料
  513. status = 0; // 預設0: 正常 1: 即將到期 2: 驗證失敗
  514. string uri = "https://graph.facebook.com/debug_token?";
  515. var dicData = new Dictionary<string, string>()
  516. {
  517. { "input_token", authorizationToken },
  518. { "access_token", string.Format("{0}|{1}",client_id,client_secret) },
  519. };
  520. APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage);
  521. if (responseMessage.IsSuccessStatusCode)
  522. {
  523. var responseData = JsonConvert.DeserializeObject<FbTokenVerification>(responseMessage.Content.ReadAsStringAsync().Result);
  524. if (responseData.data.is_valid)
  525. {
  526. var timeStamp = responseData.data.expires_at - Convert.ToInt32(DateTime.UtcNow.AddHours(8).Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
  527. if (timeStamp > 20 * 86400) // 20天
  528. {
  529. return null;
  530. }
  531. else
  532. {
  533. status = 1;
  534. return "Token即將到期";
  535. }
  536. }
  537. else
  538. {
  539. status = 2;
  540. return "Token驗證失敗";
  541. }
  542. }
  543. else
  544. {
  545. status = 2;
  546. return "Request失敗";
  547. }
  548. }
  549. /// <summary>
  550. /// Send FB Message
  551. /// </summary>
  552. /// <param name="messenger_id_"></param>
  553. /// <param name="message_"></param>
  554. /// <param name="access_token_"></param>
  555. /// <param name="errorHandle_"></param>
  556. /// <returns></returns>
  557. public void SendMessage(ref string messenger_id_, ref string message_, ref string access_token_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_)
  558. {
  559. string url = ApiUrlHelper.SendMessage(access_token_);
  560. var dataContents = new
  561. {
  562. recipient = new { id = messenger_id_ },
  563. messaging_type = "MESSAGE_TAG",
  564. message = new { text = message_},
  565. tag = "POST_PURCHASE_UPDATE"
  566. };
  567. SendPostFbApi(url, dataContents, successHandle_, errorHandle_);
  568. }
  569. /// <summary>
  570. ///
  571. /// </summary>
  572. /// <returns></returns>
  573. public void CheckAccessToken(ref string access_token_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_)
  574. {
  575. string url = ApiUrlHelper.CheckAccessToken(access_token_);
  576. SendGetFbApi(url, successHandle_, errorHandle_);
  577. }
  578. public void GetUserAccessToken(ref string user_access_token_, ref string app_id_, ref string app_secret_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_)
  579. {
  580. string url = ApiUrlHelper.GetUserAccessToken(user_access_token_, app_id_, app_secret_);
  581. SendGetFbApi(url, successHandle_, errorHandle_);
  582. }
  583. public void GetPageAccessToken(ref string user_id_, ref string long_lived_user_access_token, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_)
  584. {
  585. string url = ApiUrlHelper.GetPageAccessToken(user_id_, long_lived_user_access_token);
  586. SendGetFbApi(url, successHandle_, errorHandle_);
  587. }
  588. public void GetGroupPublicDescription(string group_id_, string user_access_token_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_)
  589. {
  590. string url = ApiUrlHelper.GetGroupPublicDescription(group_id_, user_access_token_);
  591. SendGetFbApi(url, successHandle_, errorHandle_);
  592. }
  593. #endregion
  594. #region 專案獨有
  595. ///// <summary>
  596. ///// 貼文資料新增到SQL
  597. ///// </summary>
  598. ///// <param name="state"></param>
  599. ///// <returns></returns>
  600. private void GetFbPostData(FbGetPost fbGetPost)
  601. {
  602. ArsenalInterface ai;
  603. List<Command> lCmds = new List<Command>();
  604. // 取社團
  605. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  606. QueryJsonElement qjeOrigin = lBlocks.GetInst();
  607. qjeOrigin.table = tb_grp_group.TABLENAME;
  608. qjeOrigin.displaycols = new List<string>() { tb_grp_group.CN_UID, tb_grp_group.CN_FB_GROUP_ID };
  609. qjeOrigin.wherecols = new WhereNode(tb_grp_group.CN_FB_GROUP_ID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_group), fbGetPost.data[0].id.Split("_")[0]);
  610. lBlocks.Add(qjeOrigin);
  611. var sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  612. ai = ArsenalDBMgr.GetInst(cRes);
  613. List<tb_grp_group> group = ai.RunQueryList<tb_grp_group>(cRes);
  614. // 取貼文資料
  615. lBlocks.Clear();
  616. QueryJsonElement qjeArticle = lBlocks.GetInst();
  617. qjeArticle.table = tb_grp_article.TABLENAME;
  618. qjeArticle.displaycols = new List<string>() { tb_grp_article.CN_UID, tb_grp_article.CN_GROUP_UID, tb_grp_article.CN_FB_ARTICLE_ID };
  619. qjeArticle.wherecols = new WhereNode(tb_grp_article.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), group.First().uid);
  620. lBlocks.Add(qjeArticle);
  621. sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cArt);
  622. ai = ArsenalDBMgr.GetInst(cArt);
  623. List<tb_grp_article> article = ai.RunQueryList<tb_grp_article>(cArt);
  624. // 取媒體資料
  625. lBlocks.Clear();
  626. QueryJsonElement qjeArticleMedia = lBlocks.GetInst();
  627. qjeArticleMedia.table = tb_grp_article_media.TABLENAME;
  628. qjeArticleMedia.displaycols = new List<string>() { tb_grp_article_media.CN_UID, tb_grp_article_media.CN_ARTICLE_UID, tb_grp_article_media.CN_MEDIA_ID, tb_grp_article_media.CN_URI };
  629. lBlocks.Add(qjeArticleMedia);
  630. sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cMedia);
  631. ai = ArsenalDBMgr.GetInst(cMedia);
  632. List<tb_grp_article_media> lsmedia = ai.RunQueryList<tb_grp_article_media>(cMedia);
  633. fbGetPost.data.ForEach(x =>
  634. {
  635. var uid = string.Empty;
  636. // 如果貼文存在則更新 否則新增
  637. if (!article.Any(y => y.fb_article_id == x.id))
  638. {
  639. uid = Guid.NewGuid().ToString();
  640. tb_grp_article cNew = new tb_grp_article()
  641. {
  642. uid = uid,
  643. group_uid = group.First().uid,
  644. message = x.message,
  645. post_status = (int)EPostStatus.EPS_FETCH_FROM_FB,
  646. fb_article_id = x.id,
  647. release_date = x.created_time
  648. };
  649. lCmds.Add(Command.SetupInsertCmd(cNew));
  650. }
  651. else
  652. {
  653. uid = article.First(y => y.fb_article_id == x.id).uid;
  654. tb_grp_article cWhere = new tb_grp_article() { uid = uid };
  655. tb_grp_article cUpdate = new tb_grp_article()
  656. {
  657. group_uid = group.First().uid,
  658. message = x.message,
  659. post_status = (int)EPostStatus.EPS_FETCH_FROM_FB,
  660. fb_article_id = x.id,
  661. release_date = x.created_time
  662. };
  663. lCmds.Add(Command.SetupUpdateCmd(cUpdate, cWhere));
  664. }
  665. if (!lsmedia.Any(y => y.uri == x.full_picture) && x.full_picture != null)
  666. {
  667. tb_grp_article_media media = new tb_grp_article_media()
  668. {
  669. article_uid = uid,
  670. uri = x.full_picture,
  671. type = BLWording.MediaType.Photo,
  672. status_flag = (int)MediaType.GetFb
  673. };
  674. lCmds.Add(Command.SetupInsertCmd(media));
  675. }
  676. if (!lsmedia.Any(y => y.uri == x.full_picture) && x.source != null)
  677. {
  678. tb_grp_article_media media = new tb_grp_article_media()
  679. {
  680. article_uid = uid,
  681. uri = x.source,
  682. type = BLWording.MediaType.Video,
  683. status_flag = (int)MediaType.GetFb
  684. };
  685. lCmds.Add(Command.SetupInsertCmd(media));
  686. }
  687. });
  688. if (lCmds.Any())
  689. {
  690. ai = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo());
  691. ai.RunEditCmds(lCmds);
  692. sMsg = GetLastErrorCode(lCmds);
  693. }
  694. }
  695. /// <summary>
  696. /// 貼文留言存進SQL
  697. /// </summary>
  698. /// <param name="fbGetPost"></param>
  699. /// <param name="id"></param>
  700. private string GetFCommentsData(string articleId, FbCommentData fbGetPost, string post_id, out List<tb_grp_comment> comments)
  701. {
  702. // 沒有留言
  703. if (fbGetPost.data.Count == 0)
  704. {
  705. comments = null;
  706. return null;
  707. }
  708. List<Command> lCmds = new List<Command>();
  709. // 用文章 ID取文章 data
  710. var article = GetArticleByPostID(articleId);
  711. comments = new List<tb_grp_comment>();
  712. // 取回原先的留言
  713. List<tb_grp_comment> originComments = GetComments(article.uid);
  714. // 如果先前已有匯入留言,已匯入過的留言不再重複匯入
  715. List<string> existFbCommentID = originComments.Select(x => x.fb_comment_id).ToList();
  716. // 取回該社團可以取貨的地點
  717. var branches = GetBranches(article.group_uid).ToDictionary(x => x.uid, x => x.branch_name);
  718. var products = GetProducts(article.uid);
  719. // 會員預設取貨地點(中文)的對應表,沒設定取貨地點不會放進列表
  720. var memberDefaultBranchDict = GetMembers(post_id.Split('_')[0])
  721. .Where(x => !string.IsNullOrEmpty(x.default_branch) && branches.ContainsKey(x.default_branch))
  722. .ToDictionary(x => x.group_user_id, x => branches[x.default_branch]);
  723. // 將名稱以['A', 'B'...]這樣依序產生,如果產品有3個,就要放入['A', 'B', 'C']
  724. List<GroupBuyParser.ProductInfo> productInfoNames = new List<GroupBuyParser.ProductInfo>();
  725. //productInfoNames = products.Select((x, i) => new GroupBuyParser.ProductInfo
  726. //{
  727. // Name = x.name ?? "",
  728. // Specifications = string.IsNullOrEmpty(x.specification) ? null : x.specification.Split(',', StringSplitOptions.RemoveEmptyEntries)
  729. //}).ToList();
  730. var productInfos = products.Select((x, i) => new GroupBuyParser.ProductInfo
  731. {
  732. Name = ((char)('A' + x.seq)).ToString(),
  733. Specifications = string.IsNullOrEmpty(x.specification) ? null : x.specification.Split(',', StringSplitOptions.RemoveEmptyEntries).OrderByDescending(x => x.Count()).ToArray()
  734. }).ToList();
  735. //var productInfos = productInfoNames.Concat(productInfosChar).ToList();
  736. Logger.Info($"開始解析貼文 文章ID: {article.uid} 設定: {JsonConvert.SerializeObject(productInfos)}");
  737. var parser = new GroupBuyParser.GroupBuyParser
  738. {
  739. Settings = new GroupBuyParser.ParserSettings
  740. {
  741. Products = productInfos,
  742. Branches = branches.Values.ToList()
  743. }
  744. };
  745. StringBuilder parseCommentErrorLog = new StringBuilder();
  746. foreach (var item in fbGetPost.data)
  747. {
  748. // 沒有留言就不處理
  749. if (string.IsNullOrEmpty(item.message))
  750. {
  751. continue;
  752. }
  753. // 判斷已經重複的ID
  754. if (existFbCommentID.Contains(item.id))
  755. {
  756. continue;
  757. }
  758. // 判斷是否為回覆留言
  759. string parentUid = null;
  760. if (item.parent != null)
  761. {
  762. parentUid = item.parent.id;
  763. }
  764. // 如果取不回fb_id(使用者沒有允許應用程式查看貼文)仍要處理
  765. string group_user_id = item.from?.id;
  766. string json = "";
  767. int status = 0;
  768. // 傳入該會員預設取貨地點(非會員則為null)
  769. string defaultBranch = null;
  770. if (!string.IsNullOrEmpty(group_user_id) && memberDefaultBranchDict.ContainsKey(group_user_id))
  771. {
  772. defaultBranch = memberDefaultBranchDict[group_user_id];
  773. }
  774. var parseData = new GroupBuyParser.ParserData
  775. {
  776. Text = item.message,
  777. DefaultBranch = defaultBranch
  778. };
  779. parser.Parse(parseData);
  780. if (parseData.Success)
  781. {
  782. bool isProductCorrect = true;
  783. foreach (var product in parseData.Product.ToList())
  784. {
  785. if (product.Name == "I")
  786. {
  787. isProductCorrect = false;
  788. break;
  789. }
  790. }
  791. if (isProductCorrect) // 名稱有I 不Insert進資料庫
  792. {
  793. json = JsonConvert.SerializeObject(parseData.Product);
  794. status = (int)CommentStatus.OK;
  795. }
  796. else
  797. {
  798. status = (int)CommentStatus.InvalidFormat;
  799. }
  800. }
  801. else
  802. {
  803. status = (int)CommentStatus.InvalidFormat;
  804. // 增加log紀錄確認解析失敗的原因
  805. parseCommentErrorLog.AppendLine($"解析貼文失敗 姓名: {item.from?.name} 內容: {item.message} 原因: {parseData.ErrorMessage}");
  806. }
  807. if (string.IsNullOrEmpty(group_user_id))
  808. {
  809. status = (int)CommentStatus.UnknownMember;
  810. }
  811. else if (!memberDefaultBranchDict.ContainsKey(group_user_id))
  812. {
  813. status = (int)CommentStatus.UnknownMember;
  814. }
  815. else if (comments.Any(x => x.group_user_id == group_user_id)) // 是否有重複留言
  816. {
  817. status = (int)CommentStatus.Duplicate;
  818. }
  819. if (parentUid != null)
  820. {
  821. status = (int)CommentStatus.Duplicate;
  822. }
  823. tb_grp_comment cNew = new tb_grp_comment
  824. {
  825. uid = Guid.NewGuid().ToString(),
  826. article_uid = article.uid,
  827. origin_comment = item.message,
  828. comment = json,
  829. group_user_id = group_user_id,
  830. comment_time = item.created_time,
  831. fb_comment_id = item.id,
  832. status = status,
  833. user_name = item.from?.name,
  834. user_picture = item.from?.picture.data.url,
  835. parent_comment_id = parentUid == null ? null : parentUid
  836. };
  837. comments.Add(cNew);
  838. }
  839. if(parseCommentErrorLog.Length != 0)
  840. {
  841. // 參考原本寫法, 解析貼文失敗訊息標記為Info
  842. parseCommentErrorLog.Insert(0, Environment.NewLine);
  843. Logger.Info(parseCommentErrorLog.ToString());
  844. }
  845. // 沒有新增任何留言就不處理
  846. if (comments.Count == 0)
  847. {
  848. return null;
  849. }
  850. lCmds.AddRange(comments.Select(x => Command.SetupInsertCmd(x)));
  851. var ai = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo());
  852. ai.RunEditCmds(lCmds);
  853. var sMsg = GetLastErrorCode(lCmds);
  854. return sMsg;
  855. }
  856. /// <summary>
  857. /// 將留言轉成訂單(結單)
  858. /// </summary>
  859. /// <param name="article_uid"></param>
  860. public string CheckOrder(string article_uid, JArray jData)
  861. {
  862. // 貼文資料
  863. var article = GetArticle(article_uid);
  864. // 商品資料
  865. var productData = GetProducts(article_uid).OrderBy(x => x.seq).ToArray();
  866. // 貼文對應的群組UID
  867. var groupUid = article.group_uid;
  868. // 取得社團成員ID對應的UID
  869. var fb_group_id = article.fb_article_id.Split('_')[0];
  870. var memberDict = GetMembers(fb_group_id).ToDictionary(x => x.group_user_id, x => x.uid);
  871. // 分店的對應表
  872. var branchDict = GetBranches(groupUid).ToDictionary(x => x.branch_name, x => x.uid);
  873. // 取回過去的訂單主檔
  874. var IsOrderMaster = GetOrderMasters(article_uid);
  875. // 如果過去已經有結單,使用同一個order_code,反之取回新的訂單編號(這不就是article_uid嗎?)
  876. var orderCode = IsOrderMaster.Any() ? IsOrderMaster.First().order_code : GetOrderCode();
  877. var orderName = IsOrderMaster.Any() ? IsOrderMaster.First().name : article.name; // 有結單過的貼文使用舊名稱
  878. var orderMasterDic = new Dictionary<string, tb_ord_order_master>();
  879. // 再次結單屬於新的order_master
  880. // 先取回所有留言
  881. var comments = GetComments(article_uid);
  882. // 留言解析成功的才更新
  883. List<CommentModel> data = new List<CommentModel>();
  884. foreach (JToken token in jData)
  885. {
  886. Dictionary<string, object> dicData = token.ToObject<Dictionary<string, object>>();
  887. var commentData = comments.Where(x => x.status != (int)CommentStatus.TransferOrder && !string.IsNullOrEmpty(x.comment) &&
  888. x.status_flag == BLWording.STATUS_FLAG_ON && !string.IsNullOrEmpty(x.group_user_id) && x.uid == dicData["uid"].ToString()).Select(x => new
  889. {
  890. x.uid,
  891. x.group_user_id,
  892. x.comment,
  893. x.comment_time
  894. });
  895. if (commentData.Any())
  896. {
  897. CommentModel tempComment = new CommentModel()
  898. {
  899. uid = commentData.Select(x => x.uid).FirstOrDefault(),
  900. comment = commentData.Select(x => x.comment).FirstOrDefault(),
  901. group_user_id = commentData.Select(x => x.group_user_id).FirstOrDefault(),
  902. comment_time = commentData.Select(x => x.comment_time).FirstOrDefault()
  903. };
  904. data.Add(tempComment);
  905. }
  906. }
  907. if (!data.Any())
  908. {
  909. return null;
  910. }
  911. List<Command> lCmds = new List<Command>();
  912. List<tb_ord_order_detail> lOrderDetails = new List<tb_ord_order_detail>();
  913. ArsenalInterface ai = null;
  914. foreach (var item in data)
  915. {
  916. // 解析留言訂購格式,以每一項為單位塞到DB去
  917. var products = JsonConvert.DeserializeObject<IEnumerable<GroupBuyParser.ParserProduct>>(item.comment);
  918. foreach (var product in products)
  919. {
  920. // 目前暫定A = 0 B = 1...
  921. var productIndex = product.Name[0] - 'A';
  922. var productItem = productData.FirstOrDefault(x => x.seq == productIndex);
  923. if (product.Branch == "未知" || string.IsNullOrWhiteSpace(product.Branch))
  924. {
  925. break;
  926. }
  927. var branch_uid = branchDict[product.Branch];
  928. // 如果目前沒有主檔,新增主檔
  929. if (!orderMasterDic.ContainsKey(branch_uid))
  930. {
  931. // 查詢group_uid
  932. tb_grp_branch cBranch = new tb_grp_branch();
  933. cBranch.SetDirty(tb_grp_branch.CN_GROUP_UID);
  934. tb_grp_branch cCon = new tb_grp_branch() { uid = branch_uid };
  935. Command cSelect = Command.SetupSelectCmd(cBranch, cCon);
  936. ai = ArsenalDBMgr.GetInst(cSelect);
  937. tb_grp_branch qds = ai.RunQuerySingleORM<tb_grp_branch>(cSelect);
  938. var newOrderMaster = new tb_ord_order_master
  939. {
  940. uid = Guid.NewGuid().ToString(),
  941. type = 1,
  942. name = orderName,
  943. order_code = orderCode,
  944. article_uid = article_uid,
  945. branch_uid = branch_uid,
  946. group_uid = qds.group_uid,
  947. status = (int)OrderStatus.NotArrived,
  948. };
  949. lCmds.Add(Command.SetupInsertCmd(newOrderMaster));
  950. // 增加Dictionary的內容,避免內容被重複新增
  951. orderMasterDic.Add(branch_uid, newOrderMaster);
  952. }
  953. if (product.Qty > 0)
  954. {
  955. var order = new tb_ord_order_detail
  956. {
  957. uid = Guid.NewGuid().ToString(),
  958. order_uid = orderMasterDic[branch_uid].uid,
  959. article2product_uid = productItem.uid,
  960. member_uid = memberDict[item.group_user_id],
  961. specification = product.Specification != "" ? product.Specification : null,
  962. order_qty = product.Qty,
  963. price = productItem.price * product.Qty,
  964. comment_time = item.comment_time,
  965. comment_uid = item.uid,
  966. status = (int)OrderStatus.NotArrived
  967. };
  968. lOrderDetails.Add(order);
  969. // 更新留言變成不顯示
  970. tb_grp_comment updateComment = new tb_grp_comment { status = (int)CommentStatus.TransferOrder };
  971. tb_grp_comment updateCommentCond = new tb_grp_comment { uid = item.uid };
  972. lCmds.Add(Command.SetupUpdateCmd(updateComment, updateCommentCond));
  973. }
  974. }
  975. }
  976. if (lOrderDetails.Count == 0)
  977. {
  978. return "結單錯誤(請確認訂單資訊)";
  979. }
  980. if (article.post_status < 64)
  981. {
  982. tb_grp_article updateArticle = new tb_grp_article { post_status = (int)EPostStatus.EPS_ORDER };
  983. tb_grp_article updateArticleCond = new tb_grp_article { uid = article_uid };
  984. lCmds.Add(Command.SetupUpdateCmd(updateArticle, updateArticleCond));
  985. }
  986. lCmds.AddRange(lOrderDetails.Select(x => Command.SetupInsertCmd(x)));
  987. ai = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo());
  988. ai.RunEditCmds(lCmds);
  989. var sMsg = GetLastErrorCode(lCmds);
  990. return sMsg;
  991. }
  992. private List<tb_ord_order_master> GetOrderMasters(string article_uid)
  993. {
  994. tb_ord_order_master cDisplay = new tb_ord_order_master();
  995. cDisplay.SetFullDirty();
  996. var whereNode = new WhereNode(tb_ord_order_master.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_ord_order_master), article_uid);
  997. var cSelect = Command.SetupSelectCmd(cDisplay, whereNode);
  998. var ai = ArsenalDBMgr.GetInst(cSelect);
  999. var data = ai.RunQueryList<tb_ord_order_master>(cSelect);
  1000. return data;
  1001. }
  1002. /// <summary>
  1003. /// 用文章FB ID取回貼文部分資訊
  1004. /// </summary>
  1005. /// <param name="post_id"></param>
  1006. /// <returns></returns>
  1007. private static tb_grp_article GetArticleByPostID(string articleId)
  1008. {
  1009. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  1010. QueryJsonElement qjeOrigin = lBlocks.GetInst();
  1011. qjeOrigin.table = tb_grp_article.TABLENAME;
  1012. qjeOrigin.displaycols = new List<string>() { tb_grp_article.CN_UID, tb_grp_article.CN_FB_ARTICLE_ID, tb_grp_article.CN_GROUP_UID };
  1013. qjeOrigin.wherecols = new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), articleId);
  1014. lBlocks.Add(qjeOrigin);
  1015. string sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  1016. var ai = ArsenalDBMgr.GetInst(cRes);
  1017. var articles = ai.RunQueryList<tb_grp_article>(cRes);
  1018. return articles.First();
  1019. }
  1020. /// <summary>
  1021. /// 用文章UID取回貼文部分資訊
  1022. /// </summary>
  1023. /// <param name="article_uid"></param>
  1024. /// <returns></returns>
  1025. private tb_grp_article GetArticle(string article_uid)
  1026. {
  1027. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  1028. QueryJsonElement qjeOrigin = lBlocks.GetInst();
  1029. qjeOrigin.table = tb_grp_article.TABLENAME;
  1030. qjeOrigin.displaycols = new List<string>
  1031. {
  1032. tb_grp_article.CN_GROUP_UID,
  1033. tb_grp_article.CN_FB_ARTICLE_ID,
  1034. tb_grp_article.CN_POST_STATUS,
  1035. tb_grp_article.CN_NAME
  1036. };
  1037. qjeOrigin.wherecols = new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), article_uid);
  1038. lBlocks.Add(qjeOrigin);
  1039. string sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  1040. var ai = ArsenalDBMgr.GetInst(cRes);
  1041. var articles = ai.RunQueryList<tb_grp_article>(cRes);
  1042. return articles.First();
  1043. }
  1044. /// <summary>
  1045. /// 用文章UID取回原先的留言
  1046. /// </summary>
  1047. /// <param name="article_uid"></param>
  1048. /// <returns></returns>
  1049. private List<tb_grp_comment> GetComments(string article_uid)
  1050. {
  1051. tb_grp_comment cDisplay = new tb_grp_comment();
  1052. cDisplay.SetFullDirty();
  1053. var whereNode = new WhereNode(tb_grp_comment.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), article_uid);
  1054. var cSelect = Command.SetupSelectCmd(cDisplay, whereNode);
  1055. var ai = ArsenalDBMgr.GetInst(cSelect);
  1056. var originComments = ai.RunQueryList<tb_grp_comment>(cSelect);
  1057. return originComments;
  1058. }
  1059. /// <summary>
  1060. /// 用社團UID取回取貨地點
  1061. /// </summary>
  1062. /// <param name="group_uid"></param>
  1063. /// <returns></returns>
  1064. private List<tb_grp_branch> GetBranches(string group_uid)
  1065. {
  1066. tb_grp_branch cDisplay = new tb_grp_branch();
  1067. cDisplay.SetFullDirty();
  1068. var whereNode = new WhereNode(tb_grp_branch.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_branch), group_uid);
  1069. var cSelect = Command.SetupSelectCmd(cDisplay, whereNode);
  1070. var ai = ArsenalDBMgr.GetInst(cSelect);
  1071. var data = ai.RunQueryList<tb_grp_branch>(cSelect);
  1072. return data;
  1073. }
  1074. /// <summary>
  1075. /// 用貼文UID取回該貼文所有商品的部分資訊
  1076. /// </summary>
  1077. /// <param name="article_uid"></param>
  1078. /// <returns></returns>
  1079. private List<tb_prd_article2product> GetProducts(string article_uid)
  1080. {
  1081. /**開始組指令**/
  1082. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  1083. QueryJsonElement qjeArticleToProduct = lBlocks.GetInst();
  1084. qjeArticleToProduct.table = tb_prd_article2product.TABLENAME;
  1085. qjeArticleToProduct.displaycols = new List<string>()
  1086. {
  1087. tb_prd_article2product.CN_UID,
  1088. tb_prd_article2product.CN_NAME,
  1089. tb_prd_article2product.CN_PRICE,
  1090. tb_prd_article2product.CN_SEQ,
  1091. tb_prd_article2product.CN_SPECIFICATION
  1092. };
  1093. qjeArticleToProduct.wherecols = new WhereNode(tb_prd_article2product.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_prd_article2product), article_uid);
  1094. lBlocks.Add(qjeArticleToProduct);
  1095. QueryJsonElement qjeProduct = lBlocks.GetInst();
  1096. qjeProduct.table = tb_prd_product.TABLENAME;
  1097. qjeProduct.jointable = qjeArticleToProduct;
  1098. qjeProduct.joincols = new Dictionary<string, string>()
  1099. {
  1100. { tb_prd_product.CN_UID, tb_prd_article2product.CN_PRD_UID }
  1101. };
  1102. lBlocks.Add(qjeProduct);
  1103. var sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  1104. var ai = ArsenalDBMgr.GetInst(cRes);
  1105. List<tb_prd_article2product> data = ai.RunQueryList<tb_prd_article2product>(cRes);
  1106. return data.ToList();
  1107. }
  1108. /// <summary>
  1109. /// 用FB社團ID取回所有使用者資訊
  1110. /// </summary>
  1111. /// <param name="group_id"></param>
  1112. /// <returns></returns>
  1113. private List<tb_meb_member> GetMembers(string group_id)
  1114. {
  1115. tb_meb_member tDisplay = new tb_meb_member();
  1116. tDisplay.SetFullDirty();
  1117. List<WhereNode> lwWhereData = new List<WhereNode>();
  1118. lwWhereData.Add(new WhereNode(tb_meb_member.CN_GROUP_ID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_meb_member), group_id));
  1119. lwWhereData.Add(new WhereNode(tb_meb_member.CN_NAME, WhereNode.EColumnOperation.EOT_NEQ, typeof(tb_meb_member), "現貨銷售"));
  1120. Command cSelect = Command.SetupSelectCmd(tDisplay, new WhereNode(WhereNode.ENodeOperation.ENO_AND, lwWhereData.ToArray()));
  1121. ArsenalInterface ai = ArsenalDBMgr.GetInst(cSelect);
  1122. List<tb_meb_member> members = ai.RunQueryList<tb_meb_member>(cSelect);
  1123. return members;
  1124. }
  1125. /// <summary>
  1126. /// 取得目前的訂單號碼
  1127. /// </summary>
  1128. /// <param name="post_id"></param>
  1129. /// <returns></returns>
  1130. public string GetOrderCode()
  1131. {
  1132. string dateString = DateTime.Now.ToString("yyMMdd");
  1133. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  1134. QueryJsonElement qjeOrigin = lBlocks.GetInst();
  1135. qjeOrigin.table = tb_ord_order_master.TABLENAME;
  1136. qjeOrigin.displaycols = new List<string>() { tb_ord_order_master.CN_ORDER_CODE };
  1137. qjeOrigin.wherecols = new WhereNode(tb_ord_order_master.CN_ORDER_CODE, WhereNode.EColumnOperation.EOT_LIKE, typeof(tb_ord_order_master), dateString + "%");
  1138. lBlocks.Add(qjeOrigin);
  1139. string sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  1140. var ai = ArsenalDBMgr.GetInst(cRes);
  1141. var orders = ai.RunQueryList<tb_ord_order_master>(cRes);
  1142. // 兩碼流水號,例如20082801 = 2020/8/28 第一批訂單
  1143. var lastOrderNo = orders.Select(x => x.order_code).OrderByDescending(x => x).FirstOrDefault();
  1144. int newIndex = 1;
  1145. if (!string.IsNullOrEmpty(lastOrderNo))
  1146. {
  1147. newIndex = int.Parse(lastOrderNo.Substring(6, 2)) + 1;
  1148. }
  1149. return dateString + newIndex.ToString("00");
  1150. }
  1151. #endregion
  1152. private void SendGetFbApi(string url, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_)
  1153. {
  1154. APIHelper.BaseGet(url, null, new Dictionary<string, string>(), out HttpResponseMessage responseMessage);
  1155. FbApiResponseHandler(responseMessage, successHandle_, errorHandle_);
  1156. }
  1157. private void SendPostFbApi(string url, dynamic postContent, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_)
  1158. {
  1159. APIHelper.BasePost(url, null, postContent, out HttpResponseMessage responseMessage, "json");
  1160. FbApiResponseHandler(responseMessage, successHandle_, errorHandle_);
  1161. }
  1162. /// <summary>
  1163. /// If FB API response SUCCESS return true, else you can defined your error handle function like write log
  1164. /// </summary>
  1165. /// <param name="httpResponseMessage_"></param>
  1166. /// <param name="errorHandle_"></param>
  1167. /// <returns></returns>
  1168. private void FbApiResponseHandler(HttpResponseMessage httpResponseMessage_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_)
  1169. {
  1170. // check response header
  1171. if (!httpResponseMessage_.IsSuccessStatusCode)
  1172. {
  1173. var headerError = $"{httpResponseMessage_.ReasonPhrase}, {httpResponseMessage_.Headers.WwwAuthenticate}";
  1174. errorHandle_(httpResponseMessage_, headerError);
  1175. return;
  1176. }
  1177. // check response content
  1178. var bodyError = GetFbApiError(httpResponseMessage_);
  1179. if (!string.IsNullOrWhiteSpace(bodyError))
  1180. {
  1181. errorHandle_(httpResponseMessage_, bodyError);
  1182. return;
  1183. }
  1184. successHandle_(httpResponseMessage_);
  1185. }
  1186. /// <summary>
  1187. /// 檢查Response code 200後, FB回傳的內容是否包含錯誤訊息
  1188. /// </summary>
  1189. /// <param name="httpMessage_"></param>
  1190. /// <returns></returns>
  1191. public static string GetFbApiError(HttpResponseMessage httpMessage_)
  1192. {
  1193. var sContent = httpMessage_.Content.ReadAsStringAsync().Result;
  1194. var jsonObject = JObject.Parse(sContent);
  1195. if (jsonObject["error"] != null)
  1196. {
  1197. return jsonObject["error"].ToString();
  1198. }
  1199. return "";
  1200. }
  1201. }
  1202. }