Exemple #1
0
        /// <summary>
        /// 存储用户微信Cookie标识
        /// </summary>
        /// <param name="redisHelper"></param>
        /// <param name="userName"></param>
        /// <param name="cookie"></param>
        public void SetUserSyncKeys(string wxuin, SyncKey SyncKeys)
        {
            var    tablename = userRedisKey(wxuin);
            string keysJson  = (JsonConvert.SerializeObject(SyncKeys));

            _redisHelper.SetHash(tablename, _synckeys_redis_key_, keysJson);
        }
Exemple #2
0
        /// <summary>
        /// 消息同步
        /// </summary>
        void wxSync()
        {
            string url = String.Format("{0}/cgi-bin/mmwebwx-bin/webwxsync?sid={1}&skey={2}&pass_ticket={3}", gateway, baseRequest.Sid, baseRequest.Skey, passticket);
            var    o   = new
            {
                BaseRequest = baseRequest,
                SyncKey     = _syncKey,
                rr          = getcurrentseconds()
            };
            var rsp = wc.PostStr(url, Serialize.ToJson(o));

            outLog("sync->" + Serialize.ToJson(rsp));

            if (rsp.err)
            {
                throw new Exception("消息获取失败->" + Serialize.ToJson(rsp));
            }

            _syncKey = Serialize.FromJson <SyncKey>(rsp.data + "", "SyncKey");

            var msglist = Serialize.FromJson <List <Msg> >(rsp.data + "", "AddMsgList");

            foreach (var m in msglist)
            {
                if (m.FromUserName != user.UserName)
                {
                    outLog("msg->" + user.Uin + "->" + m.Content); NewMsg?.Invoke(m, ukey);
                }                                                                                                                                      // Debug.WriteLine(user.Uin + "收到消息->" + m.MsgId + "--->>>" + m.Content);
            }
        }
Exemple #3
0
        public SyncResponse Sync(SyncKey syncKey, string pass_ticket, BaseRequest baseReq)
        {
            SetHttpHeader("Accept", "application/json, text/plain, */*");
            SetHttpHeader("Connection", "keep-alive");
            SetHttpHeader("Accept-Encoding", "gzip, deflate, br");
            SetHttpHeader("Origin", this.root_uri);

            string url = this.root_uri + "/cgi-bin/mmwebwx-bin/webwxsync?sid={0}&skey={1}&lang=zh_CN&pass_ticket={2}";

            url = string.Format(url, baseReq.Sid, baseReq.Skey, pass_ticket);
            SyncRequest req = new SyncRequest();

            req.BaseRequest = baseReq;
            req.SyncKey     = syncKey;
            req.rr          = ~getR();
            string requestJson = JsonConvert.SerializeObject(req);
            string repJsonStr  = PostString(url, requestJson);

            if (repJsonStr == null)
            {
                return(null);
            }
            var rep = JsonConvert.DeserializeObject <SyncResponse>(repJsonStr);



            return(rep);
        }
Exemple #4
0
        private void HandleSync()
        {
            if (mSyncKey == null)
            {
                CurrentStatus = ClientStatusType.GetUUID;
                return;
            }
            if (mSyncKey.Count <= 0)
            {
                return;
            }

            var checkResult = mAPIService.SyncCheck(mSyncKey.List, mBaseReq);

            if (checkResult.retcode != "0")
            {
                CurrentStatus = ClientStatusType.GetUUID;
                return;
            }
            if (checkResult.selector == "0")
            {
                return;
            }
            var syncResult = mAPIService.Sync(mSyncKey, mPass_ticket, mBaseReq);

            mSyncKey = syncResult.SyncKey;

            // 处理同步
            ProcessSyncResult(syncResult);
        }
Exemple #5
0
        /// <summary>
        /// 第六步:获取消息内容
        /// </summary>
        /// <returns></returns>
        public SyncResult Sync(WechatCookie wechatCookie, string cookieStr, SyncKey syncKey)
        {
            if (wechatCookie == null)
            {
                throw new Exception("cookie值为空");
            }
            string       url   = string.Format(WechatUrl.SnycUrl, wechatCookie.Wxsid, wechatCookie.Skey, wechatCookie.Pass_Ticket);
            SyncParamter param = new SyncParamter();

            param.SyncKey = syncKey;
            param.rr      = WechatCommon.GetTicks();
            BaseRequest request = new BaseRequest();

            request.Uin       = wechatCookie.Wxuin;
            request.DeviceID  = DeviceID;
            request.Sid       = wechatCookie.Wxsid;
            request.Skey      = wechatCookie.Skey;
            param.BaseRequest = request;

            string postData = JsonConvert.SerializeObject(param);
            string html     = HttpCommon.instance.PostHttp(url, postData, ContentType.json, cookieStr);

            AppLog.WriteInfo(string.Format("协议:{0},结果:{1}", "Sync", html));

            //HttpItem item = new HttpItem()
            //{
            //    URL = url,//URL     必需项
            //    Method = "POST",//URL     可选项 默认为Get
            //    Encoding = Encoding.UTF8,
            //    UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统     可选项有默认值
            //    Accept = "text/html, application/xhtml+xml, */*",//    可选项有默认值
            //    ContentType = "application/json; charset=UTF-8",//返回类型    可选项有默认值
            //    Cookie = CookieStr,//字符串Cookie     可选项
            //    Postdata = postData,//Post数据     可选项GET时不需要写
            //};
            //HttpResult result = http.GetHtml(item);
            //string html = result.Html;
            SyncResult sync = new SyncResult();

            try
            {
                if (!string.IsNullOrEmpty(html) && html != "操作超时")
                {
                    sync = JsonConvert.DeserializeObject <SyncResult>(html);
                    //SyncKey = sync.SyncKey;
                    //SyncKeyFormat();
                    //msg = sync.AddMsgList;
                }
            }
            catch (Exception ex)
            {
                AppLog.WriteError(ex.Message);
            }

            return(sync);
        }
        private void HandleInit()
        {
            List <Contact> list       = new List <Contact>();
            var            initResult = client.Init(mPass_ticket, mBaseReq);

            if (initResult != null && initResult.BaseResponse.ret == 0)
            {
                Self = CreateContact(initResult.User);
                OnGetUser?.Invoke(this, new GetUserEvent()
                {
                    Self = Self
                });
                foreach (var item in initResult.ContactList)
                {
                    list.Add(CreateContact(item));
                }

                mSyncKey = initResult.SyncKey;
                // 开启系统通知
                var statusNotifyRep = client.Statusnotify(Self.ID, Self.ID, mPass_ticket, mBaseReq);
                if (statusNotifyRep != null && statusNotifyRep.BaseResponse != null && statusNotifyRep.BaseResponse.ret == 0)
                {
                    CurrentStatus = ClientStatusType.WeixinSync;
                    IsLogin       = true;
                }
                else
                {
                    LogHandler.i("WechatAPIService", "HandleInit()", statusNotifyRep);
                    CurrentStatus = ClientStatusType.GetUUID;
                    return;
                }
            }
            else
            {
                LogHandler.i("WechatAPIService", "HandleInit()", initResult);
                CurrentStatus = ClientStatusType.GetUUID;
                return;
            }

            if (!InitContactAndGroups())
            {
                CurrentStatus = ClientStatusType.WeixinInit;
                IsLogin       = false;
                return;
            }


            OnInited?.Invoke(this, new InitedEvent()
            {
                LastContact = list
            });
        }
Exemple #7
0
        public static string SyncKeyFormat(SyncKey syncKey)
        {
            StringBuilder result = new StringBuilder();

            foreach (var key in syncKey.List)
            {
                result.AppendFormat("{0}_{1}|", key.Key, key.Val);
            }

            string str = result.ToString().TrimEnd('|');

            str = HttpHelper.URLEncode(str);
            return(str);
        }
Exemple #8
0
        /// <summary>
        /// 登陆后初始化
        /// </summary>
        void wxInit()
        {
            string url = String.Format("{0}/cgi-bin/mmwebwx-bin/webwxinit?pass_ticket={1}&skey={2}&r={3}", gateway, passticket, baseRequest.Skey, getcurrentseconds());
            var    rsp = wc.PostStr(url, Serialize.ToJson(new { BaseRequest = baseRequest }));

            outLog("init->" + Serialize.ToJson(rsp));

            if (rsp.err)
            {
                throw new Exception("初始化失败->" + Serialize.ToJson(rsp));
            }

            user     = Serialize.FromJson <Contact>(rsp.data + "", "User");
            _syncKey = Serialize.FromJson <SyncKey>(rsp.data + "", "SyncKey");
        }
Exemple #9
0
        /// <summary>
        /// 消息同步
        /// </summary>
        void wxSync()
        {
            string url = String.Format("{0}/cgi-bin/mmwebwx-bin/webwxsync?sid={1}&skey={2}&pass_ticket={3}", gateway, baseRequest.Sid, baseRequest.Skey, passticket);
            var    o   = new
            {
                BaseRequest = baseRequest,
                SyncKey     = _syncKey,
                rr          = getcurrentseconds()
            };
            var rsp = wc.PostStr(url, Serialize.ToJson(o));

            outLog("sync->" + Serialize.ToJson(rsp));

            if (rsp.err)
            {
                throw new Exception("消息获取失败->" + Serialize.ToJson(rsp));
            }

            _syncKey = Serialize.FromJson <SyncKey>(rsp.data + "", "SyncKey");

            var msglist = Serialize.FromJson <List <Msg> >(rsp.data + "", "AddMsgList");

            foreach (var m in msglist)
            {
                if (m.FromUserName == user.UserName)
                {
                    continue;
                }



                //outLog("msg->" + user.Uin + "->" + m.Content);

                //if (m.Content.Contains("你的朋友验证请求,") && m.Content.Contains("可以开始聊天了"))
                //{
                //    var rp = db.x_reply.Where(r => r.user_id == lg.user_id);
                //}

                //var rps = db.x_reply.FirstOrDefault(o => o.keys)

                NewMsg?.Invoke(m);
            }

            // Debug.WriteLine(user.Uin + "收到消息->" + m.MsgId + "--->>>" + m.Content);
        }
