Thursday, July 15, 2010

呼叫Yahoo! API 介紹

先前介紹了Yahoo! OAuth導入分享,在其中Step 4 取得xoauth_yahoo_guid後,就可以拿來使用在其他Yahoo! API上了,而這邊以呼叫Yahoo! Contacts API為範例來介紹如何運用。

相關文件請參考Contact online documentation

從文件中所述,要與Contacts API溝通,是對下面這個網址
http://social.yahooapis.com/v1/user/{guid}/contacts
以GET、POST、PUT的方式呼叫,使用GET只有讀取的權限,POST跟PUT則可以寫入。

呼叫的方式,文件上是用JSON的方式送值,不過我測試的結果,也可以用一般QueryString的方式去送GET/POST,所以我就介紹這個方式。

呼叫的參數基本上跟OAuth使用的一樣,所以就不特別介紹了,值得一提的是,呼叫Yahoo! API時,使用的oauth_signature_method不能是明碼,所以我使用的是HMAC-SHA1加密,這邊稍微介紹一下,HMAC-SHA1加密時是以一段BaseText為被加密的本體,一段Key為加密金鑰,在Yahoo! API的呼叫上,BaseText與Key有其特定的規則。



BaseText : http method&Link&Parameter
KeyText : Cunsumer_Secret&Token_Secret

需注意的是,BaseText除了用來分隔的兩個&之外,都必須符合RFC3986 URI的規範(如果懶得自己寫可以參考Yammyy寫好的code),而Link的部分不能有問號,Parameter須按照字母順序排列。

KeyText部分比較單純,Cunsumer_Secret後面接&,再接上Token_Secret,如果沒有Token Secret就不用,但&還是要。

範例如下
BaseText
GET&http%3A%2F%2Fsocial.yahooapis.com%2Fv1%2Fuser%2Fyour_yahoo_guid%2Fcontacts&count%3Dmax%26oauth_consumer_key%3Ddjaabbccddeff%26oauth_nonce%3D12345%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1122334455%26oauth_token%3Dyour_oauth_token%26oauth_version%3D1.0

KeyText

cacacdcaccfcac123grfwccdacasdacacacadsdw&
編碼後的結果
z/qfMm99XVkI6przEHM/IZDOd4g=


實際上呼叫時的整串連結為

http://social.yahooapis.com/v1/user/your_yahoo_guid/contactsoauth_token=your_oauth_token&oauth_consumer_key=djaabbccddeff&oauth_signature_method=HMAC-SHA1&oauth_nonce=12345&oauth_timestamp=1122334455&oauth_version=1.0&count=max&oauth_signature=z%2fqfMm99XVkI6przEHM%2fIZDOd4g%3d


如果之前有用過OAuth的話,你會發現我在呼叫的參數中多了一個count,這是因為在預設上,Yahoo! Contact只會傳回前十個聯絡人的資訊,使用start/count等參數可以控制回傳的聯絡人數量與範圍,詳情可以看線上的說明


用我上面的方式呼叫Yahoo! Contact API後,Yahoo!會傳回這個使用者XML格式的的聯絡人資訊,因為都是個人資訊所以就沒貼出範例,可以參考Contact online documentation的Example XML Response for GET Contacts的段,基本上是一樣的東西。


拿到Yahoo! Contact的Response後,就可以按照各人需求去取得所需資料來運用了,有一點要注意的是,每個聯絡人資訊所擁有的欄位不見得一致,像是你想要拿到email,但不見得所有聯絡人都有email這個欄位,取值的時候要注意一下,最好找個Yahoo聯絡人多的人來測會比較好。

