微信网页授权封装,只要传入appid和appSecret,就可以轻松获取用户信息和openid

微信 php 1541      收藏
微信网页授权封装,只要传入appid和appSecret,就可以轻松获取用户信息和openid

<?php
/**
 * 微信网页授权
 * 详细文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
 * $wechat = new WebAuth($wechatConfig['appId'],$wechatConfig['appSecret']);
 * echo $wechat->openid();
 * 或
 * print_r($wechat->userinfo())
 * @package wechat
 */
class WebAuth
{
    public $curlTimeout = 2;// 请求超时默认2秒
    // 代理设置
    public $proxy = [
        'curl_proxy_host' => '0.0.0.0',
        'curl_proxy_port' => 0
    ];
    public $appId;
    public $appSecret;
    const SNSAPI_BASE = 'snsapi_base'; // 不弹出授权页面,直接跳转,只能获取用户openid
    const SNSAPI_USERINFO = 'snsapi_userinfo'; // 弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
    /**
     * 获取code
     * 需要传递如下参数
     * appid 公众号的唯一标识
     * redirect_uri 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
     * response_type 返回类型,请填写code
     * scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
     * state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
     * #wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数
     */
    const CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=123#wechat_redirect";
    /**
     * 获取access_token
     * 需要传递如下参数
     * appid 公众号的唯一标识
     * secret 公众号的appsecret
     * code 填写第一步获取的code参数
     * grant_type 填写为authorization_code
     */
    const ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
    /**
     * 刷新access_token
     * 需要传递如下参数
     * appid 公众号的唯一标识
     * grant_type 填写为refresh_token
     * refresh_token 填写通过access_token获取到的refresh_token参数
     */
    const REFRESH_TOKEN = 'https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s';
    /**
     * 获取用户详细信息
     * 需要传递如下参数
     * access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
     * openid 用户的唯一标识
     * lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语
     */
    const USERINFO_URL = 'https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s';
    public function __construct($appId,$appSecret)
    {
        $this->appId = $appId;
        $this->appSecret = $appSecret;
    }
    /**
     * 获取openid
     * @return mixed
     */
    public function openid() {
        $code = $_GET['code'] ?? '';
        if ($code) {
            $result = $this->getAccessToken($code);
            return $result['openid'];
        } else {
            $this->getCode(self::SNSAPI_BASE);
        }
    }
    /**
     * 获取详细信息
     * @return mixed
     */
    public function userinfo() {
        $code = $_GET['code'] ?? '';
        if ($code) {
            $result = $this->getAccessToken($code);
            return $this->getUserInfo($result['access_token'],$result['openid']);
        } else {
            $this->getCode(self::SNSAPI_USERINFO);
        }
    }
    public function refreshToken($refreshToken)
    {
        $url = sprintf(self::REFRESH_TOKEN,$this->appId, $refreshToken);
        return $this->readUrl($url);
    }
    /**
     * 获取详细信息
     * @param $accessToken
     * @param $openid
     * @param string $lang
     * @return bool|mixed|string
     */
    public function getUserInfo($accessToken, $openid, $lang = 'zh_CN')
    {
        $url = sprintf(self::USERINFO_URL,$accessToken,$openid,$lang);
        return $this->readUrl($url);
    }
    /**
     * 获取accesstoken
     * @param $code
     * @return bool|mixed|string
     */
    public function getAccessToken($code)
    {
        $url = sprintf(self::ACCESS_TOKEN_URL,$this->appId,$this->appSecret,$code);
        return $this->readUrl($url);
    }
    /**
     * 获取code
     * @param string $scope 取值范围智能时 snsapi_base 或 snsapi_userinfo
     */
    public function getCode($scope)
    {
        $redirect = urlencode($this->curPageURL());
        $url = sprintf(self::CODE_URL,$this->appId,$redirect,$scope);
        header('location:' . $url, true, 302);
        exit;
    }
    /**
     * 请求接口,返回结果
     * @param $url
     * @return bool|mixed|string
     */
    private function readUrl($url)
    {
        //初始化curl
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->curlTimeout);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        if($this->proxy['curl_proxy_host'] != "0.0.0.0" && $this->proxy['curl_proxy_port'] != 0){
            curl_setopt($ch,CURLOPT_PROXY, $this->proxy['curl_proxy_host']);
            curl_setopt($ch,CURLOPT_PROXYPORT, $this->proxy['curl_proxy_port']);
        }
        //运行curl,结果以jason形式返回
        $res = curl_exec($ch);
        curl_close($ch);
        //返回数据
        return json_decode($res,true);
    }
    /**
     * 获取当前完整url
     * @return string
     */
    private function curPageURL()
    {
        $pageURL = 'http';
        if ($_SERVER["HTTPS"] == "on"){
            $pageURL .= "s";
        }
        $pageURL .= "://";
        if ($_SERVER["SERVER_PORT"] != "80"){
            $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
        }else{
            $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
        }
        return $pageURL;
    }
}