Exemple #10
0
        /// <summary>
        /// 开始初始化所有关键内容
        /// </summary>
        private void Init()
        {
            try
            {
                string  webwxinitUrl = string.Format(host + "/cgi-bin/mmwebwx-bin/webwxinit?r={0}pass_ticket={1}", Utils.Get_r(), passTicket);
                JObject postjson     = JObject.FromObject(new
                {
                    BaseRequest = baseRequest
                });
                InitResponse initMsg = httpClient.PostJson <InitResponse>(webwxinitUrl, postjson);
                if (initMsg.BaseResponse.Ret != 0)
                {
                    throw new Exception("程序初始化失败");
                }
                //初始化2次,官网也是初始化2次,这样貌似比较稳定
                httpClient.PostJson <InitResponse>(webwxinitUrl, postjson);
                user = initMsg.User;
                mpSubscribeMsgList = initMsg.MPSubscribeMsgList;
                syncKey            = initMsg.SyncKey;

                //初始化的时候会返回一个最近联系人列表,但是主要还是以第一次sync获得的最近联系人为准。
                asyncOperation.Post(
                    new SendOrPostCallback((list) =>
                {
                    BatchGetContactComplete?.Invoke(this, new TEventArgs <List <Contact> >((List <Contact>)list));
                }), initMsg.ContactList);

                asyncOperation.Post(
                    new SendOrPostCallback((obj) =>
                {
                    LoginComplete?.Invoke(this, new TEventArgs <User>((User)obj));
                }), user);
            }
            catch (Exception ex)
            {
                FileLog.Exception("Init", ex);
                asyncOperation.Post(
                    new SendOrPostCallback((obj) =>
                {
                    ExceptionCatched?.Invoke(this, new TEventArgs <Exception>((Exception)obj));
                }), ex);
                //throw ex;
            }
        }
Exemple #11
0
        private void HandleSync()
        {
            if (mSyncKey == null)//LogHandler
            {
                LogHandler.i("WechatAPIService... HandleSync() ... mSyncKey==null");
                CurrentStatus = ClientStatusType.GetUUID;
                return;
            }
            if (mSyncKey.Count <= 0)
            {
                return;
            }

            var checkResult = client.SyncCheck(mSyncKey.List, mBaseReq, ++mSyncCheckTimes);

            if (checkResult == null)
            {
                return;
            }


            if (checkResult.retcode != null && checkResult.retcode != "0")
            {
                LogHandler.i("WechatAPIService... HandleSync() ... checkResult=" + checkResult.retcode + "," + checkResult.selector);
                CurrentStatus = ClientStatusType.GetUUID;
                return;
            }
            if (checkResult.selector == "0")
            {
                return;
            }
            var syncResult = client.Sync(mSyncKey, mPass_ticket, mBaseReq);

            if (syncResult == null)
            {
                return;
            }
            mSyncKey = syncResult.SyncKey;

            // 处理同步
            ProcessSyncResult(syncResult);
        }
Exemple #12
0
        /// <summary>
        /// 获取消息
        /// </summary>
        /// <param name="sk"></param>
        /// <returns></returns>
        public static ResponseMessage GetMessage(SyncKey sk)
        {
            var body = new
            {
                BaseRequest = new
                {
                    Uin      = long.Parse(_uin),
                    Sid      = _sid,
                    Skey     = _skey,
                    DeviceID = "e155590153985983"
                },
                SyncKey = sk,
                rr      = long.Parse($"-{DataHelper.GetTimeStamp(10).Substring(0, 9).Negation()}")
            }.ObjectToJson();
            var bytes = new WebHelper().SendPostRequest(
                string.Format(_get_new_message, _sid, _skey, _pass_ticket), body);
            var response = bytes.BytesToString().JsonToObject <ResponseMessage>();

            return(response);
        }
