Beispiel #1
0
 /// <summary>
 /// 主要用于提醒手机端,同步状态
 /// </summary>
 private void StatusNotify()
 {
     try
     {
         //反馈服务器
         string webwxstatusnotifyUrl             = host + "/cgi-bin/mmwebwx-bin/webwxstatusnotify";
         StatusNotifyRequest statusNotifyRequest = new StatusNotifyRequest();
         statusNotifyRequest.BaseRequest  = baseRequest;
         statusNotifyRequest.Code         = 3;
         statusNotifyRequest.FromUserName = user.UserName;
         statusNotifyRequest.ToUserName   = user.UserName;
         statusNotifyRequest.ClientMsgId  = Utils.GetJavaTimeStamp();
         //反馈结果可以不理
         httpClient.PostJson <StatusNotifyResponse>(webwxstatusnotifyUrl, statusNotifyRequest);
     }
     catch (Exception e)
     {
         asyncOperation.Post(
             new SendOrPostCallback((obj) =>
         {
             ExceptionCatched?.Invoke(this, new TEventArgs <Exception>((Exception)obj));
         }), e);
         throw e;
     }
 }
Beispiel #2
0
 /// <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;
     }
 }
Beispiel #3
0
        /// <summary>
        /// 同步上传文件
        /// </summary>
        /// <param name="fileInfo">文件信息</param>
        /// <param name="toUserName">发送人UserName,其实没什么用,但是官方有这个参数</param>
        /// <returns></returns>
        public UploadMediaResponse UploadFile(FileInfo fileInfo, string toUserName)
        {
            string             postUrl            = uploadHost + "/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json";
            int                bufferLength       = 512 * 1024;
            string             datetime           = DateTime.Now.ToString("ddd MMM dd yyyy HH:mm:ss", CultureInfo.CreateSpecificCulture("en-US")) + " GMT+0800 (中国标准时间)";
            UploadMediaRequest uploadMediaRequest = new UploadMediaRequest()
            {
                UploadType    = 2,
                BaseRequest   = baseRequest,
                ClientMediaId = Utils.GetJavaTimeStamp(),
                TotalLen      = fileInfo.Length,
                StartPos      = 0,
                DataLen       = fileInfo.Length,
                MediaType     = 4,
                FromUserName  = user.UserName,
                ToUserName    = toUserName,
                FileMd5       = Utils.GetFileMD5Hash(fileInfo)
            };
            UploadMediaResponse response = null;

            //文件大小超过512Kb,分块上传。
            if (fileInfo.Length > bufferLength)
            {
                int    chunks     = (int)Math.Ceiling((double)fileInfo.Length / bufferLength);
                byte[] buffer     = new byte[bufferLength];
                Stream readStream = fileInfo.OpenRead();
                int    chunk      = 0;
                int    readLength = 0;
                while ((readLength = readStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    List <FormDataItem> dataList = new List <FormDataItem>()
                    {
                        new FormDataItem("id", "WU_FILE_" + uploadMedia.Count),
                        new FormDataItem("name", fileInfo.Name),
                        new FormDataItem("type", MimeMapping.GetMimeMapping(fileInfo.Name)),
                        new FormDataItem("lastModifiedDate", datetime),
                        new FormDataItem("size", fileInfo.Length.ToString()),
                        new FormDataItem("chunks", chunks.ToString()),
                        new FormDataItem("chunk", chunk.ToString()),
                        new FormDataItem("mediatype", GetMediaType(fileInfo.Extension)),
                        new FormDataItem("uploadmediarequest", JsonConvert.SerializeObject(uploadMediaRequest, Newtonsoft.Json.Formatting.None)),
                        new FormDataItem("webwx_data_ticket", httpClient.CookieContainer.GetCookies(new Uri(cookieRedirectUri))["webwx_data_ticket"].Value),
                        new FormDataItem("pass_ticket", passTicket),
                        new FormDataItem("filename", fileInfo.Name, buffer, readLength)
                    };
                    string result = httpClient.PostMutipart(postUrl, dataList);
                    response = JsonConvert.DeserializeObject <UploadMediaResponse>(result);
                    chunk++;
                }
            }
            else
            {
                byte[] buffer                = new byte[fileInfo.Length];
                Stream readStream            = fileInfo.OpenRead();
                int    readLength            = readStream.Read(buffer, 0, buffer.Length);
                List <FormDataItem> dataList = new List <FormDataItem>()
                {
                    new FormDataItem("id", "WU_FILE_" + uploadMedia.Count),
                    new FormDataItem("name", fileInfo.Name),
                    new FormDataItem("type", MimeMapping.GetMimeMapping(fileInfo.Name)),
                    new FormDataItem("lastModifiedDate", datetime),
                    new FormDataItem("size", fileInfo.Length.ToString()),
                    new FormDataItem("mediatype", GetMediaType(fileInfo.Extension)),
                    new FormDataItem("uploadmediarequest", JsonConvert.SerializeObject(uploadMediaRequest, Newtonsoft.Json.Formatting.None)),
                    new FormDataItem("webwx_data_ticket", httpClient.CookieContainer.GetCookies(new Uri(cookieRedirectUri))["webwx_data_ticket"].Value),
                    new FormDataItem("pass_ticket", passTicket),
                    new FormDataItem("filename", fileInfo.Name, buffer, readLength)
                };
                string result = httpClient.PostMutipart(postUrl, dataList);
                response = JsonConvert.DeserializeObject <UploadMediaResponse>(result);
            }
            uploadMedia.Add(fileInfo.Name, response.MediaId);
            return(response);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        /// <summary>
        /// 开始轮询检测是否有新消息
        /// </summary>
        private void Sync()
        {
            while (syncPolling)
            {
                try
                {
                    string syncCheckUrl    = string.Format(pushHost + "/cgi-bin/mmwebwx-bin/synccheck?r={0}&skey={1}&sid={2}&uin={3}&deviceid={4}&synckey={5}&_={6}", Utils.GetJavaTimeStamp(), baseRequest.Skey, baseRequest.Sid, baseRequest.Uin, baseRequest.DeviceID, syncKey.ToString(), syncKey.Step);
                    string syncCheckResult = httpClient.GetString(syncCheckUrl);
                    if (!syncPolling)
                    {
                        return;
                    }
                    MatchCollection matchCollection = Regex.Matches(syncCheckResult, @"\d+");
                    string          retcode         = matchCollection[0].Value;
                    string          selector        = matchCollection[1].Value;
                    Utils.Debug("retcode:" + retcode + " selector:" + selector);
                    switch (retcode)
                    {
                    case "0":
                        if (selector != "0")
                        {
                            //有新消息,拉取信息。
                            SyncRequest syncRequest = new SyncRequest();
                            syncRequest.BaseRequest = baseRequest;
                            syncRequest.SyncKey     = syncKey;
                            syncRequest.rr          = Utils.Get_r();
                            string       syncUrl      = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxsync?sid={0}&skey={1}&pass_ticket={2}", baseRequest.Sid, baseRequest.Skey, passTicket);
                            SyncResponse syncResponse = httpClient.PostJson <SyncResponse>(syncUrl, syncRequest);
                            if (!syncPolling)
                            {
                                return;
                            }
                            else
                            {
                                syncKey = syncResponse.SyncKey;
                                //只要不是0,就是有消息,有消息我们处理就行了,不管selector是几
                                if (syncResponse.AddMsgCount == 0 && syncResponse.DelContactCount == 0 && syncResponse.ModContactCount == 0 && syncResponse.ModChatRoomMemberCount == 0)
                                {
                                    //会有这么一种情况,selector=2,但是没有任何消息体,这样会导致持续快速的空交互
                                    //除非下次有新消息,或者主动点击手机触发消息
                                    //为了防止这种情况,做个5秒停顿。
                                    Thread.Sleep(5000);
                                }
                                else
                                {
                                    if (syncResponse.AddMsgList.Count > 0)
                                    {
                                        asyncOperation.Post(
                                            new SendOrPostCallback((obj) =>
                                        {
                                            ReceiveMsg?.Invoke(this, new TEventArgs <List <AddMsg> >((List <AddMsg>)obj));
                                        }), syncResponse.AddMsgList);
                                    }

                                    if (syncResponse.ModContactCount > 0)
                                    {
                                        asyncOperation.Post(
                                            new SendOrPostCallback((obj) =>
                                        {
                                            ModContactListComplete?.Invoke(this, new TEventArgs <List <ModContactItem> >((List <ModContactItem>)obj));
                                        }), syncResponse.ModContactList);
                                    }
                                    if (syncResponse.DelContactCount > 0)
                                    {
                                        asyncOperation.Post(
                                            new SendOrPostCallback((obj) =>
                                        {
                                            DelContactListComplete?.Invoke(this, new TEventArgs <List <DelContactItem> >((List <DelContactItem>)obj));
                                        }), syncResponse.DelContactList);
                                    }
                                    if (syncResponse.ModChatRoomMemberCount > 0)
                                    {
                                        //待分析,这个消息基本没有
                                    }
                                }
                            }
                        }
                        break;

                    case "1100":
                        //登出了微信,很可能是wx.qq.com和wx2.qq.com调用接口不一致导致的,注意登陆时候的跳转地址
                        Close();
                        asyncOperation.Post(
                            new SendOrPostCallback((obj) =>
                        {
                            LogoutComplete?.Invoke(this, new TEventArgs <User>((User)obj));
                        }), user);
                        break;

                    case "1101":
                        Close();
                        asyncOperation.Post(
                            new SendOrPostCallback((obj) =>
                        {
                            LogoutComplete?.Invoke(this, new TEventArgs <User>((User)obj));
                        }), user);
                        throw new Exception("1101可能其他地方登录/登出了 WEB 版微信,请检查手机端已登出WEB微信,然后稍后再试");
                        break;

                    case "1102":
                        Close();
                        asyncOperation.Post(
                            new SendOrPostCallback((obj) =>
                        {
                            LogoutComplete?.Invoke(this, new TEventArgs <User>((User)obj));
                        }), user);
                        throw new Exception("1102被强制登出(很可能cookie冲突),请检查手机端已登出WEB微信,然后稍后再试");
                        break;

                    default:
                        //有其他任何异常,取消轮询
                        throw new Exception("轮询结果异常,停止轮询:" + syncCheckResult);
                        break;
                    }
                    Thread.Sleep(1000);
                }
                catch (Exception ex)
                {
                    FileLog.Exception("Init", ex);
                    asyncOperation.Post(
                        new SendOrPostCallback((obj) =>
                    {
                        ExceptionCatched?.Invoke(this, new TEventArgs <Exception>((Exception)obj));
                    }), ex);
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// 读取用户的联系人列表,其中只包含公众号,个人号,如果返回值seq不为0,那么用户列表还没获取完(因为可能会有几千人的号,不可能一次获取完),则附带上seq的值继续获取。
        /// </summary>
        private void GetContact()
        {
            try
            {
                //获取联系人列表
                finishGetContactList = false;
                string getContactUrl = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxgetcontact?r={0}&seq={1}&skey={2}", Utils.GetJavaTimeStamp(), 0, baseRequest.Skey);
                while (!finishGetContactList)
                {
                    string             contactResult      = httpClient.GetStringOnce(getContactUrl);
                    GetContactResponse getContactResponse = JsonConvert.DeserializeObject <GetContactResponse>(contactResult);
                    asyncOperation.Post(
                        new SendOrPostCallback((list) =>
                    {
                        GetContactComplete?.Invoke(this, new TEventArgs <List <Contact> >((List <Contact>)list));
                    }), getContactResponse.MemberList);

                    if (getContactResponse.Seq == 0)
                    {
                        finishGetContactList = true;
                    }
                    else
                    {
                        getContactUrl = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxgetcontact?r={0}&seq={1}&skey={2}", Utils.GetJavaTimeStamp(), getContactResponse.Seq, baseRequest.Skey);
                    }
                }

                //获取完联系人中的公众号,才能获得名称,这个时候再发送图文消息事件。
                asyncOperation.Post(
                    new SendOrPostCallback((obj) =>
                {
                    MPSubscribeMsgListComplete?.Invoke(this, new TEventArgs <List <MPSubscribeMsg> >((List <MPSubscribeMsg>)obj));
                }), mpSubscribeMsgList);
            }
            catch (Exception e)
            {
                if (e is WebException)
                {
                    WebException we = e as WebException;
                    if (we.Status == WebExceptionStatus.ProtocolError && ((HttpWebResponse)we.Response).StatusCode == HttpStatusCode.ServiceUnavailable)
                    {
                        //过千人账号有时候获取不到联系人列表,服务器返回503,官方测试结果也是反馈503导致获取不到,为了不影响正常使用,跳过获取联系人步骤
                        asyncOperation.Post(
                            new SendOrPostCallback((obj) =>
                        {
                            ExceptionCatched?.Invoke(this, new TEventArgs <Exception>((Exception)obj));
                        }), new GetContactException("无法获取好友列表"));
                    }
                }
                else
                {
                    asyncOperation.Post(
                        new SendOrPostCallback((obj) =>
                    {
                        ExceptionCatched?.Invoke(this, new TEventArgs <Exception>((Exception)obj));
                    }), e);
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// 获取联系人信息,例如初始化、群聊里面。
        /// </summary>
        /// <param name="statusNotifyUserName">需要获取的UserName列表,包括群,个人用户,用英文,分割</param>
        /// <param name="EncryChatRoomId">默认为空,如果是获取群内成员详细信息,则填写encryChatRoomId,也就是群的UserName</param>
        public void GetBatchGetContactAsync(string statusNotifyUserName, string encryChatRoomId = "")
        {
            Task.Factory.StartNew(() =>
            {
                try
                {
                    //获取历史会话列表
                    string webwxbatchgetcontactUrl = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r={0}", Utils.GetJavaTimeStamp());
                    string[] chatNameArr           = statusNotifyUserName.Split(',');
                    bool finishGetChatList         = false;
                    BatchGetContactRequest batchGetContactRequest = new BatchGetContactRequest();
                    batchGetContactRequest.BaseRequest            = baseRequest;
                    int count = chatNameArr.Length;
                    int index = 0;
                    //一批次最多获取50条,多出来分批获取
                    while (!finishGetChatList)
                    {
                        batchGetContactRequest.List = new List <ChatRoom>();
                        if (((index + 1) * 50) < count)
                        {
                            for (int i = index * 50; i < (index + 1) * 50; i++)
                            {
                                batchGetContactRequest.List.Add(new ChatRoom {
                                    UserName = chatNameArr[i], EncryChatRoomId = encryChatRoomId
                                });
                            }
                        }
                        else
                        {
                            for (int i = index * 50; i < count; i++)
                            {
                                batchGetContactRequest.List.Add(new ChatRoom {
                                    UserName = chatNameArr[i], EncryChatRoomId = encryChatRoomId
                                });
                            }
                            finishGetChatList = true;
                        }
                        BatchGetContactResponse batchGetContactMsg = httpClient.PostJson <BatchGetContactResponse>(webwxbatchgetcontactUrl, batchGetContactRequest);
                        asyncOperation.Post(
                            new SendOrPostCallback((list) =>
                        {
                            BatchGetContactComplete?.Invoke(this, new TEventArgs <List <Contact> >((List <Contact>)list));
                        }), batchGetContactMsg.ContactList);

                        index++;
                    }
                }
                catch (Exception e)
                {
                    asyncOperation.Post(
                        new SendOrPostCallback((obj) =>
                    {
                        ExceptionCatched?.Invoke(this, new TEventArgs <Exception>((Exception)obj));
                    }), e);
                }
            });
        }
Beispiel #8
0
 /// <summary>
 /// 获取登陆二维码
 /// </summary>
 private void GetLoginQrCode()
 {
     try
     {
         string jsloginUrl = $"https://login.wx2.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx2.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_={Utils.GetJavaTimeStamp()}";
         string result     = httpClient.GetString(jsloginUrl);
         Utils.Debug("GetLoginQrCode " + result);
         string qruuidStr = "window.QRLogin.uuid = \"";
         int    index     = result.IndexOf("window.QRLogin.uuid = \"");
         if (index == -1)
         {
             throw new Exception("获取登陆二维码失败,请稍后再试。");
         }
         else
         {
             uuid = result.Substring(index + qruuidStr.Length, result.Length - index - qruuidStr.Length - "\";".Length);
         }
         string qrcodeUrl = string.Format("https://login.weixin.qq.com/qrcode/{0}", uuid);
         var    img       = httpClient.GetImage(qrcodeUrl);
         asyncOperation.Post(
             new SendOrPostCallback((obj) =>
         {
             GetLoginQrCodeComplete?.Invoke(this, new TEventArgs <byte[]>((byte[])obj));
         }), img);
     }
     catch (Exception e)
     {
         asyncOperation.Post(
             new SendOrPostCallback((obj) =>
         {
             ExceptionCatched?.Invoke(this, new TEventArgs <Exception>((Exception)obj));
         }), e);
         throw e;
     }
 }
Beispiel #9
0
        /// <summary>
        /// 同步通过好友认证
        /// </summary>
        /// <param name="info">sync中获得的申请信息</param>
        /// <returns></returns>
        public SimpleResponse VerifyUser(RecommendInfo info)
        {
            string            verifyUserUrl = host + "/cgi-bin/mmwebwx-bin/webwxverifyuser?r=" + Utils.GetJavaTimeStamp();
            VerifyUserRequest request       = new VerifyUserRequest();

            request.BaseRequest = baseRequest;
            request.Opcode      = VERIFYUSER_OPCODE.VERIFYUSER_OPCODE_VERIFYOK;
            request.SceneList   = new List <int>()
            {
                (int)ADDSCENE_PF.ADDSCENE_PF_WEB
            };
            request.VerifyUserList = new List <Modal.Request.VerifyUser>()
            {
                new Modal.Request.VerifyUser {
                    Value = info.UserName, VerifyUserTicket = info.Ticket
                }
            };
            request.skey = baseRequest.Skey;
            //反馈结果可以不理
            return(httpClient.PostJson <SimpleResponse>(verifyUserUrl, request));
        }