微信扫描登录

[复制链接]
发表于 2014-2-2 21:55:19 | 显示全部楼层 |阅读模式
用户通过扫描网页提供的二维码实现登陆信息获取
# f  B3 c; t- J& C4 G
  1. <?php; D3 @& c2 f' ~' B' |
  2. /**/ c8 k3 `$ ^2 B* I5 ?; G7 N
  3. *  微信公众平台PHP-SDK! f2 N7 G3 m+ O0 R: i9 y; N
  4. *  Wechatauth为非官方微信登陆API
    - W2 ~% C' P+ {+ a8 f
  5. *  用户通过扫描网页提供的二维码实现登陆信息获取
    ; g5 h' @4 P1 k8 d
  6. *  主要实现如下功能:
    0 L' J4 N/ M% m2 N' O
  7. *  get_login_code() 获取登陆授权码, 通过授权码才能获取二维码3 T! q8 s" j; T2 C) [
  8. *  get_code_image($code='') 将上面获取的授权码转换为图片二维码
    - z4 c$ e( z% [, T: E* D
  9. *  verify_code() 鉴定是否登陆成功,返回200为最终授权成功.8 y6 l2 Y/ ]% X+ G
  10. *  get_login_cookie() 鉴定成功后调用此方法即可获取用户基本信息
    : x/ i! w5 o- l7 }
  11. *  sendNews($account,$title,$summary,$content,$pic,$srcurl='') 向一个微信账户发送图文信息3 w( t9 N3 I- {5 z5 n, ]( @
  12. *  get_avatar($url) 获取用户头像图片数据
    ! y/ w7 Z0 f+ z5 E: f$ f/ c$ Q' N
  13. *  @author dodge <dodgepudding@gmail.com>
    3 C( a* @) f$ s* _
  14. *  @link https://github.com/dodgepudding/wechat-php-sdk: F- E* k$ j5 _. S. U" w4 n) U8 O) S
  15. *  @version 1.1
    9 j. g! q1 [% @* d+ c
  16. *  , \$ T0 E4 z# T5 R+ @  [/ n+ x* P- K6 t
  17. */
    5 W+ D/ V0 D& Y  F  k$ o0 g
  18. include "snoopy.class.php";
    0 T2 ^, r, \1 P& D
  19. class Wechatauth" c, }9 V. N7 R7 {) C
  20. {6 Q5 m! r4 y( W' q2 ?4 Z
  21.         private $cookie;& |; Q6 U; f* d* \3 c
  22.         private $_cookiename;
    ( F, T# [  h% g+ ~$ ?1 A
  23.         private $_cookieexpired = 3600;
    ! X; e7 J9 h$ @! \" M+ r
  24.         private $_account = 'test';
    # m! v3 j0 E3 u$ ?9 k) v/ A
  25.         private $_datapath = './data/cookie_';
    7 z3 \, G$ M5 o, U, F& w$ w
  26.         private $debug;4 z$ x/ y2 k  R" H5 u* i
  27.         private $_logcallback;
    ! P+ I) l5 K! V
  28.         public $login_user; //当前登陆用户, 调用get_login_info后获取- S$ w/ P" o- s. z1 \
  29.         9 `0 ]9 M4 [+ B" j: J
  30.         public function __construct($options)/ H/ }4 P" y, r
  31.         {
    ' }( {& A/ A8 Y/ M) d. w  o9 I3 q
  32.                 $this->_account = isset($options['account'])?$options['account']:'';: E; s/ \+ w0 e- O" m
  33.                 $this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;
    0 S; x$ J0 k1 O2 l7 A
  34.                 $this->debug = isset($options['debug'])?$options['debug']:false;6 c0 O) \: j" [
  35.                 $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;, D" P- |) S1 p0 E
  36.                 $this->_cookiename = $this->_datapath.$this->_account;% ^# p) w& r# ~$ B
  37.                 $this->getCookie($this->_cookiename);& S8 ^1 A( K. p) s- a8 s# U
  38.         }
      F4 [( X8 f& T
  39.         /**% j) }( P/ H; y. r6 t$ g  S- k
  40.          * 把cookie写入缓存
    8 b, N$ `4 B6 Z
  41.          * @param  string $filename 缓存文件名
    9 D  t: X1 b; |: D
  42.          * @param  string $content  文件内容# J# b' j9 s$ m
  43.          * @return bool4 A8 T$ K" y" h$ Q0 l1 c) j+ X$ H, N" Z9 V
  44.          *// b; m& q! a# `& {( E' b+ q2 Y
  45.         public function saveCookie($filename,$content){
    * Q7 ]+ E4 j: T. `
  46.                 return file_put_contents($filename,$content);* k. i  D1 K4 y3 i8 S& q! S
  47.         }8 _8 H) D' @; q& e% L% q) N0 J
  48. + h6 p8 K* T3 P! ^# m
  49.         /**
    # U8 A& k9 Z+ @
  50.          * 读取cookie缓存内容
    $ I- @9 B' \5 {8 h4 l
  51.          * @param  string $filename 缓存文件名
    ' k7 M! W3 S6 f0 w  F  n% R4 D
  52.          * @return string cookie7 [; [; e5 D& p% \6 ^$ B$ U
  53.          */
    8 [# R( X' ~: w$ E9 t, G
  54.         public function getCookie($filename){+ E1 L6 V# |- R8 H0 W9 Z3 k
  55.                 if (file_exists($filename)) {) I4 x3 S9 z& s
  56.                         $mtime = filemtime($filename);' w" Q( {9 v2 P9 ?3 ~- d, s
  57.                         if ($mtime<time()-$this->_cookieexpired) return false;
    ( ~  c3 L& f, B# i) g. t
  58.                         $data = file_get_contents($filename);
    ) Q% z- ^1 M( g* D! L0 m
  59.                         if ($data) $this->cookie = $data;
    + A+ a+ O1 H. H; s; }8 ]  R! R
  60.                 }
    . B* N; l" o+ k7 l4 j$ F! D9 g7 e8 s8 |
  61.                 return $this->cookie;+ {* C! ^; y0 K/ P# D& m2 Q7 V
  62.         }
    / x  V- b; i  r1 b$ i  S- v1 r
  63.         
    $ h8 F! A' F3 q& h) \& Z
  64.         /*: e5 W5 |# |8 F; k, u$ `
  65.          * 删除cookie* Y9 k7 k. j2 c1 P% l" Q0 Z/ U6 C
  66.          */
    1 b' P8 D% @1 f! p5 [- R' N7 b
  67.         public function deleteCookie($filename) {
    " C1 [4 w  S  w& @3 X+ v" ^& D' |
  68.                 $this->cookie = '';
    2 C; Q8 R1 E/ h2 V- S/ u0 @" L8 j
  69.                 @unlink($filename);, a* l; ?5 g0 l% `
  70.                 return true;. U% H$ g. n9 @9 Y; E' n/ v% s
  71.         }
    1 T" V6 I- K/ g. G) Z1 E1 |
  72.         
    , J7 ], H) Z0 D+ @& L( [7 n
  73.         private function log($log){
    ! I+ K0 }& m# N$ f
  74.                 if ($this->debug && function_exists($this->_logcallback)) {
    . A! k' I; {9 t! \+ [" z
  75.                         if (is_array($log)) $log = print_r($log,true);& n) @6 ?& u; c# C$ C. q
  76.                         return call_user_func($this->_logcallback,$log);
    : T5 {! v! \3 f3 t6 ~
  77.                 }/ `9 Q, z3 g$ }! a. M
  78.         }
    6 G4 \$ S  W' g( j3 ~
  79.         
    % S6 X; H! q, A7 }& ?- V. l, G4 j5 z
  80.         /**7 i- ?0 m- @' n9 }) H& i7 q
  81.          * 获取登陆二维码对应的授权码
      N$ [. p% I2 Y# u% K& n
  82.          */
    + f9 p. Q# o+ e' `
  83.         public function get_login_code(){
    : N; U. L- f; W; u9 _7 D
  84.                 if ($this->_logincode) return $this->_logincode;
    / |9 o( {9 K9 d9 u4 T" R' h
  85.                 $t = time().strval(mt_rand(100,999));$ D' Z; Z9 }; N7 Z: `) D3 Q7 k/ t- @
  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;
    # t1 O8 S1 c2 [
  87.                 $send_snoopy = new Snoopy; 8 @1 j' u! v) r
  88.                 $send_snoopy->fetch($codeurl);3 ^$ J* n. N  u+ F
  89.                 $result = $send_snoopy->results;
    3 R6 v9 E! r  p) `" z
  90.                 if ($result) {
    6 n- G) z7 J, |3 W$ [/ O8 b
  91.                         preg_match("/window.QRLogin.uuid\s+=\s+"([^"]+)"/",$result,$matches);! ?1 g7 ~- |2 M' M$ A2 c& N
  92.                         if(count($matches)>1) {
    1 a4 j8 X0 i1 i# H$ a
  93.                                 $this->_logincode = $matches[1];7 F0 |1 \! W* {% O8 p5 }. o; q
  94.                                 $_SESSION['login_step'] = 0;
    6 g: ?/ h: E/ C3 b8 W6 o' L
  95.                                 return $this->_logincode;
    , p8 e- H  l) G7 n6 R5 u! Q# I
  96.                         }6 e& i, A9 n) v! _
  97.                 }
    + v( U( Z& {/ W1 G
  98.                 return $result;) T6 b8 q! d5 g$ N" w9 ~( a
  99.         }
    ; p' z+ i6 a8 L/ P: Y0 K; f
  100. - |" S9 w4 P" A) D) Z5 M0 @- k
  101.         /**
    3 \. X2 x! r  X7 G+ F- g5 l
  102.          * 通过授权码获取对应的二维码图片地址
    ) i6 W: V2 n9 \5 d' s1 t
  103.          * @param string $code
    - S! b; ?" ]) C1 ~# P2 K/ {' B; I
  104.          * @return string image url
    * A$ p7 i: h4 U" V6 `) B" D
  105.          */0 W6 K$ U8 w! |* \, Z% J
  106.         public function get_code_image($code=''){* k0 ]( D3 k" q' U5 Q' S: Q! E
  107.                 if ($code=='') $code = $this->_logincode;
    7 A3 H8 @8 a8 X9 S; p4 j* e2 ?
  108.                 if (!$code) return false;
    5 x) P# s) K" R% t" g% A+ {5 L8 d1 v
  109.                 return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';
    ) K! l) a) E4 B2 c  b* N& [
  110.         }
      G- O. u9 D. A4 L8 N3 U% w9 [
  111.         
    4 r4 o2 h* b' \1 I5 G$ R/ C
  112.         /**0 C4 {" |9 S6 o; O: M, E4 |/ X
  113.          * 设置二维码对应的授权码
    ! z9 @# K3 A5 R- h  T. G
  114.          * @param string $code
    - q: F& `) D) R$ ~$ [
  115.          * @return class $this6 ]+ s( n1 _+ Y; ~
  116.          */5 F8 \+ l$ }. e4 o# J7 J
  117.         public  function set_login_code($code) {4 O; f  P% a6 V/ g0 [# i) J
  118.                 $this->_logincode = $code;0 h% U7 c7 k4 j2 U$ V
  119.                 return $this;
    6 {6 \9 ^6 f# [+ m
  120.         }6 z7 s/ C* j  d, L
  121.         0 s/ B) z1 J2 k4 ]# ]9 a& c$ y
  122.         /**1 i" i0 w4 d' e6 F" Z& \4 _% k" c
  123.          * 二维码登陆验证- s  i! D& f% Y+ A) `: Q
  124.          *
    $ I4 J* d+ `6 o# I, v. j9 `
  125.          * @return status:' N4 s+ O$ x/ e& ]
  126.          * >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired
    " U1 \+ I8 R& q
  127.          * 201: just scaned but not confirm' [3 p5 z1 m/ ~/ }7 C
  128.          * 200: confirm then you can get user info8 k& I! X: q; ~/ S4 ^
  129.          */
    # t& F. Z* t% F6 a( g4 y0 H
  130.         public function verify_code() {# T5 m6 Z1 z) G1 C- K' Z: a6 v
  131.                 if (!$this->_logincode) return false;& u1 \7 ?& ?" d; K- l/ ?4 F$ P
  132.                 $t = time().strval(mt_rand(100,999));
    $ E" _, r/ t6 E8 Y% W
  133. - J& `6 W9 M8 Z. @& M, ^- Y
  134.                         $url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=1&_='.$t;
    , e! h. o6 ^+ L; b; |
  135.                         $send_snoopy = new Snoopy; 5 b! ^( W: W# J! j
  136.                         $send_snoopy->referer = "https://wx.qq.com/";
    9 G6 Y" n+ b' s& }
  137.                         $send_snoopy->fetch($url);$ }, v$ b, D/ a; R; `
  138.                         $result = $send_snoopy->results;
    & X, d/ s" X4 v4 E9 U' ^6 e
  139.                         $this->log('step1:'.$result);  b& h/ s$ X" G
  140.                         if ($result) {
      P2 F, ?8 k5 i: p
  141.                                 preg_match("/window\.code=(\d+)/",$result,$matches);
    3 ^: D% J/ a% p! ?. E
  142.                                 if(count($matches)>1) {3 ^& R" I) Y/ S, E. C. }; P! Q! `
  143.                                         $status = intval($matches[1]);7 o: x' u+ t& v  |) k9 E" M8 x) |
  144.                                         if ($status==201) $_SESSION['login_step'] = 1;' K; A& M6 y5 o' V/ S+ P5 h# q
  145.                                         if ($status==200) {5 j7 x4 W( a" N+ \* E/ V
  146.                                                 preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);/ Q, V- ?( V5 f% e
  147.                                                 $this->log('step2:'.print_r($matches,true));8 K% |7 K" D% a/ v7 p) h. S
  148.                                                 if (count($matches)>1) {  J- l! [! Z/ G8 `  V
  149.                                                         $ticket = $matches[1];9 b4 ]+ a1 V8 S, }. @0 z% Y
  150.                                                         $scan = $matches[2];6 i( w% @$ y% f, A& ~  h; [
  151.                                                         $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
  152.                                                         $send_snoopy = new Snoopy;
    & ^4 i$ S& b6 k8 \- e  Y6 r
  153.                                                         $send_snoopy->referer = "https://wx.qq.com/";* ?, q0 |8 i0 G6 n2 ]4 F
  154.                                                         $send_snoopy->fetch($loginurl);4 l* h7 Y9 k5 }4 F% m# z+ ~1 e
  155.                                                         $this->log('step3:'.print_r($send_snoopy->headers,true));
    $ T7 A0 Q* u7 R: D
  156.                                                         foreach ($send_snoopy->headers as $key => $value) {# _8 U  U. U9 q- c# _1 P
  157.                                                                 $value = trim($value);  x, E, W; w" k5 I+ w9 c' J
  158.                                                                 if(strpos($value,'Set-Cookie: ') !== false){
    - ~5 p0 L8 C: p5 W# C( s+ p, E
  159.                                                                         $tmp = str_replace("Set-Cookie: ","",$value);
      k8 m6 H: \: \2 V
  160.                                                                         $tmp = str_replace("Path=/","",$tmp);
    - s" h2 Z$ ]& E) S3 d/ C
  161.                                                                         $tmp = str_replace("Domain=.qq.com; ","",$tmp);4 C. L0 @4 ^/ z- @! S4 E
  162.                                                                         $cookie.=$tmp;
    9 O: d$ P( ~# E# ?# ^6 @
  163.                                                                 }
    5 _0 k7 A1 q4 p
  164.                                                         }
    / f; Y8 u! l3 c  H
  165.                                                         $cookie .="Domain=.qq.com;";
    9 I  O0 Y3 ~+ c5 F9 M4 w
  166.                                                         $this->cookie = $cookie;; y% w( x& N4 I+ q6 W  ?/ ?5 S
  167.                                                         $this->saveCookie($this->_cookiename,$this->cookie);% \& E; D1 S! Q0 c
  168.                                                 }0 G# r# k. S% m8 M5 _) `
  169.                                         }
    8 c* W3 c, p# ?5 g2 n% |  X2 o" L
  170.                                         return $status;3 |! a, y5 D! m* F
  171.                                 }* W* s3 v7 V1 z" n
  172.                         }
    ) Y" H' I, [* \
  173.                 return false;
    1 b# L; c. ]* Y9 @. O- V) \
  174.         }
    ' L% A" X$ c4 k6 W% U% Y# e
  175.         
    6 x! ]% a# u( v
  176.         /*** t8 q6 Y5 X2 F3 U5 B* r
  177.          * 获取登陆的cookie
    " I- @3 x" ]3 }- _) U
  178.          *
    ; P( D0 \# E$ c. V8 X
  179.          * @param bool $is_array 是否以数值方式返回,默认否,返回字符串' X2 C, n+ w! i$ {
  180.          * @return string|array
    6 G, {& n" B1 L" t& n( a7 F4 H. D
  181.          */
    - v0 F, r* O7 I$ g& H
  182.         public function get_login_cookie($is_array = false){
    : R, O! p' y/ @6 Y2 e5 A
  183.                 if (!$is_array)        return $this->cookie;) _3 C$ T' ^/ K1 g  O
  184.                 $c_arr = explode(';',$this->cookie);
    1 Z  s9 F1 F# m/ O4 U$ W2 y9 {
  185.                 $cookie = array();
    / `4 R" ]0 g0 D1 z
  186.                 foreach($c_arr as $item) {7 O3 w8 t% m1 r
  187.                         $kitem = explode('=',trim($item));* V: ?8 i, ]3 @$ {8 l2 Y$ N
  188.                         if (count($kitem)>1) {
    " Q7 r  W: q5 d; i6 V! K
  189.                                 $key = trim($kitem[0]);) {9 E- M. h1 |7 q& ^
  190.                                 $val = trim($kitem[1]);# f; H) `3 g, P0 s! k" m% ?1 r  |
  191.                                 if (!empty($val)) $cookie[$key] = $val;
    ( q8 t0 o. k% d8 a! D. j/ A: Y9 ^
  192.                         }
      @; J$ p) J1 i9 b) S
  193.                 }6 V! x. e8 k' x, c. q' J* X( d
  194.                 return $cookie;8 o% Q. k3 l# v, Q7 K8 g4 q! }
  195.         }
    7 }; ?/ \9 A7 a8 y( K
  196.         9 d$ H$ \6 I* |: _" j1 [
  197.         /**
    " w% u2 U. }# `3 @( }/ y, H
  198.          *          授权登陆后获取用户登陆信息) ~" A5 N; x: ]6 W  N
  199.          */: \8 ]# d, E; u( h3 Q
  200.         public function get_login_info(){5 E- O/ C" }# a: Y/ I
  201.                 if (!$this->cookie) return false;& ~9 T1 {# Z( x- I. T, i
  202.                 $t = time().strval(mt_rand(100,999));& _8 O" s* d2 n- E9 O5 ~7 m
  203.                 $send_snoopy = new Snoopy; # f' I  F" R- A. ~$ E6 f
  204.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t;
    / a& i1 q( S3 {5 V& ]$ a
  205.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;/ R4 P( ]/ x, I: [6 d3 g
  206.                 $send_snoopy->referer = "https://wx.qq.com/";( `5 F' R4 W6 V/ w) z+ M
  207.                 $send_snoopy->submit($submit,array());
    + K% K  ^6 y/ V
  208.                 $this->log('login_info:'.$send_snoopy->results);
    + K. o. m. e# I2 f/ Z
  209.                 $result = json_decode($send_snoopy->results,true);% p* _: `8 a% m/ y0 f1 Q3 S& |
  210.                 if ($result['BaseResponse']['Ret']<0) return false;; q* _% u3 t  F3 `* G" c0 @8 A
  211.                 $this->_login_user = $result['User'];
    * `  q6 D$ K4 e4 t3 _9 d- t
  212.                 return $result;
    9 @  _* ~% b  Y  g7 n; n5 ^$ y9 a
  213.         }1 _& r! @# t! w$ _; C
  214.         
    % R& H. A! O3 X* ]  n$ N, f! T6 q0 k
  215.         /**
    % \: S) y: c9 h, G
  216.          *  获取头像5 A0 ?; I+ }$ D/ h  v4 w, ~
  217.          *  @param string $url 传入从用户信息接口获取到的头像地址
    & J; D0 R4 P+ t
  218.          */1 m) \3 G- \/ z& \& X7 Y! M
  219.         public function get_avatar($url) {
    $ p8 W" E5 H6 q, w- @% e
  220.                 if (!$this->cookie) return false;
    ! `  f# t$ T. [. \  P
  221.                 if (strpos($url, 'http')===false) {$ M: C8 }; x  N$ P( ]0 N: I6 |4 Z
  222.                         $url = 'http://wx.qq.com'.$url;% D: B8 j9 @8 Q0 r( ^  e6 P
  223.                 }4 h& S1 a# W& \
  224.                 $send_snoopy = new Snoopy; ! |$ K7 k: e0 h8 O! ]( k
  225.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;, c9 n7 E/ Y0 w- o) h
  226.                 $send_snoopy->referer = "https://wx.qq.com/";# E3 E  G% I' t2 M' T0 \
  227.                 $send_snoopy->fetch($url);
    % p' R1 X( L/ l4 D# A4 M- k: V" O) g
  228.                 $result = $send_snoopy->results;" `% J8 l5 O% i% E/ ^  b
  229.                 if ($result) / I0 i' S  e, e( r
  230.                         return $result;
    - ^. L! R* c0 e: O# T- C
  231.                 else0 D, v; {8 x6 S; \  ~2 X
  232.                         return false;
    ; t' _9 J( |# ?, N
  233.         }3 D4 k! p; h6 ?  A( f+ j5 r
  234.         * H: ]& }0 g: G
  235.         /**
    + p8 W) s! O) Q- s
  236.          * 登出当前登陆用户
    ) M0 d. P5 _! v; W
  237.          */
    , K9 A; x- w' W% x" u
  238.         public function logout(){
    - x7 w6 t5 B# G" r, W
  239.                 if (!$this->cookie) return false;' R* y' {9 m! C
  240.                 preg_match("/wxuin=(\w+);/",$this->cookie,$matches);
    , l# r) J* R( _+ M
  241.                 if (count($matches)>1) $uid = $matches[1];
    ( a8 L4 ~' G/ w* _
  242.                 preg_match("/wxsid=(\w+);/",$this->cookie,$matches);0 e" y9 u9 z; J) V% G( [, n
  243.                 if (count($matches)>1) $sid = $matches[1];1 R& {7 I+ ]8 b' A  w2 D' k
  244.                 $this->log('logout: uid='.$uid.';sid='.$sid);
    8 @7 s5 e" ~1 K" X
  245.                 $send_snoopy = new Snoopy; / y: f. T5 q; R8 o; f
  246.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';
    0 y9 v8 ]# d2 |0 k( v
  247.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;
    8 @: \! c7 c" o/ b
  248.                 $send_snoopy->referer = "https://wx.qq.com/";
    8 L* e9 ?3 D6 u8 W
  249.                 $send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));8 x0 s0 i7 c, i. J
  250.                 $this->deleteCookie($this->_cookiename);
    - C, K3 m0 \2 X& B0 Q: ^
  251.                 return true;
    5 [( k; J7 ~. P3 x/ [" U5 G
  252.         }5 ]5 Y+ Y6 W! |) ?
  253. }
复制代码
; w: D: d, b6 a3 H0 p




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

使用道具 举报

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

支付宝扫一扫打赏

微信扫一扫打赏

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