隐藏

用C#在winform项目中写一个微信登录软件

发布:2022/12/14 10:46:23作者:管理员 来源:本站 浏览次数:741

为什么会写这个?

我本来想用于参加高中(普通高中 编程是自己学的)的一个竞赛,但是由于微信号被微信限制网页登录,所以无法继续进行编写. 于是想写个教程,从头到尾详细的分享给大家制作过程,造福以后想做的人.


效果预览

打开软件,第一步需要你扫码.


描述扫码后,会获取微信号头像,并且显示已扫码,要求在微信确认.


描述当用户登录后,会显示已登录.

一些附加功能: 如果长时间不登录,会提示二维码过期,并且刷新二维码,头像回到默认头像.


一个小菜蛋, 最终也没有用于参赛…

在这里插入图片描述

开始教程:

首先我们要知道,制作一个微信登录软件,对接的其实是微信网页版.

大致步骤为:

1.获取UUID

2.获取二维码

3.检测二维码状态


以下URL均可以抓包获取


先创建一个类似于这样的页面 这里使用了winform 当然,你也可以用wpf在这里插入图片描述

首先,在界面加载事件中,我们需要做的事情有二行代码(有三行代码 建议加第一行)


private void Form1_Load(object sender, EventArgs e)

{

           System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

           flushQRCode();

           checkLoginState();

}




我们先来看第一个 刷新二维码(flushQRCode) 函数

这里面包含了获取UUID的步骤,先来获取UUID(有了UUID才能像微信要对应的二维码)

我们像微信获取UUID 要访问的URL为: wx.qq.com/jslogin

当然,光这个URL还不行,我们还需要参数,这里我们使用(GET)请求,然后获取response并读取内容.

参数有


1.appid = wx782c26e4c19acffb (固定的)

2.redirect_uri = https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage

3.fun = new (这个应该是代表新登录协议)

4.lang = zh_CN (语言,zh_CN表示中文)

5._ = 时间戳


 


知道了参数,我们先先同过这些参数获取UUID


TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);

String returnn = sendGetRequestAndGetReturn("https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=" + Convert.ToInt64(ts.TotalSeconds).ToString());


  


private String sendGetRequestAndGetReturn(String url)

{

           req = (HttpWebRequest)WebRequest.Create(new Uri(url));

           HttpWebResponse response = (HttpWebResponse)req.GetResponse();

           StreamReader php = new StreamReader(response.GetResponseStream(), Encoding.Default);

           return php.ReadToEnd();

}


 


我们输出一下 " returnn"

可以输出到:

在这里插入图片描述

window.QRlogin.uuid = 后面的引号里就是UUID了

每次请求到的UUID都不一样,如果你的和这个不一样很正常

下面我们截取uuid(我们定义一个全局变量 String UUID = “”; )


UUID = SubstringUUID(returnn);


 


private String SubstringUUID(String before)

{

           return before.Substring(before.IndexOf("\"") + 1, before.LastIndexOf("\"") - before.IndexOf("\"") - 1);

}


 


在这里插入图片描述

这就是我们的UUID了

下面我们根据UUID获取二维码

二维码需要从 ‘https://wx.qq.com/qrcode/’ + UUID 就可以请求到

我们获取一下图片


this.QRCodePictrue.BackgroundImage = getQRCodeImg("https://wx.qq.com/qrcode/" + UUID);


 


private System.Drawing.Image getQRCodeImg(String url)

{

           WebRequest wreq = WebRequest.Create(url);

           wreq.Proxy = null;

           System.Net.ServicePointManager.Expect100Continue = false;

           HttpWebResponse wresp = (HttpWebResponse)wreq.GetResponse();

           Stream s = wresp.GetResponseStream();

           System.Drawing.Image img;

           img = System.Drawing.Image.FromStream(s);

           return img;

}


 


好了,我们的QRpictrue控件已经显示了!

在这里插入图片描述

我们再来看Form1_Load中的checkLoginState()函数

这里我们要不停向url请求状态 检测是否已扫码 或是 已登录

https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=" + UUID + @"&tip=0&_=" + Convert.ToInt64(ts.TotalSeconds).ToString()