Exemple #13
0
        public IResult <FetchMessageResponse> FetchMessage(LoginResponse loginResponse, SyncKey syncKey)
        {
            var result = new Result <FetchMessageResponse>();

            try
            {
                var fetchMessageUrl = string.Format(UrlEndPoints.FetchMessageUrl, loginResponse.WxSid, loginResponse.Skey, loginResponse.PassTicket);
                var request         = new FetchMessageRequest()
                {
                    BaseRequest = new BaseRequest()
                    {
                        DeviceID = SystemInfo.DeviceId,
                        Sid      = loginResponse.WxSid,
                        Skey     = loginResponse.Skey,
                        Uin      = loginResponse.WxUin.ToString()
                    },
                    SyncKey = syncKey,
                    rr      = DateTimeHelper.Default.GetTimestamp(13)
                };
                var postStr = JsonConvert.SerializeObject(request);
                var content = new StringContent(postStr);
                content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
                var response             = _HttpClient.PostAsync(fetchMessageUrl, content).Result;
                var respage              = response.Content.ReadAsStringAsync().Result;
                var fetchMessageResponse = JsonConvert.DeserializeObject <FetchMessageResponse>(respage);

                result.SetSuccess();
                result.SetData(fetchMessageResponse);
                return(result);
            }
            catch (Exception ex)
            {
                LogHelper.Default.LogDay($"消息拉取异常,{ex}");
                LogHelper.Default.LogPrint($"消息拉取异常,{ex.Message}", 4);

                result.SetFailed();
                result.SetDesc($"消息拉取异常,{ex.Message}");
                return(result);
            }
        }
Exemple #14
0
        public static byte[] mergeKeyBuf(byte[] oldbuf, byte[] newbuf)
        {
            if ((oldbuf == null) || (oldbuf.Length == 0))
            {
                return(newbuf);
            }
            if ((newbuf == null) || (newbuf.Length == 0))
            {
                return(oldbuf);
            }
            SyncKey key = null;

            try
            {
                key = SyncKey.ParseFrom(oldbuf);
            }
            catch (Exception exception)
            {
                Log.e("NetSceneNewInit", "synckey oldbuf is invalid" + exception.Message);
                return(newbuf);
            }
            SyncKey key2 = null;

            try
            {
                key2 = SyncKey.ParseFrom(newbuf);
            }
            catch (Exception exception2)
            {
                Log.e("NetSceneNewInit", "synckey newbuf is invalid" + exception2.Message);
                return(oldbuf);
            }
            IList <KeyVal>          keyList    = key.KeyList;
            IList <KeyVal>          list2      = key2.KeyList;
            Dictionary <uint, uint> dictionary = new Dictionary <uint, uint>();

            for (int i = 0; i < keyList.Count; i++)
            {
                if (!dictionary.ContainsKey(keyList[i].Key))
                {
                    dictionary.Add(keyList[i].Key, keyList[i].Val);
                }
            }
            for (int j = 0; j < list2.Count; j++)
            {
                if (dictionary.ContainsKey(list2[j].Key))
                {
                    dictionary[list2[j].Key] = list2[j].Val;
                }
                else
                {
                    dictionary.Add(list2[j].Key, list2[j].Val);
                }
            }
            SyncKey defaultInstance = SyncKey.DefaultInstance;

            SyncKey.Builder builder = new SyncKey.Builder().SetKeyNum((uint)dictionary.Count);
            foreach (KeyValuePair <uint, uint> pair in dictionary)
            {
                KeyVal.Builder introduced17 = KeyVal.CreateBuilder().SetKey(pair.Key);
                KeyVal         item         = introduced17.SetVal(pair.Value).Build();
                builder.KeyList.Add(item);
            }
            return(builder.Build().ToByteArray());
        }
Exemple #15
0
        /// <summary>
        /// 心跳检测微信状态
        /// </summary>
        public static void HeartbeatWxStatus(HttpResponse httpResponse, string wxHosts, string wxCookie, PassTicketXmlInfo keys, SyncKey syncKey)
        {
            var status = WeiXinHelper.GetWxStatus(wxHosts, wxCookie, keys, syncKey);
            var wxnews = WeiXinHelper.GetNews(wxHosts, wxCookie, keys, syncKey);

            if (status)
            {
                Thread.Sleep(20000);
                HeartbeatWxStatus(httpResponse, wxHosts, wxCookie, keys, syncKey);
            }
            else
            {
                throw new CustomerException(String.Format("当前登录状态消失 时间:", DateTime.Now), -2);
            }
        }
Exemple #16
0
        public static bool CheckStatus(HttpResponse httpResponse, string wxHosts, string wxCookie, PassTicketXmlInfo keys, SyncKey syncKey)
        {
            var status = WeiXinHelper.GetWxStatus(wxHosts, wxCookie, keys, syncKey);

            if (!status)
            {
                AuthCore.DeleteUin(httpResponse);
                throw new CustomerException("登录过期,请重新登录", -2);
            }
            return(status);
        }
Exemple #17
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);
                }
            }
        }
