Web微信

Web微信
 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)

  

 

Web微信

上一篇:使用微信airkiss配置网络出现system:access_denied


下一篇:7663VR竞技平台新品发布会圆满落幕,盘点四大亮点