//public List<SendMsgResponse> SendMsgs(IEnumerable<Msg> msgs, string pass_ticket, BaseRequest baseReq) //{ // var results = new List<SendMsgResponse>(); // Func<Msg, string, BaseRequest, SendMsgResponse> sendmsg = SendMsg; // foreach(var msg in msgs) // { // var task = new Task<SendMsgResponse>(sendmsg(msg, pass_ticket, baseReq)); // } // Task.WaitAll(); // return results; //} ////private Func<SendMsgResponse> SendMsgAsyn(Msg msg,string pass_ticket,BaseRequest baseReq) //{ // return SendMsg; //} public void SendMsg(Msg msg, string pass_ticket, BaseRequest baseReq, Action <SendMsgResponse> CallBack) { string url = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?sid={0}&r={1}&lang=zh_CN&pass_ticket={2}"; url = string.Format(url, baseReq.Sid, GetR(), pass_ticket); SendMsgRequest req = new SendMsgRequest { BaseRequest = baseReq, Msg = msg, rr = DateTime.Now.Millisecond }; string requestJson = JsonConvert.SerializeObject(req); http.Item.Request.HeadersDic["Accept"] = "application/json, text/plain, */*"; http.Item.Request.HeadersDic["Origin"] = "https://wx2.qq.com"; http.GetHtml(url, "post", requestJson, referer: "https://wx2.qq.com/", callBack: (x) => { var repJsonStr = x.response.DataString(); if (repJsonStr == null) { CallBack?.Invoke(null); } var rep = JsonConvert.DeserializeObject <SendMsgResponse>(repJsonStr); CallBack?.Invoke(rep); }); }
/// <summary> /// 同步发送文字消息 /// </summary> /// <param name="msg">文字</param> /// <param name="toUserName">发送人UserName</param> /// <returns></returns> public SendMsgResponse SendMsg(string msg, string toUserName) { try { string time = Utils.GetJavaTimeStamp().ToString(); string sendMsgUrl = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket={0}", passTicket); SendMsgRequest sendMsgRequest = new SendMsgRequest() { BaseRequest = baseRequest, Msg = new Msg() { FromUserName = user.UserName, ToUserName = toUserName, ClientMsgId = time, LocalID = time, Type = MSGTYPE.MSGTYPE_TEXT, Content = msg }, Scene = 0 }; SendMsgResponse sendMsgResponse = httpClient.PostJson <SendMsgResponse>(sendMsgUrl, sendMsgRequest); return(sendMsgResponse); } catch (Exception ex) { Console.WriteLine($"Send Msg {ex.Message}"); throw ex; } }
public async Task <ResponseMessage> SendMsgAsync([FromBody] SendMsgRequest request) { // 日志输出:请求体 Console.WriteLine("WS------ Request: \r\n" + JsonUtil.ToJson(request)); // 创建响应体 ResponseMessage response = new ResponseMessage(); // 参数检查:空检查与有效性检查 try { /// 业务处理 await _SendManager.SendMessageAsync(response, request, default(CancellationToken)); } catch (Exception e) { response.Code = ResponseDefine.ServiceError; response.Message += "\r\n" + e.Message; // 日志输出:服务器错误 Console.WriteLine("WS------ ServiceError: \r\n" + e); } // 日志输出:响应体 Console.WriteLine("WS------ Response: \r\n" + response != null ? JsonUtil.ToJson(response) : ""); return(response); }
/// <summary> /// 将队列中的推送消息,丢到程序池中处理 /// </summary> public void HandleMsgToTreadPool() { while (true) { //检查信号量是否改变 CheckSemaphoreCountChange(); SendMsgRequest sendMsgRequest = queueLogic.Dequeue(); if (sendMsgRequest != null) { try { _semaphore.WaitOne(); //HandleMsgToDB(sendMsgRequest); ThreadPool.QueueUserWorkItem(new WaitCallback(HandleMsgToDB), sendMsgRequest); //LogHelper.Info.Write("HandleMsgToTreadPool", "已加入线程池1条数据"); } catch (Exception ex) { //LogHelper.Info.Write("HandleMsgToTreadPool", ex); continue; } } else { //LogHelper.Info.Write("HandleMsgToTreadPool", "接收信息的队列中没有数据处理,等待1000ms"); Thread.Sleep(1000); } } }
/// <summary> /// 接收外部推送消息,如果时效时间为空。默认24小时 /// </summary> /// <param name="model"></param> /// <param name="retMsg"></param> /// <returns></returns> public ErrCode AcceptMsgList(SendMsgListRequest model, out string retMsg) { retMsg = string.Empty; ErrCode errorCode = CheckAcceptMsg(model, out retMsg); if (errorCode != ErrCode.Sucess) { return(errorCode); } int length = model.TokenList.Count; //判断接收人的个数是否超出上限 var tokenMaxNum = Convert.ToInt32(_configLogic.GetConfigValue(ConfigKey.TokenMaxNum)); if (length > tokenMaxNum) { retMsg = string.Format("Token的个数太多,网关限制上限:{0}", tokenMaxNum); return(ErrCode.Failure); } List <SendMsgRequest> sendMsgRequestList = new List <SendMsgRequest>(); foreach (var item in model.TokenList) { SendMsgRequest sendMsgRequest = _mapper.Map <SendMsgRequest>(model); sendMsgRequest.Token = item; sendMsgRequestList.Add(sendMsgRequest); } AcceptMsgListToTheardPool(sendMsgRequestList, out retMsg); return(ErrCode.Sucess); }
/// <summary> /// 处理数据传给DB /// 将消息一拆为n个消息 /// </summary> /// <param name="model"></param> private void HandleMsgToDB(object model) { //var _logger = _loggerFactory.CreateLogger<MsgService>(); using (var scope = SherlockEngine.Current.CreateScope()) { try { string serialNO = Guid.NewGuid().ToString();//同一条消息进行拆解 SendMsgRequest sendMsgRequest = (SendMsgRequest)model; //将推送消息推送消息中心 PushMessageToMessageCenter(sendMsgRequest); //拆分数据 //获取设备和通道 IPushTokenBrandService pushTokenBrandService = scope.ServiceProvider.GetService(typeof(IPushTokenBrandService)) as IPushTokenBrandService; List <DeviceChannelDomainModel> deviceChannelDomainModelList = pushTokenBrandService.GetDeviceChannelListAsync(sendMsgRequest.Token, sendMsgRequest.AppId).Result; List <DeviceChannelDto> deviceChannelList = _mapper.Map <List <DeviceChannelDto> >(deviceChannelDomainModelList); //未获取到,接收的消息直接进历史表,标记为账号登出 if (deviceChannelList == null || deviceChannelList.Count == 0) { //直接入历史表,标记错误 SendProcessDto sendProcessDto = SendMsgToSendProcess(sendMsgRequest, serialNO); sendProcessDto.Token = sendMsgRequest.Token; ISendProcessLogic sendProcessLogic = scope.ServiceProvider.GetService(typeof(ISendProcessLogic)) as ISendProcessLogic; sendProcessLogic.RecordErrorProcess(sendProcessDto, ErrorTypeEnum.Logout, string.Empty); return; } //获取到,根据设备Token拆分数据 List <SendProcessDto> sendProcessDtoList = new List <SendProcessDto>(); foreach (var item in deviceChannelList) { SendProcessDto sendProcessDto = SendMsgToSendProcess(sendMsgRequest, serialNO); sendProcessDto.Token = sendMsgRequest.Token; //将获取到的TokenBrandId(核心),BrandId,ChannelId,DeviceToken 赋给对象,可做到新老接口兼容 //老接口发送数据时,可根据TokenBrandId直接找到需要发送的ChannelId和DeviceToken //新接口发送数据时,通过ChannelId,DeviceToken 发送数据 sendProcessDto.TokenBrandId = item.Id; sendProcessDto.BrandId = item.BrandId; sendProcessDto.ChannelId = item.ChannelId; sendProcessDto.DeviceToken = item.DeviceToken; sendProcessDtoList.Add(sendProcessDto); } IMapper mapper = scope.ServiceProvider.GetService(typeof(IMapper)) as IMapper; List <PushSendProcessDomainModel> domainList = mapper.Map <List <PushSendProcessDomainModel> >(sendProcessDtoList); IPushSendProcessService pushSendProcessService = scope.ServiceProvider.GetService(typeof(IPushSendProcessService)) as IPushSendProcessService; int rows = pushSendProcessService.InsertProcessListAsync(domainList).Result; } catch (Exception ex) { //_logger.LogError(ex.Message.ToString()); //LogHelper.Error.Write("HandleMsgToDB", ex); } finally { _semaphore.Release(); //LogHelper.Info.Write("HandleMsgToDB", "信号量释放之前使用的数量:" + count); } } }
public void MsgToTheardPoolByTokenList(List <string> tokenList, SendMsgListRequest model, out string retMsg) { List <SendMsgRequest> sendMsgRequestList = new List <SendMsgRequest>(); foreach (var item in tokenList) { SendMsgRequest sendMsgRequest = _mapper.Map <SendMsgRequest>(model); sendMsgRequest.Token = item; sendMsgRequestList.Add(sendMsgRequest); } AcceptMsgListToTheardPool(sendMsgRequestList, out retMsg); }
/// <summary> /// 接收外部推送消息,直接通知产线已经接受成功 /// 处理数据丢到线程池中进行 /// </summary> /// <param name="model"></param> /// <param name="retMsg"></param> /// <param name="sprint">3</param> /// <returns></returns> public ErrCode AcceptMsgToTheardPool(SendMsgRequest model, out string retMsg) { retMsg = string.Empty; ErrCode errorCode = CheckAcceptMsg(model, out retMsg); if (errorCode != ErrCode.Sucess) { return(errorCode); } //丢到队列中,使用新的线程,将数据丢到线程池中 //_msgQueue.Enqueue(model);//使用队列存储数据,使用信号量控制线程中量。开启一个新的后台线程,将数据丢到线程池中 queueLogic.Enqueue(model); return(ErrCode.Sucess); }
public object AcceptSingleMsg(SendMsgRequest req) { string retMsg; var ret = _msgServiceLazy.Value.AcceptMsgToTheardPool(req, out retMsg); var logger = _loggerFactoryLazy.Value.CreateLogger(nameof(AcceptMsgController)); if (ret == ErrCode.Sucess) { logger.LogDebug("接受消息成功:" + Newtonsoft.Json.JsonConvert.SerializeObject(req)); return(this.Success(true)); } logger.LogDebug("接受消息失败:" + retMsg); return(this.Error(ret, retMsg)); }
public SendMsgResponse SendMsg(Msg msg, string pass_ticket, BaseRequest baseReq) { string url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?sid={0}&r={1}&lang=zh_CN&pass_ticket={2}"; url = string.Format(url, baseReq.Sid, getTimestamp(DateTime.Now), pass_ticket); SendMsgRequest req = new SendMsgRequest(); req.BaseRequest = baseReq; req.Msg = msg; req.rr = DateTime.Now.Millisecond; string requestJson = JsonConvert.SerializeObject(req); string repJsonStr = http.POST_UTF8String(url, requestJson); var rep = JsonConvert.DeserializeObject <SendMsgResponse>(repJsonStr); return(rep); }
public SendMsgResponse SendMsg(Msg msg, string pass_ticket, BaseRequest baseReq) { string url = this.root_uri + "/cgi-bin/mmwebwx-bin/webwxsendmsg?sid={0}&r={1}&lang=zh_CN&pass_ticket={2}"; url = string.Format(url, baseReq.Sid, getR(), pass_ticket); SendMsgRequest req = new SendMsgRequest(); req.BaseRequest = baseReq; req.Msg = msg; req.rr = DateTime.Now.Millisecond; string requestJson = JsonConvert.SerializeObject(req); string repJsonStr = PostString(url, requestJson); if (repJsonStr == null) { return(null); } var rep = JsonConvert.DeserializeObject <SendMsgResponse>(repJsonStr); return(rep); }
/// <summary> /// 单发单聊消息:sendmsg /// </summary> /// <param name="request"></param> /// <returns></returns> public async Task <SendMsgResult> SendMsgAsync(SendMsgRequest request) { return(await RequestAsync <SendMsgRequest, SendMsgResult>(ServiceName, "sendmsg", request)); }
/// <summary> /// 发送消息,验证发送体,不验证登陆用户(Controller验证) /// </summary> /// <param name="response"></param> /// <param name="request"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task SendMessageAsync([Required] ResponseMessage response, [Required] SendMsgRequest request, CancellationToken cancellationToken) { // 参数验证:发送体不为null,发送人id和接收人id存在,消息内容不能为 string.IsNullOrWhiteSpace,消息不能重复发送(客户端监控) // 判断请求体是否存在错误 if (request.Send == null) { response.Wrap(ResponseDefine.BadRequset, "发送体不能为空"); return; } if (request.Send.Msg == null) { response.Wrap(ResponseDefine.BadRequset, "消息体不能为空"); return; } if (request.Send.FromUserId == null || request.Send.ToUserId == null) { response.Wrap(ResponseDefine.BadRequset, "发送或接收人的ID不能为0"); return; } if (string.IsNullOrWhiteSpace(request.Send.Msg.Detail)) { response.Wrap(ResponseDefine.BadRequset, "消息内容不能为空"); return; } // 判断发信人与收信人存在 User fromUser = _UserStore.ReadAsync(a => a.Where(b => b.Id == request.Send.FromUserId), CancellationToken.None).Result; if (fromUser == null) { Def.Response.UserNotFound(response, request.Send.FromUserId); } User toUser = _UserStore.ReadAsync(a => a.Where(b => b.Id == request.Send.ToUserId), CancellationToken.None).Result; if (toUser == null) { Def.Response.UserNotFound(response, request.Send.ToUserId); } // 消息不可重复:在数据库中比较与上一条消息的发送时间是否一致,TODO: 另外可以比较当前时间与上一条的内容一致但是时间间隔过短 // 改造,生成LastMessage(long )方法 var lastSend = await Store.ReadAsync(a => a.Where(b => b.FromUserId == fromUser.Id && b.ToUserId == toUser.Id && b.FromTime == a.Max(c => c.FromTime)), CancellationToken.None); if (lastSend != null && request.Send.FromTime == lastSend.FromTime) { response.Wrap(ResponseDefine.PostRepeat, "消息不可以重复发送"); } else { // 使用事务刷新数据,保持数据一致性 using (var trans = await _transaction.BeginTransaction()) { try { // 先保存Msg获取MsgId var msg = await _MessageStore.CreateAsync(new Message { Detail = request.Send.Msg.Detail }); // 再保存Send获取保存后的Send if (msg.Id == null) { throw new Exception("WS------ 再数据库中创建Message时返回保存的Message不完整:\r\n" + msg); } else { //Thread.Sleep(5); var send = await Store.CreateAsync(new Send { Type = request.Send.Type ?? "Private", FromUserId = request.Send.FromUserId, FromTime = request.Send.FromTime ?? DateTime.Now, ToUserId = request.Send.ToUserId, MsgId = msg.Id, _CreateUserId = "1" }, cancellationToken); } trans.Commit(); } catch (Exception e) { trans.Rollback(); throw new Exception("使用事务保存数据时出现异常:\r\n", e); } } } }
/// <summary> /// 同步发送文件,自动分块上传,文件较大可能会卡住进程,建议异步发送 /// </summary> /// <param name="fileInfo">文件信息</param> /// <param name="toUserName">发送人UserName</param> /// <returns></returns> public SendMsgResponse SendMsg(FileInfo fileInfo, string toUserName) { string mediaId = string.Empty; if (uploadMedia.Keys.Contains(fileInfo.Name)) { mediaId = uploadMedia[fileInfo.Name]; } else { UploadMediaResponse uploadMediaResponse = UploadFile(fileInfo, toUserName); mediaId = uploadMediaResponse.MediaId; } string mime = MimeMapping.GetMimeMapping(fileInfo.Name); string time = Utils.GetJavaTimeStamp().ToString(); SendMsgResponse response = null; if (mime.StartsWith("image")) { string sendMsgUrl = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxsendmsgimg?fun=async&f=json&lang=zh_CN&pass_ticket={0}", passTicket); SendMediaMsgRequest sendImgMsgRequest = new SendMediaMsgRequest() { BaseRequest = baseRequest, Msg = new MediaMsg() { ClientMsgId = time, FromUserName = user.UserName, LocalID = time, MediaId = mediaId, ToUserName = toUserName, Type = MSGTYPE.MSGTYPE_IMAGE }, Scene = 0 }; response = httpClient.PostJson <SendMsgResponse>(sendMsgUrl, sendImgMsgRequest); } else if (mime.StartsWith("video")) { string sendMsgUrl = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxsendvideomsg?fun=async&f=json&lang=zh_CN&pass_ticket={0}", passTicket); SendMediaMsgRequest sendImgMsgRequest = new SendMediaMsgRequest() { BaseRequest = baseRequest, Msg = new MediaMsg() { ClientMsgId = time, FromUserName = user.UserName, LocalID = time, MediaId = mediaId, ToUserName = toUserName, Type = MSGTYPE.MSGTYPE_IMAGE }, Scene = 0 }; response = httpClient.PostJson <SendMsgResponse>(sendMsgUrl, sendImgMsgRequest); } else { string sendMsgUrl = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxsendappmsg?fun=async&f=json&lang=zh_CN&pass_ticket={0}", passTicket); SendMsgRequest sendAppMsgRequest = new SendMsgRequest() { BaseRequest = baseRequest, Msg = new Msg() { ClientMsgId = time, Content = string.Format("<appmsg appid='wxeb7ec651dd0aefa9' sdkver=''><title>{0}</title><des></des><action></action><type>6</type><content></content><url></url><lowurl></lowurl><appattach><totallen>{1}</totallen><attachid>{2}</attachid><fileext>{3}</fileext></appattach><extinfo></extinfo></appmsg>", fileInfo.Name, fileInfo.Length, mediaId, fileInfo.Extension.Substring(1)), FromUserName = user.UserName, ToUserName = toUserName, LocalID = time, Type = MSGTYPE.MSGTYPE_DOC }, Scene = 0 }; response = httpClient.PostJson <SendMsgResponse>(sendMsgUrl, sendAppMsgRequest); } return(response); }
/// <summary> /// 将消息推送给消息中心 /// </summary> /// <param name="model"></param> private void PushMessageToMessageCenter(SendMsgRequest sendMsgRequest) { PushMessageDomainModel pushMessageDomainModel = _mapper.Map <PushMessageDomainModel>(sendMsgRequest); _eventNotification.Notify("AddMessageToMessageCenter", null, pushMessageDomainModel); }
public virtual SendMsgResult SendMsg(SendMsgRequest request) { return(Request <SendMsgResult>("openim", "sendmsg", request)); }