基于TP5、EasyWeChat、fastadmin微信公众号网页授权登录

第一种使用EasyWeChat拉起登录

使用 composer 安装 EasyWeChat

$ composer require overtrue/wechat:~5.0 -vvv

或者在composer.json文件renquire里面添加

"overtrue/wechat": "4.2.11",

接着 composer update 就可以了

use EasyWeChat\Factory;

class Login extends Api
{
    protected $app;
    protected $oauth;
    protected $config;
    protected $noNeedLogin = ['getCode', 'loginRes'];
    protected $noNeedRight = ['*'];

	// 基本配置
    public function _initialize()
    {
        parent::_initialize();
        // 这里的配置信息可以写入基本配置里面,这里只是为了练手
        $this->config = [
            'app_id' => "wx04ff******edd2a1",
            'secret' => "581671ce************5c4f634b321e",
            // 下面为可选项
            // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',

            'log' => [
                'level' => 'debug',
                'file'  =>  ROOT_PATH . '/public/logs/wxOfficialAccountsLogin.log'
            ],
            'oauth' => [
                'scopes'   => ['snsapi_userinfo'],
                'callback' => $this->request->domain() . '/api/Login/loginRes'
            ],
        ];
        $this->app = Factory::officialAccount($this->config);
        $this->oauth = $this->app->oauth;
    }

    /**
     * 网页授权获取code
     */
    public function getCode(){
        // TODO 前期测试用于清空值 session('wechat_user',NULL);
        if (!session('wechat_user')) {
            return $this->oauth->redirect()->send();
        }else {
            $this->success('授权登录成功(缓存)', session('wechat_user'));
        }
    }

    /**
     * 授权登录
     */
    public function loginRes()
    {
        $code = $this->request->param('code');

        if(!$code){
            $this->error(__('缺少参数code!'));
        }

        $wechat_user = $this->oauth->user();

        $result = json_decode(json_encode($wechat_user),true);

        /* $result 输出结果
         * Array (
            [id] => oaWII632e55s0ZuqCRQHsYQkMgFE
            [name] => 霍文霆
            [nickname] => 霍文霆
            [avatar] => https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJn6TuXOPKCAsrDl8SfriaZcaetY04blVTKVE0deman5ApWIOe6uPOXfK8Rq5MhEETaS1ulIE4whXQ/132
            [email] =>
            [original] => Array (
                [openid] => oaWII632e55s0ZuqCRQHsYQkMgFE
                [nickname] => 霍文霆
                [sex] => 1
                [language] => zh_CN
                [city] =>
                [province] => 安徽
                [country] => 中国
                [headimgurl] => https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJn6TuXOPKCAsrDl8SfriaZcaetY04blVTKVE0deman5ApWIOe6uPOXfK8Rq5MhEETaS1ulIE4whXQ/132
                [privilege] => Array ( )
            )
            [token] => 44_XMZF2a0HHwE7Z268c_Qoi44a75hIvvw9lQi6I072ws2lop22xcYXMHoKWoA_NOo0hFH18aeXDrLejOBPf75A0Q
            [access_token] => 44_XMZF2a0HHwE7Z268c_Qoi44a75hIvvw9lQi6I072ws2lop22xcYXMHoKWoA_NOo0hFH18aeXDrLejOBPf75A0Q
            [refresh_token] => 44_SAM1LhD3MrQZ-xYc6uDP6fvglzDhl82wI_k2GM8wbUlG-6AcR22pXflwMTIg5fTwmYYFRYZuGhzD3ZuHE894VA
            [provider] => WeChat
        )*/

        // 分参
        extract($result);

        if (!empty($result)) {

            $user = User::get(['openid' => $original['openid']]);

            if ($user) {
                if ($user->status != 'normal') {
                    $this->error(__('Account is locked'));
                }
                // 每次调用都会更新一次用户基本数据---例如用户修改头像和昵称,这样就会实时更新数据了
                $user->nickname = base64_decode(base64_encode($original['nickname']));
                $user->avatar = $original['headimgurl'];
                $user->save();
                // 直接登陆
                $ret = $this->auth->direct($user->id);
            } else {
                $ret = $this->auth->wxOfficialAccountsLogin($original);
            }

            if ($ret) {
                $wechat_user = $this->auth->getUserInfo();

                // 把用户登录信息写入session中,这样就不需要每次都发起请求了
                session('wechat_user', $wechat_user);

                $this->success('授权登录成功', $wechat_user);
            } else {
                $this->error('授权登录失败了!');
            }
        }else{
            $this->error(__('授权登录失败了!'));
        }
    }