16 comments:

  1. 太感謝大大的好文分享~~~~小弟我已經可以成功呼叫yahoo的API了~~~
    我幫大大補充幾點:

    1.關於大大說的"BaseText除了用來分隔的兩個&之外,都必須符合RFC3986 URI的規範" , 如果是java的開發者,可以直接用sdk提供的,可以直接用URLEncoder.encode("XXXX")

    2. 關於 "HMAC-SHA1加密法" java開發者可以參考:
    http://www.iteye.com/topic/604440

    3. 在HMAC-SHA1之後的加密文(就是oauth_signature) 要記得也要符合RFC3986 URI的規範(亦可用URLEncoder.encode("XXXX"))

    4. 這點很重要~~我卡超久的!!!就是timestamp 的格式是 "YYYY/MM/DD HH:mm:ss" 有注意到嗎??沒有"毫秒",
    因為小弟我是用java,所以Calendar.getInstance().getTimeInMillis()時,要除以1000, 真的要非常注意!!!!

    經過大大的文章,再加上我補充的四點!!我相信應該可以call簡單的YAHOO api!!!!

    ReplyDelete
  2. 小弟在這遇到另一個問題了:
    因為小弟我想要利用yahoo api 建立相本,
    但是我看(
    http://tw.developer.yahoo.com/wretch/api.php#albumService/[guid]/albums)
    裡面有說:"以下參數必須以 "XML的格式" 帶在 "Content" 中 "
    請問版大 我要如何帶xml的content在http post呢??

    ReplyDelete
  3. 補問一個問題~~由get改用post的時候,需要有甚麼需要注意的地方嗎??

    ReplyDelete
  4. shih :
    感謝補充資料,
    關於你的問題1,應該是直接用他的example湊成一行然後urlencode當參數資料丟出去吧。
    Q2的話就把method從get改成post(誤)....印象中沒特別要注意的

    ReplyDelete
  5. 通常用post,不是都是用 key=value的方式submit嗎?
    如果把範例的xml ,urlencode當參數資料(value),那key要怎麼指定呢??

    ReplyDelete
  6. 對了~~請問版大~~不知道是否有相關的範例可以提供給我參考呢??(我開始懷疑會不會是我header或是什麼地方沒有符合yahoo api的規範....所以一直沒辦法成功呼叫)

    小弟我這幾天被這個yahoo api 搞到快死了~~~可能因為一個參數 或是小細節沒注意~~就沒辦法呼叫成功.....重點是官方doc 都寫的不清不楚....就算填錯~他也不會跟我說哪裡錯......真痛苦 >"<

    拜託版主了~~希望版主能夠幫幫忙~~~

    我mail: [email protected](如果有相關檔案可以寄給我參考嗎??)

    大力謝謝

    ReplyDelete
  7. 我的code要找一下耶,因為很久之前寫的,不曉得還在不在
    除錯的話可以用curl或是wget去除錯,我都是用wget
    你可以參考這篇
    http://www.died.tw/2010/05/wget-troubleshooting.html
    Java我十多年沒碰了,不過有google到一篇get跟post的範例
    http://allen080.blogspot.com/2010/03/javahttp-getpost.html
    不曉得你用不用的上 ?

    另外有事找我也可以直接寫信給我,信箱就放在右上角..

    ReplyDelete
  8. 我終於過了~~~~!!!!!YEA~~~~可以建立相本了~~

    只能說是我自己耍笨!!!
    由原本get改成post時,忘記改
    "BaseText : http method&Link&Parameter"......

    ==================================
    最後~~~再次感謝版主提供這兩篇對我非常有用的文章~~~
    本來想放棄使用yahoo api的~~因為這兩篇文章,讓我堅持下去~~我相信很多人應該都跟我一樣~~在第一關:在申請consumer_key &consumer_secret 時就卡關了....就算申請了~~也會卡在oauth的繁瑣步驟...好在有版主的好文~~

    ReplyDelete
  9. shih :
    感謝你的誇獎,我之前也是卡了很久,關關過關關卡啊...
    大概花了兩個星期才把yahoo oauth跟openid都搞定
    所以想說寫文章出來,能幫到也卡關的人

    有幫到你我就很開心啦

    ReplyDelete
  10. 哈囉!這篇文章寫得很好,
    我分享一下剛剛卡關一個下午的經驗。

    BaseText裡的Parameter部分,必須先url_encode之後,
    放到BaseText之後再url_encode一次,

    也就是假設原本query_string長這樣:
    a=http://123.456&b=abc
    經過第一次url_encode會變成
    a=http%3A%2F%2F123.456&b=abc
    而丟進BaseText的最終版本是
    a%3Dhttp%253A%252F%252F123.456%26b%3Dabc

    提醒也為此卡關的人XD

    ReplyDelete
  11. 感謝樓上回答,我很久沒寫其實有點忘了,yahoo也不確定有沒有修改過XD

    ReplyDelete
  12. 版大,
    我也有如何帶xml的content在http post的問題,
    我看到shih有試成功了,
    不知道shih是否有留email給您, 是否可以請您轉介
    謝謝!

    [email protected]

    ReplyDelete
  13. sorry, 我被這問題搞到頭昏了 ><
    謝謝~~~ ^^

    ReplyDelete
  14. 終於成功了!非常感謝作者以及各位的意見

    也提供我的操作經驗:
    1. 「RFC3986 URI」在php轉碼要使用「urlencode(內容)」這個函數
    2.「HMAC-SHA1」要使用「base64_encode(hash_hmac('sha1',BaseText,KeyText,true))」
    3.只有「BaseText」跟「Link」各需要一次「RFC3986 URI[php就是urlencode();]」,其餘不用

    大致上就是這樣!

    ReplyDelete
  15. 請問有人有使用 Yahoo Mail API 的經驗嗎?

    我在使用 "GetUserData" 碰到 "Not Found on Accelerator" response (404) 問題。

    按照官方文件和 SDK 範例,應該只要滿足以下 四件事
    1. 設定 url 為 http://mail.yahooapis.com/ws/mail/v1.1/jsonrpc
    2. 設定 Content-Type 為 application/json
    3. 設定 Accept 為 application/json
    4. 設定 Body 為 {"method":"GetUserData',"":[{}]}
    5. 使用 POST method
    (Oauth 本來就應該要 sign, 故省略不提)

    送出 request 後,卻得不到應有的 JSON response. 而是 "Not Found on Accelerator" response (404)
    已經使用 HTTP sniffer 確定送出的 Headers, Body, Method 皆正確。
    但卻得不到正確的回值。

    請有經驗的朋友提供意見,萬分感謝。

    Ivan
    [email protected]

    ReplyDelete