Software engineering notes

PHP yahoo oauth

申請

[1] 到Yahoo! Developer Network登入後 -> 右上角 My Projects -> Create a Project

[2] 申請好會有一組 Application ID, Consumer Key, Consumer Secret

[3] 填入 domain 後記得驗證它, 才能用於線上

登入 Oauth, 並透過 yql 取得使用者資料 (使用 Codeigniter)

Oauth

原先 Oauth 那邊打算使用官方的 SDK, 但是怎麼試都會有 ERROR, 於是參考網路的資源重刻了一個輪子

YQL

原以為做登入 Oauth 取得的 GUID 再透過 YQL Console 的結果網址就可以取得使用者資料, 而不透過 YQL 的 SDK

例如我想取得使用者資料 YQL Console 執行

select * from social.profile where guid = "{我的GUID}"

完成後頁面下面有 url : http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20social.profile%20where%20guid%20%3D%20%22{我的GUID}%22&format=json&diagnostics=true&callback=

果然事情不是憨人想得這麼簡單, 直接拿來用會得到 ERROR 頁面

{
    error: {
        lang: "en-US",
        diagnostics: null,
        description: "Authentication Error. The table social.profile requires a higher security level than is provided, you provided ANY but at least APP is expected"
    }
}

YQL Console 頁面應該是塞了 Token, 所以只好使用正統的方法來取得了

我們要使用 Yahoo! Social SDK 請將 yos-social-php 下載到 /application/third_party, 稍後的 Library 會引入它

此練習只是取得使用者資料為例子, 取得 YQL 其它資料應該也是差不多

Oauth Library :

<?php defined('BASEPATH') OR exit('No direct script access allowed');

class Oauth {

    const CONSUMER_KEY    = "(填你自己的)";
    const CONSUMER_SECRET = "(填你自己的)";
    const APP_ID          = "(填你自己的)";
    const CALLBACK_URL    = "http://{你的 domain}/{你的 controller}/get_access_token";
    private $TOKEN;

    public function curl_post($url, $post = NULL, $options = array()) {
        $defaults = array(
            CURLOPT_POST           => 1,
            CURLOPT_HEADER         => 0,
            CURLOPT_URL            => $url,
            CURLOPT_FRESH_CONNECT  => 1,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_FORBID_REUSE   => 1,
            CURLOPT_TIMEOUT        => 4,
            CURLOPT_POSTFIELDS     => http_build_query($post),
        );

        $ch = curl_init();
        curl_setopt_array($ch, $defaults);
        if( ! $result = curl_exec($ch))
        {
            trigger_error(curl_error($ch));
        }
        curl_close($ch);
        return $result;
    }

    public function get_request_token()
    {
        $post = array(
            "oauth_nonce"            => md5(uniqid(rand(), true)),
            "oauth_timestamp"        => time(),
            "oauth_consumer_key"     => OAUTH::CONSUMER_KEY,
            "oauth_signature_method" => "PLAINTEXT",
            "oauth_signature"        => OAUTH::CONSUMER_SECRET."&",
            "oauth_version"          => "1.0",
            "oauth_callback"         => OAUTH::CALLBACK_URL,
        );

        $r = $this->curl_post("https://api.login.yahoo.com/oauth/v2/get_request_token", $post);
        parse_str($r, $output);
        return $output;
    }

    public function get_access_token($data)
    {
        if ( ! isset($data) || ! is_array($data))
        {
            return FALSE;
        }
        $post = array(
            "oauth_nonce"            => md5(uniqid(rand(), true)),
            "oauth_timestamp"        => time(),
            "oauth_consumer_key"     => OAUTH::CONSUMER_KEY,
            "oauth_signature_method" => "PLAINTEXT",
            "oauth_version"          => "1.0",
            "oauth_signature"        => OAUTH::CONSUMER_SECRET."&". $data["oauth_token_secret"],
            "oauth_token"            => $data['oauth_token'],
            "oauth_verifier"         => $data['oauth_verifier'],
        );

        $r = $this->curl_post("https://api.login.yahoo.com/oauth/v2/get_token", $post);
        parse_str($r, $output);
        return $output;
    }

    public function refresh_access_token($data)
    {
        if ( ! isset($data) || ! is_array($data))
        {
            return FALSE;
        }
        $cookie = get_object_vars(http_parse_cookie(getenv("HTTP_COOKIE")));
        $_COOKIE = $cookie["cookies"];
        $post = array(
            "oauth_nonce"            => md5(uniqid(rand(), true)),
            "oauth_timestamp"        => time(),
            "oauth_consumer_key"     => OAUTH::CONSUMER_KEY,
            "oauth_signature_method" => "PLAINTEXT",
            "oauth_version"          => "1.0",
            "oauth_signature"        => OAUTH::CONSUMER_SECRET."&".$data["oauth_token_secret"],
            "oauth_token"            => $data["oauth_token"],
            "oauth_session_handle"   => $data["oauth_session_handle"],
        );

        $r = $this->curl_post("https://api.login.yahoo.com/oauth/v2/get_token", $post);
        parse_str($r, $output);
        return $output;
    }

    /*
     * api : [yos-social-php github](https://github.com/yahoo/yos-social-php)
     */
    public function get_user_profile($guid = "")
    {
        if (empty($guid))
        {
            return FALSE;
        }
        require_once (APPPATH.'third_party/yos-social-php/lib/Yahoo.inc');
        $session = YahooSession::requireSession(OAUTH::CONSUMER_KEY, OAUTH::CONSUMER_SECRET, OAUTH::APP_ID);
        $user = $session->getSessionedUser();
        return $session->query("select * from social.profile where guid ='{$guid}'");
    }
}

Controller :

public function __construct()
{
    parent::__construct();
    header("Content-type: text/html; charset=utf-8");
    $this->load->library('Oauth');
    error_reporting(E_ALL ^ E_STRICT);    // ignore php notice
}

public function get_request_token()
{
    $output = $this->oauth->get_request_token();
    if ($output)
    {
        setcookie('oauth_token_secret', $output['oauth_token_secret']);
        header('Location: '. $output['xoauth_request_auth_url']);
        exit;
    }
    $this->_output_JSON(FALSE);
}

public function get_access_token()
{
    $data['oauth_token_secret'] = $_COOKIE['oauth_token_secret'];
    $data['oauth_token'] = $this->input->get_post('oauth_token');
    $data['oauth_verifier'] = $this->input->get_post('oauth_verifier');
    $output = $this->oauth->get_access_token($data);
    if ($output)
    {
        $this->get_user_profile($output['xoauth_yahoo_guid']);
    }
    $this->_output_JSON(FALSE);
}

public function get_user_profile($guid)
{
    $result = $this->oauth->get_user_profile($guid);
    $this->_output_JSON($result);
    exit;
}

private function _output_JSON_raw($result)
{
    echo json_encode(
        array(
            'status'    => (($result) ? 'ok' : 'fail'),
            'data'      => (($result) ? $result : ''),
        ),
        JSON_UNESCAPED_UNICODE
    );
}

瀏覽器執行 http://{你的 domain}/{你的 controller}/get_request_token, 輸出結果如下 :

yahoo-oauth.jpg

ref : http://code.gunblues.com/2011/02/yahoo-api-oauth.html