jiliangliang

web 微信登录 和微信分享的类
<?php namespace Think; class WxUtil { private $a...
扫描右侧二维码阅读全文
05
2019/09

web 微信登录 和微信分享的类

<?php
namespace Think;

class WxUtil
{

    private $appId;

    private $appSecret;

    private $jsshare_url;

    private $callback_url;

    private $root_dir = "";

    private $authorize = "https://open.weixin.qq.com/connect/oauth2/authorize";

    private $user_access_token = "https://api.weixin.qq.com/sns/oauth2/access_token";

    private $user_info = "https://api.weixin.qq.com/sns/userinfo";

    private $errorMsg = "";

    private $errorCode = "";

    public function __construct($config)
    {
        $this->appId = $config['appId'];
        $this->appSecret = $config['appSecret'];
        $this->jsshare_url = $config['jsshare_url'];
        $this->callback_url = $config['callback_url'];
        $this->root_dir = $config['root_dir'];
    }

    // 微信回调地址
    public function wxLoginStart()
    {
        $url = $this->authorize . '?appid=' . $this->appId . '&redirect_uri=' . urlencode($this->callback_url) . '&response_type=code&scope=snsapi_userinfo&state=state#wechat_redirect';
        header('location:' . $url);
    }

    /**
     * 获取授权token
     * 通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息。网页授权access_token是通过code换取的凭证,用于获取用户的基本信息,次数不限,时间最长5分钟。
     *
     * @param
     *            $code
     * @return bool|string
     */
    public function getUserAccessToken($code)
    {
        $url = $this->user_access_token . "?appid=$this->appId&secret=$this->appSecret&code=$code&grant_type=authorization_code";
        
        $res = $this->curlGet($url);
        return json_decode($res);
    }

    /**
     * 获取用户信息
     *
     * @param
     *            $accessToken
     * @return mixed
     */
    public function getUserInfo($userAccessToken)
    {
        $url = $this->user_info . "?access_token=$userAccessToken->access_token&openid=$userAccessToken->openid&lang=zh_CN";
        $UserInfo = $this->curlGet($url);
        return $UserInfo;
    }

    /**
     * 使用 回调地址使用
     */
    public function getWxUserInfo($code)
    {
        if (empty($code)) {
            $code = $_GET['code'];
        }
        if (empty($code)) {
            $this->errorMsg = "没有返回code码";
            $this->errorCode = "00001";
            return array();
        }
        // {"errcode":41001,"errmsg":"access_token missing, hints: [ req_id: GiHdeNLoRa-Bq.Pda ]"}
        $userAccessToken = $this->getUserAccessToken($code);
        
        if (isset($userAccessToken->errcode) && ! empty($userAccessToken->errcode)) {
            $this->errorCode = $userAccessToken->errcode;
            $this->errorMsg = $userAccessToken->errmsg;
            return array();
        }
        
        // {"errcode":41001,"errmsg":"access_token missing, hints: [ req_id: hiHdqJmGE-cVYDSA ]"}
        
        $UserInfo = $this->getUserInfo($userAccessToken);
        
        if (isset($UserInfo->errcode) && ! empty($UserInfo->errcode)) {
            $this->errorCode = $UserInfo->errcode;
            $this->errorMsg = $UserInfo->errmsg;
            return array();
        }
        
        return json_decode($UserInfo, true);
    }

    public function getErrorMsg()
    {
        return $this->errorMsg;
    }

    public function getErrorCode()
    {
        return $this->errorCode;
    }

    public function getSignPackage()
    {
        // 接收到前端的转义url转义回来
        $durl = urldecode($this->jsshare_url);
        
        $jsapiTicket = $this->getJsApiTicket();
        
        $timestamp = time();
        $nonceStr = $this->createNonceStr();
        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=" . $durl;
        
        $signature = sha1($string);
        
        $signPackage = [
            "appId" => $this->appId,
            "nonceStr" => $nonceStr,
            "timestamp" => $timestamp,
            "url" => $url,
            "signature" => $signature,
            "rawString" => $string
        ];
        // var_dump($signPackage);die;
        return $signPackage;
    }

    public function curlGet($url)
    {
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true); // 从证书中检查SSL加密算法是否存在
        $tmpInfo = curl_exec($curl); // 返回api的json对象
                                     // 关闭URL请求
        curl_close($curl);
        return $tmpInfo; // 返回json对象
    }

    public function curlPost($url, $data)
    {
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
        $tmpInfo = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            echo 'Errno' . curl_error($curl); // 捕抓异常
        }
        curl_close($curl); // 关闭CURL会话
        return $tmpInfo; // 返回数据,json格式
    }

    private function createNonceStr($length = 16)
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i ++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    private function getJsApiTicket()
    {
        // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
        $data = json_decode(file_get_contents( $this->root_dir . "/jssdk/jsapi_ticket.json"));
        if (empty($data) || $data->expire_time < time()) {
            $accessToken = $this->getAccessToken();
            // 定义传递的参数数组
            $params['type'] = 'jsapi';
            $params['access_token'] = $accessToken;
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" . $params['access_token'] . "&type=" . $params['type'] . "";
            $res = json_decode($this->curlGet($url));
            $ticket = isset($res->ticket) ? $res->ticket : NULL;
            if ($ticket) {
                $res->expire_time = time() + 7000;
                $res->jsapi_ticket = $ticket;
                $fp = fopen( $this->root_dir . "/jssdk/jsapi_ticket.json", "w");
                fwrite($fp, json_encode($res));
                fclose($fp);
            }
        } else {
            $ticket = $data->jsapi_ticket;
        }
        return $ticket;
    }

    /**
     * 全局access_token:其他微信接口需要通过基础支持中的“获取access_token”接口来获取到的全局access_token调用。全局access_token是HTML5网页调用基础接口的全局唯一凭证,有效时间为2小时,每天最多调用2000次。
     *
     * @return NULL
     */
    private function getAccessToken()
    {
        // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
        $data = json_decode(file_get_contents( $this->root_dir . "/jssdk/access_token.json"));
        if (empty($data) || $data->expire_time < time()) {
            // 定义传递的参数数组
            $params['grant_type'] = 'client_credential';
            $params['appid'] = $this->appId;
            $params['secret'] = $this->appSecret;
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" . $params['grant_type'] . "&appid=" . $params['appid'] . "&secret=" . $params['secret'] . "";
            $res = json_decode($this->curlPost($url, $params));
            $access_token = isset($res->access_token) ? $res->access_token : NULL;
            if ($access_token) {
                $res->expire_time = time() + 7000;
                $res->access_token = $access_token;
                $fp = fopen( $this->root_dir . "/jssdk/access_token.json", "w");
                fwrite($fp, json_encode($res));
                fclose($fp);
            }
        } else {
            $access_token = $data->access_token;
        }
        return $access_token;
    }
}
Last modification:September 5th, 2019 at 10:33 am
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment