Home > php教程 > PHP源码 > thinkcmf增加微信自动登录

thinkcmf增加微信自动登录

PHP中文网
Release: 2016-05-23 16:41:06
Original
1922 people have browsed it

配置文件:
'THINK_SDK_WEIXIN' => array(
'APP_KEY' => 'xxxxxxxx',
'APP_SECRET' => '7xxxxxxxxxxxxxxxxx',
'AUTHORIZE' => 'response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect',
'CALLBACK' => 'http://host/index.php?g=api&m=oauth&a=callback&type=weixin',
        ),

ThinkOauth.class.php

<?php
// +----------------------------------------------------------------------
// | TOPThink [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// | ThinkOauth.class.php 2013-02-25
// +----------------------------------------------------------------------
 
abstract class ThinkOauth{
    /**
     * oauth版本
     * @var string
     */
    protected $Version = &#39;2.0&#39;;
     
    /**
     * 申请应用时分配的app_key
     * @var string
     */
    protected $AppKey = &#39;&#39;;
     
    /**
     * 申请应用时分配的 app_secret
     * @var string
     */
    protected $AppSecret = &#39;&#39;;
     
    /**
     * 授权类型 response_type 目前只能为code
     * @var string
     */
    protected $ResponseType = &#39;code&#39;;
     
    /**
     * grant_type 目前只能为 authorization_code
     * @var string 
     */
    protected $GrantType = &#39;authorization_code&#39;;
     
    /**
     * 回调页面URL  可以通过配置文件配置
     * @var string
     */
    protected $Callback = &#39;&#39;;
     
    /**
     * 获取request_code的额外参数 URL查询字符串格式
     * @var srting
     */
    protected $Authorize = &#39;&#39;;
     
    /**
     * 获取request_code请求的URL
     * @var string
     */
    protected $GetRequestCodeURL = &#39;&#39;;
     
    /**
     * 获取access_token请求的URL
     * @var string
     */
    protected $GetAccessTokenURL = &#39;&#39;;
 
    /**
     * API根路径
     * @var string
     */
    protected $ApiBase = &#39;&#39;;
     
    /**
     * 授权后获取到的TOKEN信息
     * @var array
     */
    protected $Token = null;
 
    /**
     * 调用接口类型
     * @var string
     */
    private $Type = &#39;&#39;;
     
