zoukankan      html  css  js  c++  java
  • 微信登录原理

    微信机器人原理:
    
    $self->_login()
    $self->_init();
    $self->_get_chatroom();
    $self->_update_chatroom_member();
    $self->update_friend();
    
    
    安装路径:
    /usr/local/share/perl5/Weixin
    
    
    my $client = Weixin::Client->new(debug=>0);
    $client->load("ShowMsg");
    $client->login();
    $client->on_receive_msg = sub{
        my $msg = shift ;
        #打印收到的消息
        $client->call("ShowMsg",$msg);
        #对收到的消息,以相同的内容回复
        #$client->reply_msg($msg,$msg->{Content});
    };
    $client->on_send_msg = sub {
        my ($msg,$is_success,$status) = @_;    
        #打印发送的消息
        $client->call("ShowMsg",$msg);
    };
    $client->run();
    
    
    1.问下 微信的$client->on_receive_msg = sub{
        my $msg = shift ; 这个$msg 最初的来源在哪里的
    最初的接收的消息 
    灰灰(308165330)  10:41:33
    Weixin/Message.pm line 73
    
    Client/Private/_sync.pm  接收消息  异步方式
    
    $self->asyn_http_post()
    $self->http_post()
    异步http请求,阻塞http请求 我封装了这两个
    
    sub asyn_http_get {
        my $self = shift;
        my $callback = pop;
        my $ua = $self->{asyn_ua};
        $ua->get(@_,sub{
            my $response = shift;
            $self->{cookie_jar}->save;
            print $response->content(),"
    " if $self->{debug};
            $callback->($response);
        });
    }
    sub http_post{
        my $self = shift;
        my $ua = $self->{ua};
        my $res = $ua->post(@_);
        $self->{cookie_jar}->save;
        return (defined $res and $res->is_success)?$res->content:undef;
    }
    
    
    Client/Private/_send_text_msg.pm 发送消息
    发异步请求 就是使用 Weixin::UserAgent 这个异步请求的类
    这个异步请求的类 又是封装了 AnyEvent::HTTTP 这个模块 这个模块又是基于AnyEvent的异步来实现http起步请求的
    
    my $client = Weixin::Client->new(debug=>0); 调用Weixin::Client 类的new方法如下,传入参数为debug=>0
    sub new{
        my $class = shift;
        my %p = @_;
        my $agent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062'; 
        my $tmpdir = File::Spec->tmpdir();
        my $cookie_filename = $p{login_file} || "$tmpdir/weixin_client_login.dat";
        my $self = {
            cookie_jar              => HTTP::Cookies->new(hide_cookie2=>1,file=>$cookie_filename,autosave=>1),
            debug                   => $p{debug},
            _token                  => {},
            _watchers               => {},
            _intervals              => {},
            _synccheck_error_count  => 0,
            _synccheck_running      => 0,
            _sync_running           => 0,
            _sync_interval          => 1,
            _synccheck_interval     => 1,
            _send_msg_interval      => 4,
            _last_sync_time         => undef,
            _last_synccheck_time    => undef,
            _send_message_queue     => Weixin::Message::Queue->new,
            _receive_message_queue  => Weixin::Message::Queue->new,       
            _data       => {
                user                => {},  
                friend              => [],
                chatroom            => [],
            },
            on_run                  => undef,
            on_receive_msg          => undef,
            on_send_msg             => undef,
            is_stop                 => 0,
            plugin_num              => 0,
            plugins                 => {},
            ua_retry_times          => 5,
            tmpdir                  => $tmpdir,
            client_version          => $VERSION,
        };
        $self->{ua} = LWP::UserAgent->new(
            cookie_jar      =>  $self->{cookie_jar},
            agent           =>  $agent,
            timeout         =>  300,
            ssl_opts        =>  {verify_hostname => 0},
        );
        $self->{asyn_ua} = Weixin::UserAgent->new(
            cookie_jar  =>  $self->{cookie_jar},
            agent       =>  $agent,
            request_timeout =>  300,
            inactivity_timeout  =>  300,
        );
    
        if($self->{debug}){
            $self->{ua}->add_handler(request_send => sub {
                my($request, $ua, $h) = @_;
                print $request->as_string;
                return;
            });
            $self->{ua}->add_handler(
                response_header => sub { my($response, $ua, $h) = @_;
                print $response->as_string;
                return;
                
            });
            $self->{ua}->add_handler(
                response_done => sub { my($response, $ua, $h) = @_;
                print substr($response->content,0,1000),"
    " if $response->header("content-type")=~/^text/;
                return;
            });
        }
        bless $self,$class;
        $self->prepare();
        return $self;
    }
    
    
    
    登录、获取好友信息等这些http请求是阻塞的,必须等待执行返回
    
    
    接收消息、发送消息这些http请求是异步的 不需要阻塞在那里
    
    
    
    
    这里传入的:
    $class is Weixin::Client
    
    %p is debug0
    
    
    返回的对象:
    $self is ------
    $VAR1 = bless( {
                     'ua' => bless( {
                                      'max_redirect' => 7,
                                      'protocols_forbidden' => undef,
                                      'show_progress' => undef,
                                      'handlers' => {
                                                      'request_prepare' => bless( [
                                                                                    {
                                                                                      'owner' => 'LWP::UserAgent::cookie_jar',
                                                                                      'callback' => sub { "DUMMY" },
                                                                                      'line' => '/usr/share/perl5/LWP/UserAgent.pm:630'
                                                                                    }
                                                                                  ], 'HTTP::Config' ),
                                                      'response_header' => bless( [
                                                                                    {
                                                                                      'owner' => 'LWP::UserAgent::parse_head',
                                                                                      'callback' => sub { "DUMMY" },
                                                                                      'm_media_type' => 'html',
                                                                                      'line' => '/usr/share/perl5/LWP/UserAgent.pm:609'
                                                                                    }
                                                                                  ], 'HTTP::Config' ),
                                                      'response_done' => bless( [
                                                                                  {
                                                                                    'owner' => 'LWP::UserAgent::cookie_jar',
                                                                                    'callback' => sub { "DUMMY" },
                                                                                    'line' => '/usr/share/perl5/LWP/UserAgent.pm:633'
                                                                                  }
                                                                                ], 'HTTP::Config' )
                                                    },
                                      'no_proxy' => [],
                                      'protocols_allowed' => undef,
                                      'use_eval' => 1,
                                      'requests_redirectable' => [
                                                                   'GET',
                                                                   'HEAD'
                                                                 ],
                                      'timeout' => 300,
                                      'cookie_jar' => bless( {
                                                               'autosave' => 1,
                                                               'COOKIES' => {
                                                                              'wx.qq.com' => {
                                                                                               '/' => {
                                                                                                        'wxuin' => [
                                                                                                                     '0',
                                                                                                                     '1284510822',
                                                                                                                     undef,
                                                                                                                     1,
                                                                                                                     '',
                                                                                                                     1452669645,
                                                                                                                     ''
                                                                                                                   ],
                                                                                                        'webwxuvid' => [
                                                                                                                         '0',
                                                                                                                         '9ee169770fb187e18f67d0876923a8c8e8fdf604d9850d7de806072c57af7ed9e9cd9c8adf120369fc1514659d14ec90',
                                                                                                                         undef,
                                                                                                                         1,
                                                                                                                         '',
                                                                                                                         1767754495,
                                                                                                                         ''
                                                                                                                       ],
                                                                                                        'wxloadtime' => [
                                                                                                                          '0',
                                                                                                                          '1452394495_expired',
                                                                                                                          undef,
                                                                                                                          1,
                                                                                                                          '',
                                                                                                                          1452437951,
                                                                                                                          ''
                                                                                                                        ],
                                                                                                        'mm_lang' => [
                                                                                                                       '0',
                                                                                                                       'zh_CN',
                                                                                                                       undef,
                                                                                                                       1,
                                                                                                                       '',
                                                                                                                       1452799407,
                                                                                                                       ''
                                                                                                                     ],
                                                                                                        'wxpluginkey' => [
                                                                                                                           '0',
                                                                                                                           '1452396606',
                                                                                                                           undef,
                                                                                                                           1,
                                                                                                                           '',
                                                                                                                           1452453645,
                                                                                                                           ''
                                                                                                                         ]
                                                                                                      }
                                                                                             }
                                                                            },
                                                               'file' => '/tmp/weixin_client_login.dat',
                                                               'hide_cookie2' => 1
                                                             }, 'HTTP::Cookies' ),
                                      'def_headers' => bless( {
                                                                'user-agent' => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062'
                                                              }, 'HTTP::Headers' ),
                                      'proxy' => {},
                                      'max_size' => undef
                                    }, 'LWP::UserAgent' ),
                     'is_stop' => 0,
                     '_send_message_queue' => bless( {
                                                       'callback_for_get_bak' => sub { "DUMMY" },
                                                       'callback_for_get' => $VAR1->{'_send_message_queue'}{'callback_for_get_bak'},
                                                       'queue' => []
                                                     }, 'Weixin::Message::Queue' ),
                     '_send_msg_interval' => 4,
                     'tmpdir' => '/tmp',
                     'plugins' => {},
                     'on_receive_msg' => undef,
                     '_data' => {
                                  'friend' => [],
                                  'user' => {},
                                  'chatroom' => []
                                },
                     '_last_sync_time' => undef,
                     '_sync_running' => 0,
                     'asyn_ua' => bless( {
                                           'inactivity_timeout' => 300,
                                           'max_redirects' => 5,
                                           'agent' => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062',
                                           'cookie_jar' => $VAR1->{'ua'}{'cookie_jar'},
                                           'request_timeout' => 300
                                         }, 'Weixin::UserAgent' ),
                     '_token' => {},
                     '_last_synccheck_time' => undef,
                     '_synccheck_interval' => 1,
                     'plugin_num' => 0,
                     'on_send_msg' => undef,
                     'debug' => 0,
                     '_watchers' => {},
                     '_synccheck_error_count' => 0,
                     '_intervals' => {},
                     '_receive_message_queue' => bless( {
                                                          'callback_for_get_bak' => sub { "DUMMY" },
                                                          'callback_for_get' => $VAR1->{'_receive_message_queue'}{'callback_for_get_bak'},
                                                          'queue' => []
                                                        }, 'Weixin::Message::Queue' ),
                     '_synccheck_running' => 0,
                     'ua_retry_times' => 5,
                     'on_run' => undef,
                     '_sync_interval' => 1,
                     'cookie_jar' => $VAR1->{'ua'}{'cookie_jar'},
                     'client_version' => '2.0'
                   }, 'Weixin::Client' );
    			   
    			   
    			   
    			   
    			   load 方法:
    			   sub load {
        my $self = shift;
        my @module_name = @_;
        for my $module_name (@module_name){
            my $module_function = undef;
            if(substr($module_name,0,1) eq '+'){
                substr($module_name,0,1) = "";
                $module = $module_name;
            }
    		
    		第一个参数为对象:
    		
    $msg is ------
    $VAR1 = bless( {
                     'ToUin' => 1284510822,
                     'MsgClass' => 'recv',
                     'CreateTime' => 1452758596,
                     'ToNickName' => '我',
                     'FromId' => '@2c33cb9d541cc8e0cd7c5ec018b56cda185aa0174f181f9d4e0136b286035a02',
                     'FromRemarkName' => undef,
                     'ToRemarkName' => undef,
                     'Type' => 'friend_message',
                     'MsgType' => 'text',
                     'FromNickName' => undef,
                     'FromUin' => undef,
                     'Content' => '你也147258369',
                     'TTL' => 5,
                     'ToId' => '@355da879478ba362e808fa906075a50823712e71e19f4a06ceba0ff4c56d238f',
                     'MsgId' => '800096966135914975'
                   }, 'Weixin::Message::Recv' ); 
    			   
    			   
    			   
    			   
    接收消息的类:
    Weixin::Message::Recv 这个类 来自于:
    
    Weixin::Message::Recv
    
    
    jrhmpt01:/usr/local/share/perl5/Weixin# vim Message.pm 
    
    
    sub _mk_ro_accessors {
        my $self = shift;  ### 第一个参数$self对象
        my $msg =shift;    ###
        my $msg_pkg = shift;
        no strict 'refs';
        for my $field (keys %$msg){
            *{__PACKAGE__ . "::${msg_pkg}::$field"} = sub{
                my $obj = shift;
                my $pkg = ref $obj; ##获得类名字
                die "the value of "$field" in $pkg is read-only
    " if @_!=0;
                return $obj->{$field};
            };
        }
        return bless $msg,__PACKAGE__."::$msg_pkg";
    }
    
    这里的当前包是Weixin::Message
    
    
    
    
    1.登录接口:
    https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=4fbNLiMKhA==&tip=0&r=-1570013618&_=1453268946261
    
    微信登录接口:
     my $api = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login';
    
     _login.pm  方法:
    
    package Weixin::Client;
    use Weixin::Client::Private::_get_qrcode_uuid;
    use Weixin::Client::Private::_get_qrcode_image;
    use Weixin::Client::Private::_is_need_login;
    
    1.1获取 uuid
    _get_qrcode_uuid 方法:
    
    https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=1453269277552
    
    响应:
    window.QRLogin.code = 200; window.QRLogin.uuid = "4dyqQzTV_g==";
    			   
    1.2  获取二维码
    
    https://login.weixin.qq.com/qrcode/Ab3x-F9bqw==
    
    返回2维码
    
    1.3
    
    https://wx.qq.com/?&lang=zh_CN
    
    返回帮助信息
    
    
    
    
    2 _init
    
    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-1571406762&lang=zh_CN&pass_ticket=gII3G4F43MHyoE3NXEpQGjnL%252FO4Kh9oT7L9qOJyNBqYicc6NB%252FJzkt%252F0GHZFtdRm
    
    返回群好友信息
    
    3._get_chatroom();
    
    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact?type=ex&r=1453270436253&lang=zh_CN&pass_ticket=gII3G4F43MHyoE3NXEpQGjnL%252FO4Kh9oT7L9qOJyNBqYicc6NB%252FJzkt%252F0GHZFtdRm
    
    返回聊天群及成员
    
    4._update_chatroom_member
    
    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact
    
    
    5._update_friend
    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=gII3G4F43MHyoE3NXEpQGjnL%252FO4Kh9oT7L9qOJyNBqYicc6NB%252FJzkt%252F0GHZFtdRm&r=1453270435381&seq=0&skey=@crypt_597aeefd_52e341350b71c7dae5c660c45c50eb31
    
    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact
    
    
    获取好友信息
    
    3.
    收消息:
    Client/Private/_sync.pm  接收消息  异步方式
    
    sub _sync {
        my $self = shift;
        return if $self->{_synccheck_running} 
    如果 $self->{_synccheck_running} 就直接return 什么也不干
    
    
    my $callback = sub{
            $self->{_sync_running} = 0;
            my $response = shift;
            print $response->content(),"
    " if $self->{debug};
            my $d = $self->json_decode($response->content());
            #return if $d->{BaseResponse}{Ret}!=0;
            $self->_parse_sync_data($d);
    
        };
     my $response = shift;
     
     https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=g+05x/2cwXtfEmV5&skey=@crypt_597aeefd_52e341350b71c7dae5c660c45c50eb31&lang=zh_CN
     
     
     接收消息:
     "AddMsgCount": 1,
    "AddMsgList": [{
    "MsgId": "8442920128804454773",
    "FromUserName": "@78a7a53674f57a5a6070221eeb8fcf706a7aaf965ce2d205b1ec8d76597953c7",
    "ToUserName": "@c2afb19006a336777800351b8f1a5142c5dde8dfd2f68b86b6cb196a76dddac1",
    "MsgType": 1,
    "Content": "kjk7787czcb<br/>",
    
    4.发消息
    _send_text_msg.pm
    
    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg
    
    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN
    
    post 发送消息:
    {"BaseRequest":{"Uin":1284510822,"Sid":"g+05x/2cwXtfEmV5","Skey":"@crypt_597aeefd_52e341350b71c7dae5c660c45c50eb31"
    ,"DeviceID":"e200795958639167"},"Msg":{"Type":1,"Content":"xxxxxxx","FromUserName":"@c2afb19006a336777800351b8f1a5142c5dde8dfd2f68b86b6cb196a76dddac1"
    ,"ToUserName":"@@b866ff46bfe180745fea6a005cfeb9cad0ac90ae8e80acaca7f1553b6e5c3739","LocalID":"14532728152810691"
    ,"ClientMsgId":"14532728152810691"}}
    

  • 相关阅读:
    AFNet3.0上传图片
    最新 AFNetworking 3.0 简单实用封装
    iOS开发密码输入数字和字母混合
    IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)(转)
    iOS开发探索-图片压缩处理
    常用第三方框架插件
    2.1创建直线
    1.4用向导创建Hello,world程序
    vs2008找不到ObjectARX MFC Support
    vc6.0错误:error C2653: 'CCreateEnt' : is not a class or namespace name
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13351078.html
Copyright © 2011-2022 走看看