微信扫描登录

[复制链接]
发表于 2014-2-2 21:55:19 | 显示全部楼层 |阅读模式
用户通过扫描网页提供的二维码实现登陆信息获取 + F6 t, ~! J5 H7 q* M( Q4 [, v' q
  1. <?php
    4 K" t& o! o' c  w/ n
  2. /**3 u2 |/ {. S% n+ j# g$ b0 E& s
  3. *  微信公众平台PHP-SDK  p( ^1 F. C8 q8 L5 a& U
  4. *  Wechatauth为非官方微信登陆API0 }' b1 x" f! H( [$ e5 [4 @
  5. *  用户通过扫描网页提供的二维码实现登陆信息获取
    " |" T/ T# \! R/ y/ q
  6. *  主要实现如下功能:( k% b* _" E; H- i6 v
  7. *  get_login_code() 获取登陆授权码, 通过授权码才能获取二维码
    $ A% V$ N% p- S  d8 m
  8. *  get_code_image($code='') 将上面获取的授权码转换为图片二维码
    - y- ~+ f% W8 t) I
  9. *  verify_code() 鉴定是否登陆成功,返回200为最终授权成功.( {4 O5 K) Q( a$ ?" Q
  10. *  get_login_cookie() 鉴定成功后调用此方法即可获取用户基本信息9 e# h1 s- l+ R
  11. *  sendNews($account,$title,$summary,$content,$pic,$srcurl='') 向一个微信账户发送图文信息
    + G/ F* O( K) a( D+ r% Q, G6 e, _4 g# Q
  12. *  get_avatar($url) 获取用户头像图片数据, }/ |- h! H* L
  13. *  @author dodge <dodgepudding@gmail.com>
    ; f- j) _" n8 E4 F- ~0 x
  14. *  @link https://github.com/dodgepudding/wechat-php-sdk
    , \. r1 Y  T, B
  15. *  @version 1.1
    + v; p0 ~* W5 b2 B! ]
  16. *  
    2 M) b& d/ Y1 l1 Y) \8 `- H
  17. *// u7 m5 U4 K6 f/ E
  18. include "snoopy.class.php";; Y- |1 l) I0 ]/ G( \: ]
  19. class Wechatauth" _" p5 z1 n8 e0 a
  20. {
    + C2 |( t; W/ E7 l" d& ?9 ^* V; u/ X
  21.         private $cookie;
    3 N( {9 H: A+ ~7 d) Y! u: {9 S; a
  22.         private $_cookiename;
    $ u% L; \6 s; [$ e9 s( J0 b
  23.         private $_cookieexpired = 3600;
    ) C) L& k  F# R6 E( J
  24.         private $_account = 'test';3 Y2 c% k: {: x
  25.         private $_datapath = './data/cookie_';
    6 a# \1 K" `) }% i. y8 v
  26.         private $debug;
    # I4 {/ Y) b$ k" c1 h# U( t% f
  27.         private $_logcallback;
    1 m3 B& y# C* ]4 X
  28.         public $login_user; //当前登陆用户, 调用get_login_info后获取
    2 _: {9 U0 X. M8 o$ X$ y% W1 W
  29.         
    ; a7 l- j, j4 {
  30.         public function __construct($options)/ a4 M" m, V8 M: X; |- W; N
  31.         {
    ; ?4 b/ W( ?) p+ p
  32.                 $this->_account = isset($options['account'])?$options['account']:'';. j/ k- _1 M; ^) Y) Z. |
  33.                 $this->_datapath = isset($options['datapath'])?$options['datapath']:$this->_datapath;5 z* r; k( j6 R# |
  34.                 $this->debug = isset($options['debug'])?$options['debug']:false;# B% @( ~4 S) W2 Q
  35.                 $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;" D* _  J- H) S7 h) G
  36.                 $this->_cookiename = $this->_datapath.$this->_account;8 c+ D: j9 a; N: O; R2 Q8 d
  37.                 $this->getCookie($this->_cookiename);8 E/ d2 R, L6 V1 Y! _. m# [7 a
  38.         }
    5 I1 ?5 t' F9 K$ `0 z& O& |/ ?
  39.         /**+ l( w& Q6 P' V# S/ t- `3 w( X5 |  G
  40.          * 把cookie写入缓存5 c( p4 p  e/ D: F9 i$ Z6 J9 j* H
  41.          * @param  string $filename 缓存文件名
    7 I6 H, ]- q9 q7 `- Z# x- L+ U+ l, i
  42.          * @param  string $content  文件内容+ ~' r0 i6 N) b7 e
  43.          * @return bool: Z+ v1 V, R" Z. W, u0 n
  44.          */. [( k& l2 X; Y2 f3 k2 R
  45.         public function saveCookie($filename,$content){8 K3 Z- ?, I7 M7 a; M  B# Q
  46.                 return file_put_contents($filename,$content);2 o$ f- ?" |3 y% H
  47.         }( V/ G8 N) n$ ~2 i: \2 l+ {
  48. - ]. o( F8 ~% }" V/ q6 F( A6 x
  49.         /*** F8 S) i# t2 @7 R) i
  50.          * 读取cookie缓存内容" X" p+ ~$ R) I4 c8 v. P
  51.          * @param  string $filename 缓存文件名
    ' {$ p/ ~5 ?4 N2 x; a2 p
  52.          * @return string cookie
    0 u) F( |6 w! ~, Y3 `, L
  53.          */  U6 t% h8 L3 A, Q  a3 ~
  54.         public function getCookie($filename){* L5 L3 o% m+ \1 K
  55.                 if (file_exists($filename)) {
    , C4 {# s3 x3 [* x
  56.                         $mtime = filemtime($filename);
    5 t" V# }- I' _
  57.                         if ($mtime<time()-$this->_cookieexpired) return false;9 a/ g4 ]- f7 g( u1 V
  58.                         $data = file_get_contents($filename);
    * p# ~$ S' s0 v& o; N# a
  59.                         if ($data) $this->cookie = $data;
    2 M( k3 t& z$ U, C' I3 y
  60.                 } 6 E# f) n, \$ ?
  61.                 return $this->cookie;
    % ^- w- a" w( L* t
  62.         }
    5 O; c7 f1 m6 `/ S' f
  63.         ! r' q. c  u* J& c, C0 F1 r
  64.         /*3 O& [" B- [7 h! n- H/ Q
  65.          * 删除cookie8 B0 x% b7 [: I5 D8 j/ H
  66.          */. Z+ o" {4 {% J
  67.         public function deleteCookie($filename) {% z2 q5 a8 @6 @* P0 w- M$ t/ `
  68.                 $this->cookie = '';
    + w9 ]- [; k7 Z% _4 X# D; g
  69.                 @unlink($filename);( P& V3 r) }; j
  70.                 return true;& `* ?8 b+ `- _
  71.         }1 K  K+ Y: V4 B; T% ^5 }
  72.         " Z# w% q6 f& r+ i) c" ^1 J
  73.         private function log($log){- b$ O5 E% `9 A/ p2 r/ m
  74.                 if ($this->debug && function_exists($this->_logcallback)) {. D1 F* s! |) j0 n2 v$ @: A" G) n6 [
  75.                         if (is_array($log)) $log = print_r($log,true);
    - ^  ^# ?, Z& i
  76.                         return call_user_func($this->_logcallback,$log);! t# V: `" Z7 Y' @6 U7 ~: T
  77.                 }
    5 O; I" }3 s& F9 o/ x0 V
  78.         }
      }8 Q4 p. R& Y8 B1 h
  79.         
    % k+ k# f' k3 G
  80.         /**
    ; ?  r, u3 o! N
  81.          * 获取登陆二维码对应的授权码/ Z1 W/ b6 c: e4 j" y3 I! m
  82.          */
    0 i- \# p' E1 U- [
  83.         public function get_login_code(){/ ?1 ~  B" Q4 C( b- s3 ]9 I
  84.                 if ($this->_logincode) return $this->_logincode;1 s" s1 E4 _+ \+ U
  85.                 $t = time().strval(mt_rand(100,999));' B) Y0 g) H3 {$ [9 ]. U& @
  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;+ G6 T) a3 p* ?7 o. v
  87.                 $send_snoopy = new Snoopy; + |6 a; ?7 z& D! E* ], ?- u* S& `
  88.                 $send_snoopy->fetch($codeurl);9 \1 d$ X- A1 R' D4 l
  89.                 $result = $send_snoopy->results;
    - m3 O4 _3 g* [" Z  b
  90.                 if ($result) {
    $ V3 s& @: |, c; ^9 A1 U' ^/ @4 a) T
  91.                         preg_match("/window.QRLogin.uuid\s+=\s+"([^"]+)"/",$result,$matches);& V* v4 F6 ]  e; I/ B/ ~
  92.                         if(count($matches)>1) {
    + G" |: b' I, |# I
  93.                                 $this->_logincode = $matches[1];" A3 X' f5 h$ E0 \; \( D0 d
  94.                                 $_SESSION['login_step'] = 0;5 p9 w# h* [- T5 P+ e6 F
  95.                                 return $this->_logincode;
    , ?& q; {8 q% j; Q; `1 h
  96.                         }
    & Y) E2 {6 h5 M. I0 \
  97.                 }( z, i7 L* E' O5 u  s6 @5 h: [8 n
  98.                 return $result;
    . W/ b# T# J% k* K9 X3 j
  99.         }, {/ z8 T( i7 Q9 S* h* _4 i

  100. , e: g# A2 @2 p! H
  101.         /**5 N- i& W! d( F! k2 S$ D" b( ^
  102.          * 通过授权码获取对应的二维码图片地址
    ; B5 ~- X" D$ q  F+ b0 X$ F# D; }
  103.          * @param string $code
    * `% y: U% s2 ]; S. P
  104.          * @return string image url
    5 Z2 L3 J" T8 c. O
  105.          */" m1 E$ G9 M0 w/ K
  106.         public function get_code_image($code=''){
    + G- d# [' b# p7 y6 u1 o& R1 c
  107.                 if ($code=='') $code = $this->_logincode;% q4 ^; D8 w4 X: ?: }. ^5 m
  108.                 if (!$code) return false;+ l  s6 b) \4 k2 ^4 y: ]% T# A/ o& I
  109.                 return 'http://login.weixin.qq.com/qrcode/'.$this->_logincode.'?t=webwx';, ^/ Y8 R3 M" q* Q7 {7 B; ~
  110.         }
    3 ~9 c$ h" n2 z: v* n/ ^) [
  111.         
    $ o( h' k% t& w/ F# c" z: {
  112.         /**: n( q0 [9 _% a  f2 z, h
  113.          * 设置二维码对应的授权码+ r3 O: D# W# L: s$ c% n
  114.          * @param string $code) i- `9 v" s8 q4 [. j
  115.          * @return class $this
    % j8 L. _) ~7 v3 |  }. [7 g
  116.          */% V' F. m- ?$ B1 @) l0 B; T
  117.         public  function set_login_code($code) {
    7 j6 `$ p2 z8 J! x: |, |
  118.                 $this->_logincode = $code;
    " y2 Y  n$ t  C# k
  119.                 return $this;) S& P1 f& ~* c" ?/ |
  120.         }: ^" }- k/ @9 F* C, ]0 u
  121.         
    0 ]6 t- H; d- j5 N) J! |" T& ]  j
  122.         /**8 l' \7 W* p& w" s
  123.          * 二维码登陆验证1 A/ g2 C; A2 \& D9 Z6 L8 x8 z
  124.          *
    8 s2 d- C% T+ U+ g0 n" x3 b# F
  125.          * @return status:; y& \& Q( A; b: U4 \, d8 q6 q3 n/ p
  126.          * >=400: invaild code; 408: not auth and wait, 400,401: not valid or expired# m4 [+ q/ }$ A) @; p; p
  127.          * 201: just scaned but not confirm0 Z. ~. B. _, f4 {3 R
  128.          * 200: confirm then you can get user info6 b( P( M' t$ [8 |- f$ ^# M
  129.          */! P+ S' j1 D. O' I
  130.         public function verify_code() {
    3 m% ]3 t! D5 A5 {/ D) P: [
  131.                 if (!$this->_logincode) return false;* l5 A, w" @( C  K" c  r
  132.                 $t = time().strval(mt_rand(100,999));0 I1 X9 m5 C, \( H5 B, Y  L
  133. 6 }! \4 s: W1 m: u, a
  134.                         $url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid='.$this->_logincode.'&tip=1&_='.$t;
    , Z4 s, b6 O3 N/ X' N2 I# e, L0 k
  135.                         $send_snoopy = new Snoopy; : O' N" s; [! r/ [1 L- M1 v
  136.                         $send_snoopy->referer = "https://wx.qq.com/";0 d8 f9 K' ^4 D) B, `  f( X1 t
  137.                         $send_snoopy->fetch($url);
    ( B& I4 j% {+ M7 |- S8 A
  138.                         $result = $send_snoopy->results;
    , c2 }+ U/ m* W1 X
  139.                         $this->log('step1:'.$result);
    1 h/ e/ [9 T+ H/ ]: D
  140.                         if ($result) {
    2 V* M: N- A4 G  n. ^
  141.                                 preg_match("/window\.code=(\d+)/",$result,$matches);& d( U9 {% s/ b( h/ A" q3 L+ n
  142.                                 if(count($matches)>1) {
    , Q& p- k7 ]0 E6 F1 v
  143.                                         $status = intval($matches[1]);# m, i/ k4 b& J% y$ t% x. ^; N
  144.                                         if ($status==201) $_SESSION['login_step'] = 1;
    1 C* X3 r, f4 q+ U; w( N
  145.                                         if ($status==200) {
    . @. T' j' k% }& _
  146.                                                 preg_match("/ticket=([0-9a-z-_]+)&lang=zh_CN&scan=(\d+)/",$result,$matches);
    + n, w, h4 ~* ]
  147.                                                 $this->log('step2:'.print_r($matches,true));
    ! x, D; I# j, t7 i& n7 a
  148.                                                 if (count($matches)>1) {0 s1 f) |% ^7 j) U/ ?
  149.                                                         $ticket = $matches[1];2 y2 p4 o2 X, S1 b$ ~- `; N
  150.                                                         $scan = $matches[2];4 [$ D7 U! {- Y% X
  151.                                                         $loginurl = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket='.$ticket.'&lang=zh_CN&scan='.$scan.'&fun=new';8 @" j( m# ]6 W/ F/ O
  152.                                                         $send_snoopy = new Snoopy; 2 h" I% b0 W9 b0 l/ T) I- ~- P
  153.                                                         $send_snoopy->referer = "https://wx.qq.com/";" H! A; Y- A+ e& s) n0 T
  154.                                                         $send_snoopy->fetch($loginurl);
    5 d- I0 z* o  e3 [+ T. A4 U
  155.                                                         $this->log('step3:'.print_r($send_snoopy->headers,true));( G7 g: H* i7 Q6 K: ?/ s+ h
  156.                                                         foreach ($send_snoopy->headers as $key => $value) {
    ) l0 U1 D0 @% N) ~$ ^
  157.                                                                 $value = trim($value);
    & w* H! W6 G% E8 g& P, _/ g
  158.                                                                 if(strpos($value,'Set-Cookie: ') !== false){
    0 n! E6 E6 u; L2 |( Y% |
  159.                                                                         $tmp = str_replace("Set-Cookie: ","",$value);5 K( b0 y& ~: i3 V4 u
  160.                                                                         $tmp = str_replace("Path=/","",$tmp);
    ( l+ M: H  }4 X& W- s
  161.                                                                         $tmp = str_replace("Domain=.qq.com; ","",$tmp);% [- B+ D% Z) n2 ~; e) a: K
  162.                                                                         $cookie.=$tmp;2 x8 U, Z0 N% W% p; w
  163.                                                                 }! j+ x+ _6 O8 M7 N
  164.                                                         }
    # v$ H/ T/ ~* s9 l
  165.                                                         $cookie .="Domain=.qq.com;";
    : ?, Q, u# }1 Q  C" Q
  166.                                                         $this->cookie = $cookie;
    1 c" u5 @- }3 a: d# j+ Y
  167.                                                         $this->saveCookie($this->_cookiename,$this->cookie);
    - u& Z( L& |7 B# }( C
  168.                                                 }
    . v& j9 o( d% n' O+ H, n2 c; U+ f! `
  169.                                         }! J' ?2 v4 A4 e3 g, G/ W
  170.                                         return $status;
    * G: z- H7 y! l2 |. d( M+ q; C0 Z
  171.                                 }. }6 w. r9 [7 f! o+ s
  172.                         }. m' u2 D2 x# E* E0 ?' Y
  173.                 return false;/ c  X: U' G! ?- A9 b% ~8 R
  174.         }
    & x8 ?, X# ?9 H7 Z
  175.         
    % n4 r' g. U" e" `6 c* D
  176.         /**
    2 v  c6 x* q  k+ s, b
  177.          * 获取登陆的cookie$ W" E8 d' b! _) E
  178.          *) ]5 e( e! Q! H$ T
  179.          * @param bool $is_array 是否以数值方式返回,默认否,返回字符串
    # P% y3 _7 t9 G# r/ ^* g. O
  180.          * @return string|array
    ; y1 _& a' R8 n8 M& ~
  181.          */3 d( c. h4 u, P; d3 l7 L
  182.         public function get_login_cookie($is_array = false){
    3 d8 W& p% k6 d$ N" ^/ Y' t0 \# C
  183.                 if (!$is_array)        return $this->cookie;, X7 T6 I9 b, Z5 @( f# x) }8 `
  184.                 $c_arr = explode(';',$this->cookie);, q, S; `. }$ K" \. Q: c
  185.                 $cookie = array();
    / f, c- e* Y" n  D. L
  186.                 foreach($c_arr as $item) {
      f4 U* `- R9 B& g8 _. x
  187.                         $kitem = explode('=',trim($item));6 q9 F9 X3 d6 O  o/ T# l0 v
  188.                         if (count($kitem)>1) {6 c9 B; P7 X% r: ]6 x+ Q: V! D
  189.                                 $key = trim($kitem[0]);$ c  s0 {2 {0 l/ J7 z$ ?/ e4 v
  190.                                 $val = trim($kitem[1]);& P$ c+ q0 V! l. U- @  v1 z
  191.                                 if (!empty($val)) $cookie[$key] = $val;
    ; Z8 `/ U7 K1 b# s% Y; j
  192.                         }
    1 v# `( o& W, c6 J' e
  193.                 }
    1 {0 M2 P$ h% ]) i5 F0 g3 d
  194.                 return $cookie;
    , M9 @5 C& i4 d: _8 C. W2 h$ W
  195.         }
      M" X. X6 U# Q) a
  196.         & S% S" b/ _' D, y( @
  197.         /**  j) _* A, c2 d1 v3 w
  198.          *          授权登陆后获取用户登陆信息
    5 j; j! E4 S6 O1 Z) _0 D
  199.          */
    2 Z, k# A0 ?/ ]. H! m; p; T
  200.         public function get_login_info(){0 }2 E; E2 R5 {% h
  201.                 if (!$this->cookie) return false;  I; ?0 K+ z# W9 n, x
  202.                 $t = time().strval(mt_rand(100,999));
    : k: l/ x5 G1 Y+ r/ U4 e& }: Z
  203.                 $send_snoopy = new Snoopy; " s8 N9 b1 J& I( Q0 F
  204.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r='.$t;* H' R% q* ]. C+ Q. x- f; |- b
  205.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;
    # [: s8 k( i0 `+ {
  206.                 $send_snoopy->referer = "https://wx.qq.com/";
    ( V3 b) |" R5 G6 ^
  207.                 $send_snoopy->submit($submit,array());/ e4 s+ R) y( W6 F+ m
  208.                 $this->log('login_info:'.$send_snoopy->results);1 u: I$ C3 d0 P( @, S% n8 y
  209.                 $result = json_decode($send_snoopy->results,true);% L$ L1 s  L* U4 B7 x# [; h
  210.                 if ($result['BaseResponse']['Ret']<0) return false;
    , x* N, E1 \' K3 i  k
  211.                 $this->_login_user = $result['User'];
    ' l" t: w# t) l5 u: t  D) i, @0 s
  212.                 return $result;
    & G% E: q. U9 g+ c4 ?
  213.         }
    / M. T# G6 R7 P! N
  214.         
    2 K/ j! Q( n9 O7 W9 l' _2 h
  215.         /**
    " x! K4 a# X1 F, |
  216.          *  获取头像( j) n1 @1 g( L& z2 n! g8 G
  217.          *  @param string $url 传入从用户信息接口获取到的头像地址/ p: [, m0 D; x3 ^
  218.          */
    ) @% g* ~+ A+ d+ P- [! o
  219.         public function get_avatar($url) {
    ! j4 m' J6 m, q! h
  220.                 if (!$this->cookie) return false;3 D5 o  c8 r1 x7 W
  221.                 if (strpos($url, 'http')===false) {
    2 G( n( v( P! ~! R% R
  222.                         $url = 'http://wx.qq.com'.$url;
    9 ]" Q/ L6 L  S# V- S! s) _3 `
  223.                 }0 w* }& `8 P& U7 I4 N) l4 R
  224.                 $send_snoopy = new Snoopy; % u1 P8 A) x( i  r! i. O! C
  225.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;7 d2 B4 H$ F# f; i
  226.                 $send_snoopy->referer = "https://wx.qq.com/";( A' y2 C! T0 e) O# R3 l) Z7 ~
  227.                 $send_snoopy->fetch($url);& g" ]  V; e; @- f; {
  228.                 $result = $send_snoopy->results;
    3 g: t# A1 l) h
  229.                 if ($result) ; Q" E% U5 G) d
  230.                         return $result;
    ! g. p0 D5 X% A7 J; t& M, f
  231.                 else
    1 f, n6 M, q8 ], M
  232.                         return false;
    % M& \5 g6 T6 ~! v3 C8 P
  233.         }- {: U. n0 l2 U8 f3 b( d) _
  234.         , \7 x% T5 o7 ^1 q% J* I7 m
  235.         /**2 _9 _; i+ e" x6 Y8 a8 H( E: D) J
  236.          * 登出当前登陆用户
    0 F6 r2 k6 j- `; L! U! t
  237.          */
    : F4 t4 t8 I0 c3 L8 O
  238.         public function logout(){
    ' H3 j: w9 B; M) V7 u- u
  239.                 if (!$this->cookie) return false;% I, {, O6 z, Q
  240.                 preg_match("/wxuin=(\w+);/",$this->cookie,$matches);
      H; I9 R$ n) q  k7 Y% v# s
  241.                 if (count($matches)>1) $uid = $matches[1];# d/ @4 \: H. ]( G$ z. M; W
  242.                 preg_match("/wxsid=(\w+);/",$this->cookie,$matches);
    $ B( a6 e+ z1 a# {- K5 x
  243.                 if (count($matches)>1) $sid = $matches[1];& P& P6 e0 `- Z8 b$ Q" g+ D: B
  244.                 $this->log('logout: uid='.$uid.';sid='.$sid);" ]! g; |5 F- M2 h8 b
  245.                 $send_snoopy = new Snoopy; ) m/ B/ x, y4 I7 {8 i; d
  246.                 $submit = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout?redirect=1&type=1';
    / o2 \6 M' [9 O+ @! Q& F9 |
  247.                 $send_snoopy->rawheaders['Cookie']= $this->cookie;% x) l5 j% E- d+ }% d5 M4 t
  248.                 $send_snoopy->referer = "https://wx.qq.com/";
    ! x2 q4 k" Y% O, R$ K% h  T
  249.                 $send_snoopy->submit($submit,array('uin'=>$uid,'sid'=>$sid));
    / `" z; l, a7 k+ g$ Y
  250.                 $this->deleteCookie($this->_cookiename);% }& g0 w" h5 D5 E/ f
  251.                 return true;7 ?4 Q' G" W. e
  252.         }3 r& S, n+ P8 W3 [
  253. }
复制代码

! w* ?- w/ w  K; d




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

使用道具 举报

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

支付宝扫一扫打赏

微信扫一扫打赏

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