2010年1月1日 星期五

Wretch 無名小站 API - 申請、使用完整教學

第一次使用時,因為我沒 public ip 的機器,所以就嘗試架在 EC2 上,奢侈啊。過了一陣子,我發表一篇文章紀錄:Wretch 無名小站 API - Yahoo! Developer,然後有人留言請教,於是我找了另一台機器,但我也發現碰到一樣的問題,但礙於時間關係,所以遲遲沒有幫忙,隨意 Google 關鍵字,可能是在做專題吧?!真是抱歉,現在我有空了,就在仔細紀錄一下吧!


關於 Yahoo API ,我只嘗試 無名小站 API ,主因是以前我自己曾使用 PHP 與 cURL 來模擬瀏覽器,以程式自動化完成登入,並且發表文章到無名網誌,但這種客制化的行為真的不如使用官方的 API 啦,因此還滿興奮有這個東西的出現,然而,我還是比較希望它提供 XMLRPC 。


扯遠了,現在開始教學吧!首先,一定要有一台 Public IP 供你使用,接著你需要去註冊一個 Domain Name 來使用,網路上很多免費的,像我就是使用 TWBBS.org ,但要留意的,並不是馬上申請就可以用,要等一陣子才行,可以試著用 "nslooup your_name.twbbs.org" 來試試,但最主要並不是你所在的機器能找到,而是 Yahoo 那邊的驗證機器能找到它。接著,請連到 http://tw.developer.yahoo.com/http://developer.yahoo.com/ 登入,在此以英文介面當作範例。


登入完後,請點選 My Project 並且在該頁面點選 New Project 。接著選一下有 "Wretch" 關鍵字吧!


2010/01/01 YDN - New Project


接著就是填寫一些資訊,比較重要的就是你的 Application 的網頁位置,此例是使用 Web-Based 模式


2010/01/01 YDN - New Project


記得把 Access Scopes 選則有關 private user data 囉,因為 Wretch API 是歸類在這部份的。並且在最後一項中選擇 Wretch API 啦


2010/01/01 YDN - New Project


接著就是關鍵的驗證部分,這也是為何我說要有一個 public ip 的機器,以及一個 domain name 啦,此驗證過程就是依照上頭的規定,在 Web Server 的目錄下擺放一個特定檔名的檔案,讓 Yahoo 那邊的機器去存取驗證,如果取得到,那就可以通過啦!


2010/01/01 YDN - New Project


在驗證過程中,可能會碰到一些問題,一種是你的檔名沒建好,所以它找不到,另一種比較神秘,它直接告訴你


Domain Verification Failed
There was an internal error while an application is being created. Please try agin.


像這個問題在一些討論區有提到,有可能 Applocation Name 已存在,或是 Description 沒填等等的問題,但我碰到的真正問題,其實是 Favicon URL 那欄!請為它建一個檔案吧,看起來它也會去抓這個位置來驗證,還真有點怪,它上頭明明寫 Optional !驗證成功則會顯示相關資訊囉


2010/01/01 YDN - New Project


這邊所要留意的有 Application ID 、Consumer Key 和 Consumer Secret ,其中以後兩者最為重要。緊接著,在你的 Web Server 擺上相關程式碼吧!讓我們來測測看啦!接著也可參考 Wretch 無名小站 API - Yahoo! Developer 這篇囉,上頭有其他測試的程式碼。



  • Wretch API 文件

  • 下載 PHP Library:Using Yahoo! Social SDK for PHP

    • 今天我用的版本 yahoo-yos-social-php-12c4a50



  • 讓你的 Web Server 支援 PHP - cURL ,在此就不教怎樣安裝 PHP5 了,以下動作別忘了重開 Web Server。


    • Ubuntu


      • # sudo apt-get install php5-curl



    • FreeBSD

      • # cd /usr/ports/lang/php5-extensions/ ; 

      • # make config ; // 請將 CURL support 勾選

      • # make install clean



    • Windows

      • 通常從官網下載的包裝中已經有囉,只差設定好位置以及啟用 cURL Library 啦

      • 編輯 php.ini (可能在 C:\Windows 目錄中 )

        • 設定好 extension_dir 位置

        • 把 extension=php_curl.dll 前面的 # 拿掉,以此啟用它








接著,就是把相關程式碼擺定位,以下以 Windows 平台描述



  • Yahoo Library

    • C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\wretch\yahoo-yos-social-php-12c4a50



  • 測試程式碼

    • C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\wretch\index.php

    • <?php
      require("yahoo-yos-social-php-12c4a50/lib/Yahoo.inc");  

      // Your Consumer Key (API Key) goes here.  
      define('CONSUMER_KEY', "######");

      // Your Consumer Secret goes here.  
      define('CONSUMER_SECRET', "######");

      // Your application ID goes here.  
      define('APPID', "######");  

      //$GLOBAL_YAHOO_LOGGER_DEBUG = true;
      //$GLOBAL_YAHOO_LOGGER_DEBUG_DESTINATION = "CONSOLE";

      $containerSession = YahooSession::requireSession(CONSUMER_KEY,CONSUMER_SECRET);
      $userSession = $containerSession->getSessionedUser();
      ?>