是我们要用HttpWebRequest请求的.

如果我们要实现自动检测,我们就要用到循环来检测

当没有扫码,这个url是无法getResponse()的 也就是说 获取到的response为空

但是当我们一旦扫码,将立即获取到response 我们读取后可以看到

在这里插入图片描述

这里的code=201的意思为手机上已经扫码,但是并没没有确认登录.

如果是200 那就表明已经确认登录

后面的那一大串,就包括我们的base64头像


我们先将base64代码分割出来


String bHeadImgBase64 = LoginStateMessage.Substring(LoginStateMessage.IndexOf("\'") + 1, LoginStateMessage.LastIndexOf("\'") - LoginStateMessage.IndexOf("\'") - 1);

String aHeadImgBase64 = bHeadImgBase64.Split(',')[1];

byte[] arr = Convert.FromBase64String(aHeadImgBase64);

MemoryStream ms = new MemoryStream(arr);

Bitmap bmp = new Bitmap(ms);

this.pictureBox1.BackgroundImage = bmp;


  


这样在扫码后 我们的picturebox1控件就显示头像了

在这里插入图片描述

我们还需要显示状态,可以当获取的内容中包含201 则给负责状态的label控件显示 已扫码,正在等待确认.

当内容中包含200 则给负责状态的label控件显示 已登录.

我的代码是把code专门分割出来 然后进行判断

这里我们是用循环检测的 所以是实时更新的


public void checkLoginState()

       {

           Thread th =  new Thread(()=> {

               while (!isLoginSucess)

               {

                   TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);

                   //MessageBox.Show(sendLoginConfirm("https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?" + "tip=0&uuid=" + UUID + "&_=" + Convert.ToInt64(ts.TotalSeconds).ToString()));

                   String LoginStateMessage = sendLoginConfirm(@"https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=" + UUID + @"&tip=0&_=" + Convert.ToInt64(ts.TotalSeconds).ToString());

                   String LoginStateCode = LoginStateMessage.Substring(LoginStateMessage.IndexOf("=") + 1, LoginStateMessage.IndexOf(";") - LoginStateMessage.IndexOf("=") - 1);

                   MessageBox.Show(LoginStateMessage);

                   if (LoginStateCode=="201")

                   {

                       //扫码后 没确认登录

                       this.stateLabel.Text = "已扫码,等待确认.";

                       String bHeadImgBase64 = LoginStateMessage.Substring(LoginStateMessage.IndexOf("\'") + 1, LoginStateMessage.LastIndexOf("\'") - LoginStateMessage.IndexOf("\'") - 1);

                       String aHeadImgBase64 = bHeadImgBase64.Split(',')[1];

                       byte[] arr = Convert.FromBase64String(aHeadImgBase64);

                       MemoryStream ms = new MemoryStream(arr);

                       Bitmap bmp = new Bitmap(ms);

                       this.pictureBox1.BackgroundImage = bmp;

                   }

                   else if (LoginStateCode == "200")

                   {

                       //扫码后 已经确认登录

                       this.stateLabel.Text = "已登录.";

                       MessageBox.Show(LoginStateMessage);


                   }else{

                       flushQRCode();

                   }

                   Thread.Sleep(1000);

               }

           });

           th.Start();

       }


  


public String sendLoginConfirm(String url)

       {

         

           req = (HttpWebRequest)WebRequest.Create(url);

           HttpWebResponse response = (HttpWebResponse)req.GetResponse();

           StreamReader php = new StreamReader(response.GetResponseStream(), Encoding.Default);

           return php.ReadToEnd();

       }


 


当我们检测到code不是201 也不是200 那很可能要么没连上 要么取消登录了

这时 我们就可以调用我们写的刷新方法


检测原理其实不难,就是创建新的线程 循环向微信询问用户处于什么状态.然后根据状态进行下一步.


看着很简单,作者很多地方是自己测试出来的,写起来还是不容易,参考其他的教程 其他的教程有很多都是以前是可以的 但是现在不行了 也许是微信改了.


这个本来是想做一个微信机器人的,但是我的微信被限制网页登录了 没法继续进行了,没有被限制的可以尝试做一个,都到这一步了 awa