<?php
/**
 * 微信开放平台
 */
class WechatOpen
{
    const ACCESS_URL = 'https://open.weixin.qq.com/connect/qrconnect';
    const API_URL = 'https://api.weixin.qq.com/sns/';
    const WX_STATE = 'wx_state';
    static public $CODE = array(
        '11024' => '获取access_token失败',
        '11025' => '微信错误信息',
        '11028' => '获取用户微信信息失败',
    );

    /**
     * 返回固定信息
     * @param  integer $errcode [description]
     * @param  string  $err_msg [description]
     * @param  array   $data    [description]
     * @return [type]           [description]
     */
    public function returnMsg($errcode = 0, $err_msg = '', $data = array())
    {
        if (empty($err_msg) && !empty(self::$CODE[$errcode])) {
            $err_msg = self::$CODE[$errcode];
        }
        $res = array(
            'err_code' => $errcode,
            'err_msg' => $err_msg,
            'data' => $data,
        );
        return $res;
    }

    public function __construct($options = array())
    {
        $this->appid        = isset($options['appid']) ? $options['appid'] : C('WX_OAUTH.appid');
        $this->appsecret    = isset($options['appsecret']) ? $options['appsecret'] : C('WX_OAUTH.appsecret');
        $this->callback     = isset($options['callback']) ? $options['callback'] : C('WX_OAUTH.callback');
    }

    /**
     * 获取授权二维码地址
     * @param  [type] $backUrl [description]
     * @return [type]          [description]
     */
    public function qrConnect($backUrl, $act = '')
    {
        $state = hash_key(32);
        session(self::WX_STATE, $state);
        $param = array(
            'appid'         => $this->appid,
            'redirect_uri'  => $this->callback . '?backUrl=' . urlencode($backUrl),
            'response_type' => 'code',
            'scope'         => 'snsapi_login',
            'state'         => $state,
        );
        !empty($act) && $param['redirect_uri'] .= '&act=' . urlencode($act);
        $url = self::ACCESS_URL . '?' . http_build_query($param);
        return $url;
    }

    /**
     * 获取access_token
     * @param  [type] $code [description]
     * @return [type]       [description]
     */
    public function getAccessToken($code)
    {
        // $info = session('access_info');
        // if (empty($info) || $info['expires_time'] < $_SERVER['REQUEST_TIME']) {
            $url = self::API_URL . 'oauth2/access_token';
            $param = array(
                'appid' => $this->appid,
                'secret' => $this->appsecret,
                'code' => $code,
                'grant_type' => 'authorization_code',
            );
            $res = get_curl($url, $param);
            $info = json_decode($res, true);
            if (empty($info)) {
                return $this->returnMsg(11024);
            }
            if ($info['errcode'] != 0) {
                return $this->returnMsg($info['errcode'], '微信错误信息:'.$info['errmsg']);
            }
            $info['expires_time'] = $_SERVER['REQUEST_TIME'] + $info['expires_in'] - 30;//保险,减少30秒有效期
            // session('access_info', $info);//缓存access_token
        // }
        // dump($info);
        return $this->returnMsg(0, '', $info);
    }

    /**
     * 验证csrf
     * @param  [type] $state [description]
     * @return [type]        [description]
     */
    public function validState($state)
    {
        $valid = session(self::WX_STATE);
        session(self::WX_STATE, null);
        if (empty($state) || $valid != $state) {
            return false;
        }
        return true;
    }

    /**
     * 获取用户信息
     * @param  [type] $access_token [description]
     * @param  [type] $open_id      [description]
     * @return [type]               [description]
     */
    public function getUserInfo($access_token, $open_id)
    {
        $url = self::API_URL . 'userinfo';
        $param = array(
            'access_token' => $access_token,
            'openid' => $open_id,
            'lang' => 'zh-CN',
        );
        $res = get_curl($url, $param);
        $info = json_decode($res, true);
        if (empty($info)) {
            return $this->returnMsg(11028);
        }
        if ($info['err_code'] != 0) {
            return $this->returnMsg($info['errcode'], '微信错误信息:'.$info['errmsg']);
        }
        return $this->returnMsg(0, '', $info);
    }
}