透過瀏覽器連過去你設定好的位置,若正常成功的話,它會蹦出要你輸入帳密的畫面囉,這個流程是將你導到 Yahoo 登入畫面


2010/01/01 YDN - New Project


並且完成登入後會詢問你是否允許這支程式存取你帳號的資料


2010/01/01 YDN - New Project


當然自己寫的程式比較 OK ,就允許吧!不然也沒得測。


只不過,以上的過程並沒有那麼寫意輕鬆,因為我還是跟之前一樣,卡在這個錯誤訊息


Call to a member function getSessionedUser() on a non-object


逛了幾個網站,才知道可以把 debug mode 打開,就是在引入 Yahoo.inc 後,加上片段程式


$GLOBAL_YAHOO_LOGGER_DEBUG = true;
$GLOBAL_YAHOO_LOGGER_DEBUG_DESTINATION = "CONSOLE";


此時,錯誤訊息


ERROR - Error making libcurl request(https://api.login.yahoo.com/oauth/v2/get_request_token): SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed ERROR - OAuth call to get request token failed ERROR - Failed to create request token ERROR - Failed to create authorization URLs


喔耶,至少我看得懂了,當初別人問我時,還傻傻地去 trace code 東改西改,改到後面還是沒搞定,自以為是 Yahoo API 沒做好,畢竟你用 "Wretch API" 去 Google 的第一筆結果就是在抱怨,哈。關於這個問題,恰好我有用過 PHP cURL ,所以知道可以設定一個選項來避開它,但這個動作必須修改 Yahoo Library 程式碼,說真的我也很不願意,但至少這樣做可以搞定。 


@Yahoo.inc:1811
+curl_setopt( $ch , CURLOPT_SSL_VERIFYPEER , false );


以上就是去 Yahoo.inc 這個檔案,我使用 curl_init 去搜尋,發現只有一處,很好,那我只要更新一處就行,在 curl_init 後面加上 curl_setopt( $ch , CURLOPT_SSL_VERIFYPEER , false ); 就可以了。


以上是我在 Windows 平台得到的訊息以及解決方式,然而,我在 FreeBSD 機器上時,得到的錯誤訊息則不一樣了


DEBUG - HTTP request details
DEBUG OBJECT - Array
(
    [method] => POST
    [url] => https://api.login.yahoo.com/oauth/v2/get_request_token
    [code] => 401
    [requestHeaders] => Array
        (
            [0] => Accept: application/json
            [1] => Content-Type: application/x-www-form-urlencoded
        )

    [requestBody] => ######
    [responseHeaders] => Array
        (
            [Date] => ######
            [P3P] => ######
            [WWW-Authenticate] => OAuth oauth_problem=signature_invalid
            [Connection] => close
            [Transfer-Encoding] => chunked
            [Content-Type] => application/x-www-form-urlencoded
        )

    [responseBody] => oauth_problem=signature_invalid
)

ERROR - Failed to create request token: signature_invalid
ERROR - Failed to create request token
ERROR - Failed to create authorization URLs


那你在使用 YahooSession::requireSession(CONSUMER_KEY,CONSUMER_SECRET); 時,請改成加上 APPID 和當初認證的 Domain Name 應該就能解決囉


<?php

$containerSession = YahooSession::requireSession(CONSUMER_KEY,CONSUMER_SECRET , APPID , 'http://your_name.twbbs.org/' );
$userSession = $containerSession->getSessionedUser();

?>


最後,可以在把 debug mode 拿掉,完成轉址到 Yahoo 登入頁面囉!


以下是簡單的列出使用者在無名小站的個人資料、網誌文章和相簿列表,詳細部分請參考 Wretch API 文件


<?php

//error_reporting(E_ALL); ini_set("display_errors", 1);
require("yahoo-yos-social-php-12c4a50/lib/Yahoo.inc");  
// Your Consumer Key (API Key) goes here.  
define('CONSUMER_KEY', "######");
// Your Consumer Secret goes here.  
define('CONSUMER_SECRET', "######");
// Your application ID goes here.  
define('APPID', "######");  

//$GLOBAL_YAHOO_LOGGER_DEBUG = true;
//$GLOBAL_YAHOO_LOGGER_DEBUG_DESTINATION = "CONSOLE";

$session = YahooSession::requireSession( CONSUMER_KEY, CONSUMER_SECRET );
$yahoo_user = $session->getSessionedUser();

// Profile
$url = 'http://wretch.yahooapis.com/v1/profileService/'.$yahoo_user->guid;
$response = $session->client->get($url);
echo "[REQUEST] $url\n";
echo "<pre>";
print_r($response);
echo "</pre>";

// Blog
//$url = 'http://wretch.yahooapis.com/v1/blogService/'.$yahoo_user->guid.'/articles';
$response = $session->client->get($url);
echo "[REQUEST] $url\n";
echo "<pre>";
print_r($response);
echo "</pre>";

// Albums
$url = 'http://wretch.yahooapis.com/v1/albumService/'.$yahoo_user->guid.'/albums';
$response = $session->client->get($url);
echo "[REQUEST] $url\n";
echo "<pre>";
print_r($response);
echo "</pre>";

?>


以上回傳的格式(以 Profile 為例):


Array
(
[method] => GET
[url] => http://wretch.yahooapis.com/v1/profileService/####
[code] => 200
[requestHeaders] => Array
(
[0] => Accept: application/json
[1] => Authorization: OAuth realm="yahooapis.com",oauth_version="1.0",oauth_nonce="######",oauth_timestamp="######",oauth_consumer_key="######",oauth_token="######",oauth_signature_method="HMAC-SHA1",oauth_signature="######"
)

[requestBody] =>
[responseHeaders] => Array
(
[Date] => Fri, 01 Jan 2010 14:05:24 GMT
[P3P] => policyref="http://info.yahoo.com/w3c/p3p.xml", CP="######"
[Set-Cookie] => lang=zh-tw; expires=Mon, 27-Dec-2010 14:05:24 GMT; path=/; domain=.wretch.cc
[cache-control] => private,must-revalidate
[content-language] => en-US
[content-location] => http://www.wretch.cc/user/######
[content-type] => application/json; charset=UTF-8
[Vary] => Accept-Encoding
[Connection] => close
[Transfer-Encoding] => chunked
[Content-Encoding] => gzip
)

[responseBody] => {"profile":{"title":"######","desc":"######","nick":"######","birthday":null,"intro":"######","sex":"######","lang":"en-US","uri":"######"}}
)

其中 code 為 200 代表正常。


此次測試,是以一個新帳號測試並且完成開通無名帳號,只是一開始回傳的還是 302 或 404 ,猜測可能是資料還未同步好,過了一陣子再試的結果就是 200 囉。以上提供給各位參考囉。


其他相關參考



5 則留言:

  1. 我剛剛測試,發現了一件詭異的事情,
    同樣的程式放在另外一台主機,另外一個DNS可以跑耶.....怎有這種事情啊= =
    有沒有可能是我的Session出問題,或者整個網域被Yahoo封鎖了呀?

    版主回覆:(11/12/2010 12:12:32 AM)


    嗯, 這的確很擾人啊啊

    當初我分別在兩台主機上測試, 一台是 Windows Server 2003, 另一台是 FreeBSD. 相同的 code, 但不同 domain.

    在 Windows 那台上很正常, 但在 FreeBSD 有問題, 最後則是找到 YahooSession::requireSession 透過指定 domain 才解決的

    或許就真的只是 domain 的使用問題, 往好處想是使用 API 時會依 domain 來決定你是否可以存取服務, 也算是另一種安全機制吧 :D

    至於 bug 的部分, 說真的只能由你慢慢解了, 當初我也花了不少時間, 但問題的成因都可能不一樣, 只能祝你好運啦

    回覆刪除
  2. 你好~我按著你的教學步驟操作~最後也有在 Web Server 的目錄下擺放一個特定檔名的檔案~但是始終出現Domain verification failed. Please check that the verification file is in the location above and is named correctly~明明檔案就沒設錯~怎麼還是沒辦法拿到授權的KEY

    版主回覆:(02/17/2010 04:46:44 PM)


    要擺在 Web Server 的根目錄喔, 例如你的網站是 http://host/index.php , 然後在系統對應的位置是 /data/web/index.php , 那你就要把指定的檔案建立在 /data/web 裡.

    另外, 我記得之前在使用時, 只接受 80 port 的網站位置, 也就是預設為 http://host/ 這樣的而已, 不接受 http://host:8080/ 這類有改變 port 的, 剩下的就是你要確定別人可以連到你的網站囉( 記得要申請 domain name 吧, 我印象中只用 IP 好像不行, 但有點久了, 不太確定, 當作參考吧)

    回覆刪除
  3. 你好~請問一下~我將PHP的程式碼複製後API一些KEY的設定也設定完~但是送出網頁後畫面是呈現空白~沒有導到 Yahoo 登入畫面~怎麼回事呢?謝謝你

    版主回覆:(02/24/2010 11:27:08 PM)


    試著用 debug mode 吧 :D 在呼叫 YahooSession::requireSession 前加上以下兩行吧, 或許就有錯誤訊息可以看囉

    $GLOBAL_YAHOO_LOGGER_DEBUG = true;
    $GLOBAL_YAHOO_LOGGER_DEBUG_DESTINATION = "CONSOLE";

    另外, 你的 server 的網站位置也要留意, 我之前測試過 http://test.com/~user/ 這種方式的會有問題, 而制定其他 port 也會有問題(http://test.com:8080/ ), 所以盡量用預設的port(80)測試吧

    回覆刪除
  4. 不好意思 請問申請的部份 kind of application: 若選Client/DeskTop
    則Favicon URL: 要填什麼 因為不管我怎麼申請都出現 "There was an internal error that caused a failure over here. Please try again." 錯誤

    回覆刪除
  5. 請問要如何讓登入畫面為"台灣中文"呢?

    回覆刪除