1 D:\soft\work\Python_17\day23\weixin>tree /F 2 卷 NewDisk 的文件夹 PATH 列表 3 卷序列号为 2E8B-8205 4 D:. 5 │ db.sqlite3 6 │ manage.py 7 │ 8 ├─.idea 9 │ │ misc.xml 10 │ │ modules.xml 11 │ │ weixin.iml 12 │ │ workspace.xml 13 │ │ 14 │ └─inspectionProfiles 15 │ profiles_settings.xml 16 │ 17 ├─statics 18 │ ├─css 19 │ │ bbs.css 20 │ │ bootstrap-select.min.css 21 │ │ bootstrap-theme.css 22 │ │ bootstrap-theme.css.map 23 │ │ bootstrap-theme.min.css 24 │ │ bootstrap-theme.min.css.map 25 │ │ bootstrap.css 26 │ │ bootstrap.css.map 27 │ │ bootstrap.min.css 28 │ │ bootstrap.min.css.map 29 │ │ bootstrapValidator.min.css 30 │ │ 31 │ ├─fonts 32 │ │ glyphicons-halflings-regular.eot 33 │ │ glyphicons-halflings-regular.svg 34 │ │ glyphicons-halflings-regular.ttf 35 │ │ glyphicons-halflings-regular.woff 36 │ │ glyphicons-halflings-regular.woff2 37 │ │ 38 │ └─js 39 │ bootstrap-select.js.map 40 │ bootstrap-select.min.js 41 │ bootstrap.js 42 │ bootstrap.min.js 43 │ bootstrapValidator.min.js 44 │ city_info.js 45 │ jquery-3.2.1.js 46 │ jquery-3.2.1.min.js 47 │ jquery.cookie.js 48 │ npm.js 49 │ 50 ├─templates 51 │ contactList.html 52 │ index.html 53 │ login.html 54 │ 55 ├─utils 56 │ │ get_sync_key.py 57 │ │ myResponse.py 58 │ │ 59 │ └─__pycache__ 60 │ get_sync_key.cpython-35.pyc 61 │ myResponse.cpython-35.pyc 62 │ 63 ├─wechat 64 │ │ admin.py 65 │ │ apps.py 66 │ │ demo.py 67 │ │ models.py 68 │ │ tests.py 69 │ │ views.py 70 │ │ __init__.py 71 │ │ 72 │ ├─migrations 73 │ │ │ __init__.py 74 │ │ │ 75 │ │ └─__pycache__ 76 │ │ __init__.cpython-35.pyc 77 │ │ 78 │ └─__pycache__ 79 │ admin.cpython-35.pyc 80 │ apps.cpython-35.pyc 81 │ models.cpython-35.pyc 82 │ views.cpython-35.pyc 83 │ __init__.cpython-35.pyc 84 │ 85 └─weixin 86 │ settings.py 87 │ urls.py 88 │ wsgi.py 89 │ __init__.py 90 │ 91 └─__pycache__ 92 settings.cpython-35.pyc 93 urls.cpython-35.pyc 94 wsgi.cpython-35.pyc 95 __init__.cpython-35.pyc 96 97 98 D:\soft\work\Python_17\day23\weixin>
# login.html {% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <img id="wx_pic" src="{{ img_url }}" style="height: 200px; width: 200px"> </div> <script src="{% static "js/jquery-3.2.1.js" %}"></script> <script> $(function () { checkLogin(); }); function checkLogin() { TIP = 0; console.log("checkLogin ... "); $.ajax({ url: ‘/loginCheck.htm‘, type: ‘GET‘, data: {‘tip‘:TIP}, success:function (data) { var data=JSON.parse(data); if(‘201‘ == data.code){ $("#wx_pic").attr(‘src‘,data.data); checkLogin(); {# tip=0;#} } else if(‘200‘ == data.code){ location.href = ‘/index.htm‘; } else { console.log(">>> "+data.code); checkLogin(); } console.log(typeof data); console.log(data); } }) } </script> </body> </html>
# index.html {% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>个人信息</h3> <img src="/showAvatar.htm?img={{ init_dict.User.HeadImgUrl }}" > <ul> <li>{{ init_dict.User.NickName }}</li> <li>{{ init_dict.User.UserName }}</li> <li>{{ init_dict.User.Signature }}</li> </ul> <h3>最近联系人列表</h3> <ul> {% for item in init_dict.ContactList %} <img src="/showAvatar.htm?img={{ item.HeadImgUrl }}" > <li>{{ item.NickName }}</li> <li>{{ item.UserName }}</li> <li>{{ item.Signature }}</li> {% endfor %} <li><a href="/contactList.htm">查看所有联系人</a></li> </ul> <script src="{% static "js/jquery-3.2.1.js" %}"></script> <script> </script> </body> </html>
# contactList.html {% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="{% static "css/bootstrap.css" %}"> <script src="{% static "js/bootstrap.js" %}"></script> </head> <body> <h3>发送消息...</h3> {% csrf_token %} <div class="input-group"> <span class="input-group-addon" id="sizing-addon2">发送给谁</span> <input type="text" class="form-control" placeholder="请输入对方的id" aria-describedby="sizing-addon2" id="to_user"> </div> <div class="input-group"> <span class="input-group-addon" id="sizing-addon2">消息内容</span> <input type="text" class="form-control" placeholder="请输入要发送的内容" aria-describedby="sizing-addon2" id="msg"> </div> <button id="btn" type="button" class="btn btn-success">发送</button> <button id="logout" type="button" class="btn btn-info">退出登录</button> <div class="private"> <h3>个人信息</h3> <img src="/showAvatar.htm?img={{ init_dict.User.HeadImgUrl }}" > <ul> <li>{{ init_dict.User.NickName }}</li> <li>{{ init_dict.User.UserName }}</li> <li>{{ init_dict.User.Signature }}</li> </ul> </div> <div class="contactList"> <h3>联系人列表</h3> <ul> {% for user in contact_list_dict.MemberList %} <li>{{ user.UserName }}</li> <li>{{ user.NickName }}</li> <li>{{ user.RemarkName }}</li> <li>{{ user.Signature }}</li> <ul> <li>{{ user.Province }}</li> <li>{{ user.City }}</li> </ul> {% endfor %} </ul> </div> <script src="{% static "js/jquery-3.2.1.js" %}"></script> <script src="{% static "js/jquery.cookie.js" %}"></script> <script> $(function () { getMsg(); bindBtnEvent(); bindLogoutEvent(); }); function bindBtnEvent() { $("#btn").click(function () { $.ajax({ url:‘/sendMsg.htm‘, type:‘POST‘, data:{‘to_user‘:$("#to_user").val(),‘msg‘:$("#msg").val()}, headers:{‘X-CSRFToken‘: $.cookie(‘csrftoken‘)}, success:function (res) { var data=JSON.parse(res); if(0 == data.BaseResponse.Ret){ alert("消息发送成功!"); }else { alert("消息发送失败:" + data.BaseResponse.ErrMsg); } }, error:function (res) { console.log("[[ bindBtnEvent ]] raise err..." + res) } }) }) } function getMsg() { $.ajax({ url:‘/syncCheck.htm‘, type:‘GET‘, success:function (res) { var data=JSON.parse(res); if(data.AddMsgCount > 0){ alert(data.AddMsgList); for(var i=0; i<data.AddMsgCount; i++) { alert("收到 " + data.AddMsgList[i].FromUserName + " 的新消息:" + data.AddMsgList[i].Content); } } getMsg(); }, error:function (res) { console.log("[[ getMsg ]] raise err..." + res); getMsg(); } }) } function bindLogoutEvent() { $("#logout").click(function () { $.ajax({ url:‘/logout.htm‘, type:‘GET‘, success:function (arg) { } }) }) } </script> </body> </html>
# urls.py from django.conf.urls import url from django.contrib import admin from wechat import views urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^login.htm$‘, views.login), url(r‘^loginCheck.htm$‘, views.loginCheck), url(r‘^index.htm$‘, views.index), url(r‘^showAvatar.htm$‘, views.showAvatar), url(r‘^contactList.htm$‘, views.contactList), url(r‘^sendMsg.htm$‘, views.sendMsg), url(r‘^syncCheck.htm$‘, views.syncCheck), url(r‘^logout.htm$‘, views.logout), ]
# views.py from django.shortcuts import render,HttpResponse,redirect import re import time import json import requests from bs4 import BeautifulSoup from utils.myResponse import BaseResponse from utils.get_sync_key import get_sync_key """ 微信网页版登录示例 GET 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&_=1508052025433 得到响应: window.QRLogin.code = 200; window.QRLogin.uuid = "IapQqsoqcA=="; 二维码src https://login.weixin.qq.com/qrcode/IapQqsoqcA== 长轮询: https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=IapQqsoqcA==&tip=0&r=-518626217&_=1508052025438 """ def login(req): ctime = time.time() * 1000 qrcode_url = "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&_={}".format(ctime) rsp1 = requests.get(url=qrcode_url) qrcode = re.findall(‘.uuid = "(.*)";‘, rsp1.text)[0] img_url = "https://login.weixin.qq.com/qrcode/{}".format(qrcode) req.session[‘qrcode‘] = qrcode req.session[‘ctime‘] = ctime return render(req,‘login.html‘,{‘img_url‘:img_url}) def get_pass_ticket(html): soup = BeautifulSoup(html, ‘html.parser‘) ret = {} for tag in soup.find(name=‘error‘).find_all(): ret[tag.name] = tag.text return ret def loginCheck(req): """ 判断是否扫码;扫码之后立即进入下一次长轮询,等待用户点击确认登录 window.code=408; 未扫码 window.code=201; 已扫码 window.userAvatar = ‘data:img/jpg;base64,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‘; window.code=200; 已确认登录 window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AZ3EYrgZt_xzrpgpevpgZdnN@qrticket_0&uuid=ochHx1cRew==&lang=zh_CN&scan=1508341438"; :param req: :return: """ res = BaseResponse() qrcode = req.session.get(‘qrcode‘) ctime = time.time()*1000 tip = req.GET.get("tip") tip = tip if tip else 0 print(qrcode, tip, ctime) url = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip={1}&r=-716232763&_={2}".format(qrcode,tip,ctime) rsp2 = requests.get(url=url) res.status = rsp2.status_code res.code = re.findall(".code=(\d+).",rsp2.text)[0] if ‘201‘ == res.code: avatar_str = re.findall("userAvatar = ‘(.*)‘.",rsp2.text)[0] res.data = avatar_str if avatar_str else "" elif ‘200‘ == res.code: # 记录用户点击登录时候获得的cookies req.session[‘LOGIN_COOKIES‘] = rsp2.cookies.get_dict() # 获取 redirect_uri redirect_uri = re.findall(‘redirect_uri="(.*)";‘, rsp2.text)[0] redirect_uri = redirect_uri + "&fun=new&version=v2" # 获取凭证 rsp3 = requests.get(url=redirect_uri) ticket_dict = get_pass_ticket(rsp3.text) # 记录请求redirect_uri之后获取的 TICKET_DITC 以及 相应cookies req.session[‘TICKET_DITC‘] = ticket_dict req.session[‘TICKET_COOKIES‘] = rsp3.cookies.get_dict() res.data = rsp3.text else: res.data = rsp2.text print(res.dict_info) return HttpResponse(json.dumps(res.dict_info)) def index(req): if not req.session.get(‘TICKET_DITC‘): return redirect(‘/login.htm‘) ticket_dict = req.session.get(‘TICKET_DITC‘) # 获取完TICKET_DITC之后开始获取最近联系人列表并初始化 init_params_dict = { ‘BaseRequest‘: { ‘DeviceID‘: "e553172362037361", ‘Sid‘: ticket_dict[‘wxsid‘], ‘Skey‘: ticket_dict[‘skey‘], ‘Uin‘: ticket_dict[‘wxuin‘] } } url_post = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-809803709&pass_ticket={}".format(ticket_dict.get(‘pass_ticket‘)) rsp4 = requests.post(url=url_post, json=init_params_dict) rsp4.encoding=‘utf-8‘ # 避免出现中文乱码 print(">>>>>>>> ", rsp4.text) # 记录初始化之后获取的cookies req.session[‘INIT_COOKIES‘] = rsp4.cookies.get_dict() init_dict = json.loads(rsp4.text) sync_key = init_dict.pop(‘SyncKey‘) # sync_key 用于在后面发送消息 # 记录拿到的初始化信息,后面需要展示在页面上,所以先存储在session里 req.session[‘init_dict‘] = init_dict req.session[‘sync_key‘] = sync_key return render(req,‘index.html‘,{‘init_dict‘:init_dict}) def showAvatar(req): # 整合cookies all_cookies = {} LOGIN_COOKIES = req.session.get(‘LOGIN_COOKIES‘) TICKET_COOKIES = req.session.get(‘TICKET_COOKIES‘) INIT_COOKIES = req.session.get(‘INIT_COOKIES‘) all_cookies.update(LOGIN_COOKIES) all_cookies.update(TICKET_COOKIES) all_cookies.update(INIT_COOKIES) # 获取前端传过来的头像参数并拼接头像url img_prefix = req.GET.get(‘img‘) # /cgi-bin/mmwebwx-bin/webwxgeticon?seq=1576406163 username = req.GET.get(‘username‘) # @c1c38ffccbf118f6f62a023364f624c1bf683d3dc4432ad0203520b5f63f2742 skey = req.GET.get(‘skey‘) # @crypt_af096eac_6563c98d6143e21bcd2911bfdb3c2c50 avatar_url = "https://wx.qq.com{0}&username={1}&skey={2}".format(img_prefix,username,skey) rsp = requests.get(url=avatar_url,cookies=all_cookies) return HttpResponse(rsp.content) def contactList(req): # 整合cookies all_cookies = {} LOGIN_COOKIES = req.session.get(‘LOGIN_COOKIES‘) TICKET_COOKIES = req.session.get(‘TICKET_COOKIES‘) INIT_COOKIES = req.session.get(‘INIT_COOKIES‘) all_cookies.update(LOGIN_COOKIES) all_cookies.update(TICKET_COOKIES) all_cookies.update(INIT_COOKIES) ctime = time.time() TICKET_DITC = req.session.get(‘TICKET_DITC‘) pass_ticket = TICKET_DITC.get(‘pass_ticket‘) skey = TICKET_DITC.get(‘skey‘) url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket={0}&r={1}&seq=0&skey={2}".format(pass_ticket,ctime,skey) rsp = requests.get(url=url,cookies=all_cookies) rsp.encoding = ‘utf-8‘ # 避免出现中文乱码 contact_list_dict = json.loads(rsp.text) print(">>>>>>>>>>>>>>>>>\n", contact_list_dict) # 把所有联系人信息存储到session里 req.session[‘contact_list_dict‘] = contact_list_dict init_dict = req.session.get(‘init_dict‘) return render(req,‘contactList.html‘,{‘contact_list_dict‘:contact_list_dict,‘init_dict‘:init_dict}) def sendMsg(req): ctime = time.time() * 1000 to_user = req.POST.get(‘to_user‘) msg = req.POST.get(‘msg‘) from_user = req.session.get(‘init_dict‘).get(‘User‘).get(‘UserName‘) print("++++++++++++++++++++++++++++++++++") print(to_user,msg) ticket_dict = req.session.get(‘TICKET_DITC‘) pass_ticket = ticket_dict.get(‘pass_ticket‘) send_msg_url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket={0}".format(pass_ticket) msg_dict = { ‘BaseRequest‘:{ ‘DeviceID‘: "e553172362037361", ‘Sid‘: ticket_dict[‘wxsid‘], ‘Skey‘: ticket_dict[‘skey‘], ‘Uin‘: ticket_dict[‘wxuin‘] }, ‘Msg‘:{ ‘ClientMsgId‘:ctime, ‘Content‘:msg, ‘FromUserName‘:from_user, ‘LocalID‘:ctime, ‘ToUserName‘:to_user, ‘Type‘:1 }, ‘Scene‘:0 } # 整合cookies all_cookies = {} LOGIN_COOKIES = req.session.get(‘LOGIN_COOKIES‘) TICKET_COOKIES = req.session.get(‘TICKET_COOKIES‘) INIT_COOKIES = req.session.get(‘INIT_COOKIES‘) all_cookies.update(LOGIN_COOKIES) all_cookies.update(TICKET_COOKIES) all_cookies.update(INIT_COOKIES) # 下面这种方式发送会出现中文乱码: # rsp = requests.post(url=send_msg_url, json=msg_dict, cookies=all_cookies) """ json序列化的时候是可以加参数的: data = { ‘name‘:‘alex‘, ‘msg‘:‘中文asa‘ } import json print(json.dumps(data)) 按Unicode显示: {"msg": "\u4e2d\u6587asa", "name": "alex"} print(json.dumps(data,ensure_ascii=False)) 按中文显示: {"msg": "中文asa", "name": "alex"} json.dumps() 之后是字符串 requests.post() 默认是按照 latin-1 编码,不支持中文 所以改成直接发bytes: requests.post(data=json.dumps(data,ensure_ascii=False).encode(‘utf-8‘)) """ rsp = requests.post( url=send_msg_url, data=json.dumps(msg_dict,ensure_ascii=False).encode(‘utf-8‘), headers={‘Content-Type‘:‘application/json; charset=utf-8‘}, cookies=all_cookies ) rsp.encoding = ‘utf-8‘ # 避免出现中文乱码 ret_dict = json.loads(rsp.text) # 将字符串转换成字典对象,这样前端接收的时候就能使用 xx.xx 形式进行取值了 return HttpResponse(json.dumps(ret_dict)) def syncCheck(req): # 整合cookies all_cookies = {} LOGIN_COOKIES = req.session.get(‘LOGIN_COOKIES‘) TICKET_COOKIES = req.session.get(‘TICKET_COOKIES‘) INIT_COOKIES = req.session.get(‘INIT_COOKIES‘) all_cookies.update(LOGIN_COOKIES) all_cookies.update(TICKET_COOKIES) all_cookies.update(INIT_COOKIES) ctime = time.time() * 1000 ticket_dict = req.session.get(‘TICKET_DITC‘) pass_ticket = ticket_dict.get(‘pass_ticket‘) sync_key = req.session.get(‘sync_key‘) sync_check_url = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck" params = { ‘r‘:ctime, ‘skey‘:ticket_dict.get(‘skey‘), ‘sid‘:ticket_dict.get(‘wxsid‘), ‘uin‘:ticket_dict.get(‘wxuin‘), ‘deviceid‘:‘e553172362037361‘, ‘synckey‘:get_sync_key(sync_key) } # 检测是否有新消息到来 rsp = requests.get(url=sync_check_url,params=params,cookies=all_cookies) print(rsp.text) # 去服务器端取回新消息 if ‘window.synccheck={retcode:"0",selector:"2"}‘ in rsp.text: data = { ‘BaseRequest‘:{ ‘DeviceID‘: "e553172362037361", ‘Sid‘: ticket_dict[‘wxsid‘], ‘Skey‘: ticket_dict[‘wxsid‘], ‘Uin‘: ticket_dict[‘wxuin‘] }, ‘SyncKey‘:sync_key, ‘rr‘:‘-1324973514‘ } sync_msg_url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid={0}&skey={1}&pass_ticket={2}".format(ticket_dict[‘wxsid‘],ticket_dict[‘wxsid‘],pass_ticket) msg_res = requests.post(url=sync_msg_url,json=data,cookies=all_cookies) msg_res.encoding = ‘utf-8‘ msg_res_dict = json.loads(msg_res.text) # 将字符串转换成字典对象,这样前端接收的时候就能使用 xx.xx 形式进行取值了 new_sync_key = msg_res_dict.get(‘SyncKey‘) # 每次同步完新消息后,sync_key都会更新,所以每次记得重新获取并存储到session里 req.session[‘sync_key‘] = new_sync_key for msg in msg_res_dict.get(‘AddMsgList‘): print(msg.get(‘FromUserName‘),msg.get(‘CreateTime‘),msg.get(‘Content‘)) return HttpResponse(json.dumps(msg_res_dict)) else: return HttpResponse(json.dumps({‘AddMsgCount‘:0,‘AddMsgList‘:None})) def logout(req): print("ByeBye...") req.session.clear() return redirect(‘/login.htm‘)
# get_sync_key.py def get_sync_key(sync_key): sync_key_list = [] for item in sync_key.get(‘List‘): tmp = "%s_%s" % (item.get(‘Key‘),item.get(‘Val‘)) sync_key_list.append(tmp) return "|".join(sync_key_list)
# myResponse.py class BaseResponse(object): def __init__(self): self.status = None self.code = None self.data = None @property def dict_info(self): return self.__dict__ class LikeResponse(BaseResponse): def __init__(self): self.msg = None super(LikeResponse, self).__init__() if __name__ == ‘__main__‘: like = LikeResponse() print(like.dict_info)