using AppletMvcService.Common; using AppletMvcService.Models; using Newtonsoft.Json; using Ninject; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.IO; using System.Net; using System.Text; using WX.CRM.Common; using WX.CRM.IBLL.weapp; using WX.CRM.Model.weapp; using WX.CRM.WebHelper.Infrastructure; namespace AppletMvcService.Hanlder { public class MessageHandler { public static IAppletMsg appletmsg = NinjectControllerFactory.ninjectKernel.Get(); public static IWX_UserInfo userinfo = NinjectControllerFactory.ninjectKernel.Get(); private static Dictionary wxaccount = null; public static Dictionary GetWxAccount() { if (wxaccount != null && wxaccount.Count > 0) return wxaccount; wxaccount = new Dictionary(); DataTable tab = userinfo.GetWxAccount(); if (tab != null && tab.Rows.Count > 0) { LogHelper.Error("wxaccount为空,需要进行初始化!"); foreach (DataRow item in tab.Rows) { WxAccount account = new WxAccount(); account.accountName = item["ACCOUNTNAME"].ToString(); account.pkid = Convert.ToDecimal(item["PKID"]); account.accountNum = item["ACCOUNTNUM"].ToString(); account.appId = item["APPID"].ToString(); account.appSecret = item["APPSECRET"].ToString(); account.fenPeiPoc = item["FENPEIPOC"].ToString(); if (!wxaccount.ContainsKey(account.accountNum)) wxaccount.Add(account.accountNum, account); account.tokenhttp = item["TOKENHTTP"].ToString(); account.isonline = Convert.ToInt32(item["ISONLINE"]); } } return wxaccount; } #region 在线客服维护 public static Dictionary> GetConnectedByRedis() { Dictionary> nn = new Dictionary>(); try { LogHelper.Error("客服数据获取"); //Dictionary naccount = GetWxAccount(); DataTable tab = userinfo.GetOnlineUser(); if (tab != null && tab.Rows.Count > 0) { foreach (DataRow item in tab.Rows) { UserDetail detial = new UserDetail(); detial.ConnectionId = item["connectionid"].ToString(); detial.DeptName = item["deptname"].ToString(); detial.LoginTime = Convert.ToDateTime(item["logintime"]); detial.UserID = item["userid"].ToString(); detial.UserName = item["username"].ToString(); string accountnum = item["accountnum"].ToString(); if (!nn.ContainsKey(accountnum)) nn.Add(accountnum, new List()); nn[accountnum].Add(detial); } } } catch (Exception x) { LogHelper.Error(x.ToString()); } return nn; } public static void AddConnectedToRedis(UserDetail connected, string accountnum) { try { userinfo.Logon(connected.ConnectionId, connected.UserID, connected.UserName, connected.DeptName, connected.LoginTime, accountnum); } catch (Exception ex) { LogHelper.Error(ex.ToString()); } } public static void RemoveConnectedToRedis(UserDetail connected, string accountnum) { try { userinfo.UnLogon(connected.UserID, accountnum); } catch (Exception ex) { LogHelper.Error(ex.ToString()); } } #endregion public static void UpdateSendTime(string v_openid, DateTime v_ctime, string v_AccountNum, decimal eid) { userinfo.UpdateSendTime(v_openid, v_ctime, v_AccountNum, eid); } public static CustoemrDetail GetCustomerHeadInfo(CustoemrDetail info) { DataTable table = userinfo.GetUserHeadInfo(info.OpenId); if (table != null && table.Rows.Count > 0) { info.NickName = table.Rows[0]["nickname"].ToString(); info.HeaderUrl = table.Rows[0]["avatarurl"].ToString(); } return info; } public static void weapp_update_subscribe(string v_openid, string v_subType, DateTime v_time, string v_AccountNum) { userinfo.weapp_update_subscribe(v_openid, v_subType, v_time, v_AccountNum); } /// /// 获取分配信息 /// /// /// 在线人员 /// 公众号 /// public static string GetFenPeiEID(int type, string openId, string onlineUser, string accountnum, string fenpei, ref int isNew) { //LogHelper.Error("1"); if (string.IsNullOrEmpty(fenpei)) return "1"; //LogHelper.Error("2"); DataTable table = userinfo.GetFenPeiCustomerService(type, openId, onlineUser, accountnum, fenpei); //LogHelper.Error("3"); string eid = "1"; isNew = 0; if (table != null && table.Rows.Count > 0) { eid = table.Rows[0]["eid"].ToString(); isNew = Convert.ToInt32(table.Rows[0]["isNew"]); } //LogHelper.Error("4"); //LogHelper.Error("eid:" + eid + ",isNew:" + isNew + ",ChatHub.ConnectedUsers:" + (ChatHub.ConnectedUsers == null)); //if (ChatHub.ConnectedUsers == null) //{ // LogHelper.Error("ChatHub.ConnectedUsers被销毁" + eid); // return "1"; //} //LogHelper.Error("ChatHub.ConnectedUsers.Count:" + ChatHub.ConnectedUsers.Count); //if (ChatHub.ConnectedUsers[accountnum].Count == 0)//没有售后客服在线 //{ // eid = "1";//系统工号 //} //else if (!string.IsNullOrEmpty(eid) && ChatHub.ConnectedUsers[accountnum].Count > 0)//检测目标售后是否在线 //{ // LogHelper.Error("count:" + ChatHub.ConnectedUsers[accountnum].Count); // UserDetail detail = ChatHub.ConnectedUsers[accountnum].FirstOrDefault(m => m.UserID == eid); // if (detail == null) // { // Random rd = new Random(); // eid = ChatHub.ConnectedUsers[accountnum][rd.Next(ChatHub.ConnectedUsers.Count)].UserID; // } //} return eid; } /// /// 获取好友列表 /// /// /// /// public static List GetFriends(decimal eid, string accountnum) { List friends = new List(); DataTable table = userinfo.GetFriends(eid, accountnum); if (table == null || table.Rows.Count == 0) return friends; CustoemrDetail fd = null; foreach (DataRow item in table.Rows) { fd = new CustoemrDetail(); fd.ConnectionId = item["openid"].ToString(); fd.HeaderUrl = item["avatarurl"].ToString(); fd.LoginTime = DateTime.Now; fd.NickName = item["nickname"].ToString(); fd.OpenId = item["openid"].ToString(); fd.Remarks = item["remarks"].ToString(); if (item["subscribe"] == DBNull.Value) fd.subscribe = 0; else fd.subscribe = Convert.ToInt32(item["subscribe"]); if (item["ChatTime"] == DBNull.Value) fd.ChatTime = new DateTime(2017, 1, 1); else fd.ChatTime = Convert.ToDateTime(item["ChatTime"]); fd.Hours = Convert.ToInt32(item["hours"]); if (string.IsNullOrEmpty(fd.HeaderUrl)) fd.HeaderUrl = "/Content/Images/defaulthead.jpg"; fd.resid = string.Format("{0}", item["resid"]); friends.Add(fd); } return friends; } public static void SendNoLineMsg(string toUserId, string accountnum) { string message = "无客服在线!请在上班9:00~11:30 13:00~18:00进行咨询"; SendMsg(toUserId, message, 1, accountnum); } private static string GetToken(string accountnum, bool GetNew = false) { string url = GetWxAccount()[accountnum].tokenhttp + accountnum + (GetNew == true ? "&isForce=true" : ""); string result = RequestHelper.CreateGetString(url, null, "", null); AccessToken imgmsg = JsonConvert.DeserializeObject(result); return imgmsg.access_token; } /// /// 发送消息 /// /// /// public static void SendMsg(string toUserId, string message, int eid, string accountnum) { string token = GetToken(accountnum); SendMsg msg = new SendMsg(); string resultJson = string.Empty; for (int i = 0; i < 2; i++) { string url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token; //LogHelper.Info(string.Format("userid:{0},token:{1}", toUserId, token)); msg.touser = toUserId.Replace("userid-", ""); msg.text = new MsgContent() { content = message }; msg.msgtype = "text"; resultJson = RequestHelper.CreatePostGetString(url, JsonConvert.SerializeObject(msg), null, "", Encoding.UTF8, null); //LogHelper.Info("返回值:" + resultJson); if (resultJson.IndexOf("\"errcode\":40001") > -1) token = GetToken(accountnum, true); else break; } ResultModel rest = JsonConvert.DeserializeObject(resultJson); if (rest.errmsg != "ok")//发送失败 { LogHelper.Error("发送文本错误:" + resultJson); } else { AppletMsgModel appletMsg = new AppletMsgModel(); appletMsg.Content = message; DateTime time1 = System.DateTime.Now; appletMsg.CreateTime = DateTimeTool.ConvertDateTimeInt(time1); appletMsg.MsgId = 0; appletMsg.MsgType = "text"; appletMsg.ToUserName = msg.touser; appletMsg.FromUserName = accountnum; appletmsg.WeapAddMessage(appletMsg, eid, 1, 1); UpdateSendTime(msg.touser, time1, accountnum, eid); } } public static string GetSuCaiUrl(string mediaId, string accountnum, ref string erroMsg) { string token = GetToken(accountnum); string resultJson = string.Empty; HttpWebResponse response = null; Stream stream = null; StreamReader sr = null; string filePath = string.Empty; byte[] mbyte = null; int startmbyte = 0; try { for (int i = 0; i < 2; i++) { string url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=" + token + "&media_id=" + mediaId; WebClient client = new WebClient(); stream = client.OpenRead(url); sr = new StreamReader(stream); mbyte = new byte[1000000]; int allmybyte = (int)mbyte.Length; while (allmybyte > 0) { int m = stream.Read(mbyte, startmbyte, allmybyte); if (m == 0) break; startmbyte += m; allmybyte -= m; } resultJson = sr.ReadToEnd(); if (resultJson.IndexOf("\"errcode\":40001") > -1) token = GetToken(accountnum, true); else break; } if (resultJson.IndexOf("errcode") > -1)//发送失败 { LogHelper.Error("素材获取失败:" + resultJson); return ""; } else { #region 下载文件 // 把 byte[] 写入文件 var yearMonth = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString(); string fileNameWithoutExt = yearMonth + "/" + mediaId; string vpath = ConfigurationManager.AppSettings["weappfile"] + fileNameWithoutExt + ".amr"; FileStream fstr = new FileStream(vpath, FileMode.OpenOrCreate, FileAccess.Write); fstr.Write(mbyte, 0, startmbyte); fstr.Flush(); fstr.Close(); #endregion #region 文件转换成MP3 var webPath = FileUnit.GetBaseDirectory(); var exePath = webPath + "silk2mp3"; //var fileNameWithoutExt = Path.GetFileNameWithoutExtension(vpath); var basePath = Utility.GetSettingByKey("weappfile"); var path = basePath + "audio/" + yearMonth; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } if (!System.IO.File.Exists(vpath)) { erroMsg = "未能找到文件!"; } var targetFileNameMp3 = Path.Combine(path, mediaId + ".mp3"); if (!System.IO.File.Exists(targetFileNameMp3)) { SilkConvertToMp3 amr = new SilkConvertToMp3(); amr.ConvertToMp3(exePath, vpath, targetFileNameMp3); } #endregion filePath = "/audio/" + yearMonth + "/" + mediaId + ".mp3"; } } catch (Exception ex) { LogHelper.Error(ex.ToString()); } finally { if (sr != null) { sr.Close(); } if (stream != null) { stream.Close(); } if (response != null) { response.Close(); } } return filePath; } /// /// 新增一个图片文件 /// public static ImageMsg SendImg(string type, string accountnum, string filename, string nfile) { string token = GetToken(accountnum); string resultJson = string.Empty; for (int i = 0; i < 2; i++) { string url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=" + token + "&type=" + type; resultJson = HttpUploadFile(url, filename); if (resultJson.IndexOf("\"errcode\":40001") > -1) token = GetToken(accountnum, true); else break; } if (resultJson.IndexOf("errcode") > -1)//发送失败 { LogHelper.Error("新增素材失败:" + resultJson); return null; } else { ImageMsg imgmsg = JsonConvert.DeserializeObject(resultJson); MessageHandler.appletmsg.WeapAddFilePath(0, imgmsg.media_id, nfile); return imgmsg; } } /// /// 发送图片素材 /// /// /// /// public static void SendImgMsg(ImageMsg imgmsg, string sucaitype, string toUser, string accountnum, int eid, string name, ref string content) { if (imgmsg == null) return; string token = GetToken(accountnum); string resultJson = string.Empty; content = string.Empty; for (int i = 0; i < 2; i++) { string url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token; var ojb = new object(); if (sucaitype == "image") { ojb = new { touser = toUser, msgtype = sucaitype, image = new { media_id = imgmsg.media_id } }; content = "图片素材【" + (string.IsNullOrEmpty(name) ? "本地图片" : name) + "】"; } else if (sucaitype == "voice") { ojb = new { touser = toUser, msgtype = sucaitype, voice = new { media_id = imgmsg.media_id } }; content = "语音素材【" + name + "】"; } else if (sucaitype == "video") { ojb = new { touser = toUser, msgtype = sucaitype, video = new { media_id = imgmsg.media_id } }; content = "视频素材【" + name + "】"; } else if (sucaitype == "mpnews") { ojb = new { touser = toUser, msgtype = "mpnews", mpnews = new { media_id = imgmsg.media_id } }; content = "图文素材【" + name + "】"; } resultJson = RequestHelper.CreatePostGetString(url, JsonConvert.SerializeObject(ojb), null, "", Encoding.UTF8, null); if (resultJson.IndexOf("\"errcode\":40001") > -1) token = GetToken(accountnum, true); else break; } ResultModel rest = JsonConvert.DeserializeObject(resultJson); if (rest.errmsg != "ok")//发送失败 { LogHelper.Error("发送" + content + "素材错误:" + resultJson); } else { AppletMsgModel appletMsg = new AppletMsgModel(); appletMsg.CreateTime = DateTimeTool.ConvertDateTimeInt(System.DateTime.Now); appletMsg.MsgId = 0; appletMsg.MsgType = sucaitype; appletMsg.ToUserName = toUser; appletMsg.FromUserName = accountnum; appletMsg.MediaId = imgmsg.media_id; appletMsg.Content = content; appletmsg.WeapAddMessage(appletMsg, eid, 1, 1); } } public static DataTable IsNeedDownLoadSuCai(string media_id) { return appletmsg.IsHasMediaId(media_id); } /// /// 下载文件素材 /// /// /// public static string DownLoadSuCaiPath(string media_id, string URLAddress) { string filepath = string.Empty; try { string fix = ".jpg"; LogHelper.Error("fix:" + fix); WebClient client = new WebClient(); Stream str = client.OpenRead(URLAddress); StreamReader reader = new StreamReader(str); byte[] mbyte = new byte[1000000]; int allmybyte = (int)mbyte.Length; int startmbyte = 0; while (allmybyte > 0) { int m = str.Read(mbyte, startmbyte, allmybyte); if (m == 0) break; startmbyte += m; allmybyte -= m; } reader.Dispose(); str.Dispose(); var yearMonth = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString(); string uploadFolder = (ConfigurationManager.AppSettings["weappfile"] ?? "weappfile") + "/" + yearMonth; if (!Directory.Exists(uploadFolder)) { Directory.CreateDirectory(uploadFolder); } string imgname = "G" + DateTime.Now.ToString("yyyyMMddHHmmssffff") + fix; string path = Path.Combine(uploadFolder, imgname); filepath = "/" + yearMonth + "/" + imgname; FileStream fstr = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write); fstr.Write(mbyte, 0, startmbyte); fstr.Flush(); fstr.Close(); } catch (Exception ex) { LogHelper.Error("download erro:" + ex.ToString()); filepath = ""; } return filepath; } public static string HttpUploadFile(string url, string path)//这个方法是两个URL第一个url是条到微信的,第二个是本地图片路径 { // 设置参数 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; CookieContainer cookieContainer = new CookieContainer(); request.CookieContainer = cookieContainer; request.AllowAutoRedirect = true; request.Method = "POST"; string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线 request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary; byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n"); byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); int pos = path.LastIndexOf("\\"); string fileName = path.Substring(pos + 1); //请求头部信息 StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\nContent-Type:application/octet-stream\r\n\r\n", fileName)); byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString()); FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); byte[] bArr = new byte[fs.Length]; fs.Read(bArr, 0, bArr.Length); fs.Close(); Stream postStream = request.GetRequestStream(); postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length); postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length); postStream.Write(bArr, 0, bArr.Length); postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); postStream.Close(); //发送请求并获取相应回应数据 HttpWebResponse response = request.GetResponse() as HttpWebResponse; //直到request.GetResponse()程序才开始向目标网页发送Post请求 Stream instream = response.GetResponseStream(); StreamReader sr = new StreamReader(instream, Encoding.UTF8); //返回结果网页(html)代码 string content = sr.ReadToEnd(); return content; } #region 获取素材 public static object GetSucaiModel(string type, int count, int offset, string accountnum) { string token = GetToken(accountnum); string resultJson = string.Empty; for (int i = 0; i < 2; i++) { string url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=" + token; SuCaiSendModel model = new SuCaiSendModel(); model.count = count; model.offset = offset; model.type = type; resultJson = RequestHelper.CreatePostGetString(url, JsonConvert.SerializeObject(model), null, "", Encoding.UTF8, null); if (resultJson.IndexOf("\"errcode\":40001") > -1) token = GetToken(accountnum, true); else break; } if (resultJson.IndexOf("errcode") > -1) { //ResultModel result = JsonConvert.DeserializeObject(resultJson); return new { result = false, msg = resultJson }; } if (type == "news") { //LogHelper.Info(resultJson); //NewsModel newsmodel = JsonConvert.DeserializeObject(resultJson); //newsmodel.result = true; //return newsmodel; NewsModel2 newmodel = new NewsModel2(); newmodel.result = true; newmodel.dataResult = resultJson; return newmodel; } else { SuCaiModel newsmodel = JsonConvert.DeserializeObject(resultJson); newsmodel.result = true; return newsmodel; } } #endregion } public class SilkConvertToMp3 { public void ConvertToPcm(string applicationPath, string fileName, string targetFileName) { string para = applicationPath + @"\silk_v3_decoder.exe " + fileName + " " + targetFileName + "&exit"; Cmd(para); } public void ConvertToMp3(string applicationPath, string fileName, string targetFilName) { string c = applicationPath + @"\ffmpeg.exe -i " + fileName + " " + targetFilName + "&exit"; ; Cmd(c); } private void Cmd(string c) { try { System.Diagnostics.Process process = new System.Diagnostics.Process(); process.StartInfo.FileName = "cmd.exe"; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardInput = true; process.Start(); process.StandardInput.WriteLine(c); process.StandardInput.AutoFlush = true; //process.StandardInput.WriteLine("exit"); var reader = process.StandardOutput.ReadToEnd(); //截取输出流 process.WaitForExit(); process.Close(); } catch (Exception ex) { LogHelper.Error("转换录音文件失败:" + ex.ToString()); } } } }