为什么会写这个?
我本来想用于参加高中(普通高中 编程是自己学的)的一个竞赛,但是由于微信号被微信限制网页登录,所以无法继续进行编写. 于是想写个教程,从头到尾详细的分享给大家制作过程,造福以后想做的人.
效果预览
打开软件,第一步需要你扫码.
描述扫码后,会获取微信号头像,并且显示已扫码,要求在微信确认.
描述当用户登录后,会显示已登录.
一些附加功能: 如果长时间不登录,会提示二维码过期,并且刷新二维码,头像回到默认头像.
一个小菜蛋, 最终也没有用于参赛…
在这里插入图片描述
开始教程:
首先我们要知道,制作一个微信登录软件,对接的其实是微信网页版.
大致步骤为:
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
Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有