Exemple #18
0
        /// <summary>
        /// 运行微信Client主逻辑,推荐放在独立的线程中执行这个方法
        /// </summary>
        public void Run()
        {
            // 启动流程
            // 1.登陆
            // 2.初始化
            // 3.开启系统通知
            // 4.获得联系人列表
            // 5.进入同步主循环


            // ----------1.登陆

            do
            {
                Debug.Write("[*] 正在获取Session ....");
                string session = api.GetNewQRLoginSessionID();
                if (!string.IsNullOrWhiteSpace(session))
                {
                    Debug.Write("成功\n");
                }
                else
                {
                    continue;
                }
                Debug.Write("[*] 正在生成二维码 ....");
                var QRImg = api.GetQRCodeImage(session);
                if (QRImg != null)
                {
                    Debug.Write("成功\n");
                }
                else
                {
                    continue;
                }
                Debug.Write("[*] 正在等待扫码 ....");
                OnGetQRCodeImage?.Invoke(QRImg);
                //login check
                while (true)
                {
                    var loginResult = api.Login(session);
                    if (loginResult.code == 200)
                    {
                        // 登录成功
                        var redirectResult = api.LoginRedirect(loginResult.redirect_uri);
                        mBaseReq      = new BaseRequest();
                        mBaseReq.Skey = redirectResult.skey;
                        mBaseReq.Sid  = redirectResult.wxsid;
                        mBaseReq.Uin  = redirectResult.wxuin;
                        // 生成DeviceID
                        Random ran   = new Random();
                        int    rand1 = ran.Next(10000, 99999);
                        int    rand2 = ran.Next(10000, 99999);
                        int    rand3 = ran.Next(10000, 99999);
                        mBaseReq.DeviceID = string.Format("e{0}{1}{2}", rand1, rand2, rand3);
                        mPass_ticket      = redirectResult.pass_ticket;
                        IsLogin           = true;
                        Debug.Write("已确认\n");
                        break;
                    }
                    else if (loginResult.code == 201)
                    {
                        // 已扫描,但是未确认登录
                        // convert base64 to image
                        byte[]       base64_image_bytes = Convert.FromBase64String(loginResult.UserAvatar);
                        MemoryStream memoryStream       = new MemoryStream(base64_image_bytes, 0, base64_image_bytes.Length);
                        memoryStream.Write(base64_image_bytes, 0, base64_image_bytes.Length);
                        var image = Image.FromStream(memoryStream);
                        OnUserScanQRCode?.Invoke(image);
                        Debug.Write("已扫码\n");
                        Debug.Write("[*] 正在等待确认 ....");
                    }
                    else
                    {
                        // 超时
                        Debug.Write("超时\n");
                        break;
                    }
                }
            } while (!IsLogin);


            // ----------2.初始化
            Debug.Write("[*] 正在初始化 ....");
            var initResult = api.Init(mPass_ticket, mBaseReq);

            if (initResult.BaseResponse.ret == 0)
            {
                Debug.Write("成功\n");
            }
            else
            {
                Debug.Write("失败.错误码:" + initResult.BaseResponse.ret);
                return;
            }

            CurrentUser = initResult.User;


            // 最近联系人
            mRecentContacts.Clear();
            if (initResult.ContactList != null)
            {
                foreach (var user in initResult.ContactList)
                {
                    CacheUser(user);
                    mRecentContacts.Add(user.UserName);
                }
            }

            // chatsets 里有需要获取详细信息的联系人.
            List <string> waitingToCacheUserList = new List <string>();
            var           chatsets = initResult.ChatSet.Split(',');

            foreach (var username in chatsets)
            {
                if (!username.StartsWith("@"))
                {
                    continue;
                }
                if (!mCachedUsers.ContainsKey(username) && !waitingToCacheUserList.Contains(username))
                {
                    waitingToCacheUserList.Add(username);
                }
            }



            // ----------3.开启状态通知
            Debug.Write("[*] 正在开启系统通知 ....");
            var statusNotifyRep = api.Statusnotify(CurrentUser.UserName, CurrentUser.UserName, mPass_ticket, mBaseReq);

            if (statusNotifyRep != null && statusNotifyRep.BaseResponse != null && statusNotifyRep.BaseResponse.ret == 0)
            {
                Debug.Write("成功\n");
            }
            else
            {
                Debug.Write("失败.错误码:" + statusNotifyRep.BaseResponse.ret);
                return;
            }


            // ----------4.获得联系人列表
            Debug.Write("[*] 正在获取联系人列表 ....");
            var getContactResult = api.GetContact(mPass_ticket, mBaseReq.Skey);

            if (getContactResult != null && getContactResult.BaseResponse != null && getContactResult.BaseResponse.ret == 0)
            {
                Debug.Write("成功\n");
                Debug.WriteLine("[*] 共有 " + getContactResult.MemberCount + " 个联系人.");
            }
            else
            {
                Debug.Write("失败. 错误码:" + getContactResult.BaseResponse.ret);
                return;
            }
            foreach (var user in getContactResult.MemberList)
            {
                CacheUser(user);
                mContactList.Add(user.UserName);
            }

            Debug.Write("[*] 正在请求群聊成员详细信息 ....\n");
            //-----------5.批量获取群组详细信息
            foreach (var user in mCachedUsers.Values)
            {
                if (user.UserName.StartsWith("@@"))
                {
                    RefreshGroupMemberInfo(user.UserName);
                }
            }

            OnLoginSucess?.Invoke();
            SyncKey syncKey = initResult.SyncKey;

            // ----------6.同步主循环
            Debug.WriteLine("[*] 进入同步循环 ....");
            while (true)
            {
                bool hasInitMsg = false;
                // 同步
                if (syncKey.Count > 0)
                {
                    var syncCheckResult = api.SyncCheck(syncKey.List, mBaseReq);
                    if (syncCheckResult == null)
                    {
                        continue;
                    }
                    if (syncCheckResult.retcode != "0")
                    {
                        Debug.WriteLine("[*] 登陆已失效,请重新登陆 ....");
                        IsLogin = false;
                        mCachedUsers.Clear();
                        mRecentContacts.Clear();
                        mContactList.Clear();
                        return;
                    }
                    if (syncCheckResult.retcode == "0" && syncCheckResult.selector != "0")
                    {
                        Debug.WriteLine(string.Format("[*] 同步检查 RetCode:{0} Selector:{1}", syncCheckResult.retcode, syncCheckResult.selector));
                        var syncResult = api.Sync(syncKey, mPass_ticket, mBaseReq);
                        syncKey = syncResult.SyncKey;
                        Debug.WriteLine(string.Format("[*] 同步结果 AddMsgCount:{0} ModContactCount:{1}", syncResult.AddMsgCount, syncResult.ModContactCount));
                        // addmsg
                        if (syncResult.AddMsgCount > 0)
                        {
                            foreach (var msg in syncResult.AddMsgList)
                            {
                                // 过滤系统信息
                                if (msg.MsgType != 51)
                                {
                                    OnRecvMsg?.Invoke(msg);
                                }
                                else
                                {
                                    hasInitMsg = true;
                                }
                                var notifyUserNames = msg.StatusNotifyUserName.Split(',');
                                foreach (var username in notifyUserNames)
                                {
                                    if (!username.StartsWith("@"))
                                    {
                                        continue;
                                    }
                                    if (!mCachedUsers.ContainsKey(username) && !waitingToCacheUserList.Contains(username))
                                    {
                                        waitingToCacheUserList.Add(username);
                                    }
                                }
                            }
                        }

                        // modify contact
                        if (syncResult.ModContactList != null)
                        {
                            foreach (var modContact in syncResult.ModContactList)
                            {
                                CacheUser(modContact);
                            }
                        }
                    }
                }
                if (waitingToCacheUserList.Count > 0)
                {
                    // 获得群详细信息
                    Debug.WriteLine("[*] 正在获取联系人详细信息 ....");

                    foreach (var userName in waitingToCacheUserList)
                    {
                        if (userName.StartsWith("@@"))
                        {
                            RefreshGroupMemberInfo(userName);
                        }
                    }

                    var batchResult = api.BatchGetContact(waitingToCacheUserList.ToArray(), mPass_ticket, mBaseReq);
                    if (batchResult != null && batchResult.ContactList != null)
                    {
                        foreach (var user in batchResult.ContactList)
                        {
                            CacheUser(user);
                        }
                        Debug.WriteLine("[*] 获取到联系人详细信息 " + batchResult.Count + "个");
                    }
                    waitingToCacheUserList.Clear();
                }


                // 初始化完成回调
                if (hasInitMsg && !firstInited)
                {
                    firstInited = true;
                    OnInitComplate?.Invoke();
                }
            }
        }