    /* loginRes() 输出结果
     * {
        "code":1,
        "msg":"授权登录成功",
        "time":"1620469689",
        "data":{
            "id":3,
            "nickname":"霍文霆",
            "avatar":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q0j4TwGTfTJn6TuXOPKCAsrDl8SfriaZcaetY04blVTKVE0deman5ApWIOe6uPOXfK8Rq5MhEETaS1ulIE4whXQ\/132",
            "mobile":"",
            "score":0,
            "token":"f3f0ce45-8dd5-4935-b292-8c5e4c66124f",
            "user_id":3,
            "createtime":1620469690,
            "expiretime":1623061690,
            "expires_in":2592000
        }
    }*/

    // TODO 不难看出此时 loginRes() 和 session('wechat_user') 的输出结果是一样的,我也就达到目的了

    /* session('wechat_user') 输出结果
     * {
        "code":1,
        "msg":"授权登录成功(缓存)",
        "time":"1620469875",
        "data":{
            "id":3,
            "nickname":"霍文霆",
            "avatar":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q0j4TwGTfTJn6TuXOPKCAsrDl8SfriaZcaetY04blVTKVE0deman5ApWIOe6uPOXfK8Rq5MhEETaS1ulIE4whXQ\/132",
            "mobile":"",
            "score":0,
            "token":"f3f0ce45-8dd5-4935-b292-8c5e4c66124f",
            "user_id":3,
            "createtime":1620469690,
            "expiretime":1623061690,
            "expires_in":2592000
        }
    }*/
}

第二种使用原生写法拉起登录

class Login extends Api
{
    protected $appid;
    protected $appSecret;
    protected $getCodeUrl;
    protected $getTokenUrl;
    protected $getUserUrl;
    protected $redirectUrl;
    protected $noNeedLogin = ['getCode','loginRes'];
    protected $noNeedRight = ['*'];

	// 基本配置
    public function _initialize()
    {
        parent::_initialize();
        $this->appid = "wx04ff******edd2a1";
        $this->appSecret = "581671ce0b**********5c4f634b321e";
        $this->getCodeUrl = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect';
        $this->getTokenUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code';
        $this->getUserUrl = 'https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN';
        $this->redirectUrl = urlencode($this->request->domain() . '/api/Login/loginRes');
    }

    /**
     * 网页授权获取code
     */
    public function getCode(){
        // TODO 前期测试用于清空值 session('wechat_user',NULL);
        if (!session('wechat_user')) {
            $url = sprintf($this->getCodeUrl, $this->appid, $this->redirectUrl);
            header("Location:" . $url);
        }else {
            $this->success('授权登录成功', session('wechat_user'));
        }
    }

