用户通过扫描网页提供的二维码实现登陆信息获取 2 o' H9 N& H5 d: d+ E( F# T8 H! j
- <?php
" ]4 F6 ]' x1 u* u# c( _ - /**$ c3 E. F/ Q7 B( }1 U9 a7 e" g0 p
- * 微信公众平台PHP-SDK" {3 a3 k. r1 F
- * Wechatauth为非官方微信登陆API. ^; C# P$ J9 n/ l0 I a# u
- * 用户通过扫描网页提供的二维码实现登陆信息获取
/ D* T0 R& }. U, z. T - * 主要实现如下功能:
) o, u0 a6 d( q4 W1 D5 l$ i* L - * get_login_code() 获取登陆授权码, 通过授权码才能获取二维码
, F- |" R; s7 i8 v% x - * get_code_image($code='') 将上面获取的授权码转换为图片二维码; F9 K- _" I$ r5 {7 p) l+ c
- * verify_code() 鉴定是否登陆成功,返回200为最终授权成功., {( ~" e% Q% s4 L; J
- * get_login_cookie() 鉴定成功后调用此方法即可获取用户基本信息
3 U) A: V5 v( _8 q. W- _! X - * sendNews($account,$title,$summary,$content,$pic,$srcurl='') 向一个微信账户发送图文信息
& R2 S3 i: K. X5 t - * get_avatar($url) 获取用户头像图片数据
/ @! G% L7 ~& I; I9 W - * @author dodge <dodgepudding@gmail.com>; A; t. [. L+ p
- * @link https://github.com/dodgepudding/wechat-php-sdk
) ?$ i+ t) k" [6 S! x - * @version 1.1; F# L8 e& p3 c2 V
- * 9 i5 t' D( Y }6 c! } s
- */
1 M8 f3 j# S" r3 C4 y7 s1 @ - include "snoopy.class.php";
. y+ _& W# Z2 f- Z: X/ D6 ?9 y - class Wechatauth' r. G4 K1 T7 u* C2 {8 g
- {) z' ~' f4 r9 e3 Y
- private $cookie;
; ^. J; Y0 H7 s* T) } - private $_cookiename;$ w6 h' N# A) A& p+ u& [, L4 u
- private $_cookieexpired = 3600;9 e( K8 ]8 ~! x; Y% Q& H
- private $_account = 'test';
: ?7 o% x! u/ k: v, X4 \9 ^. V3 f" d/ G - private $_datapath = './data/cookie_';
. C# I) Y1 L8 \ - private $debug;4 P3 G: O/ b0 X/ _# L d5 y
- private $_logcallback;& }- P _& |5 _5 e5 G$ @
- public $login_user; //当前登陆用户, 调用get_login_info后获取. v$ p" ~4 P5 Z7 E% l3 i$ N8 F
- % T+ I( ~& L2 M% `/ {4 k- ~6 M+ D
- public function __construct($options)4 y" X3 B! S; z- D0 S* O; I
- {* ?: H% @- w& i V* J3 g
- $this->_account = isset($options['account'])?$options['account']:'';7 V* y* V7 d; _" `( [, i1 Q4 Y
- $this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;6 G& L" f" h9 K# }( r7 S N# |
- $this->debug = isset($options['debug'])?$options['debug']:false;
& [! s, `5 ~/ `+ o4 g - $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;
' P( x! n& k3 U/ } N - $this->_cookiename = $this->_datapath.$this->_account;' R9 p9 l9 o( s$ R
- $this->getCookie($this->_cookiename);
9 n! W$ C3 x4 E- G4 K0 ] - }- a _2 J( ^$ ~; x
- /**
' D& z* t& m/ y+ V- v4 t - * 把cookie写入缓存" G( F a8 T4 M+ @
- * @param string $filename 缓存文件名
9 F& u0 o/ _3 q/ j2 \ - * @param string $content 文件内容
. D D! U/ @0 U; O* |! i" b - * @return bool
3 W+ k. ^1 v C' C4 i1 A% N4 T - */1 [+ B" s4 p( o$ F: `
- public function saveCookie($filename,$content){
+ r9 l6 P8 G7 N4 @( R4 ]. ~ - return file_put_contents($filename,$content);
' j; _; U8 o8 j. a$ S6 p7 ] - }
5 z% C) d& ~8 L; l- p - $ Q) d; y5 M1 r$ R3 v- l, {7 l
- /**) F! \+ n; M) {0 N1 M
- * 读取cookie缓存内容
/ X+ V8 j$ g, d: o1 [1 i - * @param string $filename 缓存文件名7 A4 f2 L2 x5 |5 h- O1 M% ]" x' ^* Z
- * @return string cookie
% e% i9 ]% L" e0 h- K/ _ - */" J4 C8 T( X5 f* }- {( T+ `
- public function getCookie($filename){
1 g% V, z$ ]; J# a - if (file_exists($filename)) {
; `1 Q$ i3 U9 s6 P( M" v3 b - $mtime = filemtime($filename);
1 h" t- ^; a, B) ^! u* X - if ($mtime<time()-$this->_cookieexpired) return false;
2 d9 P2 q& [ I& h! U# h K - $data = file_get_contents($filename);
; g- r7 @ c2 B/ f x6 H, } - if ($data) $this->cookie = $data;9 |$ k! X2 a& U) q6 A
- }
0 M, q: }2 v9 R: M - return $this->cookie;
; Q/ E$ N2 b0 i* a$ w6 P, ] - }" X3 ^ @, ^. Z5 e6 ]% s- G
-
0 ]1 V' m; ~* `, T2 Q: F - /*9 D7 y; X. h0 z' c7 R* `9 n: N( O
- * 删除cookie: b4 [0 }) m |1 z- s
- */
6 K( H3 k1 i) I: r - public function deleteCookie($filename) {- S) j0 R& v0 C; k P8 k1 ^$ ]. z% ~3 `
- $this->cookie = '';+ Q4 G+ w% e( D5 A# Z! n
- @unlink($filename);# ~: A5 i$ f5 L
- return true;) n$ K0 t$ Q4 e! j
- }6 T! F* ?% H- }- K: n |
- 1 w* I c8 m* d! `% {/ Y: N& [+ y
- private function log($log){0 `3 M% F3 ?% t; ~& o, n- d
- if ($this->debug && function_exists($this->_logcallback)) {
& y, G" h' I! a& c. w; D; W - if (is_array($log)) $log = print_r($log,true);7 L" R$ R$ i" _) Q
- return call_user_func($this->_logcallback,$log);
3 u% z, @) g3 I6 t4 W- N% l - }# A( X! F4 T5 K
- }
3 ? k! ~3 o: [* Y) y9 N -
% M/ K( c& i3 \: J4 w8 r - /**0 S& X7 k% V% f' L; e9 |
- * 获取登陆二维码对应的授权码
( N: i" Q7 e/ m% p6 U7 J% m9 O - */0 ~8 m1 X) r8 N4 x* S' z$ V4 k' p+ }
- public function get_login_code(){
b V( f5 L. b - if ($this->_logincode) return $this->_logincode;
/ L% s1 V( m5 }; F# x - $t = time().strval(mt_rand(100,999));; D( m" G8 C# X' z+ M
- $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;$ @0 @6 p" D! o+ ^8 X
- $send_snoopy = new Snoopy;
. ~& x' `; V( [ - $send_snoopy->fetch($codeurl);$ |& X$ d8 y# b, g. U7 B
- $result = $send_snoopy->results;6 y. [$ E5 X3 k8 A
- if ($result) {
% U) K7 d- P* ^" b - preg_match("/window.QRLogin.uuid\s+=\s+"([^"]+)"/",$result,$matches);) Q0 X. a& g# _9 `
- if(count($matches)>1) {- }( S4 ^6 d9 }
- $this->_logincode = $matches[1];/ T) t x0 h8 p `3 g! E
- $_SESSION['login_step'] = 0;6 W! @# u6 n9 v/ ]" u I, E' j
- return $this->_logincode;
- x, v% t8 T5 Q, y# M* ] - }
. z; D/ r3 @. a. ^ - }8 W0 u8 ?5 W( G. H
- return $result;
" m- b, ?3 X* c* W$ J - }9 P E) }; i- T! ~
- ' I3 o! C0 v/ q' R9 `4 h7 \
- /**
m/ |3 D n( I- f j2 S4 f& @1 \0 L - * 通过授权码获取对应的二维码图片地址
; X0 V. C# c7 E. f7 I1 l4 w5 y7 K - * @param string $code( h( l, _! E0 W; A6 |
- * @return string image url
2 D! R& ?1 Y5 e( W ] - */
% m. t% v' @+ t6 u - public function get_code_image($code=''){, D) e8 h9 r) ^& c6 C) e
- if ($code=='') $code = $this->_logincode;
7 a3 k) t$ E7 V - if (!$code) return false;3 a! x; ~3 E3 d: Z) ]
- return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';9 f2 F4 e/ G, C U5 B
- }% Z7 S" k8 ]+ V! X
- + G( m- R8 ?% e9 u2 J. \/ j
- /**5 Y7 _4 X" o" z8 S7 \
- * 设置二维码对应的授权码! n1 B) @9 |6 ~4 w l
- * @param string $code: c9 O. p# R/ B& r* U! Z( E
- * @return class $this
( _ E6 p C$ _ - */5 z4 v! F, b; V6 o _
- public function set_login_code($code) {
0 g, w/ x/ t$ K# V3 @2 B - $this->_logincode = $code;+ P4 t1 w' f E; `* {8 P% W
- return $this;
' U" K- j' j' B. W6 T - }
- g: m) E1 ?3 ~2 y, I+ y7 r5 M3 o - 5 l+ N5 ^; O6 n# _
- /**7 x+ G; O& h2 L1 U0 f, M
- * 二维码登陆验证
* o$ X5 N/ F2 N& ~, i - *
; D& H- O2 _0 {: ]* W! Q0 e+ }, x i - * @return status:
" j' ~+ @: K; l$ w0 ^ - * >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired
% v7 x; \/ {9 }2 E, B3 F - * 201: just scaned but not confirm
% s& {- A8 N7 _1 Z& Y( l - * 200: confirm then you can get user info+ A \, z. J, v3 S3 e6 x
- */
: [. V. ^2 H) ]. z- B - public function verify_code() {
, o9 M: z+ s1 X+ r+ X - if (!$this->_logincode) return false;+ h! r' O+ s/ e) ]7 H3 a- _5 f
- $t = time().strval(mt_rand(100,999));
& X2 b3 A" P& f( ~( N: p* H4 A F
$ E1 ~; l' F: @: y3 j/ G- $url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=1&_='.$t;
5 ~7 Y/ E2 \; P0 A- w0 A - $send_snoopy = new Snoopy;
' D, \' z/ [2 m% v: n - $send_snoopy->referer = "https://wx.qq.com/";
7 r! G' `! Y' a' n - $send_snoopy->fetch($url);
3 d. @$ _1 X; ?4 A. U/ Y* F - $result = $send_snoopy->results;# P' u4 N' v3 c' U
- $this->log('step1:'.$result);
6 _: c. v( Y% W, x1 A - if ($result) {
4 \! n7 @& x9 J4 k8 N& M- I2 u, x - preg_match("/window\.code=(\d+)/",$result,$matches);
4 r3 p) s m. t0 J4 f- _! @ - if(count($matches)>1) {
$ S2 y! `: _" V - $status = intval($matches[1]);
+ g! B3 {. I' x+ R - if ($status==201) $_SESSION['login_step'] = 1;
- X0 ]9 C5 g6 P' K: J& N" p+ U$ }0 h - if ($status==200) {
1 b! ], s0 m8 y - preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);2 [5 f9 j2 e/ r2 X# a
- $this->log('step2:'.print_r($matches,true));
5 j8 l& } ^, D# b: e+ s - if (count($matches)>1) {
6 Q1 Q$ h7 _& L) B! }$ {: d - $ticket = $matches[1];: e6 F& E" c. z0 ]3 D, s
- $scan = $matches[2];) c& p& i4 x" F, p1 X. _( K
- $loginurl = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket='.$ticket.'&lang=zh_CN&scan='.$scan.'&fun=new';
* c* O) ?1 P4 o - $send_snoopy = new Snoopy;
0 g/ o2 \5 @, m9 a; r3 m, [- W+ E - $send_snoopy->referer = "https://wx.qq.com/";5 ]. O h1 \+ f4 L( F( \$ n0 E
- $send_snoopy->fetch($loginurl);
/ v5 {/ ^: H4 N4 F: f2 a/ V8 q - $this->log('step3:'.print_r($send_snoopy->headers,true));4 _, M% Y+ i+ |: S' O. ]# e5 z. @
- foreach ($send_snoopy->headers as $key => $value) {9 J3 K! N) g6 `' q. u
- $value = trim($value);/ E# _9 K, }$ B4 W) R
- if(strpos($value,'Set-Cookie: ') !== false){
6 B8 g$ D; F3 l - $tmp = str_replace("Set-Cookie: ","",$value);' \. a& v8 O3 v$ K4 n3 y! |
- $tmp = str_replace("Path=/","",$tmp);
3 U9 @2 n. @. k0 p - $tmp = str_replace("Domain=.qq.com; ","",$tmp);
1 `' z8 e' C4 H# `2 r* C1 d - $cookie.=$tmp;
?5 h# S* s! H( F( A - }
7 x8 |, k0 ?; B* B: h4 H - }
) p2 q4 z/ t a5 T - $cookie .="Domain=.qq.com;";* p S8 `+ w, f) o! T
- $this->cookie = $cookie;
/ a) M O8 F7 P0 I8 Z: q4 ~ - $this->saveCookie($this->_cookiename,$this->cookie);! o" }6 e0 h. ^* M. I
- }7 `! I% C# ^+ u5 e
- }
8 `& ?; \2 t w - return $status;
2 ?% x$ h3 B4 m/ @' F3 [3 s - }
1 f, q6 v n9 s0 O - }
# t/ ]! [( q* w. U - return false;! \. r2 _$ A3 d" i. a- }$ d
- }' z6 F8 c3 M% P' ?# P
-
8 z# w( d+ n! K- J$ i: f! y8 t - /**# O& `2 m7 F. ^( ?+ z: d
- * 获取登陆的cookie [( d! M$ M+ S
- *; M2 ]4 f3 F0 Z9 }0 ?( w+ s" N, [
- * @param bool $is_array 是否以数值方式返回,默认否,返回字符串
+ a: v' o. ~, n( ^* U - * @return string|array
% s/ S) F6 v3 s; T4 H; n e6 A+ q - */
) v+ l6 y' P. [ - public function get_login_cookie($is_array = false){
$ K/ g/ D! y+ y/ | - if (!$is_array) return $this->cookie;5 m. P# Z; l; T
- $c_arr = explode(';',$this->cookie);
6 \# q9 N6 N) B( | - $cookie = array();
6 ]' t6 d& x4 A7 R, Z- V1 |7 d - foreach($c_arr as $item) {
# k2 M) h7 O* o - $kitem = explode('=',trim($item));; i( }% O; s2 D
- if (count($kitem)>1) {
1 ~4 q$ _7 H% Z l9 u9 v3 D0 B5 b - $key = trim($kitem[0]);
6 s( d7 J, K6 j! ^4 \9 Y$ j - $val = trim($kitem[1]);1 s- \; c) J' P( j) @. }
- if (!empty($val)) $cookie[$key] = $val;
# K% U) I9 ~2 R6 W - }
/ [- q, V2 j( l |) x# i - }
% z9 X3 Q6 I. g+ l7 n1 C, W - return $cookie;
8 J# m6 h( Z# i+ r3 P, ~+ E - }
% e7 n8 X! ?2 m; l -
$ |0 ?2 n1 j% @9 j+ C# G" t - /**9 z( p' ?) @0 f! q- Y$ v
- * 授权登陆后获取用户登陆信息) H$ [# g5 u0 a/ m
- */
6 _- _* f; h# X* r a2 E - public function get_login_info(){
# K9 |$ l O2 ~* J' _ - if (!$this->cookie) return false;9 E; e; g+ @7 b
- $t = time().strval(mt_rand(100,999)); \+ T% V8 _( {& j9 @+ D
- $send_snoopy = new Snoopy; . ?5 i+ r. n2 ^8 \
- $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t;0 c2 o9 k* v& Y+ a+ a0 O' g& `
- $send_snoopy->rawheaders['Cookie']= $this->cookie;6 {- E; z0 v* F
- $send_snoopy->referer = "https://wx.qq.com/";3 y2 y/ ^: h# S! ~
- $send_snoopy->submit($submit,array()); U% _! r- l! [7 G4 H4 i
- $this->log('login_info:'.$send_snoopy->results);- f$ @% v( g7 T, Q: @
- $result = json_decode($send_snoopy->results,true);. M9 M+ }# c ^/ \5 y
- if ($result['BaseResponse']['Ret']<0) return false;7 `7 i1 A$ v1 Q2 K* @
- $this->_login_user = $result['User'];: y4 `+ y1 |: w
- return $result;
9 Z% k) F+ n8 T* c/ f/ E! w: S - }
3 o% V$ E% i8 D, ^# _ - % h! @4 r+ Q6 ~7 w
- /**
- W' z Y" v9 l$ g9 [5 {. D - * 获取头像2 @ D5 X; ]2 |% R/ S
- * @param string $url 传入从用户信息接口获取到的头像地址! o1 u8 u8 X. }5 T/ `
- */
: p/ g/ P# S5 H& _ P! | - public function get_avatar($url) {
C, A2 b5 _. B8 D6 A0 z1 U K) O% ?5 A - if (!$this->cookie) return false;
+ h6 ]! t+ k) b N A - if (strpos($url, 'http')===false) {
0 A. Q2 i* Y2 I - $url = 'http://wx.qq.com'.$url;
7 d9 K' Z4 a' \& K6 e' a4 u z - }* N$ t G! E! n9 h
- $send_snoopy = new Snoopy;
5 _% r2 e% S8 d. d, S( t: g# A. n - $send_snoopy->rawheaders['Cookie']= $this->cookie;* M: R$ {. u" c5 x+ o
- $send_snoopy->referer = "https://wx.qq.com/";
) H1 B; \- s* d3 K2 \" q! c - $send_snoopy->fetch($url);& _4 O: m m, y9 }* c' b3 \
- $result = $send_snoopy->results;
2 B2 c. Z$ W; _( s9 v! c - if ($result) + Y* `7 s N# G6 }3 z( S
- return $result;
1 n+ f8 M2 ~8 b' {& u4 | - else0 R- u6 V; q- E y$ v
- return false;
5 o$ W% i7 D$ w7 R - }
5 Q1 ?1 g. q% S! _( F - # W0 s" P( o3 U" U! J$ R! r9 T
- /**8 [9 W4 i0 F9 G* m6 u- K8 e9 |# h0 N
- * 登出当前登陆用户
' P0 k1 {: F/ }8 b9 I/ A0 C. m) C - */2 y) E+ N* M% m* _; h7 s1 E0 _
- public function logout(){
5 ]! T( Y: D" s L& J: ? - if (!$this->cookie) return false;
0 ^1 w+ d1 o! M* v - preg_match("/wxuin=(\w+);/",$this->cookie,$matches);
2 ~% |' I; u8 ` - if (count($matches)>1) $uid = $matches[1];
; d: S0 r' G( @3 @( g - preg_match("/wxsid=(\w+);/",$this->cookie,$matches);2 U, v" Y3 C: P6 ]* f
- if (count($matches)>1) $sid = $matches[1];, S% ^6 t0 }/ ~8 _9 Z
- $this->log('logout: uid='.$uid.';sid='.$sid);
5 j( i- O/ s7 [ - $send_snoopy = new Snoopy;
& L! u j1 q2 P/ w: l7 y - $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';+ D% F0 p" m+ t$ {0 ]1 `/ c
- $send_snoopy->rawheaders['Cookie']= $this->cookie;
9 u" ~/ Y9 ?1 W! n - $send_snoopy->referer = "https://wx.qq.com/";6 Q t/ I' }6 [( p' V% D e2 e a
- $send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));
5 l) p; v6 y: ~$ U0 k, [ - $this->deleteCookie($this->_cookiename);, [8 V- P& S3 [
- return true;
1 a3 R/ C% M8 t4 x) U - }
8 p* w9 B8 H- c/ A. _& o - }
复制代码
2 k; M7 l# R' w7 u$ I3 ^ |