    /**
     * 构造方法,配置应用信息
     * @param array $token 
     */
    public function __construct($token = null){
        //设置SDK类型
        $class = get_class($this);
        $this->Type = strtoupper(substr($class, 0, strlen($class)-3));
 
        //获取应用配置
        $config = C("THINK_SDK_{$this->Type}");
        if(empty($config[&#39;APP_KEY&#39;]) || empty($config[&#39;APP_SECRET&#39;])){
            throw new Exception(&#39;请配置您申请的APP_KEY和APP_SECRET&#39;);
        } else {
            $this->AppKey    = $config[&#39;APP_KEY&#39;];
            $this->AppSecret = $config[&#39;APP_SECRET&#39;];
            $this->Token     = $token; //设置获取到的TOKEN
        }
    }
 
    /**
     * 取得Oauth实例
     * @static
     * @return mixed 返回Oauth
     */
    public static function getInstance($type, $token = null) {
        $name = ucfirst(strtolower($type)) . &#39;SDK&#39;;
        require_once "sdk/{$name}.class.php";
        if (class_exists($name)) {
            return new $name($token);
        } else {
            E(L(&#39;_CLASS_NOT_EXIST_&#39;) . &#39;:&#39; . $name);
        }
    }
 
    /**
     * 初始化配置
     */
    private function config(){
        $config = C("THINK_SDK_{$this->Type}");
        if(!empty($config[&#39;AUTHORIZE&#39;]))
            $this->Authorize = $config[&#39;AUTHORIZE&#39;];
        if(!empty($config[&#39;CALLBACK&#39;]))
            $this->Callback = $config[&#39;CALLBACK&#39;];
        else
            throw new Exception(&#39;请配置回调页面地址&#39;);
    }
 
    protected function getAppKeyParamName() {
        return "client_id";
    }
 
    protected function getAppSecretParamName() {
        return "client_secret";
    }
    /**
     * 请求code 
     */
    public function getRequestCodeURL(){
        $this->config();
        //Oauth 标准参数
        $params = array();
        $params[$this->getAppKeyParamName()] = $this->AppKey;
        $params[&#39;redirect_uri&#39;] = $this->Callback;
        $params[&#39;response_type&#39;] = $this->ResponseType;
 
        //获取额外参数
        if($this->Authorize){
            parse_str($this->Authorize, $_param);
            if(is_array($_param)){
                $params = array_merge($params, $_param);
            } else {
                throw new Exception(&#39;AUTHORIZE配置不正确!&#39;);
            }
        }
        return $this->GetRequestCodeURL . &#39;?&#39; . http_build_query($params);
 
    }
     
    /**
     * 获取access_token
     * @param string $code 上一步请求到的code
     */
    public function getAccessToken($code, $extend = null){
        $this->config();
        $params = array(
                &#39;grant_type&#39;    => $this->GrantType,
                &#39;code&#39;          => $code,
                &#39;redirect_uri&#39;  => $this->Callback,
        );
        $params[$this->getAppKeyParamName()] = $this->AppKey;
        $params[$this->getAppSecretParamName()] = $this->AppSecret;
        $data = $this->http($this->GetAccessTokenURL, $params, &#39;POST&#39;);
        $this->Token = $this->parseToken($data, $extend);
        return $this->Token;
    }
 
    /**
     * 合并默认参数和额外参数
     * @param array $params  默认参数
     * @param array/string $param 额外参数
     * @return array:
     */
    protected function param($params, $param){
        if(is_string($param))
            parse_str($param, $param);
        return array_merge($params, $param);
    }
 
    /**
     * 获取指定API请求的URL
     * @param  string $api API名称
     * @param  string $fix api后缀
     * @return string      请求的完整URL
     */
    protected function url($api, $fix = &#39;&#39;){
        return $this->ApiBase . $api . $fix;
    }
     
    /**
     * 发送HTTP请求方法,目前只支持CURL发送请求
     * @param  string $url    请求URL
     * @param  array  $params 请求参数
     * @param  string $method 请求方法GET/POST
     * @return array  $data   响应数据
     */
    protected function http($url, $params, $method = &#39;GET&#39;, $header = array(), $multi = false){
        $opts = array(
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER     => $header
        );
 
        /* 根据请求类型设置特定参数 */
        switch(strtoupper($method)){
            case &#39;GET&#39;:
                $opts[CURLOPT_URL] = $url . &#39;?&#39; . http_build_query($params);
                break;
            case &#39;POST&#39;:
                //判断是否传输文件
                $params = $multi ? $params : http_build_query($params);
                $opts[CURLOPT_URL] = $url;
                $opts[CURLOPT_POST] = 1;
                $opts[CURLOPT_POSTFIELDS] = $params;
                break;
            default:
                throw new Exception(&#39;不支持的请求方式!&#39;);
        }
         
        /* 初始化并执行curl请求 */
        $ch = curl_init();
        curl_setopt_array($ch, $opts);
        $data  = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);
        if($error) throw new Exception(&#39;请求发生错误:&#39; . $error);
        return  $data;
    }
     
    /**
     * 抽象方法,在SNSSDK中实现
     * 组装接口调用参数 并调用接口
     */
    abstract protected function call($api, $param = &#39;&#39;, $method = &#39;GET&#39;, $multi = false);
     
    /**
     * 抽象方法,在SNSSDK中实现
     * 解析access_token方法请求后的返回值
     */
    abstract protected function parseToken($result, $extend);
     
    /**
     * 抽象方法,在SNSSDK中实现
     * 获取当前授权用户的SNS标识
     */
    abstract public function openid();  
}
Copy after login

WeixinSDK.class.php

<?php
/**
 * Created by PhpStorm.
 * User: jeffrey zuo
 * Email: zuoyaofei@icloud.com
 * Date: 2015/8/5
 * Time: 10:57
 */
 
class WeixinSDK extends ThinkOauth {
    /**
     * 获取requestCode的api接口
     * @var string
     */
    protected $GetRequestCodeURL = &#39;https://open.weixin.qq.com/connect/oauth2/authorize&#39;;
 
    /**
     * 获取access_token的api接口
     * @var string
     */
    protected $GetAccessTokenURL = &#39;https://api.weixin.qq.com/sns/oauth2/access_token&#39;;
 
    /**
     * 获取request_code的额外参数,可在配置中修改 URL查询字符串格式
     * @var srting
     */
    protected $Authorize = &#39;&#39;;
 
    /**
     * API根路径
     * @var string
     */
    protected $ApiBase = &#39;https://api.weixin.qq.com/&#39;;
 
    /**
     * 抽象方法,在SNSSDK中实现
     * 组装接口调用参数 并调用接口
     */
    public function call($api, $param = &#39;&#39;, $method = &#39;GET&#39;, $multi = false)
    {
        /* 微信调用公共参数 */
        $params = array(
            &#39;access_token&#39;       => $this->Token[&#39;access_token&#39;],
            &#39;openid&#39;             => $this->openid(),
            &#39;lang&#39;             => &#39;zh_CN&#39;
        );
        $data = $this->http($this->url($api), $this->param($params, $param), $method);
        return json_decode($data, true);
    }
 
    /**
     * 抽象方法,在SNSSDK中实现
     * 解析access_token方法请求后的返回值
     */
    protected function parseToken($result, $extend)
    {
        $data = json_decode($result, true);
        if($data[&#39;access_token&#39;] && $data[&#39;expires_in&#39;]){
            $this->Token    = $data;
            $data[&#39;openid&#39;] = $this->openid();
            return $data;
        } else
            throw new Exception("获取微信 ACCESS_TOKEN 出错:{$result}");
    }
 
    /**
     * 抽象方法,在SNSSDK中实现
     * 获取当前授权用户的SNS标识
     */
    public function openid()
    {
        $data = $this->Token;
        return $data[&#39;openid&#39;];
    }
 
    protected function getAppKeyParamName() {
        return "appid";
    }
 
    protected function getAppSecretParamName() {
        return "secret";
    }
}
Copy after login

TypeEvent.class.php

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// TypeEvent.class.php 2013-02-27
namespace Api\Event;
 
class TypeEvent{
    //登录成功,获取腾讯QQ用户信息
    public function qq($token){
        //import("ORG.ThinkSDK.ThinkOauth");
        $qq   = \ThinkOauth::getInstance(&#39;qq&#39;, $token);
        $data = $qq->call(&#39;user/get_user_info&#39;);
 
        if($data[&#39;ret&#39;] == 0){
            $userInfo[&#39;type&#39;] = &#39;QQ&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;nickname&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;nickname&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;figureurl_2&#39;];
            return $userInfo;
        } else {
            throw_exception("获取腾讯QQ用户信息失败:{$data[&#39;msg&#39;]}");
        }
    }
 
    //登录成功,获取腾讯微博用户信息
    public function tencent($token){
        //import("ORG.ThinkSDK.ThinkOauth");
        $tencent = ThinkOauth::getInstance(&#39;tencent&#39;, $token);
        $data    = $tencent->call(&#39;user/info&#39;);
 
        if($data[&#39;ret&#39;] == 0){
            $userInfo[&#39;type&#39;] = &#39;TENCENT&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;data&#39;][&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;data&#39;][&#39;nick&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;data&#39;][&#39;head&#39;];
            return $userInfo;
        } else {
            throw_exception("获取腾讯微博用户信息失败:{$data[&#39;msg&#39;]}");
        }
    }
 
    //登录成功,获取新浪微博用户信息
    public function sina($token){
        $sina = \ThinkOauth::getInstance(&#39;sina&#39;, $token);
        $data = $sina->call(&#39;users/show&#39;, "uid={$sina->openid()}");
 
        if($data[&#39;error_code&#39;] == 0){
            $userInfo[&#39;type&#39;] = &#39;SINA&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;screen_name&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;avatar_large&#39;];
            return $userInfo;
        } else {
            throw_exception("获取新浪微博用户信息失败:{$data[&#39;error&#39;]}");
        }
    }
 
    //登录成功,获取网易微博用户信息
    public function t163($token){
        $t163 = ThinkOauth::getInstance(&#39;t163&#39;, $token);
        $data = $t163->call(&#39;users/show&#39;);
 
        if($data[&#39;error_code&#39;] == 0){
            $userInfo[&#39;type&#39;] = &#39;T163&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;screen_name&#39;];
            $userInfo[&#39;head&#39;] = str_replace(&#39;w=48&h=48&#39;, &#39;w=180&h=180&#39;, $data[&#39;profile_image_url&#39;]);
            return $userInfo;
        } else {
            throw_exception("获取网易微博用户信息失败:{$data[&#39;error&#39;]}");
        }
    }
 
    //登录成功,获取人人网用户信息
    public function renren($token){
        $renren = ThinkOauth::getInstance(&#39;renren&#39;, $token);
        $data   = $renren->call(&#39;users.getInfo&#39;);
 
        if(!isset($data[&#39;error_code&#39;])){
            $userInfo[&#39;type&#39;] = &#39;RENREN&#39;;
            $userInfo[&#39;name&#39;] = $data[0][&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[0][&#39;name&#39;];
            $userInfo[&#39;head&#39;] = $data[0][&#39;headurl&#39;];
            return $userInfo;
        } else {
            throw_exception("获取人人网用户信息失败:{$data[&#39;error_msg&#39;]}");
        }
    }
 
    //登录成功,获取360用户信息
    public function x360($token){
        $x360 = ThinkOauth::getInstance(&#39;x360&#39;, $token);
        $data = $x360->call(&#39;user/me&#39;);
 
        if($data[&#39;error_code&#39;] == 0){
            $userInfo[&#39;type&#39;] = &#39;X360&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;avatar&#39;];
            return $userInfo;
        } else {
            throw_exception("获取360用户信息失败:{$data[&#39;error&#39;]}");
        }
    }
 
    //登录成功,获取豆瓣用户信息
    public function douban($token){
        $douban = ThinkOauth::getInstance(&#39;douban&#39;, $token);
        $data   = $douban->call(&#39;user/~me&#39;);
 
        if(empty($data[&#39;code&#39;])){
            $userInfo[&#39;type&#39;] = &#39;DOUBAN&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;avatar&#39;];
            return $userInfo;
        } else {
            throw_exception("获取豆瓣用户信息失败:{$data[&#39;msg&#39;]}");
        }
    }
 
    //登录成功,获取Github用户信息
    public function github($token){
        $github = ThinkOauth::getInstance(&#39;github&#39;, $token);
        $data   = $github->call(&#39;user&#39;);
 
        if(empty($data[&#39;code&#39;])){
            $userInfo[&#39;type&#39;] = &#39;GITHUB&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;login&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;avatar_url&#39;];
            return $userInfo;
        } else {
            throw_exception("获取Github用户信息失败:{$data}");
        }
    }
 
    //登录成功,获取Google用户信息
    public function google($token){
        $google = ThinkOauth::getInstance(&#39;google&#39;, $token);
        $data   = $google->call(&#39;userinfo&#39;);
 
        if(!empty($data[&#39;id&#39;])){
            $userInfo[&#39;type&#39;] = &#39;GOOGLE&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;picture&#39;];
            return $userInfo;
        } else {
            throw_exception("获取Google用户信息失败:{$data}");
        }
    }
 
    //登录成功,获取Google用户信息
    public function msn($token){
        $msn  = ThinkOauth::getInstance(&#39;msn&#39;, $token);
        $data = $msn->call(&#39;me&#39;);
 
        if(!empty($data[&#39;id&#39;])){
            $userInfo[&#39;type&#39;] = &#39;MSN&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;head&#39;] = &#39;微软暂未提供头像URL,请通过 me/picture 接口下载&#39;;
            return $userInfo;
        } else {
            throw_exception("获取msn用户信息失败:{$data}");
        }
    }
 
    //登录成功,获取点点用户信息
    public function diandian($token){
        $diandian  = ThinkOauth::getInstance(&#39;diandian&#39;, $token);
        $data      = $diandian->call(&#39;user/info&#39;);
 
        if(!empty($data[&#39;meta&#39;][&#39;status&#39;]) && $data[&#39;meta&#39;][&#39;status&#39;] == 200){
            $userInfo[&#39;type&#39;] = &#39;DIANDIAN&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;response&#39;][&#39;name&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;response&#39;][&#39;name&#39;];
            $userInfo[&#39;head&#39;] = "https://api.diandian.com/v1/blog/{$data[&#39;response&#39;][&#39;blogs&#39;][0][&#39;blogUuid&#39;]}/avatar/144";
            return $userInfo;
        } else {
            throw_exception("获取点点用户信息失败:{$data}");
        }
    }
 
    //登录成功,获取淘宝网用户信息
    public function taobao($token){
        $taobao = ThinkOauth::getInstance(&#39;taobao&#39;, $token);
        $fields = &#39;user_id,nick,sex,buyer_credit,avatar,has_shop,vip_info&#39;;
        $data   = $taobao->call(&#39;taobao.user.buyer.get&#39;, "fields={$fields}");
         
        if(!empty($data[&#39;user_buyer_get_response&#39;][&#39;user&#39;])){
            $user = $data[&#39;user_buyer_get_response&#39;][&#39;user&#39;];
            $userInfo[&#39;type&#39;] = &#39;TAOBAO&#39;;
            $userInfo[&#39;name&#39;] = $user[&#39;user_id&#39;];
            $userInfo[&#39;nick&#39;] = $user[&#39;nick&#39;];
            $userInfo[&#39;head&#39;] = $user[&#39;avatar&#39;];
            return $userInfo;
        } else {
            throw_exception("获取淘宝网用户信息失败:{$data[&#39;error_response&#39;][&#39;msg&#39;]}");
        }
    }
     
    //登录成功,获取百度用户信息
    public function baidu($token){
        $baidu = ThinkOauth::getInstance(&#39;baidu&#39;, $token);
        $data  = $baidu->call(&#39;passport/users/getLoggedInUser&#39;);
         
        if(!empty($data[&#39;uid&#39;])){
            $userInfo[&#39;type&#39;] = &#39;BAIDU&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;uid&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;uname&#39;];
            $userInfo[&#39;head&#39;] = "http://tb.himg.baidu.com/sys/portrait/item/{$data[&#39;portrait&#39;]}";
            return $userInfo;
        } else {
            throw_exception("获取百度用户信息失败:{$data[&#39;error_msg&#39;]}");
        }
    }
 
    //登录成功,获取开心网用户信息
    public function kaixin($token){
        $kaixin = ThinkOauth::getInstance(&#39;kaixin&#39;, $token);
        $data   = $kaixin->call(&#39;users/me&#39;);
         
        if(!empty($data[&#39;uid&#39;])){
            $userInfo[&#39;type&#39;] = &#39;KAIXIN&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;uid&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;name&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;logo50&#39;];
            return $userInfo;
        } else {
            throw_exception("获取开心网用户信息失败:{$data[&#39;error&#39;]}");
        }
    }
 
    //登录成功,获取搜狐用户信息
    public function sohu($token){
        $sohu = ThinkOauth::getInstance(&#39;sohu&#39;, $token);
        $data = $sohu->call(&#39;i/prv/1/user/get-basic-info&#39;);
         
        if(&#39;success&#39; == $data[&#39;message&#39;] && !empty($data[&#39;data&#39;])){
            $userInfo[&#39;type&#39;] = &#39;SOHU&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;data&#39;][&#39;open_id&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;data&#39;][&#39;nick&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;data&#39;][&#39;icon&#39;];
            return $userInfo;
        } else {
            throw_exception("获取搜狐用户信息失败:{$data[&#39;message&#39;]}");
        }
    }
 
    //登录成功,获取微信用户信息
    public function weixin($token) {
        $weixin   = \ThinkOauth::getInstance(&#39;weixin&#39;, $token);
        $data = $weixin->call(&#39;sns/userinfo&#39;);
        //{"errcode":48001,"errmsg":"req id: _J0076ns23, api unauthorized"}
        if (empty($data[&#39;ret&#39;])) {
            if (!empty($data[&#39;errcode&#39;])) {
                throw_exception("获取微信用户信息失败:errcode:{$data[&#39;errcode&#39;]} errmsg: {$data[&#39;errmsg&#39;]}");
            }
        }
        if($data[&#39;ret&#39;] == 0){
            $userInfo[&#39;type&#39;] = &#39;WEIXIN&#39;;
            $userInfo[&#39;name&#39;] = $data[&#39;nickname&#39;];
            $userInfo[&#39;nick&#39;] = $data[&#39;nickname&#39;];
            $userInfo[&#39;head&#39;] = $data[&#39;headimgurl&#39;];
            return $userInfo;
        } else {
            throw_exception("获取微信用户信息失败:{$data[&#39;msg&#39;]}");
        }
    }
 
}
Copy after login
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Recommendations
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template