最近,国内主要门户网站相继开放了微博平台,对开发者而言这无疑是个利好消息,不过在实际使用中却发现平台质量良莠不齐,有很多不完善的地方,就拿PHP版SDK来说吧,多半都是用TwitterOAuth改的,一旦多平台集成,很容易出现命名冲突之类的问题。
既然官方SDK不给力,那我们只能发扬自力更生的革命精神了!好消息是PHP本身已经有了一个标准的OAuth实现:PECL OAuth!下面以此为例来讲解一下如何实现微博应用:
说明:首先需要对OAuth概念有一定的了解,如不清楚可以参考我以前写的文章:OAuth那些事儿,其次需要注册成为各个微博平台(新浪,腾讯,搜狐,网易)的开发者,拿到属于你自己的CONSUMER_KEY和CONSUMER_SECRET(有时也被称作APP_*)。
下面开始!假定我们要开发一个类似Follow5和微博通的应用,简单点说就是把消息同时发送到多个微博平台,出于安全性的考虑,不会使用HTTP Basic,而会使用OAuth,这就需要我们先拿到Access Token和Access Token Secret。
以新浪微博为例,大致的代码如下:
| 以下是代码片段: <?php session_start(); $request_token_url = ’http://api.t.sina.com.cn/oauth/request_token’; $oauth = new OAuth( if (empty($_GET[’oauth_verifier’])) { $request_token = $oauth->getRequestToken($request_token_url); $_SESSION[’oauth_token_secret’] = $request_token[’oauth_token_secret’]; $param = array( header(“Location: {$authorize_url}?” . http_build_query($param)); $oauth->setToken($_GET[’oauth_token’], $_SESSION[’oauth_token_secret’]); $access_token = $oauth->getAccessToken( var_dump($access_token); ?> |
腾讯微博相比较而言有点特殊,大致代码如下:
| 以下是代码片段: <?php session_start(); $request_token_url = ’https://open.t.qq.com/cgi-bin/request_token’; $oauth = new OAuth( $oauth->setNonce(md5(mt_rand())); if (empty($_GET[’oauth_verifier’])) { $request_token = $oauth->getRequestToken($request_token_url, $callback_url); $_SESSION[’oauth_token_secret’] = $request_token[’oauth_token_secret’]; $param = array( header(“Location: {$authorize_url}?” . http_build_query($param)); $oauth->setToken($_GET[’oauth_token’], $_SESSION[’oauth_token_secret’]); $access_token = $oauth->getAccessToken( var_dump($access_token); ?> |
注意:参数nonce和callback的设置,详见:使用 PECL 的 OAuth 库访问 QQ 微博 API。
照猫画虎就能得到搜狐和网易的Access Token和Access Token Secret了,我就不罗嗦了。
下面继续做我们的微博应用,发消息一般都是文本形式的,不过有中国特色的微薄开放平台支持文本加图片的方式:图片上传到服务器,但本身并不参与签名。这和标准OAuth是冲突的,所以要扩展一下PECL OAuth,并且尽可能兼容原类的使用方法和习惯:
| 以下是代码片段: <?php class MicroblogOAuth extends OAuth public $signature_method; public $auth_type; public $nonce; public $timestamp; public $token; public $version; public $request_engine; public $last_response; public function setAuthType($auth_type) return true; return false; public function setNonce($nonce) return true; return false; public function setTimestamp($timestamp) return true; return false; public function setToken($token, $token_secret) return true; return false; public function setVersion($version) return true; return false; public function setRequestEngine($request_engine) $this->request_engine = $request_engine; public function getLastResponse() public function upload($url, $file, $param = array(), $header = array()) $header[] = “Content-Type: multipart/form-data; boundary={$boundary}”; $oauth = array( if ($this->auth_type == OAUTH_AUTH_TYPE_FORM) { $param[’oauth_signature’] = $this->generateSignature( $oauth[’oauth_signature’] = $this->generateSignature( foreach ($oauth AS $name => $value) { $header[] = ’Authorization: OAuth ’ . implode(’, ’, $oauth_header); $content_disposition = function($name, $filename = null) { if ($filename !== null) { return $result; $content = array(); foreach ($file as $name => $value) { switch(strtolower(pathinfo($filename, PATHINFO_EXTENSION))) { $content_type = “Content-Type: {$mime}”; $content[] = “–{$boundary}”; $content[] = file_get_contents($value); ksort($param); foreach ($param as $name => $value) { $content[] = $value; $content[] = “–{$boundary}–“; $content = implode(“rn”, $content); if ($this->request_engine == OAUTH_REQENGINE_CURL) { curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($curl); curl_close($curl); $context = stream_context_create(array( $response = file_get_contents($url, false, $context); if ($response) { return true; return false; ?> |
说明:如果使用PHP Streams方式发送请求的话,需要注意HTTP版本的问题,否则某些情况下请求会被防火墙拦截,详见:由于 HTTP request 不规范导致的被防火墙拦截。
新类MicroblogOAuth直接扩展自PECL的OAuth类!随着PHP内核API的逐渐类化,这样的扩展方式将会越来越常见,值得开发人员重视。
为了让调用方式更统一,使用工厂方法包装MicroblogOAuth的实例化过程:
| 以下是代码片段: <?php function OAuth($consumer_key, $consumer_secret, $signature_method, $auth_type) $instance->consumer_key = $consumer_key; $instance->setAuthType($auth_type); if (extension_loaded(’curl’)) { $instance->last_response = null; return $instance; ?> |
先看看搜狐是如何发送文本加图片消息的:
| 以下是代码片段: <?php $text = ’hello, world.’; $oauth = OAuth( $oauth->setToken( $oauth->upload( $result = json_decode($oauth->getLastResponse(), true); var_dump($result); ?> |
说明:搜狐要求文本要先编码,然后和图片一起发送,这点不同于其它微博开放平台。
再看看网易是如何发送文本加图片消息的:
| 以下是代码片段: <?php $text = ’hello, world.’; $oauth = OAuth( $oauth->setToken( $oauth->upload( $result = json_decode($oauth->getLastResponse(), true); if (isset($result[’upload_image_url’])) { $oauth->fetch( $result = json_decode($oauth->getLastResponse(), true); var_dump($result); ?> |
说明:网易发送文本加图片消息是分两步实现的,先上传图片,然后把图片的URL附加在文本信息的后面再发送到服务器,这点不同于其它微博开放平台。
收工!微博开放平台的使用并没有太多复杂的地方,仔细看文档调试,一般的问题都很容易解决。有了上面的基础代码,只要再使用适配器模式分别包装一下各个微博平台,很容易就能实现一套通用SDK,搞定新浪,腾讯,搜狐,网易!
转自:http://huoding.com/2011/01/16/42

终于找到了提到同步冲突问题的文章了。。
先上到这里。。回头慢慢折腾。。。
(现在同步操作同步到新浪和腾讯还不能同时进行- =