Exemple #19
0
        /// <summary>
        /// 获取新消息,延长Cookie时间
        /// </summary>
        /// <param name="wxHosts"></param>
        /// <param name="wxCookie"></param>
        /// <param name="keys"></param>
        /// <param name="syncKey"></param>
        public static string GetNews(string wxHosts, string wxCookie, PassTicketXmlInfo keys, SyncKey syncKey)
        {
            var param = new
            {
                BaseRequest = new
                {
                    skey     = keys.skey,
                    sid      = keys.wxsid,
                    uin      = keys.wxuin,
                    deviceid = GetWxDeviceId(),
                },
                SyncKey = syncKey
            };
            var httpHelper = new HttpHelper(param, GetWxCookie(wxCookie));
            var result     = httpHelper.HttpPost(WxNews(wxHosts, keys.wxsid, keys.skey));
            var setcookie  = httpHelper.ReturnCookie;

            return(result);
        }
Exemple #20
0
        public static bool GetWxStatus(string wxHosts, string wxCookie, PassTicketXmlInfo keys, SyncKey syncKey)
        {
            var param = new
            {
                r        = TimeHelper.GetTimeStamp(),
                skey     = keys.skey,
                sid      = keys.wxsid,
                uin      = keys.wxuin,
                deviceid = GetWxDeviceId(),
                synckey  = String.Join("|", syncKey.List.Select(m => String.Format("{0}_{1}", m.Key, m.Val)))
            };
            var result     = new HttpHelper(param, GetWxCookie(wxCookie)).HttpGet(WxStatus(wxHosts));
            var statusJson = result.Replace("window.synccheck=", "");
            var status     = JsonConvert.DeserializeObject <WxStatus>(statusJson);

            return(status.RetCode.Equals("0"));
        }