    /**
     * 授权登录
     */
    public function loginRes()
    {
        $code = $this->request->get('code');  // 获取code

        if(!$code){
            $this->error(__('缺少参数code!'));
        }

        $getTokenUrl = sprintf($this->getTokenUrl, $this->appid, $this->appSecret, $code);

        // 获取access_token和openid
        $result = json_decode(file_get_contents($getTokenUrl),true);

        /* $result 输出结果
         * Array (
            [access_token]  => 44_ixUtEZiza2rDbtiP2JGJKwPdNi_VA6iODMCvvRIJ-k34TbU5XR04d74ekw37QfFthPzAS2bnPaycazBXl8AInQ
            [expires_in]    => 7200
            [refresh_token] => 44_LGyUp6YLNAdL2F8CppUXbjsxhnQpk1yvkAKZNnqSzDLN2itrfvPUY3mwFCsHHBbPF28GYyl1tMSxOuoj9sdQJg
            [openid]        => oaWII632e55s0ZuqCRQHsYQkMgFE
            [scope]         => snsapi_userinfo
        )*/

        if(!$result){
            $this->error('获取access_token和openid失败了');
        }

        // 分参
        extract($result);

        $getUserUrl = sprintf($this->getUserUrl, $access_token, $openid);

        // 获取用户信息
        $userInfo = json_decode(file_get_contents($getUserUrl),true);

        /* $userInfo 输出结果
         * Array (
            [openid] => oaWII632e55s0ZuqCRQHsYQkMgFE
            [nickname] => 霍文霆
            [sex] => 1
            [language] => zh_CN
            [city] =>
            [province] => 安徽
            [country] => 中国
            [headimgurl] => https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJn6TuXOPKCAsrDl8SfriaZcaetY04blVTKVE0deman5ApWIOe6uPOXfK8Rq5MhEETaS1ulIE4whXQ/132
            [privilege] => Array ()
        )*/

        // 分参
        extract($userInfo);

        if (!empty($userInfo)) {
            $user = User::get(['openid' => $openid]);

            if ($user) {
                if ($user->status != 'normal') {
                    $this->error(__('Account is locked'));
                }
                // 每次调用都会更新一次用户基本数据---例如用户修改头像和昵称,这样就会实时更新数据了
                $user->nickname = base64_decode(base64_encode($nickname));
                $user->avatar = $headimgurl;
                $user->save();
                // 直接登陆
                $ret = $this->auth->direct($user->id);
            } else {
                $ret = $this->auth->wxOfficialAccountsLogin($userInfo);
            }

            if ($ret) {
                $wechat_user = $this->auth->getUserInfo();
                // 把用户登录信息写入session中,这样就不需要每次都发起请求了
                session('wechat_user', $wechat_user);
                $this->success('授权登录成功', $wechat_user);
            } else {
                $this->error('授权登录失败了!');
            }
        }else{
            $this->error(__('获取用户信息失败了'));
        }
    }

    /* loginRes() 输出结果
     * {
        "code":1,
        "msg":"授权登录成功",
        "time":"1620468028",
        "data":{
            "id":2,
            "nickname":"霍文霆",
            "avatar":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q0j4TwGTfTJn6TuXOPKCAsrDl8SfriaZcaetY04blVTKVE0deman5ApWIOe6uPOXfK8Rq5MhEETaS1ulIE4whXQ\/132",
            "mobile":"",
            "score":0,
            "token":"d4e89893-c4fa-4d70-a373-92bd7c454250",
            "user_id":2,
            "createtime":1620468029,
            "expiretime":1623060029,
            "expires_in":2592000
        }
    }*/

    // TODO 不难看出此时 loginRes() 和 session('wechat_user') 的输出结果是一样的,我也就达到目的了

    /* session('wechat_user') 输出结果
     * {
        "code":1,
        "msg":"授权登录成功",
        "time":"1620468151",
        "data":{
            "id":2,
            "nickname":"霍文霆",
            "avatar":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q0j4TwGTfTJn6TuXOPKCAsrDl8SfriaZcaetY04blVTKVE0deman5ApWIOe6uPOXfK8Rq5MhEETaS1ulIE4whXQ\/132",
            "mobile":"",
            "score":0,
            "token":"d4e89893-c4fa-4d70-a373-92bd7c454250",
            "user_id":2,
            "createtime":1620468029,
            "expiretime":1623060029,
            "expires_in":2592000
        }
    }*/
}

在 app\common\library 添加如下方法,我是基于fastadmin开发的,也可以改写我的数据写入方式

    /**
     * 微信公众号H5注册用户
     * @param string $username 用户名
     * @param string $password 密码
     * @param string $email    邮箱
     * @param string $mobile   手机号
     * @param array  $extend   扩展参数
     * @return boolean
     */
    public function wxOfficialAccountsLogin($result)
    {
        // 分参
        extract($result);

        $params = [
            'openid'    => $openid,
            'nickname'  => base64_decode(base64_encode($nickname)),
            'avatar'    => $headimgurl,
            'jointime'  => time(),
            'joinip'    => request()->ip(),
            'logintime' => time(),
            'loginip'   => request()->ip(),
            'prevtime'  => time(),
            'status'    => 'normal'
        ];

        Db::startTrans();
        try {
            $user = User::create($params, true);
            $this->_user = User::get($user->id);
            //设置Token
            $this->_token = Random::uuid();

            Token::set($this->_token, $user->id, $this->keeptime);

            Db::commit();
        } catch (Exception $e) {
            $this->setError($e->getMessage());
            Db::rollback();
            return false;
        }

        return true;
    }
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值