用户通过扫描网页提供的二维码实现登陆信息获取
# f B3 c; t- J& C4 G- <?php; D3 @& c2 f' ~' B' |
- /**/ c8 k3 `$ ^2 B* I5 ?; G7 N
- * 微信公众平台PHP-SDK! f2 N7 G3 m+ O0 R: i9 y; N
- * Wechatauth为非官方微信登陆API
- W2 ~% C' P+ {+ a8 f - * 用户通过扫描网页提供的二维码实现登陆信息获取
; g5 h' @4 P1 k8 d - * 主要实现如下功能:
0 L' J4 N/ M% m2 N' O - * get_login_code() 获取登陆授权码, 通过授权码才能获取二维码3 T! q8 s" j; T2 C) [
- * get_code_image($code='') 将上面获取的授权码转换为图片二维码
- z4 c$ e( z% [, T: E* D - * verify_code() 鉴定是否登陆成功,返回200为最终授权成功.8 y6 l2 Y/ ]% X+ G
- * get_login_cookie() 鉴定成功后调用此方法即可获取用户基本信息
: x/ i! w5 o- l7 } - * sendNews($account,$title,$summary,$content,$pic,$srcurl='') 向一个微信账户发送图文信息3 w( t9 N3 I- {5 z5 n, ]( @
- * get_avatar($url) 获取用户头像图片数据
! y/ w7 Z0 f+ z5 E: f$ f/ c$ Q' N - * @author dodge <dodgepudding@gmail.com>
3 C( a* @) f$ s* _ - * @link https://github.com/dodgepudding/wechat-php-sdk: F- E* k$ j5 _. S. U" w4 n) U8 O) S
- * @version 1.1
9 j. g! q1 [% @* d+ c - * , \$ T0 E4 z# T5 R+ @ [/ n+ x* P- K6 t
- */
5 W+ D/ V0 D& Y F k$ o0 g - include "snoopy.class.php";
0 T2 ^, r, \1 P& D - class Wechatauth" c, }9 V. N7 R7 {) C
- {6 Q5 m! r4 y( W' q2 ?4 Z
- private $cookie;& |; Q6 U; f* d* \3 c
- private $_cookiename;
( F, T# [ h% g+ ~$ ?1 A - private $_cookieexpired = 3600;
! X; e7 J9 h$ @! \" M+ r - private $_account = 'test';
# m! v3 j0 E3 u$ ?9 k) v/ A - private $_datapath = './data/cookie_';
7 z3 \, G$ M5 o, U, F& w$ w - private $debug;4 z$ x/ y2 k R" H5 u* i
- private $_logcallback;
! P+ I) l5 K! V - public $login_user; //当前登陆用户, 调用get_login_info后获取- S$ w/ P" o- s. z1 \
- 9 `0 ]9 M4 [+ B" j: J
- public function __construct($options)/ H/ }4 P" y, r
- {
' }( {& A/ A8 Y/ M) d. w o9 I3 q - $this->_account = isset($options['account'])?$options['account']:'';: E; s/ \+ w0 e- O" m
- $this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;
0 S; x$ J0 k1 O2 l7 A - $this->debug = isset($options['debug'])?$options['debug']:false;6 c0 O) \: j" [
- $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;, D" P- |) S1 p0 E
- $this->_cookiename = $this->_datapath.$this->_account;% ^# p) w& r# ~$ B
- $this->getCookie($this->_cookiename);& S8 ^1 A( K. p) s- a8 s# U
- }
F4 [( X8 f& T - /**% j) }( P/ H; y. r6 t$ g S- k
- * 把cookie写入缓存
8 b, N$ `4 B6 Z - * @param string $filename 缓存文件名
9 D t: X1 b; |: D - * @param string $content 文件内容# J# b' j9 s$ m
- * @return bool4 A8 T$ K" y" h$ Q0 l1 c) j+ X$ H, N" Z9 V
- *// b; m& q! a# `& {( E' b+ q2 Y
- public function saveCookie($filename,$content){
* Q7 ]+ E4 j: T. ` - return file_put_contents($filename,$content);* k. i D1 K4 y3 i8 S& q! S
- }8 _8 H) D' @; q& e% L% q) N0 J
- + h6 p8 K* T3 P! ^# m
- /**
# U8 A& k9 Z+ @ - * 读取cookie缓存内容
$ I- @9 B' \5 {8 h4 l - * @param string $filename 缓存文件名
' k7 M! W3 S6 f0 w F n% R4 D - * @return string cookie7 [; [; e5 D& p% \6 ^$ B$ U
- */
8 [# R( X' ~: w$ E9 t, G - public function getCookie($filename){+ E1 L6 V# |- R8 H0 W9 Z3 k
- if (file_exists($filename)) {) I4 x3 S9 z& s
- $mtime = filemtime($filename);' w" Q( {9 v2 P9 ?3 ~- d, s
- if ($mtime<time()-$this->_cookieexpired) return false;
( ~ c3 L& f, B# i) g. t - $data = file_get_contents($filename);
) Q% z- ^1 M( g* D! L0 m - if ($data) $this->cookie = $data;
+ A+ a+ O1 H. H; s; }8 ] R! R - }
. B* N; l" o+ k7 l4 j$ F! D9 g7 e8 s8 | - return $this->cookie;+ {* C! ^; y0 K/ P# D& m2 Q7 V
- }
/ x V- b; i r1 b$ i S- v1 r -
$ h8 F! A' F3 q& h) \& Z - /*: e5 W5 |# |8 F; k, u$ `
- * 删除cookie* Y9 k7 k. j2 c1 P% l" Q0 Z/ U6 C
- */
1 b' P8 D% @1 f! p5 [- R' N7 b - public function deleteCookie($filename) {
" C1 [4 w S w& @3 X+ v" ^& D' | - $this->cookie = '';
2 C; Q8 R1 E/ h2 V- S/ u0 @" L8 j - @unlink($filename);, a* l; ?5 g0 l% `
- return true;. U% H$ g. n9 @9 Y; E' n/ v% s
- }
1 T" V6 I- K/ g. G) Z1 E1 | -
, J7 ], H) Z0 D+ @& L( [7 n - private function log($log){
! I+ K0 }& m# N$ f - if ($this->debug && function_exists($this->_logcallback)) {
. A! k' I; {9 t! \+ [" z - if (is_array($log)) $log = print_r($log,true);& n) @6 ?& u; c# C$ C. q
- return call_user_func($this->_logcallback,$log);
: T5 {! v! \3 f3 t6 ~ - }/ `9 Q, z3 g$ }! a. M
- }
6 G4 \$ S W' g( j3 ~ -
% S6 X; H! q, A7 }& ?- V. l, G4 j5 z - /**7 i- ?0 m- @' n9 }) H& i7 q
- * 获取登陆二维码对应的授权码
N$ [. p% I2 Y# u% K& n - */
+ f9 p. Q# o+ e' ` - public function get_login_code(){
: N; U. L- f; W; u9 _7 D - if ($this->_logincode) return $this->_logincode;
/ |9 o( {9 K9 d9 u4 T" R' h - $t = time().strval(mt_rand(100,999));$ D' Z; Z9 }; N7 Z: `) D3 Q7 k/ t- @
- $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;
# t1 O8 S1 c2 [ - $send_snoopy = new Snoopy; 8 @1 j' u! v) r
- $send_snoopy->fetch($codeurl);3 ^$ J* n. N u+ F
- $result = $send_snoopy->results;
3 R6 v9 E! r p) `" z - if ($result) {
6 n- G) z7 J, |3 W$ [/ O8 b - preg_match("/window.QRLogin.uuid\s+=\s+"([^"]+)"/",$result,$matches);! ?1 g7 ~- |2 M' M$ A2 c& N
- if(count($matches)>1) {
1 a4 j8 X0 i1 i# H$ a - $this->_logincode = $matches[1];7 F0 |1 \! W* {% O8 p5 }. o; q
- $_SESSION['login_step'] = 0;
6 g: ?/ h: E/ C3 b8 W6 o' L - return $this->_logincode;
, p8 e- H l) G7 n6 R5 u! Q# I - }6 e& i, A9 n) v! _
- }
+ v( U( Z& {/ W1 G - return $result;) T6 b8 q! d5 g$ N" w9 ~( a
- }
; p' z+ i6 a8 L/ P: Y0 K; f - - |" S9 w4 P" A) D) Z5 M0 @- k
- /**
3 \. X2 x! r X7 G+ F- g5 l - * 通过授权码获取对应的二维码图片地址
) i6 W: V2 n9 \5 d' s1 t - * @param string $code
- S! b; ?" ]) C1 ~# P2 K/ {' B; I - * @return string image url
* A$ p7 i: h4 U" V6 `) B" D - */0 W6 K$ U8 w! |* \, Z% J
- public function get_code_image($code=''){* k0 ]( D3 k" q' U5 Q' S: Q! E
- if ($code=='') $code = $this->_logincode;
7 A3 H8 @8 a8 X9 S; p4 j* e2 ? - if (!$code) return false;
5 x) P# s) K" R% t" g% A+ {5 L8 d1 v - return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';
) K! l) a) E4 B2 c b* N& [ - }
G- O. u9 D. A4 L8 N3 U% w9 [ -
4 r4 o2 h* b' \1 I5 G$ R/ C - /**0 C4 {" |9 S6 o; O: M, E4 |/ X
- * 设置二维码对应的授权码
! z9 @# K3 A5 R- h T. G - * @param string $code
- q: F& `) D) R$ ~$ [ - * @return class $this6 ]+ s( n1 _+ Y; ~
- */5 F8 \+ l$ }. e4 o# J7 J
- public function set_login_code($code) {4 O; f P% a6 V/ g0 [# i) J
- $this->_logincode = $code;0 h% U7 c7 k4 j2 U$ V
- return $this;
6 {6 \9 ^6 f# [+ m - }6 z7 s/ C* j d, L
- 0 s/ B) z1 J2 k4 ]# ]9 a& c$ y
- /**1 i" i0 w4 d' e6 F" Z& \4 _% k" c
- * 二维码登陆验证- s i! D& f% Y+ A) `: Q
- *
$ I4 J* d+ `6 o# I, v. j9 ` - * @return status:' N4 s+ O$ x/ e& ]
- * >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired
" U1 \+ I8 R& q - * 201: just scaned but not confirm' [3 p5 z1 m/ ~/ }7 C
- * 200: confirm then you can get user info8 k& I! X: q; ~/ S4 ^
- */
# t& F. Z* t% F6 a( g4 y0 H - public function verify_code() {# T5 m6 Z1 z) G1 C- K' Z: a6 v
- if (!$this->_logincode) return false;& u1 \7 ?& ?" d; K- l/ ?4 F$ P
- $t = time().strval(mt_rand(100,999));
$ E" _, r/ t6 E8 Y% W - - J& `6 W9 M8 Z. @& M, ^- Y
- $url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=1&_='.$t;
, e! h. o6 ^+ L; b; | - $send_snoopy = new Snoopy; 5 b! ^( W: W# J! j
- $send_snoopy->referer = "https://wx.qq.com/";
9 G6 Y" n+ b' s& } - $send_snoopy->fetch($url);$ }, v$ b, D/ a; R; `
- $result = $send_snoopy->results;
& X, d/ s" X4 v4 E9 U' ^6 e - $this->log('step1:'.$result); b& h/ s$ X" G
- if ($result) {
P2 F, ?8 k5 i: p - preg_match("/window\.code=(\d+)/",$result,$matches);
3 ^: D% J/ a% p! ?. E - if(count($matches)>1) {3 ^& R" I) Y/ S, E. C. }; P! Q! `
- $status = intval($matches[1]);7 o: x' u+ t& v |) k9 E" M8 x) |
- if ($status==201) $_SESSION['login_step'] = 1;' K; A& M6 y5 o' V/ S+ P5 h# q
- if ($status==200) {5 j7 x4 W( a" N+ \* E/ V
- preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);/ Q, V- ?( V5 f% e
- $this->log('step2:'.print_r($matches,true));8 K% |7 K" D% a/ v7 p) h. S
- if (count($matches)>1) { J- l! [! Z/ G8 ` V
- $ticket = $matches[1];9 b4 ]+ a1 V8 S, }. @0 z% Y
- $scan = $matches[2];6 i( w% @$ y% f, A& ~ h; [
- $loginurl = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket='.$ticket.'&lang=zh_CN&scan='.$scan.'&fun=new';8 K7 r( q8 ^( f) A8 I; w! q
- $send_snoopy = new Snoopy;
& ^4 i$ S& b6 k8 \- e Y6 r - $send_snoopy->referer = "https://wx.qq.com/";* ?, q0 |8 i0 G6 n2 ]4 F
- $send_snoopy->fetch($loginurl);4 l* h7 Y9 k5 }4 F% m# z+ ~1 e
- $this->log('step3:'.print_r($send_snoopy->headers,true));
$ T7 A0 Q* u7 R: D - foreach ($send_snoopy->headers as $key => $value) {# _8 U U. U9 q- c# _1 P
- $value = trim($value); x, E, W; w" k5 I+ w9 c' J
- if(strpos($value,'Set-Cookie: ') !== false){
- ~5 p0 L8 C: p5 W# C( s+ p, E - $tmp = str_replace("Set-Cookie: ","",$value);
k8 m6 H: \: \2 V - $tmp = str_replace("Path=/","",$tmp);
- s" h2 Z$ ]& E) S3 d/ C - $tmp = str_replace("Domain=.qq.com; ","",$tmp);4 C. L0 @4 ^/ z- @! S4 E
- $cookie.=$tmp;
9 O: d$ P( ~# E# ?# ^6 @ - }
5 _0 k7 A1 q4 p - }
/ f; Y8 u! l3 c H - $cookie .="Domain=.qq.com;";
9 I O0 Y3 ~+ c5 F9 M4 w - $this->cookie = $cookie;; y% w( x& N4 I+ q6 W ?/ ?5 S
- $this->saveCookie($this->_cookiename,$this->cookie);% \& E; D1 S! Q0 c
- }0 G# r# k. S% m8 M5 _) `
- }
8 c* W3 c, p# ?5 g2 n% | X2 o" L - return $status;3 |! a, y5 D! m* F
- }* W* s3 v7 V1 z" n
- }
) Y" H' I, [* \ - return false;
1 b# L; c. ]* Y9 @. O- V) \ - }
' L% A" X$ c4 k6 W% U% Y# e -
6 x! ]% a# u( v - /*** t8 q6 Y5 X2 F3 U5 B* r
- * 获取登陆的cookie
" I- @3 x" ]3 }- _) U - *
; P( D0 \# E$ c. V8 X - * @param bool $is_array 是否以数值方式返回,默认否,返回字符串' X2 C, n+ w! i$ {
- * @return string|array
6 G, {& n" B1 L" t& n( a7 F4 H. D - */
- v0 F, r* O7 I$ g& H - public function get_login_cookie($is_array = false){
: R, O! p' y/ @6 Y2 e5 A - if (!$is_array) return $this->cookie;) _3 C$ T' ^/ K1 g O
- $c_arr = explode(';',$this->cookie);
1 Z s9 F1 F# m/ O4 U$ W2 y9 { - $cookie = array();
/ `4 R" ]0 g0 D1 z - foreach($c_arr as $item) {7 O3 w8 t% m1 r
- $kitem = explode('=',trim($item));* V: ?8 i, ]3 @$ {8 l2 Y$ N
- if (count($kitem)>1) {
" Q7 r W: q5 d; i6 V! K - $key = trim($kitem[0]);) {9 E- M. h1 |7 q& ^
- $val = trim($kitem[1]);# f; H) `3 g, P0 s! k" m% ?1 r |
- if (!empty($val)) $cookie[$key] = $val;
( q8 t0 o. k% d8 a! D. j/ A: Y9 ^ - }
@; J$ p) J1 i9 b) S - }6 V! x. e8 k' x, c. q' J* X( d
- return $cookie;8 o% Q. k3 l# v, Q7 K8 g4 q! }
- }
7 }; ?/ \9 A7 a8 y( K - 9 d$ H$ \6 I* |: _" j1 [
- /**
" w% u2 U. }# `3 @( }/ y, H - * 授权登陆后获取用户登陆信息) ~" A5 N; x: ]6 W N
- */: \8 ]# d, E; u( h3 Q
- public function get_login_info(){5 E- O/ C" }# a: Y/ I
- if (!$this->cookie) return false;& ~9 T1 {# Z( x- I. T, i
- $t = time().strval(mt_rand(100,999));& _8 O" s* d2 n- E9 O5 ~7 m
- $send_snoopy = new Snoopy; # f' I F" R- A. ~$ E6 f
- $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t;
/ a& i1 q( S3 {5 V& ]$ a - $send_snoopy->rawheaders['Cookie']= $this->cookie;/ R4 P( ]/ x, I: [6 d3 g
- $send_snoopy->referer = "https://wx.qq.com/";( `5 F' R4 W6 V/ w) z+ M
- $send_snoopy->submit($submit,array());
+ K% K ^6 y/ V - $this->log('login_info:'.$send_snoopy->results);
+ K. o. m. e# I2 f/ Z - $result = json_decode($send_snoopy->results,true);% p* _: `8 a% m/ y0 f1 Q3 S& |
- if ($result['BaseResponse']['Ret']<0) return false;; q* _% u3 t F3 `* G" c0 @8 A
- $this->_login_user = $result['User'];
* ` q6 D$ K4 e4 t3 _9 d- t - return $result;
9 @ _* ~% b Y g7 n; n5 ^$ y9 a - }1 _& r! @# t! w$ _; C
-
% R& H. A! O3 X* ] n$ N, f! T6 q0 k - /**
% \: S) y: c9 h, G - * 获取头像5 A0 ?; I+ }$ D/ h v4 w, ~
- * @param string $url 传入从用户信息接口获取到的头像地址
& J; D0 R4 P+ t - */1 m) \3 G- \/ z& \& X7 Y! M
- public function get_avatar($url) {
$ p8 W" E5 H6 q, w- @% e - if (!$this->cookie) return false;
! ` f# t$ T. [. \ P - if (strpos($url, 'http')===false) {$ M: C8 }; x N$ P( ]0 N: I6 |4 Z
- $url = 'http://wx.qq.com'.$url;% D: B8 j9 @8 Q0 r( ^ e6 P
- }4 h& S1 a# W& \
- $send_snoopy = new Snoopy; ! |$ K7 k: e0 h8 O! ]( k
- $send_snoopy->rawheaders['Cookie']= $this->cookie;, c9 n7 E/ Y0 w- o) h
- $send_snoopy->referer = "https://wx.qq.com/";# E3 E G% I' t2 M' T0 \
- $send_snoopy->fetch($url);
% p' R1 X( L/ l4 D# A4 M- k: V" O) g - $result = $send_snoopy->results;" `% J8 l5 O% i% E/ ^ b
- if ($result) / I0 i' S e, e( r
- return $result;
- ^. L! R* c0 e: O# T- C - else0 D, v; {8 x6 S; \ ~2 X
- return false;
; t' _9 J( |# ?, N - }3 D4 k! p; h6 ? A( f+ j5 r
- * H: ]& }0 g: G
- /**
+ p8 W) s! O) Q- s - * 登出当前登陆用户
) M0 d. P5 _! v; W - */
, K9 A; x- w' W% x" u - public function logout(){
- x7 w6 t5 B# G" r, W - if (!$this->cookie) return false;' R* y' {9 m! C
- preg_match("/wxuin=(\w+);/",$this->cookie,$matches);
, l# r) J* R( _+ M - if (count($matches)>1) $uid = $matches[1];
( a8 L4 ~' G/ w* _ - preg_match("/wxsid=(\w+);/",$this->cookie,$matches);0 e" y9 u9 z; J) V% G( [, n
- if (count($matches)>1) $sid = $matches[1];1 R& {7 I+ ]8 b' A w2 D' k
- $this->log('logout: uid='.$uid.';sid='.$sid);
8 @7 s5 e" ~1 K" X - $send_snoopy = new Snoopy; / y: f. T5 q; R8 o; f
- $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';
0 y9 v8 ]# d2 |0 k( v - $send_snoopy->rawheaders['Cookie']= $this->cookie;
8 @: \! c7 c" o/ b - $send_snoopy->referer = "https://wx.qq.com/";
8 L* e9 ?3 D6 u8 W - $send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));8 x0 s0 i7 c, i. J
- $this->deleteCookie($this->_cookiename);
- C, K3 m0 \2 X& B0 Q: ^ - return true;
5 [( k; J7 ~. P3 x/ [" U5 G - }5 ]5 Y+ Y6 W! |) ?
- }
复制代码 ; w: D: d, b6 a3 H0 p
|