微信扫描登录

[复制链接]
发表于 2014-2-2 21:55:19 | 显示全部楼层 |阅读模式
用户通过扫描网页提供的二维码实现登陆信息获取
0 c1 F. n) ~4 `# u) b! f
  1. <?php
    + M) f/ @, n% n& @( J6 ~+ j: n
  2. /**. }6 G( x% O: a8 r
  3. *  微信公众平台PHP-SDK
    6 I; d. A5 {/ h( k
  4. *  Wechatauth为非官方微信登陆API
    ' M) u7 M2 v+ S$ `# s6 ]$ E
  5. *  用户通过扫描网页提供的二维码实现登陆信息获取
    ; y4 H1 @4 W8 ?3 i9 j0 `) _
  6. *  主要实现如下功能:) q; E1 I! V% s
  7. *  get_login_code() 获取登陆授权码, 通过授权码才能获取二维码
    # E" P8 ]- W) L, W, J: s
  8. *  get_code_image($code='') 将上面获取的授权码转换为图片二维码0 v! t: ]5 v. P9 I0 J
  9. *  verify_code() 鉴定是否登陆成功,返回200为最终授权成功.* g% f/ \) ?* ^' X  \
  10. *  get_login_cookie() 鉴定成功后调用此方法即可获取用户基本信息* J9 I% l. C; K1 ]% v- O
  11. *  sendNews($account,$title,$summary,$content,$pic,$srcurl='') 向一个微信账户发送图文信息
    ; j2 c% Y' L  {" u! g+ Q
  12. *  get_avatar($url) 获取用户头像图片数据
    + D/ q: U* ^( t2 m8 h
  13. *  @author dodge <dodgepudding@gmail.com>
    , K2 j9 _3 H6 D/ B
  14. *  @link https://github.com/dodgepudding/wechat-php-sdk  f; B- Y5 b! ]" G$ e9 o: n/ M
  15. *  @version 1.1
    - D( n$ V, [& a. _, [5 u. N$ q! p* u5 V& i
  16. *  5 V6 V( h: _6 V3 W$ r* _. y, k
  17. */6 [  P% v' n6 O
  18. include "snoopy.class.php";* U9 }+ |0 a& Z1 {- R8 e# G
  19. class Wechatauth
    8 X, v) @5 a1 W! U; \/ d2 o* V
  20. {
    - s6 {7 P/ L' h9 c9 _3 o8 U' r
  21.         private $cookie;8 r5 T4 `3 K# n; H) P
  22.         private $_cookiename;1 W& q0 }) f, T
  23.         private $_cookieexpired = 3600;: t- J/ j2 C: P4 y+ O& a
  24.         private $_account = 'test';. i/ M. V" u( W; K% g
  25.         private $_datapath = './data/cookie_';) D2 U2 K2 Q6 d; Y' r
  26.         private $debug;
    ; _% t6 R" n" f
  27.         private $_logcallback;
    $ v0 |, L7 Y. m  n. v
  28.         public $login_user; //当前登陆用户, 调用get_login_info后获取" ^: w& d2 _4 G  `  C
  29.         
    1 v+ i! `- \/ J
  30.         public function __construct($options)/ }2 q- A) x' N9 U& R
  31.         {- U3 S2 H% O1 G) k# ^
  32.                 $this->_account = isset($options['account'])?$options['account']:'';
    4 c0 \& j  B5 W3 o
  33.                 $this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;
    ) {6 ?1 b0 X$ I$ r! Q$ |- R
  34.                 $this->debug = isset($options['debug'])?$options['debug']:false;2 U3 v8 V# L% A2 ]. s" Q1 u% x
  35.                 $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;- D$ S+ r/ ?& L
  36.                 $this->_cookiename = $this->_datapath.$this->_account;% v0 n3 B- C( c' [% M
  37.                 $this->getCookie($this->_cookiename);
    + G  P  ]+ ?% t/ x1 B& ]
  38.         }
    $ I6 D! v: J' r' D+ C- E) z' C
  39.         /*** |' q5 ]% n! Z# F4 D
  40.          * 把cookie写入缓存& `5 j5 e! H* h
  41.          * @param  string $filename 缓存文件名& j" [0 I2 t$ f. X: q
  42.          * @param  string $content  文件内容
    ' m% v, I4 }% P: ?7 N
  43.          * @return bool; y: w# \. n# l, X1 a
  44.          */
    ! w9 m& h! C1 G1 V* l
  45.         public function saveCookie($filename,$content){
    7 E" A0 X6 c  m% i8 ^- Y7 W# |7 D
  46.                 return file_put_contents($filename,$content);
    / F, @9 ], d* v$ X. f4 M! W. E6 V2 h
  47.         }& N( ^+ j4 i, _
  48. ! c7 @4 ^9 x! `, A
  49.         /**3 r' L4 \1 J2 T, v* X
  50.          * 读取cookie缓存内容
    ' f1 f1 O0 h! r7 a) T- ~# \& j: Y; `% m
  51.          * @param  string $filename 缓存文件名
    + U4 g  }7 _/ F7 L! S( O! N" T1 }
  52.          * @return string cookie" n2 i. q# p" b% [, i1 p& Q
  53.          */* d( I* j; l; x$ I) o, n) s
  54.         public function getCookie($filename){
      ?" w* r+ R& N7 o4 A3 g
  55.                 if (file_exists($filename)) {
    ! H1 k+ q9 g6 H3 L
  56.                         $mtime = filemtime($filename);
    , m  B2 T; }1 [' `% t. k' q" G3 k
  57.                         if ($mtime<time()-$this->_cookieexpired) return false;
    9 C8 `5 E9 p5 a9 B% A
  58.                         $data = file_get_contents($filename);
    ; h9 m- y0 K/ }! U. i& h
  59.                         if ($data) $this->cookie = $data;& q+ G' \; W" r% h+ e
  60.                 } 1 F& T& v( Q  }0 W
  61.                 return $this->cookie;' B. Z6 N( Q$ H2 ?7 R9 g( q
  62.         }% e. y: T! V4 O8 M: D: L) e, _
  63.         9 e; j2 @9 L  T, m+ _
  64.         /*5 b4 }, L* S  Q( C8 Q( `8 j! P3 R
  65.          * 删除cookie
    * q# T/ N8 W, \) o' _# S/ r
  66.          */) a  ^( H/ u, \
  67.         public function deleteCookie($filename) {) X  j' Z4 }# D
  68.                 $this->cookie = '';9 o6 S% |4 c& O. y: g- t! V
  69.                 @unlink($filename);' [$ p0 J" t5 W9 N7 X
  70.                 return true;
    ; f7 h  o9 w- w! a% i
  71.         }" j- G+ X% n! @8 r" C3 ~6 l
  72.         
    ! O3 G" F4 K5 T
  73.         private function log($log){
    7 C  }& g' T  ^! X) w
  74.                 if ($this->debug && function_exists($this->_logcallback)) {
      M, y, l: b: n6 t7 L4 h5 s& K
  75.                         if (is_array($log)) $log = print_r($log,true);
    1 l6 H" O5 r4 J$ w
  76.                         return call_user_func($this->_logcallback,$log);! }7 a# l! W6 W5 g! K
  77.                 }3 O) P5 N' l. z
  78.         }) F- @% u! n: W
  79.         6 l/ N9 [6 r4 V& ~" h" _  J$ W
  80.         /**6 u4 R" `* m* x9 |3 \
  81.          * 获取登陆二维码对应的授权码
    - {/ {# |7 h; k, \
  82.          */
    4 k- r3 y- x6 J7 o, m! u# Z1 p, I
  83.         public function get_login_code(){: Q" B4 g+ Z' s7 n1 B. C1 W
  84.                 if ($this->_logincode) return $this->_logincode;3 _; s! w; X* `8 J; O
  85.                 $t = time().strval(mt_rand(100,999));
    % |* B* V- \+ s
  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;
    * E/ S! x4 g0 R" W6 r
  87.                 $send_snoopy = new Snoopy;
    ' U( E- d, M# B
  88.                 $send_snoopy->fetch($codeurl);
    " X3 w; h3 t, J4 |4 h0 Z: K  W3 ]
  89.                 $result = $send_snoopy->results;
    0 w7 a- m+ Z: L9 x0 d" O
  90.                 if ($result) {
    ! ^: Q9 h: G5 T% D; i
  91.                         preg_match("/window.QRLogin.uuid\s+=\s+"([^"]+)"/",$result,$matches);
    - v* s& f+ @# t5 {* F
  92.                         if(count($matches)>1) {$ C4 w* s4 [" K  r$ s- O$ z5 V
  93.                                 $this->_logincode = $matches[1];
    2 {+ D% F4 ?7 k; f$ S
  94.                                 $_SESSION['login_step'] = 0;
    3 v/ V4 z' }2 s0 }) D& V' q
  95.                                 return $this->_logincode;
    1 f) q& y5 J+ G- ]% ~2 K3 S
  96.                         }! x" i& g4 j% F3 @6 g
  97.                 }
      C' u$ T9 l* R7 T
  98.                 return $result;
    # D5 K3 }- \, \$ Z5 Y( }; F$ B( f
  99.         }
    6 B, k+ e: a/ a0 s" k
  100. ' d* s5 V/ Q. Z3 M0 L
  101.         /**; r) ~9 ~5 e/ c* U: Z! r' H8 A2 N4 J4 u
  102.          * 通过授权码获取对应的二维码图片地址' w: b7 k+ X! Y
  103.          * @param string $code) i2 l& ]7 [" U
  104.          * @return string image url
    7 X$ R1 a3 Z4 z
  105.          */
    ( r, @) |1 i3 {/ q
  106.         public function get_code_image($code=''){
    ( j2 L1 m8 g7 M, Y# P1 b4 h" `8 Y
  107.                 if ($code=='') $code = $this->_logincode;, j5 ]0 o. ~: K
  108.                 if (!$code) return false;: O7 m* m0 F5 m- d" M
  109.                 return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';
    : @6 n& N* @/ v  s1 m
  110.         }
    $ B9 R) S3 X' Y( U1 m& ~, i9 |
  111.         ( s) R3 |! h# y0 S/ \  z; {
  112.         /**& e: A) ^  K# M1 ^! Z
  113.          * 设置二维码对应的授权码
    : b$ i4 z: P/ e" \
  114.          * @param string $code
    3 E* S0 d/ i# t, T/ t
  115.          * @return class $this
    ( D7 ^2 r, f+ l4 |5 s" ]4 P
  116.          *// P$ a5 ~* q4 U. T+ H
  117.         public  function set_login_code($code) {( [& |8 Y$ S% `3 g7 ~- m( J1 Q
  118.                 $this->_logincode = $code;3 m8 o& g3 x# H1 i. _2 f0 O
  119.                 return $this;
    $ K7 {/ J2 R- ]. y6 M: l2 a
  120.         }
    $ \8 l# K$ D2 ^1 e
  121.         
    # q* v7 J7 Z& \# G
  122.         /**
    : x, J0 O% S, T, S0 V: \
  123.          * 二维码登陆验证% y# J- {, o, N8 l- f  R
  124.          *5 S* p, D) n' s% W2 q( B
  125.          * @return status:- u! k1 M) ]/ Y6 g
  126.          * >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired# q/ |4 p) R  j) H5 W3 o% U# g2 `) z+ n
  127.          * 201: just scaned but not confirm. B1 |' j1 Z. Q# z& ~5 k7 J
  128.          * 200: confirm then you can get user info" ^; |  f3 }1 D# g- r/ T
  129.          */* Z9 I+ ?6 k2 G! i+ z* W
  130.         public function verify_code() {
    1 [! O! [3 L: N' \7 z
  131.                 if (!$this->_logincode) return false;
      @2 E5 ?9 O. {0 e& k
  132.                 $t = time().strval(mt_rand(100,999));
    2 t% T! o6 ?% @; J7 v, j

  133. 3 L% L) h" n2 Z0 j  c/ _" K2 I
  134.                         $url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=1&_='.$t;- C7 K: k+ ^2 x6 u. J5 ]  O
  135.                         $send_snoopy = new Snoopy; / e1 }4 K3 w* Z5 j4 D$ `; Y" w
  136.                         $send_snoopy->referer = "https://wx.qq.com/";9 U& N) S/ e9 w
  137.                         $send_snoopy->fetch($url);
    , i3 n! k2 M9 t6 ^4 ]
  138.                         $result = $send_snoopy->results;
    7 a# C, x7 u: L3 F  g
  139.                         $this->log('step1:'.$result);# `; O* L0 q* I  |
  140.                         if ($result) {' |, n- B3 [, o5 Z% w4 A
  141.                                 preg_match("/window\.code=(\d+)/",$result,$matches);6 Q4 p0 e7 u6 f  m! z
  142.                                 if(count($matches)>1) {4 Q5 ?1 a' f( q
  143.                                         $status = intval($matches[1]);9 r, @$ c2 r. G3 q$ C& }( K) V# L6 M
  144.                                         if ($status==201) $_SESSION['login_step'] = 1;2 j" ~/ g: J7 m4 u+ {
  145.                                         if ($status==200) {
    : J+ p# v6 O$ Z2 a2 ^  c
  146.                                                 preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);
    8 E! P. H3 `. ]
  147.                                                 $this->log('step2:'.print_r($matches,true));% O: s; W1 U. q* G7 b/ Z8 z
  148.                                                 if (count($matches)>1) {0 ]6 e0 ?" Y$ U3 x( G
  149.                                                         $ticket = $matches[1];2 c3 V& V' I6 s% ?, P; ]* p6 J2 P
  150.                                                         $scan = $matches[2];! ~' H2 O5 D" u5 [& V/ f- Z& V6 j
  151.                                                         $loginurl = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket='.$ticket.'&lang=zh_CN&scan='.$scan.'&fun=new';/ H6 A. }4 e8 q7 q4 i' i7 i2 i  \
  152.                                                         $send_snoopy = new Snoopy;
    " I' E+ Y) k$ U3 g2 J* H
  153.                                                         $send_snoopy->referer = "https://wx.qq.com/";
    & ~: C$ w+ }8 A! N
  154.                                                         $send_snoopy->fetch($loginurl);4 i( w& Z1 O* V; y/ f  x1 R1 E) I
  155.                                                         $this->log('step3:'.print_r($send_snoopy->headers,true));" c& C, C  N3 A: y
  156.                                                         foreach ($send_snoopy->headers as $key => $value) {* k4 z0 i7 D0 H1 e
  157.                                                                 $value = trim($value);7 g' b* Q) H' z2 G- P! r+ ?1 g0 u
  158.                                                                 if(strpos($value,'Set-Cookie: ') !== false){. m7 y2 c/ b: M  O0 z
  159.                                                                         $tmp = str_replace("Set-Cookie: ","",$value);
    6 _. {( x" N2 q- m/ w! R% y
  160.                                                                         $tmp = str_replace("Path=/","",$tmp);
    - I" ~) q, ]' o* z+ z$ `" B
  161.                                                                         $tmp = str_replace("Domain=.qq.com; ","",$tmp);
    $ L4 i( ^- ?2 M2 V% V# T
  162.                                                                         $cookie.=$tmp;
    * j! S# Z+ G* B4 h  l
  163.                                                                 }# Q! d% D# Z1 t" j
  164.                                                         }2 h* J7 c4 J1 ^' {& ^
  165.                                                         $cookie .="Domain=.qq.com;";
    ( G& Z6 D: O% ^: D
  166.                                                         $this->cookie = $cookie;
    ; x8 }; d3 D6 T' Z, _
  167.                                                         $this->saveCookie($this->_cookiename,$this->cookie);) M3 E1 k; b; T8 c6 \
  168.                                                 }( Z  L% n- ]+ m+ A3 Y0 G: M
  169.                                         }
    ; P* I+ E6 b- K7 l" q
  170.                                         return $status;
    ! |! j' B5 j% h" m1 m) ]# `! f
  171.                                 }
    % T$ e- A5 N  W! J
  172.                         }+ {3 N, s  E5 G8 P- V
  173.                 return false;- R9 P6 `0 V& R4 G3 f/ A
  174.         }
    ! A# h: p) |* e+ R+ Z8 c( R
  175.         
    - C  w" U  J! }* K0 ]0 S$ {- f
  176.         /**
    , R* T8 ~3 Y2 F! ^
  177.          * 获取登陆的cookie( }1 N( a* N' S  T, k; E$ U( h2 Q$ C
  178.          *
      y& D# X! p4 p5 U5 ~" d
  179.          * @param bool $is_array 是否以数值方式返回,默认否,返回字符串% ~+ h  }. o2 u# h
  180.          * @return string|array
    5 G3 F. b& E6 \; ^* [) Q
  181.          */6 Y: u8 X& D7 }7 L  a% C  e  `, f
  182.         public function get_login_cookie($is_array = false){
    ! e7 j6 a) r) F
  183.                 if (!$is_array)        return $this->cookie;9 ~7 k  Z% l: n+ y: L6 ?" J: ]$ p8 x
  184.                 $c_arr = explode(';',$this->cookie);
    7 r  i9 V8 |# W/ l, G
  185.                 $cookie = array();
    & K2 ~! R: i5 m- j
  186.                 foreach($c_arr as $item) {
    7 ~0 B3 q0 C3 N9 X
  187.                         $kitem = explode('=',trim($item));( E! Z8 y7 x: z3 U  x- U
  188.                         if (count($kitem)>1) {
    4 |2 N. d' ?# X$ L
  189.                                 $key = trim($kitem[0]);
    . j- g2 M+ h5 d) }7 n4 {0 t
  190.                                 $val = trim($kitem[1]);
    ) M* u0 I$ [5 O0 }* R. e
  191.                                 if (!empty($val)) $cookie[$key] = $val;
    " Z  S* o- `8 a9 Y- Q6 u
  192.                         }
      `! W0 \0 c' E. t1 K( B* L
  193.                 }
    ! k2 G, y4 @% a# `4 e0 f5 H4 j
  194.                 return $cookie;0 `: d2 z6 \9 s. \/ j; w, w
  195.         }  d: ?* A9 {0 O; f7 k
  196.         ! Z$ G8 v# Z. }6 \+ [
  197.         /**
    - P! P+ t; f+ l2 k
  198.          *          授权登陆后获取用户登陆信息) z! o! G  a5 W9 h  [
  199.          */$ \: F) }8 S6 ?, p# {
  200.         public function get_login_info(){
    - `5 z7 x) e3 X3 o
  201.                 if (!$this->cookie) return false;6 a. H- j6 `- ^! U
  202.                 $t = time().strval(mt_rand(100,999));
    % X* J" I( h' S* N; m. |) i4 @
  203.                 $send_snoopy = new Snoopy; - E+ S* D3 V, v% u$ r  w$ L
  204.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t;
      E5 F/ u5 |  v3 K9 Q' N
  205.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;+ j; i% c6 ~4 j: U
  206.                 $send_snoopy->referer = "https://wx.qq.com/";9 j: ^: A* z8 H7 z! [2 T7 k- ?
  207.                 $send_snoopy->submit($submit,array());9 f' H1 i8 _9 v. w. Q8 y0 m. N  Y
  208.                 $this->log('login_info:'.$send_snoopy->results);2 T4 h9 k- H% i: R% B) v* r% J
  209.                 $result = json_decode($send_snoopy->results,true);
    , v1 B4 P4 M, t' K# q: m
  210.                 if ($result['BaseResponse']['Ret']<0) return false;7 a& ~" ~& q7 @) I2 }8 I
  211.                 $this->_login_user = $result['User'];
    3 y1 [3 K8 C9 A8 J$ Y
  212.                 return $result;
    - z( X  n, l8 c5 V0 ]
  213.         }$ L3 e2 |. m" I# m
  214.         
    $ L' }  p3 N7 j8 e7 i& v( I* z
  215.         /**- F, U! a7 N( T# ]! K
  216.          *  获取头像4 F0 W+ ~# K. u$ }& U# x
  217.          *  @param string $url 传入从用户信息接口获取到的头像地址) g+ x* `' U/ l8 P$ U6 i
  218.          */
    ' @% b, O; `% x/ P8 ~  K
  219.         public function get_avatar($url) {( _3 q+ O1 r7 Z% }/ k) n/ A5 J( E
  220.                 if (!$this->cookie) return false;
    . M( }4 H/ Z% r3 L
  221.                 if (strpos($url, 'http')===false) {6 X. W# E; B# M; m8 x8 ^
  222.                         $url = 'http://wx.qq.com'.$url;) }* h2 L" U) P9 @4 \
  223.                 }# W: }; g9 b5 a  S/ y
  224.                 $send_snoopy = new Snoopy;
    " J3 e* b" P: L( N0 d2 ?
  225.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;. }* F1 P& J3 ]
  226.                 $send_snoopy->referer = "https://wx.qq.com/";& @  f& v0 o$ B6 g0 c
  227.                 $send_snoopy->fetch($url);
    $ [! I( d; I0 ^5 P; [
  228.                 $result = $send_snoopy->results;$ q& ~3 J0 N6 t3 d' z
  229.                 if ($result)
    : D6 @) n6 u) r5 z# s
  230.                         return $result;
    ; F; ~7 D- p* T1 Z- o( r
  231.                 else
    ) V/ f9 M% d  ^2 ?5 H. ]
  232.                         return false;! v* {- t+ P) W. _& V3 w
  233.         }
    0 [7 d4 R# j1 x! t! P: l
  234.         % S1 G3 z, {% l4 @* p* {
  235.         /**, p3 K- ]" e1 u/ G
  236.          * 登出当前登陆用户  m9 }4 I& \" N7 z
  237.          *// R6 u: \8 a6 a4 D2 W, {% Z. ]
  238.         public function logout(){
    6 W7 D0 p+ }/ x; c  o5 p" T
  239.                 if (!$this->cookie) return false;
    % Z+ g: A, ~& p0 C7 ]6 u
  240.                 preg_match("/wxuin=(\w+);/",$this->cookie,$matches);9 G1 C3 l* ^& [" P  w1 M
  241.                 if (count($matches)>1) $uid = $matches[1];: E' h( ~, ?, f; d2 Q( x' d2 @3 A
  242.                 preg_match("/wxsid=(\w+);/",$this->cookie,$matches);
    8 `6 |1 w$ s. l7 i) q( `
  243.                 if (count($matches)>1) $sid = $matches[1];+ d% O1 n( h# f! C- \7 a1 g
  244.                 $this->log('logout: uid='.$uid.';sid='.$sid);
    $ T: L( s6 H2 C0 j+ e
  245.                 $send_snoopy = new Snoopy; , K  l9 ~" B) y$ t! J3 z! j* P
  246.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';
    ' y" y9 x) Y9 s! v4 z0 N
  247.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;2 t; d8 g( D1 W4 K, t
  248.                 $send_snoopy->referer = "https://wx.qq.com/";
    ! o1 Y* L& I3 G9 i" y' W
  249.                 $send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));5 D9 u' o6 t3 g# K; }
  250.                 $this->deleteCookie($this->_cookiename);
    9 n" u& ^+ s: B# B: W$ K
  251.                 return true;) E) e( x* ^, H, `+ [
  252.         }" d3 E& ^5 M0 g2 _6 i- c6 d
  253. }
复制代码
% W( ]7 X/ f0 U) Z




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

使用道具 举报

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

支付宝扫一扫打赏

微信扫一扫打赏

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