微信扫描登录

[复制链接]
发表于 2014-2-2 21:55:19 | 显示全部楼层 |阅读模式
用户通过扫描网页提供的二维码实现登陆信息获取 ; [; \' Y! q0 z) E. s
  1. <?php
    / B5 H9 s3 Q* \7 \+ D+ Z0 s: T
  2. /**
    2 v7 J+ G6 u& }/ x
  3. *  微信公众平台PHP-SDK6 K* J/ h6 z: ~4 W. j# V: ^0 I
  4. *  Wechatauth为非官方微信登陆API( S9 c+ D0 P' ], U
  5. *  用户通过扫描网页提供的二维码实现登陆信息获取8 H, P& s$ g6 y
  6. *  主要实现如下功能:0 Z9 I" `4 E& t  h
  7. *  get_login_code() 获取登陆授权码, 通过授权码才能获取二维码
    % `& g/ b. z# J3 I# ]# H" w. C
  8. *  get_code_image($code='') 将上面获取的授权码转换为图片二维码
    7 i- D- D" B2 J2 \
  9. *  verify_code() 鉴定是否登陆成功,返回200为最终授权成功.# v5 K+ B7 D6 w
  10. *  get_login_cookie() 鉴定成功后调用此方法即可获取用户基本信息
    3 c3 x. m, s/ J2 M1 z- w
  11. *  sendNews($account,$title,$summary,$content,$pic,$srcurl='') 向一个微信账户发送图文信息
    ; o. r( t$ M+ q$ z/ M" Y
  12. *  get_avatar($url) 获取用户头像图片数据
    6 W7 g3 h, T+ p3 e
  13. *  @author dodge <dodgepudding@gmail.com>" _4 W3 P" }0 M* t: z! S% k0 k
  14. *  @link https://github.com/dodgepudding/wechat-php-sdk
    9 g, j  P, O+ X1 |) l2 N
  15. *  @version 1.1
    ! j+ }" ?+ |, j' q2 }# R+ e; i
  16. *  
    / I: d; X. X( Z5 a7 h
  17. */( Y2 Q" x3 r0 w/ V, @2 m+ U
  18. include "snoopy.class.php";
    4 X0 }0 L4 m  Q" F* [4 X. Q- i
  19. class Wechatauth
    ; b, }+ Z4 S: g! V/ P
  20. {) d2 r) R/ R$ O9 L" k6 {
  21.         private $cookie;  P3 D3 J: r& M4 g
  22.         private $_cookiename;  ~% e- a: {2 b- {2 H1 h' a
  23.         private $_cookieexpired = 3600;! S8 _( C3 U: S
  24.         private $_account = 'test';( Z- `: A# `4 A1 o  L7 k
  25.         private $_datapath = './data/cookie_';
    # \8 B6 s& \  C2 M; y7 O
  26.         private $debug;
    3 B: k5 s  Q$ K, c
  27.         private $_logcallback;
    + w5 j! L# l; Y3 W! ?- M  I
  28.         public $login_user; //当前登陆用户, 调用get_login_info后获取
    ( Y+ ?- `; v( T! n1 F) }
  29.         
    7 B, F7 {. U4 d
  30.         public function __construct($options)
    2 Y. n  k" a0 X% }  Z
  31.         {" x3 G  M3 W7 ^# x' {: }. H$ b
  32.                 $this->_account = isset($options['account'])?$options['account']:'';; m$ @- M; \3 w4 h8 [
  33.                 $this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;
    8 ^% W1 d+ L8 T' y! M
  34.                 $this->debug = isset($options['debug'])?$options['debug']:false;& _8 v% E2 i7 h% E& j( ?! O
  35.                 $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;
      \0 W1 g% i, @# i
  36.                 $this->_cookiename = $this->_datapath.$this->_account;
    1 u+ [; w- a- B) b  {
  37.                 $this->getCookie($this->_cookiename);
    ; D* Y9 @2 q3 w( D8 O/ _
  38.         }
    . k. z$ f& l9 D& K% u. m
  39.         /**4 C/ p* h# B8 ]+ y" A
  40.          * 把cookie写入缓存$ \: v" O; l2 F2 P/ Z6 f
  41.          * @param  string $filename 缓存文件名
    . O! a3 L: {9 q! W/ ~8 Z6 ?
  42.          * @param  string $content  文件内容
    - Z" B0 X) I: x! q* W2 q. O9 J
  43.          * @return bool( ~5 m1 T/ M0 X7 ^8 f
  44.          */& I8 k$ F2 J+ O, b' k+ Y2 a
  45.         public function saveCookie($filename,$content){* [! ^6 T9 ^4 n7 A
  46.                 return file_put_contents($filename,$content);) D$ X6 `( P5 ?6 i1 y( |
  47.         }
      K$ B9 q/ V' d. [2 ]
  48. % L% z1 Z' `' k& V
  49.         /**
    6 V, N* ^* R  `' A
  50.          * 读取cookie缓存内容; ^' P$ k4 p4 u) L* N9 ~" L
  51.          * @param  string $filename 缓存文件名
    # D/ ~" h# O7 |' B
  52.          * @return string cookie
    : B# _+ \- B2 @+ L# m/ r
  53.          */
    + ]$ ]/ z6 L+ m: Y. O
  54.         public function getCookie($filename){
    $ h' b9 J5 G, {* e7 J, ?) D, g$ J  v
  55.                 if (file_exists($filename)) {) w& P- [% |: o2 d2 L0 Z. X
  56.                         $mtime = filemtime($filename);- r# @) f+ Z( M9 n
  57.                         if ($mtime<time()-$this->_cookieexpired) return false;% Z; K) }3 h2 @% y/ A3 k
  58.                         $data = file_get_contents($filename);7 A  Z& W/ f7 O; U9 z
  59.                         if ($data) $this->cookie = $data;
    + C( m' b; W! p* K
  60.                 }   ^" U0 J3 l& D
  61.                 return $this->cookie;
    ; U7 [) V4 A+ E
  62.         }
    % i9 r. t: [7 Y# w/ M
  63.         
    , u) Z" P0 ^% z5 R3 [
  64.         /*
    1 r4 `+ q. Q9 B$ H5 h! x* H6 Q
  65.          * 删除cookie
    4 m- F2 d6 D7 G9 Z# c3 v
  66.          */
    7 C+ L7 \1 U. D+ D/ j) B0 G
  67.         public function deleteCookie($filename) {
    0 f7 t7 z& B% L$ }9 Y
  68.                 $this->cookie = '';
    7 ?3 S# z4 H2 Z# T: E4 k) ]
  69.                 @unlink($filename);
    : k: V% C) ^% w, B  c! \$ {
  70.                 return true;
    + C# f& y* n$ @( y, t
  71.         }
    ! z, D8 s' U) M* {$ i
  72.         
    & `! M% o# l3 P) d, d% t
  73.         private function log($log){
    * x# J& h' F3 p
  74.                 if ($this->debug && function_exists($this->_logcallback)) {. T) g, n9 A  B
  75.                         if (is_array($log)) $log = print_r($log,true);- p1 L! G( g2 E6 K. e1 c  E
  76.                         return call_user_func($this->_logcallback,$log);
    1 G% b0 G% k- k5 W- l
  77.                 }$ T) K) D. K3 S, K" ?. b  I
  78.         }
    7 x* `; g' U# K& m: m5 |! D! n7 N
  79.         8 u7 S% @; r- L
  80.         /**; S. b. @$ l+ X) o9 x+ I# J
  81.          * 获取登陆二维码对应的授权码% d: g& l  ?, n) O( h/ J
  82.          */4 f) b* [0 F+ m. S) L
  83.         public function get_login_code(){
    ) Z/ j8 ^2 w  {& ?  T
  84.                 if ($this->_logincode) return $this->_logincode;  {/ R$ m1 F6 j5 {5 ~$ ]# k" b7 v7 j
  85.                 $t = time().strval(mt_rand(100,999));
    1 @9 Q6 A& j/ Z& T# d
  86.                 $codeurl = '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&_='.$t;
    1 B* I, c; S0 b  g) U% ^0 X
  87.                 $send_snoopy = new Snoopy;
    : Y7 K, O! g* j! N
  88.                 $send_snoopy->fetch($codeurl);- c2 j* T& ~1 z: W) t+ v: c
  89.                 $result = $send_snoopy->results;
    ( z2 l( V* D7 S: ~- c
  90.                 if ($result) {
    6 j% L  Q# U  x0 W; `+ a
  91.                         preg_match("/window.QRLogin.uuid\s+=\s+"([^"]+)"/",$result,$matches);
    ' [. @' a, P* Y5 n1 l; ?) u
  92.                         if(count($matches)>1) {
    ; Q! j7 A, h% `  F: V
  93.                                 $this->_logincode = $matches[1];3 w5 y! |9 v9 E4 j7 P* L
  94.                                 $_SESSION['login_step'] = 0;# J0 x; q8 H4 X
  95.                                 return $this->_logincode;9 X% `( b# F- O9 M" w, \1 g
  96.                         }% W$ |! p, ^* x  P9 s
  97.                 }
    2 R* e6 m) W7 s" P7 ~
  98.                 return $result;- u, ?) H2 g: k4 j. E
  99.         }
    . T. G" ~1 J- Y. Q8 S# B2 I! S' P
  100. # K% A" d* k6 y! V7 Q* l( ~
  101.         /*** ~2 m7 u/ q2 _
  102.          * 通过授权码获取对应的二维码图片地址/ B4 M+ e6 }* R6 N
  103.          * @param string $code
    - V6 r! D1 k* F- }- z: W& w4 v
  104.          * @return string image url7 k9 i9 c& A! Z# @
  105.          */
    6 V8 A( e0 l2 Q
  106.         public function get_code_image($code=''){
    & T# p, ]4 S; ]8 ]# r3 A1 a* s
  107.                 if ($code=='') $code = $this->_logincode;, h7 {0 N' r, W. U
  108.                 if (!$code) return false;. J; b8 D' V3 C" d. G* S
  109.                 return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';( `$ ?4 S% c+ c; Q" `( K
  110.         }
    # W( B' Y1 s% K: f" j
  111.         
    ( I: e, J' \$ l
  112.         /**& g5 L* i) F% H( M- z1 d) L
  113.          * 设置二维码对应的授权码
    2 E( B2 \: X2 h3 N( M/ T
  114.          * @param string $code, S' {! L0 x: `  G; V1 Y) ^8 H
  115.          * @return class $this
    9 X( Z" r$ R8 o& x/ m. O6 |
  116.          */
    % w! j) h1 g- Z
  117.         public  function set_login_code($code) {! {1 y/ r& v2 i. q
  118.                 $this->_logincode = $code;
    / m2 s5 F' j2 V8 M; E9 ~
  119.                 return $this;. g* p  Y0 F/ ^5 X
  120.         }
    / V6 x8 l1 T( g! C& ]
  121.         . F/ }$ k: ~" u
  122.         /**9 Y8 [0 a+ O4 X6 f9 j
  123.          * 二维码登陆验证
    0 h+ S# w- m2 Q% d7 r
  124.          *$ x6 ^9 o$ T% S! j/ z( Z
  125.          * @return status:( H& o+ ~2 f: G
  126.          * >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired# _( [: v" P/ p( U) F
  127.          * 201: just scaned but not confirm8 q! a9 j; r% T% K) ]: n) Y2 Y
  128.          * 200: confirm then you can get user info5 _: |( Z% a# `+ S1 h
  129.          */4 T* s2 ?# u5 X( \6 S) m$ D7 W8 G
  130.         public function verify_code() {
    ( o8 K. q' W' Q
  131.                 if (!$this->_logincode) return false;
    9 @  P& ?( F( @* t, s  v
  132.                 $t = time().strval(mt_rand(100,999));
    ' ]: L  ]  ^4 T% \) k- o
  133. & G  y: a7 M, A7 N2 M9 Y* ]
  134.                         $url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=1&_='.$t;+ C, z. z; \& `% _) d% |) v) V# i# m
  135.                         $send_snoopy = new Snoopy;
    $ h! |* y+ |* h+ ]  z& F$ J9 w2 v
  136.                         $send_snoopy->referer = "https://wx.qq.com/";8 j/ [( S% z4 ~2 t1 ~9 u  E
  137.                         $send_snoopy->fetch($url);1 D% W- C; O( e4 b/ C; N
  138.                         $result = $send_snoopy->results;/ h+ p7 y, X) |8 Q; O, M
  139.                         $this->log('step1:'.$result);! ]! S8 x$ R# G/ q+ ^% N, _
  140.                         if ($result) {- o  v9 }  t& ~  D3 ^8 G$ f
  141.                                 preg_match("/window\.code=(\d+)/",$result,$matches);3 o! o7 i) c4 L  k# e
  142.                                 if(count($matches)>1) {
      D! f7 r; ^+ ^4 P) }- M
  143.                                         $status = intval($matches[1]);
    - X; @$ o+ H, z% S5 h
  144.                                         if ($status==201) $_SESSION['login_step'] = 1;$ E- c0 Z6 C; E6 \. M; B
  145.                                         if ($status==200) {( m6 [( ~7 W- Z* U2 _# ?# E* a; m
  146.                                                 preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);
    + B( o: R) p$ t! f) e
  147.                                                 $this->log('step2:'.print_r($matches,true));
    * {6 m  N1 K* q/ U1 T/ I
  148.                                                 if (count($matches)>1) {
    8 W3 R" l9 `% c& d+ U1 n1 Y8 b
  149.                                                         $ticket = $matches[1];
    4 |8 Q& g4 n8 T: m
  150.                                                         $scan = $matches[2];$ t% \+ f  Z: z' R) p9 d. Q
  151.                                                         $loginurl = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket='.$ticket.'&lang=zh_CN&scan='.$scan.'&fun=new';9 g" {: X8 l' X8 l
  152.                                                         $send_snoopy = new Snoopy; : e7 P- j4 g- B9 [
  153.                                                         $send_snoopy->referer = "https://wx.qq.com/";. Q" s% z5 b$ a, {3 E8 Z' l
  154.                                                         $send_snoopy->fetch($loginurl);' n7 d5 H/ H3 z
  155.                                                         $this->log('step3:'.print_r($send_snoopy->headers,true));; h3 v1 d9 I- p
  156.                                                         foreach ($send_snoopy->headers as $key => $value) {
    ; |3 w: W0 Q4 ]' `/ m
  157.                                                                 $value = trim($value);! f" t6 `, c1 D* g
  158.                                                                 if(strpos($value,'Set-Cookie: ') !== false){' {, F6 ^; j# c& X: |
  159.                                                                         $tmp = str_replace("Set-Cookie: ","",$value);5 A3 a" o- W$ D1 C
  160.                                                                         $tmp = str_replace("Path=/","",$tmp);
    + @) q* a8 @/ m. J: P( K: \
  161.                                                                         $tmp = str_replace("Domain=.qq.com; ","",$tmp);8 R# d& f1 @( g3 ~1 G  I
  162.                                                                         $cookie.=$tmp;$ g/ g/ G( v$ Q0 }* N+ o6 ]. ?
  163.                                                                 }: Z$ n! p! W: S8 K  U* k  g; t* Z
  164.                                                         }1 q# |6 I0 P3 T0 H( z# B  m
  165.                                                         $cookie .="Domain=.qq.com;";
    9 s2 a, Y& T2 q
  166.                                                         $this->cookie = $cookie;
    # R0 c8 y" g$ e5 o  S
  167.                                                         $this->saveCookie($this->_cookiename,$this->cookie);5 \5 B! |7 _3 Z% n; t
  168.                                                 }
    " y! s5 V/ z; M. ?' b$ y1 k
  169.                                         }1 O$ U! O- w. `8 g$ O0 k8 \
  170.                                         return $status;* f6 }( o! c& A: K0 R# z' ?
  171.                                 }: R; C5 e) p, n; a7 v1 q1 z
  172.                         }  t% Y* i5 `) {/ `$ G
  173.                 return false;( y3 ^" v, U, _$ J
  174.         }# r# t1 C' P, ~4 ]
  175.         % v# s5 w4 t3 U- a/ P9 a: Z4 y, N
  176.         /**
    , j3 J. Y+ W. a9 g) @0 l  j
  177.          * 获取登陆的cookie( \" x- D2 ^+ U. {! P3 d
  178.          *& _, M4 V5 q1 o; G& u& a
  179.          * @param bool $is_array 是否以数值方式返回,默认否,返回字符串* [  p. @: \8 @" _0 n, m: j
  180.          * @return string|array) [+ q6 p4 w6 n. t7 f( f
  181.          */4 @9 p2 c% n2 F% r  A& }2 O
  182.         public function get_login_cookie($is_array = false){
    : p7 J5 Z+ C' M! H% k" E# T
  183.                 if (!$is_array)        return $this->cookie;
    4 J( A  R$ b# e5 x
  184.                 $c_arr = explode(';',$this->cookie);: Y2 q" T1 s: W3 j/ J3 k& a% \
  185.                 $cookie = array();- S6 E! S" r- \) A
  186.                 foreach($c_arr as $item) {1 J! P* C2 D- _6 ~# z! r
  187.                         $kitem = explode('=',trim($item));
    ! h, {- V5 r6 w6 o- M! N2 @
  188.                         if (count($kitem)>1) {4 A( S" h- P: F% `9 L; L, S$ C
  189.                                 $key = trim($kitem[0]);' C/ H9 [& B) z) U& I
  190.                                 $val = trim($kitem[1]);
    9 ~  q( c. G! Q0 `$ Z
  191.                                 if (!empty($val)) $cookie[$key] = $val;
    ! W% G2 z; S3 N
  192.                         }
    3 c  U; g( g' u) z$ O* V& B( @: n
  193.                 }  I8 J5 M2 _, ?* x
  194.                 return $cookie;
    * _1 i( `! u$ p
  195.         }" a3 O( Z9 {0 g! j
  196.         ) F5 N4 n8 D6 k& i2 N
  197.         /**
    3 y. s% ]/ _% \5 u, i4 `0 @$ N0 X
  198.          *          授权登陆后获取用户登陆信息5 v4 d$ w7 A) Z$ W3 M! x
  199.          */8 b. z% I; z# |" X* M
  200.         public function get_login_info(){# l1 u/ t; X( K" J& a4 ?
  201.                 if (!$this->cookie) return false;( u: w) U5 Y: o4 W
  202.                 $t = time().strval(mt_rand(100,999));
    # L( H. a; N! ]; v2 n, B) z
  203.                 $send_snoopy = new Snoopy; + ]1 W6 n% X. D0 u: {- {
  204.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t;
    * ~7 r. v! }# w, ~/ }% B7 E0 O
  205.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;
    / X. s1 B) b! f. I' _% D! x
  206.                 $send_snoopy->referer = "https://wx.qq.com/";
    7 y! `( |" m5 Y8 O
  207.                 $send_snoopy->submit($submit,array());% b6 k" e7 y0 u, B3 ~
  208.                 $this->log('login_info:'.$send_snoopy->results);4 V( @+ s1 G5 V  p  d1 m
  209.                 $result = json_decode($send_snoopy->results,true);
    ' p/ N* o' E$ G4 |: s
  210.                 if ($result['BaseResponse']['Ret']<0) return false;+ i& j$ s: o8 O9 ~
  211.                 $this->_login_user = $result['User'];
    * n1 M  l9 u+ N: |* s1 V# ]9 Y
  212.                 return $result;8 b2 R1 G4 ?+ G) ?& k1 ?3 g" x
  213.         }) l9 w$ d- L/ u$ p3 Q
  214.         8 N% J- b& O! p
  215.         /**
    ) F' A( m( t8 V5 m+ k
  216.          *  获取头像0 B( X: G; d% E
  217.          *  @param string $url 传入从用户信息接口获取到的头像地址! O7 T1 l) ]' Q7 K4 l
  218.          */
    $ {0 Z; n0 T1 l9 N* c
  219.         public function get_avatar($url) {
    / v; Q! M# u. }" \* ^" {/ e
  220.                 if (!$this->cookie) return false;, C1 ?2 ^9 I6 l9 p( e" @/ V
  221.                 if (strpos($url, 'http')===false) {2 I8 I' v2 S; J( H4 z  a
  222.                         $url = 'http://wx.qq.com'.$url;
    / u: i( J! g/ T3 Y
  223.                 }" B# A# O! {! F$ I0 B9 ?
  224.                 $send_snoopy = new Snoopy;
    8 H- ~  ~$ g0 c9 _/ g; ~" y
  225.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;3 {, K- ?* a( d- C' @
  226.                 $send_snoopy->referer = "https://wx.qq.com/";  ?$ T" Y, d" U9 e/ R
  227.                 $send_snoopy->fetch($url);0 u# U  ], m% m
  228.                 $result = $send_snoopy->results;
    # ^1 h) ~7 `' z& \" [& i! a
  229.                 if ($result)
    : l) }0 I4 |2 I. @
  230.                         return $result;
    * q! `* l0 w: c$ ^
  231.                 else
    7 @# y% S/ [3 H# m* W$ i
  232.                         return false;
    % M7 v$ K& V% x1 ^6 k. B6 K, a* Y
  233.         }! F8 b) I( ~8 q  j+ e
  234.         $ |: L/ F9 N* T' i" `4 S) @
  235.         /**
    9 W( M  n9 V7 m+ D) y) N
  236.          * 登出当前登陆用户4 p, ^" i. P' A% I( @' B- D
  237.          */" b% _- S8 }1 h% d2 f
  238.         public function logout(){: n% I0 J/ e3 p/ D$ f  n- A
  239.                 if (!$this->cookie) return false;
    7 N' B& b; F4 c; X
  240.                 preg_match("/wxuin=(\w+);/",$this->cookie,$matches);) L0 W+ w* u* |' Z. K/ t/ N9 ~
  241.                 if (count($matches)>1) $uid = $matches[1];
    6 e7 s* j# Q* R  q& k: }- A( ~6 }
  242.                 preg_match("/wxsid=(\w+);/",$this->cookie,$matches);
    . U7 w* I. k% l4 J* U* A4 Z
  243.                 if (count($matches)>1) $sid = $matches[1];; k9 x5 b* q1 P# K. d
  244.                 $this->log('logout: uid='.$uid.';sid='.$sid);
    ; }6 r4 o- N( A" v/ J* Z4 y+ z
  245.                 $send_snoopy = new Snoopy; 2 t/ V9 B! g3 ]  w* L9 O1 u# `
  246.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';
    1 h2 C" b8 k4 Y) H/ L& T& g
  247.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;
    ! O" s8 C) E. V8 u& L2 v
  248.                 $send_snoopy->referer = "https://wx.qq.com/";
    4 D5 ?. g# L% y' Y2 A: j  X) K. E
  249.                 $send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));6 M) M  e6 W3 l
  250.                 $this->deleteCookie($this->_cookiename);& N" x0 l3 Q) z+ e" v# ~. Z: C5 l9 E
  251.                 return true;2 ^! r' x, G# _8 i' m5 H# B0 C
  252.         }+ `: p) c3 g3 e7 V' G3 U2 J
  253. }
复制代码

, p" g$ G1 Y- {6 i8 ~5 u" z- q




上一篇:[Discuz插件] Discuz!微信登录插件配置前提
下一篇:Emacs逆袭:开发微信公众平台小游戏
回复

使用道具 举报

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

快速回复 返回顶部 返回列表