微信web_微信webapp - CSDN
精华内容
参与话题
  • 微信手机端调试工具[下载地址] ...如果安装调试工具-微信Web开发者工具需要卸载以前安装过的微信Web开发者工具(比如小程序-微信Web开发者工具),建议使用腾讯管家之类的清理干净。2.安装好后,选择移动调试,X5 Blin

    微信手机端调试工具[下载地址]

    (https://mp.weixin.qq.com/wiki/10/e5f772f4521da17fa0d7304f68b97d7e.html)
    进入后的页面
    这里写图片描述
    这里写图片描述

    注意:

    1.如果安装调试工具-微信Web开发者工具需要卸载以前安装过的微信Web开发者工具(比如小程序-微信Web开发者工具),建议使用腾讯管家之类的清理干净。

    2.安装好后,选择移动调试,X5 Blink内核调试,先验证手机是否支持X5 Blink内核调试,如果不支持,找一台支持的手机。
    这里写图片描述
    3.翻墙,用usb线连接移动设备与本机,在手机设置里搜索usb调试,打开usb调试功能,用移动设备扫描以上二维码,勾选信息>TBS setting > 是否打开TBS内核 Inspector调试功能,点击开始调试。
    4.退出微信,从新登录打开微信端的网页后会出现下图(如果未出现,或空白则需要翻墙),点击inspect
    这里写图片描述
    5.现在进入了我们熟悉的chrome调试界面

    这里写图片描述

    展开全文
  • Web微信协议详解

    千次阅读 2017-12-06 19:37:35
    微信web协议分析(微信网页版 wx2.qq.com) 1.打开首页,分配一个随机uuid, 2.根据该uuid获取二维码图片。 3.微信客户端扫描该图片,在客户端确认登录。 4.浏览器不停的调用一个接口,如果返回登录成功,则调用...

    转:http://www.php.cn/weixin-kaifa-361662.html

    Java版实现源码:https://github.com/biezhi/wechat-robot
    Python实现:https://github.com/Urinx/WeixinBot
    C#实现:https://github.com/sherlockchou86/WeChat.NET
    QT实现:https://github.com/xiangzhai/qwx
    Perl实现:https://github.com/sjdy521/Mojo-Weixin
    go实现: https://github.com/songtianyi/wechat-go


    微信web协议分析(微信网页版 wx2.qq.com)

    1.打开首页,分配一个随机uuid,
    2.根据该uuid获取二维码图片。
    3.微信客户端扫描该图片,在客户端确认登录。
    4.浏览器不停的调用一个接口,如果返回登录成功,则调用登录接口
    5.此时可以获取联系人列表,可以发送消息。然后不断调用同步接口。
    6.如果同步接口有返回,则可以获取新消息,然后继续调用同步接口。

    源码地址:github.com/biezhi/wechat-robot

    执行流程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
           +--------------+     +---------------+   +---------------+
           |              |     |               |   |               |
           |   Get UUID   |     |  Get Contact  |   | Status Notify |
           |              |     |               |   |               |
           +-------+------+     +-------^-------+   +-------^-------+
                   |                    |                   |
                   |                    +-------+  +--------+
                   |                            |  |
           +-------v------+               +-----+--+------+      +--------------+
           |              |               |               |      |              |
           |  Get QRCode  |               |  Weixin Init  +------>  Sync Check  <----+
           |              |               |               |      |              |    |
           +-------+------+               +-------^-------+      +-------+------+    |
                   |                              |                      |           |
                   |                              |                      +-----------+
                   |                              |                      |
           +-------v------+               +-------+--------+     +-------v-------+
           |              | Confirm Login |                |     |               |
    +------>    Login     +---------------> New Login Page |     |  Weixin Sync  |
    |      |              |               |                |     |               |
    |      +------+-------+               +----------------+     +---------------+
    |             |
    |QRCode Scaned|
    +-------------+

    WebWechat API

    1. 获取UUID(参考方法 getUUID)

    API 获取 UUID
    url https://login.weixin.qq.com/jslogin
    method GET
    data URL Encode
    params appid : wx782c26e4c19acffb
    fun : new
    lang: zh_CN
    _ : 时间戳

    返回数据(String):

    1
    window.QRLogin.code = 200; window.QRLogin.uuid ="xxx"

    2. 显示二维码(参考方法 showQrCode)

    API 显示二维码
    url login.weixin.qq.com/qrcode/{uuid}
    method POST
    params t : webwx <br/> _ : 时间戳


    3. 等待登录(参考方法 waitForLogin)这里是微信确认登录

    API 二维码扫描登录
    url login.weixin.qq.com/cgi-bin/mmwebwx-bin/login
    method GET
    params tip : 1:未扫描 0:已扫描
    uuid : 获取到的uuid
    _ : 时间戳

    返回数据(String):

    1
    2
    3
    4
    5
    6
    window.code=xxx;
     
    xxx:    408 登陆超时    201 扫描成功    200 确认登录
     
    当返回200时,还会有
    window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=xxx&uuid=xxx&lang=xxx&scan=xxx";

    4. 登录获取Cookie(参考方法 login)

    API webwxnewloginpage
    url wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage
    method GET
    params ticket : xxx
    uuid : xxx
    lang : zh_CN
    scan : xxx
    fun : new

    返回数据(XML):

    1
    2
    3
    4
    5
    6
    7
    8
    <error>
        <ret>0</ret>
        <message>OK</message>
        <skey>xxx</skey>
        <wxsid>xxx</wxsid>
        <wxuin>xxx</wxuin>
        <pass_ticket>xxx</pass_ticket>
        <isgrayscale>1</isgrayscale></error>

    在这一步获取xml中的 skey, wxsid, wxuin, pass_ticket

    5. 微信初始化(参考方法 wxInit)

    API webwxinit
    url wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit
    method POST
    data JSON
    header Content-Type: application/json; charset=UTF-8
    params {
    BaseRequest: {
    Uin: xxx,
    Sid: xxx,
    Skey: xxx,
    DeviceID: xxx,
    }
    }

    返回数据(JSON):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    {
        "BaseResponse": {
            "Ret": 0,
            "ErrMsg": ""
        },
        "Count": 11,
        "ContactList": [...],
        "SyncKey": {
            "Count": 4,
            "List": [
                {
                    "Key": 1,
                    "Val": 635705559
                },
                ...
            ]
        },
        "User": {
            "Uin": xxx,
            "UserName": xxx,
            "NickName": xxx,
            "HeadImgUrl": xxx,
            "RemarkName": "",
            "PYInitial": "",
            "PYQuanPin": "",
            "RemarkPYInitial": "",
            "RemarkPYQuanPin": "",
            "HideInputBarFlag": 0,
            "StarFriend": 0,
            "Sex": 1,
            "Signature": "Apt-get install B",
            "AppAccountFlag": 0,
            "VerifyFlag": 0,
            "ContactFlag": 0,
            "WebWxPluginSwitch": 0,
            "HeadImgFlag": 1,
            "SnsFlag": 17
        },
        "ChatSet": xxx,
        "SKey": xxx,
        "ClientVersion": 369297683,
        "SystemTime": 1453124908,
        "GrayScale": 1,
        "InviteStartCount": 40,
        "MPSubscribeMsgCount": 2,
        "MPSubscribeMsgList": [...],
        "ClickReportInterval": 600000
    }

    这一步中获取 SyncKey, User 后面的消息监听用。

    6. 开启微信状态通知(参考方法 wxStatusNotify)

    API webwxstatusnotify
    url wx2.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify
    method POST
    data JSON
    header Content-Type: application/json; charset=UTF-8
    params {
    BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx },
    Code: 3,
    FromUserName: 自己的ID,
    ToUserName: 自己的ID,
    ClientMsgId: 时间戳
    }

    返回数据(JSON):

    1
    2
    3
    4
    5
    6
    7
    {
        "BaseResponse": {
            "Ret": 0,
            "ErrMsg": ""
        },
        ...
    }

    7. 获取联系人列表(参考方法 getContact)

    API webwxgetcontact
    url wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact
    method POST
    data JSON
    header ContentType: application/json; charset=UTF-8
    params {
    BaseRequest: {
    Uin: xxx,
    Sid: xxx,
    Skey: xxx,
    DeviceID: xxx,
    }
    }

    返回数据(JSON):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    {
        "BaseResponse": {
            "Ret": 0,
            "ErrMsg": ""
        },
        "MemberCount": 334,
        "MemberList": [
            {
                "Uin": 0,
                "UserName": xxx,
                "NickName": "Urinx",
                "HeadImgUrl": xxx,
                "ContactFlag": 3,
                "MemberCount": 0,
                "MemberList": [],
                "RemarkName": "",
                "HideInputBarFlag": 0,
                "Sex": 0,
                "Signature": "我是二蛋",
                "VerifyFlag": 8,
                "OwnerUin": 0,
                "PYInitial": "URINX",
                "PYQuanPin": "Urinx",
                "RemarkPYInitial": "",
                "RemarkPYQuanPin": "",
                "StarFriend": 0,
                "AppAccountFlag": 0,
                "Statues": 0,
                "AttrStatus": 0,
                "Province": "",
                "City": "",
                "Alias": "Urinxs",
                "SnsFlag": 0,
                "UniFriend": 0,
                "DisplayName": "",
                "ChatRoomId": 0,
                "KeyWord": "gh_",
                "EncryChatRoomId": ""
            },
            ...
        ],
        "Seq": 0
    }

    8.消息检查(参考方法 syncCheck)

    API synccheck
    url webpush2.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck
    method GET
    data JSON
    header ContentType: application/json; charset=UTF-8
    params {
    BaseRequest: {
    Uin: xxx,
    Sid: xxx,
    Skey: xxx,
    DeviceID: xxx,
    }
    }

    返回数据(String):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    window.synccheck={retcode:"xxx",selector:"xxx"}
     
    retcode:
        0 正常
        1100 失败/登出微信
    selector:
        0 正常
        2 新的消息
        7 进入/离开聊天界面

    9. 获取最新消息(参考方法 webwxsync)

    API webwxsync
    url wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=xxx&skey=xxx&pass_ticket=xxx
    method POST
    data JSON
    header ContentType: application/json; charset=UTF-8
    params {
    BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx },
    SyncKey: xxx,
    rr: 时间戳取反
    }

    返回数据(JSON):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    {
        'BaseResponse': {'ErrMsg': '', 'Ret': 0},
        'SyncKey': {
            'Count': 7,
            'List': [
                {'Val': 636214192, 'Key': 1},
                ...
            ]
        },
        'ContinueFlag': 0,
        'AddMsgCount': 1,
        'AddMsgList': [
            {
                'FromUserName': '',
                'PlayLength': 0,
                'RecommendInfo': {...},
                'Content': "",
                'StatusNotifyUserName': '',
                'StatusNotifyCode': 5,
                'Status': 3,
                'VoiceLength': 0,
                'ToUserName': '',
                'ForwardFlag': 0,
                'AppMsgType': 0,
                'AppInfo': {'Type': 0, 'AppID': ''},
                'Url': '',
                'ImgStatus': 1,
                'MsgType': 51,
                'ImgHeight': 0,
                'MediaId': '',
                'FileName': '',
                'FileSize': '',
                ...
            },
            ...
        ],
        'ModChatRoomMemberCount': 0,
        'ModContactList': [],
        'DelContactList': [],
        'ModChatRoomMemberList': [],
        'DelContactCount': 0,
        ...
    }

    10. 发送消息(参考方法 webwxsendmsg)

    API webwxsendmsg
    url wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket=xxx
    method POST
    data JSON
    header ContentType: application/json; charset=UTF-8
    params {
    BaseRequest: { Uin: xxx, Sid: xxx, Skey: xxx, DeviceID: xxx },
    Msg: {
    Type: 1 文字消息,
    Content: 要发送的消息,
    FromUserName: 自己的ID,
    ToUserName: 好友的ID,
    LocalID: 与clientMsgId相同,
    ClientMsgId: 时间戳左移4位随后补上4位随机数
    }
    }

    返回数据(JSON):

    1
    2
    3
    4
    5
    6
    7
    {
        "BaseResponse": {
            "Ret": 0,
            "ErrMsg":""
        },
        ...
    }

    更多资料:
    github.com/xiangzhai/qwx
    github.com/Urinx/WeixinBot
    www.07net01.com/2016/01/1201188.html
    www.cnblogs.com/xiaozhi_5638/p/4923811.html

    展开全文
  • Web微信

    2019-07-10 08:15:06
    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 │ ...10 │ │ modules.x...
     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 }}" alt="">
    <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 }}" alt="">
            <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 }}" alt="">
        <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)
    

      

     

    转载于:https://www.cnblogs.com/standby/p/7739797.html

    展开全文
  • 微信web开发者工具简介

    万次阅读 2016-10-03 00:12:51
    微信web开发者工具 为帮助开发者更方便、更安全地开发和调试基于微信的网页,我们推出了 web 开发者工具。它是一个桌面应用,通过模拟微信客户端的表现,使得开发者可以使用这个工具方便地在 PC 或者 Mac 上进行开发...

    微信web开发者工具

    为帮助开发者更方便、更安全地开发和调试基于微信的网页,我们推出了 web 开发者工具。它是一个桌面应用,通过模拟微信客户端的表现,使得开发者可以使用这个工具方便地在 PC 或者 Mac 上进行开发和调试工作。

    下载地址

    https://mp.weixin.qq.com/wiki/10/e5f772f4521da17fa0d7304f68b97d7e.html#.E4.B8.8B.E8.BD.BD.E5.9C.B0.E5.9D.80

    该工具界面主要由几大部分组成,如下图所示:


    顶部菜单栏是刷新、后退、选中地址栏等动作的统一入口,以及微信客户端版本的模拟设置页。左侧是微信的 webview 模拟器,可以直接操作网页,模拟用户真实行为。右侧上方是地址栏,用于输入待调试的页面链接,以及清除缓存按钮。右侧下方是相关的请求和返回结果,以及调试界面和登录按钮。 为了保证开发者身份信息的安全,对于希望调试的公众号,我们要求开发者微信号与之建立绑定关系。具体操作为:公众号登录管理后台,启用开发者中心,在开发者工具——web 开发者工具页面,向开发者微信号发送绑定邀请。


    此时输入url,只能在微信客户端显示的页面这里也可以看到效果。



    可以看到有输出信息,非常方便。不用使用微信手机客户端来访问页面。

    展开全文
  • 如何开发一个个性化的Web微信(1)

    千次阅读 2018-09-14 18:13:04
    Web微信登录 github地址:https://github.com/hty7/vue-wechat 如有不足与错误,请见谅 Web微信主要参考Web微信协议进行设计开发 项目主要分成三大模块 登录模块:微信扫码登录流程 微信容器:微信...
  • web 网页登录 微信授权

    千次阅读 2018-11-30 08:32:59
    接口步骤: https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&amp;t=resource/res_list&amp;verify=1&amp;id=open1419316505&amp;token=&amp;lang=zh_CN ...
  • 微信web协议分析

    万次阅读 2016-11-16 19:03:55
    微信web协议分析和实现微信机器人(微信网页版 wx2.qq.com) 1.打开首页,分配一个随机uuid, 2.根据该uuid获取二维码图片。 3.微信客户端扫描该图片,在客户端确认登录。 4.浏览器不停的调用一个接口,如果返回...
  • 微信web版接口api

    2019-11-08 18:16:17
    安卓微信的api,个人微信开发API协议,微信 ipad sdk,微信ipad协议,微信web版接口api,微信网页版接口,微信电脑版sdk,微信开发sdk,微信开发API,微信协议,微信接口文档sdk,替代微信ipad协议的api接口,网页...
  • 背景:使用微信web开发者工具进行移动调试,按照 配置网络代理后,如图: 当重启微信后,发现公共号上不去了,也不能正常的上网了 可以将服务器地址更改为: 去掉http://后再尝试,就可以了,然后...
  • 微信网页版无法登录

    万次阅读 热门讨论 2018-05-15 10:46:16
    为了你的帐号安全,暂时不能登录web微信。你可以通过Windows微信、Mac微信或者手机客户端微信登录导致微信无法登录解决方法:清除浏览器的history然后重新登录就可以了不过发现这个方法在每次登录前都要执行,否则...
  • 小程序web-view使用方法是子恒老师《子恒说小程序开发》视频...详细讲解了小程序web-view组件的使用,内容包含web view打开网页,网页与小程序之间的跳转,在web view中实现微信支付等等。欢迎反馈,微信号:QQ68183131
  • 微信web开发者工具无法打开的解决方法

    万次阅读 热门讨论 2017-09-09 16:14:28
    安装了之后,除了刚安装完可以自动打开后续无论是用快捷方式,还是跑到文件目录里,都无法打开这个磨人的小家伙其实解决这个问题很简单,只需要使用你的管理员权限便可轻松打开微信Web开发者工具。 1、第一步,右键...
  • 微信web开发者工具 移动调试

    万次阅读 2018-06-13 10:03:16
    1 下载 微信web开发者工具:https://mp.weixin.qq.com/wiki?t=resource/res_main&...3 打开微信web开发者工具 ,选择如下图PS:我使用了很多手机,小米max ,iphoneX,小米5sp等等。。。没有一个能使用 X5Blin...
  • 微信web开发者工具的使用

    万次阅读 2016-03-22 23:10:48
    2016年初微信发布微信web开发者工具,可以在PC或Mac上模拟访问微信内网页,帮助开发者更方便地进行开发和调试 1、上一篇文章微信企业号jssdk拍照http://blog.csdn.net/u014520797/article/details/50890513也可以...
  • 不要用百度分享等分享工具,这样做的目的是为了能自定义分享按钮的样式。类似于36kr 的分享到微信的功能,点击按钮,弹出该文章的二维码。 研究了蛮久,没懂 求高人指教!
  • 我做的web app,相当于手机端的网页,可以直接用微信授权登录吗?如果可以怎么实现呢,给个思路好嘛
  • 网页版微信登录异常 解决方法: 清理下当前浏览器的历史记录、缓存和cookie应该就可以了。
  • http://www.jiathis.com/ 打开以上网页,将代码复制到你的页面中,即可 优点:使用方便 缺点:无法做统计
  • 1.首先下载web微信开发者工具:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 2.安装:点击下一步   点击我接受 选择路径 等待程序安装成功就可以了 运行查看程序是否能...
  • 今天遇到一个问题,开发微信公众号和小程序的微信web开发者工具,突然打不开了,无论怎么点击,怎么重启电脑都打不开,昨天都好好的,今天上班就出问题了。 刚刚解决,现在把解决办法附上,希望对大家有帮助: ...
1 2 3 4 5 ... 20
收藏数 135,404
精华内容 54,161
关键字:

微信web