Twitter.php 5.2 KB
<?php

namespace anerg\OAuth2\Gateways;

use anerg\OAuth2\Connector\Gateway;
use anerg\OAuth2\Helper\Str;

class Twitter extends Gateway
{
    const API_BASE = 'https://api.twitter.com/';

    private $tokenSecret = '';

    /**
     * 构造函数
     *
     * @param array $config
     */
    public function __construct($config = null)
    {
        parent::__construct($config);
        $this->clientParams();
    }

    /**
     * 设置客户端请求的参数
     *
     * @return void
     */
    private function clientParams()
    {
        if (isset($this->config['oauth_token']) && !empty($this->config['oauth_token'])) {
            $this->token['oauth_token'] = $this->config['oauth_token'];
        }
        if (isset($this->config['oauth_token_secret']) && !empty($this->config['oauth_token_secret'])) {
            $this->token['oauth_token_secret'] = $this->config['oauth_token_secret'];
            $this->tokenSecret                 = $this->config['oauth_token_secret'];
        }
        if (isset($this->config['user_id']) && !empty($this->config['user_id'])) {
            $this->token['user_id'] = $this->config['user_id'];
        }
        if (isset($this->config['screen_name']) && !empty($this->config['screen_name'])) {
            $this->token['screen_name'] = $this->config['screen_name'];
        }
    }
    /**
     * 得到跳转地址
     */
    public function getRedirectUrl()
    {
        $oauthToken = $this->call('oauth/request_token', ['oauth_callback' => $this->config['callback']], 'POST');
        return self::API_BASE . 'oauth/authenticate?oauth_token=' . $oauthToken['oauth_token'];
    }

    /**
     * 获取当前授权用户的openid标识
     */
    public function openid()
    {
        $data = $this->userinfoRaw();
        return $data['id_str'];
    }

    /**
     * 获取格式化后的用户信息
     */
    public function userinfo()
    {
        $data = $this->userinfoRaw();

        $return = [
            'openid'  => $data['id_str'],
            'channel' => 'twitter',
            'nick'    => $data['name'],
            'gender'  => 'n', //twitter不返回用户性别
            'avatar'  => $data['profile_image_url_https'],
        ];
        return $return;
    }

    /**
     * 获取原始接口返回的用户信息
     */
    public function userinfoRaw()
    {
        if (!$this->token) {
            $this->token = $this->getAccessToken();
            if (isset($this->token['oauth_token_secret'])) {
                $this->tokenSecret = $this->token['oauth_token_secret'];
            } else {
                throw new \Exception("获取Twitter ACCESS_TOKEN 出错:" . json_encode($this->token));
            }
        }

        return $this->call('1.1/users/show.json', $this->token, 'GET', true);
    }

    /**
     * 发起请求
     *
     * @param string $api
     * @param array $params
     * @param string $method
     * @return array
     */
    private function call($api, $params = [], $method = 'GET', $isJson = false)
    {
        $method  = strtoupper($method);
        $request = [
            'method' => $method,
            'uri'    => self::API_BASE . $api,
        ];
        $oauthParams                    = $this->getOAuthParams($params);
        $oauthParams['oauth_signature'] = $this->signature($request, $oauthParams);

        $headers = ['Authorization' => $this->getAuthorizationHeader($oauthParams)];

        $data = $this->$method($request['uri'], $params, $headers);
        if ($isJson) {
            return json_decode($data, true);
        }
        parse_str($data, $data);
        return $data;
    }

    /**
     * 获取oauth参数
     *
     * @param array $params
     * @return array
     */
    private function getOAuthParams($params = [])
    {
        $_default = [
            'oauth_consumer_key'     => $this->config['app_id'],
            'oauth_nonce'            => Str::random(),
            'oauth_signature_method' => 'HMAC-SHA1',
            'oauth_timestamp'        => $this->timestamp,
            'oauth_token'            => '',
            'oauth_version'          => '1.0',
        ];
        return array_merge($_default, $params);
    }

    /**
     * 签名操作
     *
     * @param array $request
     * @param array $params
     * @return string
     */
    private function signature($request, $params = [])
    {
        ksort($params);
        $sign_str = Str::buildParams($params, true);
        $sign_str = $request['method'] . '&' . rawurlencode($request['uri']) . '&' . rawurlencode($sign_str);
        $sign_key = $this->config['app_secret'] . '&' . $this->tokenSecret;

        return rawurlencode(base64_encode(hash_hmac('sha1', $sign_str, $sign_key, true)));
    }

    /**
     * 获取请求附带的Header头信息
     *
     * @param array $params
     * @return string
     */
    private function getAuthorizationHeader($params)
    {
        $return = 'OAuth ';
        foreach ($params as $k => $param) {
            $return .= $k . '="' . $param . '", ';
        }
        return rtrim($return, ', ');
    }

    /**
     * 获取access token
     * twitter不是标准的oauth2
     *
     * @return array
     */
    protected function getAccessToken()
    {
        return $this->call('oauth/access_token', $_GET, 'POST');
    }
}