Exemple #21
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="list"></param>
        /// <param name="cts"></param>
        /// <param name="nks"></param>
        /// <param name="t"></param>
        List <object> toContact(List <Contact> list, Dictionary <string, int> nks, long gpid)
        {
            var cts = new List <x_contact>();
            var gps = new List <object>();

            foreach (var c in list)
            {
                var n = c.NickName;
                if (!string.IsNullOrEmpty(c.RemarkName))
                {
                    n = c.RemarkName;
                }
                if (gpid > 0)
                {
                    n += gpid;
                }
                n += user.Uin;
                if (nks.ContainsKey(n))
                {
                    c.RemarkName = c.NickName + (++nks[n]).ToString("000");
                }                                                                                  //SetRemark(c.UserName, c.RemarkName);
                else
                {
                    nks.Add(n, 0); c.RemarkName = n;
                }

                var no = Secret.MD5(n);
                var ct = db.x_contact.FirstOrDefault(t => t.no == no && t.uin == user.Uin);
                if (ct == null)
                {
                    ct = new x_contact()
                    {
                        uin = user.Uin, no = no
                    }
                }
                ;

                ct.user_id     = lg.user_id;
                ct.remarkname  = c.RemarkName;
                ct.nickname    = Tools.RemoveHtml(c.NickName);
                ct.flag        = c.UserName[1] == '@' ? 2 : 1;
                ct.group_id    = gpid;
                ct.membercount = c.MemberCount;
                ct.signature   = c.Signature;
                ct.username    = c.UserName;
                ct.imgurl      = c.HeadImgUrl;

                var m = new Regex("(\\d{11})").Match(c.NickName);
                if (m.Success)
                {
                    ct.tel = m.Groups[1].Value;
                }
                if (ct.contact_id == 0)
                {
                    cts.Add(ct);
                }

                if (c.UserName[1] == '@')
                {
                    gps.Add(new
                    {
                        EncryChatRoomId = c.EncryChatRoomId,
                        UserName        = c.UserName
                    });
                }
            }
            if (cts.Count > 0)
            {
                db.x_contact.InsertAllOnSubmit(cts);
            }
            try
            {
                db.SubmitChanges(ConflictMode.ContinueOnConflict);
                db.SubmitChanges(ConflictMode.FailOnFirstConflict);
            }
            catch (ChangeConflictException)
            {
                foreach (ObjectChangeConflict occ in db.ChangeConflicts)
                {
                    occ.Resolve(RefreshMode.KeepChanges);
                }
            }
            catch (Exception ex)
            {
                outLog("toContact->err:" + ex.Message);
            }
            return(gps);
        }

        /// <summary>
        /// 同步检测
        /// </summary>
        void SyncCheck()
        {
            var url = String.Format("{0}/cgi-bin/mmwebwx-bin/synccheck?r={1}&sid={2}&uin={3}&skey={4}&deviceid={5}&synckey={6}&_{7}", gateway, getcurrentseconds(), baseRequest.Sid, baseRequest.Uin, baseRequest.Skey, baseRequest.DeviceID, synckey, getcurrentseconds());
            var rsp = wc.GetStr(url);

            outLog("synccheck->" + Serialize.ToJson(rsp));

            if (rsp.err)
            {
                return; throw new Exception("心跳同步失败->" + Serialize.ToJson(rsp));
            }

            var reg = new Regex("{retcode:\"(\\d+)\",selector:\"(\\d+)\"}");
            var m   = reg.Match(rsp.data + "");

            var rt  = int.Parse(m.Groups[1].Value);
            var sel = int.Parse(m.Groups[2].Value);

            if (isquit || rt != 0)
            {
                exit(1);
            }
            else if (sel == 2 || sel == 4 || sel == 6)
            {
                wxSync();
            }
        }

        /// <summary>
        /// 消息同步
        /// </summary>
        void wxSync()
        {
            string url = String.Format("{0}/cgi-bin/mmwebwx-bin/webwxsync?sid={1}&skey={2}&pass_ticket={3}", gateway, baseRequest.Sid, baseRequest.Skey, passticket);
            var    o   = new
            {
                BaseRequest = baseRequest,
                SyncKey     = _syncKey,
                rr          = getcurrentseconds()
            };
            var rsp = wc.PostStr(url, Serialize.ToJson(o));

            outLog("sync->" + Serialize.ToJson(rsp));

            if (rsp.err)
            {
                throw new Exception("消息获取失败->" + Serialize.ToJson(rsp));
            }

            _syncKey = Serialize.FromJson <SyncKey>(rsp.data + "", "SyncKey");

            var msglist = Serialize.FromJson <List <Msg> >(rsp.data + "", "AddMsgList");

            foreach (var m in msglist)
            {
                if (m.FromUserName == user.UserName)
                {
                    continue;
                }
                outLog("msg->" + user.Uin + "->" + m.Content);

                if (m.Content.Contains("你的朋友验证请求,") && m.Content.Contains("可以开始聊天了"))
                {
                    var rp = db.x_reply.Where(r => r.user_id == lg.user_id);
                }

                //var rps = db.x_reply.FirstOrDefault(o => o.keys)

                NewMsg?.Invoke(m);
            }

            // Debug.WriteLine(user.Uin + "收到消息->" + m.MsgId + "--->>>" + m.Content);
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="ToUserName"></param>
        /// <param name="Content"></param>
        void sendText(string ToUserName, string Content)
        {
            string url = String.Format("{0}/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket={1}", gateway, passticket);

            Content = Content.Replace("<br/>", "\n");
            var o = new
            {
                BaseRequest = baseRequest,
                Msg         = new
                {
                    Type         = 1,
                    Content      = Content,
                    FromUserName = user.UserName,
                    ToUserName   = ToUserName,
                    LocalID      = getcurrentseconds(),
                    ClientMsgId  = getcurrentseconds()
                }
            };

            var rsp = op.PostStr(url, Serialize.ToJson(o));

            outLog("SendMsg->" + Serialize.ToJson(rsp));
        }

        /// <summary>
        /// 发送图片
        /// </summary>
        /// <param name="ToUserName"></param>
        /// <param name="url"></param>
        void sendImg(string ToUserName, string mmid)
        {
            //var mmid = uploadImg(ToUserName, url);
            //if (string.IsNullOrEmpty(mmid)) return;

            string api = String.Format("{0}/cgi-bin/mmwebwx-bin/webwxsendmsgimg?fun=async&f=json&pass_ticket={1}", gateway, passticket);
            var    o   = new
            {
                BaseRequest = baseRequest,
                Msg         = new
                {
                    Type         = 3,
                    MediaId      = mmid,
                    FromUserName = user.UserName,
                    ToUserName   = ToUserName,
                    LocalID      = getcurrentseconds(),
                    ClientMsgId  = getcurrentseconds()
                },
                Scene = 0
            };

            var rsp = op.PostStr(api, Serialize.ToJson(o));

            if (!(rsp.data + "").Contains("\"Ret\": 0"))
            {
                Thread.Sleep(5 * 1000);
            }

            outLog("SendImg->" + Serialize.ToJson(rsp));
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        string uploadImg(string img)
        {
            var fs = op.GetFile(img);

            if (fs.err)
            {
                return("");
            }

            string url = gateway.Replace("https://", "https://file.") + "/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json";
            var    o   = new
            {
                UploadType    = 2,
                BaseRequest   = baseRequest,
                ClientMediaId = getcurrentseconds(),
                TotalLen      = (fs.data as byte[]).Length,
                StartPos      = 0,
                DataLen       = (fs.data as byte[]).Length,
                MediaType     = 4
            };

            Dictionary <string, string> dict = new Dictionary <string, string>();

            dict.Add("id", "WU_FILE_" + filecount++);
            dict.Add("name", img.Substring(img.LastIndexOf('/') + 1));
            dict.Add("type", Tools.GetMimeType(img.Substring(img.LastIndexOf('.') + 1)));
            dict.Add("lastModifiedDate", "Wed Sep 07 2016 10:38:12 GMT+0800");//DateTime.Now.ToString("r")
            dict.Add("size", (fs.data as byte[]).Length + "");
            dict.Add("mediatype", "pic");
            dict.Add("uploadmediarequest", Serialize.ToJson(o));
            dict.Add("webwx_data_ticket", wc.GetCookie("webwx_data_ticket"));
            dict.Add("pass_ticket", passticket);

            var rsp = op.PostFile(url, dict, fs.data as byte[]);

            outLog("UploadImg->" + Serialize.ToJson(rsp));

            if (rsp.err)
            {
                return("");
            }

            return(Serialize.FromJson <string>(rsp.data + "", "MediaId"));
        }

        /// <summary>
        /// 退出
        /// </summary>
        /// <param name="c"></param>
        void exit(int c)
        {
            outLog("exit");
            isquit = true;

            if (lg != null)
            {
                lg.uuid   = null;
                lg.qrcode = null;
                lg.status = 1;

                try
                {
                    db.SubmitChanges();
                    db.Dispose();
                }
                catch (Exception ex)
                {
                    outLog("exit->err:" + ex.Message);
                }
            }
            if (c == 1)
            {
                Logout?.Invoke();
            }
        }