|
|
using log4net; using CounsellorBL.Helper; using MonumentDefine; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OT.COM.ArsenalDB; using SoldierData.EnterprizeV4; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using static CounsellorBL.GROUP.ConstDefinition.GrpBLWording; using static MonumentDefine.Enums; using System.Text;
namespace CounsellorBL.GROUP.Helper { /// <summary>
/// 類別名稱:Mailer
/// 類別說明:
/// 起始作者:
/// 起始日期:
/// 最新修改人:
/// 最新修改日:
/// </summary>
public class FbHelper : DBService { private static ILog _inst = null; private static ILog Logger { get { if (_inst == null) { _inst = LogManager.GetLogger(typeof(FbHelper)); } return _inst; } } public override string MainTable => null; #region 類別
/// <summary>
/// Fb留言資料
/// </summary>
private class FbCommentData { public List<data> data { get; set; } public JObject paging { get; set; } } private class data { public DateTime created_time { get; set; } public from from { get; set; } public string message { get; set; } public string id { get; set; } public parent parent { get; set; } public int comment_count { get; set; } } private class from { public string name { get; set; } public string id { get; set; } public Picture picture { get; set; }
public class Picture { public PictureData data { get; set; }
public class PictureData { public string url { get; set; } } } } private class parent { public string id { get; set; } }
/// <summary>
/// Fb 延長token
/// </summary>
private class FbToken { public string access_token { get; set; } public string type { get; set; } }
/// <summary>
/// Fb token 驗證
/// </summary>
public class FbTokenVerification { public VerificationContent data { get; set; } } public class VerificationContent { public string app_id { get; set; } public string type { get; set; } public int data_access_expires_at { get; set; } //public error error { get; set; }
public int expires_at { get; set; } public bool is_valid { get; set; } public string user_id { get; set; } } private class error { public int code { get; set; } public string message { get; set; } public int subcode { get; set; } } /// <summary>
/// FB API get token response information
/// </summary>
public class FbGetTokenEntity { public string access_token { get; set; } public string token_type { get; set; } public string expires_in { get; set; } }
public class FbGroupEntity { public string name { get; set; } public string id { get; set; } public string privacy { get; set; } }
APIURLHelper ApiUrlHelper = new APIURLHelper();
/// <summary>
/// fb 貼文
/// </summary>
public class FbGetPost { public List<FbGetPostdata> data { get; set; } public JObject paging { get; set; } }
public class FbGetPostdata { public string id { get; set; } public string message { get; set; } public string full_picture { get; set; } public string source { get; set; } public DateTime updated_time { get; set; } public DateTime created_time { get; set; } }
public class PushPost { public string id { get; set; }
} #endregion
public enum CommentStatus { /// <summary>
/// 無問題 (綠)
/// </summary>
OK = 1, /// <summary>
/// 有問題【無數量】【無分店】【無產品】【數字有更新】 (紅)
/// </summary>
InvalidFormat = 2, /// <summary>
/// 會員無登入系統 (橘)
/// </summary>
UnknownMember = 3, /// <summary>
/// 黑名單或其他回覆的留言 (黑)
/// </summary>
Duplicate = 4, /// <summary>
/// 已轉成訂單,不顯示其中
/// </summary>
TransferOrder = 9 } class CommentModel { public string uid { get; set; } public string group_user_id { get; set; } public string comment { get; set; } public DateTime comment_time { get; set; } } #region FbAPI
// 針對應用程式 可以使用{應用程式ID}|{應用程式密鑰}
/// <summary>
/// 上傳貼文的POST
/// </summary>
/// <param name="authorizationToken"></param>
/// <param name="message"></param>
/// <param name="path">圖片路徑</param>
public string CallFbPostPushAPI(string authorizationToken, string message, string groupId, List<string> path, out string o_sPostFBID) { string sMsg = null; string sPostFBID = null; Logger.Info($"CallFbPostPushAPI start groupId={groupId}");
if(path != null) { path.ForEach(p => { Logger.Info($"CallFbPostPushAPI path={p}"); }); } try { do { // 送出資料
string uri = string.Format("https://graph.facebook.com/v8.0/{0}/feed", groupId); var lsData = new List<APIHelper.DataContent>() { new APIHelper.DataContent { Key = "access_token" , Type = typeof(StringContent) , Content = authorizationToken }, new APIHelper.DataContent { Key = "message", Type = typeof(StringContent), Content = message }, new APIHelper.DataContent { Key = "published", Type = typeof(StringContent), Content = "false" } };
Logger.Info($"CallFbPostPushAPI f2 uri={uri}"); if (path != null && path.Any()) { int i = 0; path.ForEach(x => { if (x != null) { lsData.Add(new APIHelper.DataContent { Key = $"attached_media[{i}]", Type = typeof(StringContent), Content = "{\"media_fbid\":" + x + "}" }); } i++; }); } Logger.Info($"CallFbPostPushAPI f3 uri={uri}");
sMsg = APIHelper.BasePost(uri, null, lsData, out HttpResponseMessage responseMessage);
if (sMsg != null) { Logger.Error(sMsg); break; }
Logger.Info($"CallFbPostPushAPI responseMessage.IsSuccessStatusCode = {responseMessage.IsSuccessStatusCode}");
if (responseMessage.IsSuccessStatusCode) { var fb_error = GetFbApiError(responseMessage);
if (!string.IsNullOrWhiteSpace(fb_error)) { sMsg = fb_error; Logger.Error($"CallFbPostPushAPI f7"); Logger.Error($"CallFbPostPushAPI sMsg={sMsg}"); break; }
Logger.Info($"CallFbPostPushAPI f6"); string sContent = responseMessage.Content.ReadAsStringAsync().Result; Logger.Info($"CallFbPostPushAPI f6 sContent={sContent}"); sPostFBID = JsonConvert.DeserializeObject<PushPost>(sContent).id; Logger.Info($"CallFbPostPushAPI f6 sPostFBID={sPostFBID}"); } else { Logger.Error($"CallFbPostPushAPI f7"); sMsg = JsonConvert.SerializeObject(responseMessage); Logger.Error($"CallFbPostPushAPI sMsg={sMsg}"); break; } } while (false); } catch (Exception ex) { sMsg = ex.Message; Logger.Error($"Exception={sMsg}"); }
o_sPostFBID = sPostFBID; Logger.Info($"CallFbPostPushAPI end groupId={groupId}"); return sMsg; }
/// <summary>
/// 上傳圖片的POST
/// </summary>
/// <param name="authorizationToken"></param>
/// <param name="message"></param>
/// <param name="path">圖片路徑</param>
public string CallFbPicturePushAPI(string authorizationToken, string groupId, string path, out string o_sPicID) { string sMsg = null; string sPicID = null; Logger.Info($"CallFbPicturePushAPI start groupId={groupId} path={path}"); try { do { // 送出資料
//string uri = string.Format("https://graph.facebook.com/v7.0/{0}/photos", groupId);
//Logger.Info($"CallFbPicturePushAPI uri = {uri}");
//var lsData = new List<APIHelper.DataContent>()
//{
// new APIHelper.DataContent { Key = "access_token" , Type = typeof(StringContent) , Content = authorizationToken },
// new APIHelper.DataContent { Key = "url", Type = typeof(StringContent), Content = path },
// new APIHelper.DataContent { Key = "published", Type = typeof(StringContent), Content = "false" },
// new APIHelper.DataContent { Key = "attempt", Type = typeof(StringContent), Content = "3" }
//};
// 送出資料
string uri = string.Format("https://graph.facebook.com/v7.0/{0}/photos?access_token={1}", groupId, authorizationToken); Logger.Info($"CallFbPicturePushAPI uri = {uri}"); var lsData = new List<APIHelper.DataContent>() { //new APIHelper.DataContent { Key = "access_token" , Type = typeof(StringContent) , Content = authorizationToken },
new APIHelper.DataContent { Key = "url", Type = typeof(StringContent), Content = path }, new APIHelper.DataContent { Key = "published", Type = typeof(StringContent), Content = "false" }, new APIHelper.DataContent { Key = "attempt", Type = typeof(StringContent), Content = "3" }, new APIHelper.DataContent { Key = "suppress_http_code", Type = typeof(StringContent), Content = "1" }, new APIHelper.DataContent { Key = "format", Type = typeof(StringContent), Content = "json" }, new APIHelper.DataContent { Key = "pretty", Type = typeof(StringContent), Content = "0" }, //new APIHelper.DataContent { Key = "debug", Type = typeof(StringContent), Content = "all" },
new APIHelper.DataContent { Key = "transport", Type = typeof(StringContent), Content = "cors" }, };
sMsg = APIHelper.BasePost(uri, null, lsData, out HttpResponseMessage responseMessage);
if (sMsg != null) { Logger.Error($"CallFbPicturePushAPI uri = {uri} sMsg={sMsg}"); break; }
if (responseMessage.IsSuccessStatusCode) { var fb_error = GetFbApiError(responseMessage);
if (!string.IsNullOrWhiteSpace(fb_error)) { sMsg = fb_error; Logger.Error($"CallFbPicturePushAPI f7"); Logger.Error($"CallFbPicturePushAPI sMsg={sMsg}"); break; }
string sContent = responseMessage.Content.ReadAsStringAsync().Result; Logger.Info($"CallFbPicturePushAPI sContent={sContent}"); sPicID = JsonConvert.DeserializeObject<PushPost>(sContent).id; Logger.Info($"CallFbPicturePushAPI sPicID={sPicID}"); } else { Logger.Error($"CallFbPicturePushAPI f7"); sMsg = JsonConvert.SerializeObject(responseMessage); Logger.Error($"CallFbPicturePushAPI sMsg={sMsg}"); break; } } while (false); } catch (Exception ex) { sMsg = ex.Message; Logger.Error($"CallFbPicturePushAPI exception={sMsg}"); }
o_sPicID = sPicID; Logger.Info($"CallFbPicturePushAPI end groupId={groupId} path={path} sResult={sPicID}"); return sMsg; }
/// <summary>
/// 貼文的Get(抓貼文、圖片、影片)
/// </summary>
/// <param name="authorizationToken"></param>
/// <param name="message"></param>
/// <param name="path">圖片路徑</param>
public bool CallFbPostGetAPI(string authorizationToken, string groupId) { // 送出資料 取1000筆資料
string uri = string.Format("https://graph.facebook.com/v7.0/{0}/feed?fields=full_picture,message,source,updated_time,created_time&limit=1000&", groupId); var dicData = new Dictionary<string, string>() { { "access_token", authorizationToken }
}; APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage); if (responseMessage.IsSuccessStatusCode) { GetFbPostData(JsonConvert.DeserializeObject<FbGetPost>(responseMessage.Content.ReadAsStringAsync().Result)); } return responseMessage.IsSuccessStatusCode; }
/// <summary>
/// 貼文的Get(抓貼文、圖片、影片)
/// </summary>
/// <param name="authorizationToken"></param>
/// <param name="message"></param>
/// <param name="path">圖片路徑</param>
public FbGetPost CallFbPostGetDataAPI(string authorizationToken, string groupId, int grabDate_ = 0) { if (grabDate_ == 0 || grabDate_ > 30) grabDate_ = 30;// 30日為預設天數
// 送出資料 撈取30天內之文章 並重複取至無資料
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}&", groupId, DateTime.Now.AddDays(-grabDate_).ToString("yyyy-MM-dd") ); FbGetPost rawResult = null; FbGetPost result = new FbGetPost() { data = new List<FbGetPostdata>(), paging = new JObject() }; bool isOver = false; var dicData = new Dictionary<string, string>() { { "access_token", authorizationToken } }; while (!isOver) { APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage); if (responseMessage.IsSuccessStatusCode) { rawResult = JsonConvert.DeserializeObject<FbGetPost>(responseMessage.Content.ReadAsStringAsync().Result); result.data.AddRange(rawResult.data); uri = rawResult.paging != null ? rawResult.paging["next"].ToString() : null; if (rawResult.data.Count == 0) { isOver = true; } } else { isOver = true; } } return result; }
/// <summary>
/// 貼文的Get(抓單篇貼文)
/// </summary>
/// <param name="authorizationToken"></param>
/// <param name="message"></param>
/// <param name="path">圖片路徑</param>
public FbGetPostdata CallSingleFbPostGetDataAPI(string authorizationToken, string postId) { string uri = string.Format("https://graph.facebook.com/v7.0/{0}?fields=created_time&", postId); FbGetPost result = new FbGetPost() { data = new List<FbGetPostdata>(), paging = new JObject() }; var dicData = new Dictionary<string, string>() { { "access_token", authorizationToken } }; FbGetPostdata rawResult = null; APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage); if (responseMessage.IsSuccessStatusCode) { rawResult = JsonConvert.DeserializeObject<FbGetPostdata>(responseMessage.Content.ReadAsStringAsync().Result); }
return rawResult; }
/// <summary>
/// 取回留言的Get
/// </summary>
/// <param name="authorizationToken"></param>
/// <param name="message"></param>
/// <param name="path">圖片路徑</param>
public bool CallFbCommentGetAPI(string articleId, string authorizationToken, string postId, out List<tb_grp_comment> comments) { // 送出資料
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"); FbCommentData rawResult = null; FbCommentData result = new FbCommentData() { data = new List<data>(), paging = new JObject() };
bool isOver = false; while (!isOver) { APIHelper.BaseGet(uri, null, new Dictionary<string, string>(), out HttpResponseMessage responseMessage); if (responseMessage.IsSuccessStatusCode) { var fb_error = GetFbApiError(responseMessage);
if (!string.IsNullOrWhiteSpace(fb_error)) { Logger.Error($"{nameof(CallFbCommentGetAPI)} FB API response error message: {fb_error} "); }
rawResult = JsonConvert.DeserializeObject<FbCommentData>(responseMessage.Content.ReadAsStringAsync().Result); result.data.AddRange(rawResult.data); uri = rawResult.paging != null && rawResult.paging.ContainsKey("next") ? rawResult.paging["next"].ToString() : null; if (rawResult.data.Count == 0 || uri == null) { isOver = true; } } else { var error = $"{nameof(CallFbCommentGetAPI)} Error, ReasonPhrase:{responseMessage.ReasonPhrase} hrmResult.Headers.WwwAuthenticate:{responseMessage.Headers.WwwAuthenticate} "; Logger.Error(error); isOver = true; } } if (result.data.Count > 0) { string sMsg = GetFCommentsData(articleId, result, postId, out comments); // 儲存出錯
if (sMsg != null) { comments = null; } } else { comments = null; } return true; }
/// <summary>
/// 延長token
/// </summary>
/// <param name="authorizationToken"></param>
/// <param name="message"></param>
/// <param name="path">圖片路徑</param>
public bool CallFbLongTokenGetAPI(string authorizationToken, string client_id, string client_secret) { // 送出資料
string uri = "https://graph.facebook.com/oauth/access_token?"; var dicData = new Dictionary<string, string>() { { "grant_type", "fb_exchange_token" }, { "client_id", client_id }, { "client_secret", client_secret }, { "fb_exchange_token", authorizationToken }, }; APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage); if (responseMessage.IsSuccessStatusCode) { var responseData = JsonConvert.DeserializeObject<FbToken>(responseMessage.Content.ReadAsStringAsync().Result); } return responseMessage.IsSuccessStatusCode; }
/// <summary>
/// 驗證token, 可改用 Function FbApiCheckToken
/// </summary>
/// <param name="authorizationToken"></param>
/// <param name="message"></param>
/// <param name="path">圖片路徑</param>
public string CallFbCheckTokenGetAPI(string authorizationToken, string client_id, string client_secret, out int status) { // 送出資料
status = 0; // 預設0: 正常 1: 即將到期 2: 驗證失敗
string uri = "https://graph.facebook.com/debug_token?"; var dicData = new Dictionary<string, string>() { { "input_token", authorizationToken }, { "access_token", string.Format("{0}|{1}",client_id,client_secret) }, }; APIHelper.BaseGet(uri, null, dicData, out HttpResponseMessage responseMessage); if (responseMessage.IsSuccessStatusCode) { var responseData = JsonConvert.DeserializeObject<FbTokenVerification>(responseMessage.Content.ReadAsStringAsync().Result); if (responseData.data.is_valid) { var timeStamp = responseData.data.expires_at - Convert.ToInt32(DateTime.UtcNow.AddHours(8).Subtract(new DateTime(1970, 1, 1)).TotalSeconds); if (timeStamp > 20 * 86400) // 20天
{ return null; } else { status = 1; return "Token即將到期"; } } else { status = 2; return "Token驗證失敗"; } } else { status = 2; return "Request失敗"; } }
/// <summary>
/// Send FB Message
/// </summary>
/// <param name="messenger_id_"></param>
/// <param name="message_"></param>
/// <param name="access_token_"></param>
/// <param name="errorHandle_"></param>
/// <returns></returns>
public void SendMessage(ref string messenger_id_, ref string message_, ref string access_token_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_) { string url = ApiUrlHelper.SendMessage(access_token_);
var dataContents = new { recipient = new { id = messenger_id_ }, messaging_type = "MESSAGE_TAG", message = new { text = message_}, tag = "POST_PURCHASE_UPDATE" };
SendPostFbApi(url, dataContents, successHandle_, errorHandle_); }
/// <summary>
///
/// </summary>
/// <returns></returns>
public void CheckAccessToken(ref string access_token_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_) { string url = ApiUrlHelper.CheckAccessToken(access_token_);
SendGetFbApi(url, successHandle_, errorHandle_); }
public void GetUserAccessToken(ref string user_access_token_, ref string app_id_, ref string app_secret_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_) { string url = ApiUrlHelper.GetUserAccessToken(user_access_token_, app_id_, app_secret_);
SendGetFbApi(url, successHandle_, errorHandle_); }
public void GetPageAccessToken(ref string user_id_, ref string long_lived_user_access_token, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_) { string url = ApiUrlHelper.GetPageAccessToken(user_id_, long_lived_user_access_token);
SendGetFbApi(url, successHandle_, errorHandle_); }
public void GetGroupPublicDescription(string group_id_, string user_access_token_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_) { string url = ApiUrlHelper.GetGroupPublicDescription(group_id_, user_access_token_);
SendGetFbApi(url, successHandle_, errorHandle_); }
#endregion
#region 專案獨有
///// <summary>
///// 貼文資料新增到SQL
///// </summary>
///// <param name="state"></param>
///// <returns></returns>
private void GetFbPostData(FbGetPost fbGetPost) { ArsenalInterface ai; List<Command> lCmds = new List<Command>();
// 取社團
QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeOrigin = lBlocks.GetInst(); qjeOrigin.table = tb_grp_group.TABLENAME; qjeOrigin.displaycols = new List<string>() { tb_grp_group.CN_UID, tb_grp_group.CN_FB_GROUP_ID }; 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]); lBlocks.Add(qjeOrigin); var sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
ai = ArsenalDBMgr.GetInst(cRes); List<tb_grp_group> group = ai.RunQueryList<tb_grp_group>(cRes);
// 取貼文資料
lBlocks.Clear(); QueryJsonElement qjeArticle = lBlocks.GetInst(); qjeArticle.table = tb_grp_article.TABLENAME; qjeArticle.displaycols = new List<string>() { tb_grp_article.CN_UID, tb_grp_article.CN_GROUP_UID, tb_grp_article.CN_FB_ARTICLE_ID }; qjeArticle.wherecols = new WhereNode(tb_grp_article.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), group.First().uid); lBlocks.Add(qjeArticle); sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cArt); ai = ArsenalDBMgr.GetInst(cArt); List<tb_grp_article> article = ai.RunQueryList<tb_grp_article>(cArt);
// 取媒體資料
lBlocks.Clear(); QueryJsonElement qjeArticleMedia = lBlocks.GetInst(); qjeArticleMedia.table = tb_grp_article_media.TABLENAME; 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 }; lBlocks.Add(qjeArticleMedia); sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cMedia); ai = ArsenalDBMgr.GetInst(cMedia); List<tb_grp_article_media> lsmedia = ai.RunQueryList<tb_grp_article_media>(cMedia);
fbGetPost.data.ForEach(x => { var uid = string.Empty;
// 如果貼文存在則更新 否則新增
if (!article.Any(y => y.fb_article_id == x.id)) { uid = Guid.NewGuid().ToString(); tb_grp_article cNew = new tb_grp_article() { uid = uid, group_uid = group.First().uid, message = x.message, post_status = (int)EPostStatus.EPS_FETCH_FROM_FB, fb_article_id = x.id, release_date = x.created_time }; lCmds.Add(Command.SetupInsertCmd(cNew)); } else { uid = article.First(y => y.fb_article_id == x.id).uid; tb_grp_article cWhere = new tb_grp_article() { uid = uid }; tb_grp_article cUpdate = new tb_grp_article() { group_uid = group.First().uid, message = x.message, post_status = (int)EPostStatus.EPS_FETCH_FROM_FB, fb_article_id = x.id, release_date = x.created_time }; lCmds.Add(Command.SetupUpdateCmd(cUpdate, cWhere)); } if (!lsmedia.Any(y => y.uri == x.full_picture) && x.full_picture != null) { tb_grp_article_media media = new tb_grp_article_media() { article_uid = uid, uri = x.full_picture, type = BLWording.MediaType.Photo, status_flag = (int)MediaType.GetFb }; lCmds.Add(Command.SetupInsertCmd(media)); } if (!lsmedia.Any(y => y.uri == x.full_picture) && x.source != null) { tb_grp_article_media media = new tb_grp_article_media() { article_uid = uid, uri = x.source, type = BLWording.MediaType.Video, status_flag = (int)MediaType.GetFb }; lCmds.Add(Command.SetupInsertCmd(media)); } }); if (lCmds.Any()) { ai = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo()); ai.RunEditCmds(lCmds); sMsg = GetLastErrorCode(lCmds); } }
/// <summary>
/// 貼文留言存進SQL
/// </summary>
/// <param name="fbGetPost"></param>
/// <param name="id"></param>
private string GetFCommentsData(string articleId, FbCommentData fbGetPost, string post_id, out List<tb_grp_comment> comments) { // 沒有留言
if (fbGetPost.data.Count == 0) { comments = null; return null; }
List<Command> lCmds = new List<Command>();
// 用文章 ID取文章 data
var article = GetArticleByPostID(articleId); comments = new List<tb_grp_comment>();
// 取回原先的留言
List<tb_grp_comment> originComments = GetComments(article.uid);
// 如果先前已有匯入留言,已匯入過的留言不再重複匯入
List<string> existFbCommentID = originComments.Select(x => x.fb_comment_id).ToList();
// 取回該社團可以取貨的地點
var branches = GetBranches(article.group_uid).ToDictionary(x => x.uid, x => x.branch_name); var products = GetProducts(article.uid);
// 會員預設取貨地點(中文)的對應表,沒設定取貨地點不會放進列表
var memberDefaultBranchDict = GetMembers(post_id.Split('_')[0]) .Where(x => !string.IsNullOrEmpty(x.default_branch) && branches.ContainsKey(x.default_branch)) .ToDictionary(x => x.group_user_id, x => branches[x.default_branch]); // 將名稱以['A', 'B'...]這樣依序產生,如果產品有3個,就要放入['A', 'B', 'C']
List<GroupBuyParser.ProductInfo> productInfoNames = new List<GroupBuyParser.ProductInfo>(); //productInfoNames = products.Select((x, i) => new GroupBuyParser.ProductInfo
//{
// Name = x.name ?? "",
// Specifications = string.IsNullOrEmpty(x.specification) ? null : x.specification.Split(',', StringSplitOptions.RemoveEmptyEntries)
//}).ToList();
var productInfos = products.Select((x, i) => new GroupBuyParser.ProductInfo { Name = ((char)('A' + x.seq)).ToString(), Specifications = string.IsNullOrEmpty(x.specification) ? null : x.specification.Split(',', StringSplitOptions.RemoveEmptyEntries).OrderByDescending(x => x.Count()).ToArray() }).ToList();
//var productInfos = productInfoNames.Concat(productInfosChar).ToList();
Logger.Info($"開始解析貼文 文章ID: {article.uid} 設定: {JsonConvert.SerializeObject(productInfos)}");
var parser = new GroupBuyParser.GroupBuyParser { Settings = new GroupBuyParser.ParserSettings { Products = productInfos, Branches = branches.Values.ToList() } };
StringBuilder parseCommentErrorLog = new StringBuilder(); foreach (var item in fbGetPost.data) { // 沒有留言就不處理
if (string.IsNullOrEmpty(item.message)) { continue; } // 判斷已經重複的ID
if (existFbCommentID.Contains(item.id)) { continue; } // 判斷是否為回覆留言
string parentUid = null; if (item.parent != null) { parentUid = item.parent.id; }
// 如果取不回fb_id(使用者沒有允許應用程式查看貼文)仍要處理
string group_user_id = item.from?.id;
string json = ""; int status = 0;
// 傳入該會員預設取貨地點(非會員則為null)
string defaultBranch = null;
if (!string.IsNullOrEmpty(group_user_id) && memberDefaultBranchDict.ContainsKey(group_user_id)) { defaultBranch = memberDefaultBranchDict[group_user_id]; }
var parseData = new GroupBuyParser.ParserData { Text = item.message, DefaultBranch = defaultBranch }; parser.Parse(parseData); if (parseData.Success) { bool isProductCorrect = true; foreach (var product in parseData.Product.ToList()) { if (product.Name == "I") { isProductCorrect = false; break; } } if (isProductCorrect) // 名稱有I 不Insert進資料庫
{ json = JsonConvert.SerializeObject(parseData.Product); status = (int)CommentStatus.OK; } else { status = (int)CommentStatus.InvalidFormat; } } else { status = (int)CommentStatus.InvalidFormat; // 增加log紀錄確認解析失敗的原因
parseCommentErrorLog.AppendLine($"解析貼文失敗 姓名: {item.from?.name} 內容: {item.message} 原因: {parseData.ErrorMessage}"); } if (string.IsNullOrEmpty(group_user_id)) { status = (int)CommentStatus.UnknownMember; } else if (!memberDefaultBranchDict.ContainsKey(group_user_id)) { status = (int)CommentStatus.UnknownMember; } else if (comments.Any(x => x.group_user_id == group_user_id)) // 是否有重複留言
{ status = (int)CommentStatus.Duplicate; }
if (parentUid != null) { status = (int)CommentStatus.Duplicate; }
tb_grp_comment cNew = new tb_grp_comment { uid = Guid.NewGuid().ToString(), article_uid = article.uid, origin_comment = item.message, comment = json, group_user_id = group_user_id, comment_time = item.created_time, fb_comment_id = item.id, status = status, user_name = item.from?.name, user_picture = item.from?.picture.data.url, parent_comment_id = parentUid == null ? null : parentUid }; comments.Add(cNew); } if(parseCommentErrorLog.Length != 0) { // 參考原本寫法, 解析貼文失敗訊息標記為Info
parseCommentErrorLog.Insert(0, Environment.NewLine); Logger.Info(parseCommentErrorLog.ToString()); }
// 沒有新增任何留言就不處理
if (comments.Count == 0) { return null; } lCmds.AddRange(comments.Select(x => Command.SetupInsertCmd(x)));
var ai = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo()); ai.RunEditCmds(lCmds); var sMsg = GetLastErrorCode(lCmds);
return sMsg; }
/// <summary>
/// 將留言轉成訂單(結單)
/// </summary>
/// <param name="article_uid"></param>
public string CheckOrder(string article_uid, JArray jData) { // 貼文資料
var article = GetArticle(article_uid); // 商品資料
var productData = GetProducts(article_uid).OrderBy(x => x.seq).ToArray(); // 貼文對應的群組UID
var groupUid = article.group_uid; // 取得社團成員ID對應的UID
var fb_group_id = article.fb_article_id.Split('_')[0]; var memberDict = GetMembers(fb_group_id).ToDictionary(x => x.group_user_id, x => x.uid); // 分店的對應表
var branchDict = GetBranches(groupUid).ToDictionary(x => x.branch_name, x => x.uid); // 取回過去的訂單主檔
var IsOrderMaster = GetOrderMasters(article_uid); // 如果過去已經有結單,使用同一個order_code,反之取回新的訂單編號(這不就是article_uid嗎?)
var orderCode = IsOrderMaster.Any() ? IsOrderMaster.First().order_code : GetOrderCode(); var orderName = IsOrderMaster.Any() ? IsOrderMaster.First().name : article.name; // 有結單過的貼文使用舊名稱
var orderMasterDic = new Dictionary<string, tb_ord_order_master>(); // 再次結單屬於新的order_master
// 先取回所有留言
var comments = GetComments(article_uid); // 留言解析成功的才更新
List<CommentModel> data = new List<CommentModel>(); foreach (JToken token in jData) { Dictionary<string, object> dicData = token.ToObject<Dictionary<string, object>>();
var commentData = comments.Where(x => x.status != (int)CommentStatus.TransferOrder && !string.IsNullOrEmpty(x.comment) && x.status_flag == BLWording.STATUS_FLAG_ON && !string.IsNullOrEmpty(x.group_user_id) && x.uid == dicData["uid"].ToString()).Select(x => new { x.uid, x.group_user_id, x.comment, x.comment_time }); if (commentData.Any()) { CommentModel tempComment = new CommentModel() { uid = commentData.Select(x => x.uid).FirstOrDefault(), comment = commentData.Select(x => x.comment).FirstOrDefault(), group_user_id = commentData.Select(x => x.group_user_id).FirstOrDefault(), comment_time = commentData.Select(x => x.comment_time).FirstOrDefault() }; data.Add(tempComment); } }
if (!data.Any()) { return null; }
List<Command> lCmds = new List<Command>(); List<tb_ord_order_detail> lOrderDetails = new List<tb_ord_order_detail>(); ArsenalInterface ai = null; foreach (var item in data) { // 解析留言訂購格式,以每一項為單位塞到DB去
var products = JsonConvert.DeserializeObject<IEnumerable<GroupBuyParser.ParserProduct>>(item.comment); foreach (var product in products) { // 目前暫定A = 0 B = 1...
var productIndex = product.Name[0] - 'A'; var productItem = productData.FirstOrDefault(x => x.seq == productIndex);
if (product.Branch == "未知" || string.IsNullOrWhiteSpace(product.Branch)) { break; } var branch_uid = branchDict[product.Branch];
// 如果目前沒有主檔,新增主檔
if (!orderMasterDic.ContainsKey(branch_uid)) { // 查詢group_uid
tb_grp_branch cBranch = new tb_grp_branch(); cBranch.SetDirty(tb_grp_branch.CN_GROUP_UID); tb_grp_branch cCon = new tb_grp_branch() { uid = branch_uid }; Command cSelect = Command.SetupSelectCmd(cBranch, cCon); ai = ArsenalDBMgr.GetInst(cSelect); tb_grp_branch qds = ai.RunQuerySingleORM<tb_grp_branch>(cSelect); var newOrderMaster = new tb_ord_order_master { uid = Guid.NewGuid().ToString(), type = 1, name = orderName, order_code = orderCode, article_uid = article_uid, branch_uid = branch_uid, group_uid = qds.group_uid, status = (int)OrderStatus.NotArrived, };
lCmds.Add(Command.SetupInsertCmd(newOrderMaster)); // 增加Dictionary的內容,避免內容被重複新增
orderMasterDic.Add(branch_uid, newOrderMaster); } if (product.Qty > 0) { var order = new tb_ord_order_detail { uid = Guid.NewGuid().ToString(), order_uid = orderMasterDic[branch_uid].uid, article2product_uid = productItem.uid, member_uid = memberDict[item.group_user_id], specification = product.Specification != "" ? product.Specification : null, order_qty = product.Qty, price = productItem.price * product.Qty, comment_time = item.comment_time, comment_uid = item.uid, status = (int)OrderStatus.NotArrived };
lOrderDetails.Add(order);
// 更新留言變成不顯示
tb_grp_comment updateComment = new tb_grp_comment { status = (int)CommentStatus.TransferOrder }; tb_grp_comment updateCommentCond = new tb_grp_comment { uid = item.uid }; lCmds.Add(Command.SetupUpdateCmd(updateComment, updateCommentCond)); } } } if (lOrderDetails.Count == 0) { return "結單錯誤(請確認訂單資訊)"; }
if (article.post_status < 64) { tb_grp_article updateArticle = new tb_grp_article { post_status = (int)EPostStatus.EPS_ORDER }; tb_grp_article updateArticleCond = new tb_grp_article { uid = article_uid }; lCmds.Add(Command.SetupUpdateCmd(updateArticle, updateArticleCond)); }
lCmds.AddRange(lOrderDetails.Select(x => Command.SetupInsertCmd(x)));
ai = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo()); ai.RunEditCmds(lCmds); var sMsg = GetLastErrorCode(lCmds);
return sMsg; }
private List<tb_ord_order_master> GetOrderMasters(string article_uid) { tb_ord_order_master cDisplay = new tb_ord_order_master(); cDisplay.SetFullDirty(); var whereNode = new WhereNode(tb_ord_order_master.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_ord_order_master), article_uid); var cSelect = Command.SetupSelectCmd(cDisplay, whereNode); var ai = ArsenalDBMgr.GetInst(cSelect); var data = ai.RunQueryList<tb_ord_order_master>(cSelect);
return data; }
/// <summary>
/// 用文章FB ID取回貼文部分資訊
/// </summary>
/// <param name="post_id"></param>
/// <returns></returns>
private static tb_grp_article GetArticleByPostID(string articleId) { QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeOrigin = lBlocks.GetInst(); qjeOrigin.table = tb_grp_article.TABLENAME; qjeOrigin.displaycols = new List<string>() { tb_grp_article.CN_UID, tb_grp_article.CN_FB_ARTICLE_ID, tb_grp_article.CN_GROUP_UID }; qjeOrigin.wherecols = new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), articleId); lBlocks.Add(qjeOrigin); string sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes); var ai = ArsenalDBMgr.GetInst(cRes); var articles = ai.RunQueryList<tb_grp_article>(cRes);
return articles.First(); }
/// <summary>
/// 用文章UID取回貼文部分資訊
/// </summary>
/// <param name="article_uid"></param>
/// <returns></returns>
private tb_grp_article GetArticle(string article_uid) { QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeOrigin = lBlocks.GetInst(); qjeOrigin.table = tb_grp_article.TABLENAME; qjeOrigin.displaycols = new List<string> { tb_grp_article.CN_GROUP_UID, tb_grp_article.CN_FB_ARTICLE_ID, tb_grp_article.CN_POST_STATUS, tb_grp_article.CN_NAME }; qjeOrigin.wherecols = new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), article_uid); lBlocks.Add(qjeOrigin); string sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes); var ai = ArsenalDBMgr.GetInst(cRes); var articles = ai.RunQueryList<tb_grp_article>(cRes);
return articles.First(); }
/// <summary>
/// 用文章UID取回原先的留言
/// </summary>
/// <param name="article_uid"></param>
/// <returns></returns>
private List<tb_grp_comment> GetComments(string article_uid) { tb_grp_comment cDisplay = new tb_grp_comment(); cDisplay.SetFullDirty(); var whereNode = new WhereNode(tb_grp_comment.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), article_uid); var cSelect = Command.SetupSelectCmd(cDisplay, whereNode); var ai = ArsenalDBMgr.GetInst(cSelect); var originComments = ai.RunQueryList<tb_grp_comment>(cSelect);
return originComments; }
/// <summary>
/// 用社團UID取回取貨地點
/// </summary>
/// <param name="group_uid"></param>
/// <returns></returns>
private List<tb_grp_branch> GetBranches(string group_uid) { tb_grp_branch cDisplay = new tb_grp_branch(); cDisplay.SetFullDirty(); var whereNode = new WhereNode(tb_grp_branch.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_branch), group_uid); var cSelect = Command.SetupSelectCmd(cDisplay, whereNode); var ai = ArsenalDBMgr.GetInst(cSelect); var data = ai.RunQueryList<tb_grp_branch>(cSelect);
return data; }
/// <summary>
/// 用貼文UID取回該貼文所有商品的部分資訊
/// </summary>
/// <param name="article_uid"></param>
/// <returns></returns>
private List<tb_prd_article2product> GetProducts(string article_uid) { /**開始組指令**/ QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
QueryJsonElement qjeArticleToProduct = lBlocks.GetInst(); qjeArticleToProduct.table = tb_prd_article2product.TABLENAME; qjeArticleToProduct.displaycols = new List<string>() { tb_prd_article2product.CN_UID, tb_prd_article2product.CN_NAME, tb_prd_article2product.CN_PRICE, tb_prd_article2product.CN_SEQ, tb_prd_article2product.CN_SPECIFICATION }; qjeArticleToProduct.wherecols = new WhereNode(tb_prd_article2product.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_prd_article2product), article_uid); lBlocks.Add(qjeArticleToProduct);
QueryJsonElement qjeProduct = lBlocks.GetInst(); qjeProduct.table = tb_prd_product.TABLENAME; qjeProduct.jointable = qjeArticleToProduct; qjeProduct.joincols = new Dictionary<string, string>() { { tb_prd_product.CN_UID, tb_prd_article2product.CN_PRD_UID } }; lBlocks.Add(qjeProduct);
var sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes); var ai = ArsenalDBMgr.GetInst(cRes); List<tb_prd_article2product> data = ai.RunQueryList<tb_prd_article2product>(cRes);
return data.ToList(); }
/// <summary>
/// 用FB社團ID取回所有使用者資訊
/// </summary>
/// <param name="group_id"></param>
/// <returns></returns>
private List<tb_meb_member> GetMembers(string group_id) { tb_meb_member tDisplay = new tb_meb_member(); tDisplay.SetFullDirty(); List<WhereNode> lwWhereData = new List<WhereNode>(); lwWhereData.Add(new WhereNode(tb_meb_member.CN_GROUP_ID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_meb_member), group_id)); lwWhereData.Add(new WhereNode(tb_meb_member.CN_NAME, WhereNode.EColumnOperation.EOT_NEQ, typeof(tb_meb_member), "現貨銷售")); Command cSelect = Command.SetupSelectCmd(tDisplay, new WhereNode(WhereNode.ENodeOperation.ENO_AND, lwWhereData.ToArray())); ArsenalInterface ai = ArsenalDBMgr.GetInst(cSelect); List<tb_meb_member> members = ai.RunQueryList<tb_meb_member>(cSelect); return members; }
/// <summary>
/// 取得目前的訂單號碼
/// </summary>
/// <param name="post_id"></param>
/// <returns></returns>
public string GetOrderCode() { string dateString = DateTime.Now.ToString("yyMMdd");
QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeOrigin = lBlocks.GetInst(); qjeOrigin.table = tb_ord_order_master.TABLENAME; qjeOrigin.displaycols = new List<string>() { tb_ord_order_master.CN_ORDER_CODE }; qjeOrigin.wherecols = new WhereNode(tb_ord_order_master.CN_ORDER_CODE, WhereNode.EColumnOperation.EOT_LIKE, typeof(tb_ord_order_master), dateString + "%"); lBlocks.Add(qjeOrigin); string sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes); var ai = ArsenalDBMgr.GetInst(cRes); var orders = ai.RunQueryList<tb_ord_order_master>(cRes);
// 兩碼流水號,例如20082801 = 2020/8/28 第一批訂單
var lastOrderNo = orders.Select(x => x.order_code).OrderByDescending(x => x).FirstOrDefault(); int newIndex = 1; if (!string.IsNullOrEmpty(lastOrderNo)) { newIndex = int.Parse(lastOrderNo.Substring(6, 2)) + 1; }
return dateString + newIndex.ToString("00"); } #endregion
private void SendGetFbApi(string url, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_) { APIHelper.BaseGet(url, null, new Dictionary<string, string>(), out HttpResponseMessage responseMessage);
FbApiResponseHandler(responseMessage, successHandle_, errorHandle_); }
private void SendPostFbApi(string url, dynamic postContent, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_) { APIHelper.BasePost(url, null, postContent, out HttpResponseMessage responseMessage, "json");
FbApiResponseHandler(responseMessage, successHandle_, errorHandle_); }
/// <summary>
/// If FB API response SUCCESS return true, else you can defined your error handle function like write log
/// </summary>
/// <param name="httpResponseMessage_"></param>
/// <param name="errorHandle_"></param>
/// <returns></returns>
private void FbApiResponseHandler(HttpResponseMessage httpResponseMessage_, Action<HttpResponseMessage> successHandle_, Action<HttpResponseMessage, string> errorHandle_) { // check response header
if (!httpResponseMessage_.IsSuccessStatusCode) { var headerError = $"{httpResponseMessage_.ReasonPhrase}, {httpResponseMessage_.Headers.WwwAuthenticate}"; errorHandle_(httpResponseMessage_, headerError); return; }
// check response content
var bodyError = GetFbApiError(httpResponseMessage_); if (!string.IsNullOrWhiteSpace(bodyError)) { errorHandle_(httpResponseMessage_, bodyError); return; }
successHandle_(httpResponseMessage_); }
/// <summary>
/// 檢查Response code 200後, FB回傳的內容是否包含錯誤訊息
/// </summary>
/// <param name="httpMessage_"></param>
/// <returns></returns>
public static string GetFbApiError(HttpResponseMessage httpMessage_) { var sContent = httpMessage_.Content.ReadAsStringAsync().Result; var jsonObject = JObject.Parse(sContent);
if (jsonObject["error"] != null) { return jsonObject["error"].ToString(); }
return ""; } } }
|