使用 PECL 的 OAuth 库访问 QQ 微博 API

大势所趋,QQ 也在自家门上开了个小洞让诸位看客过过瘾。不过 API 文档不给力,疏漏多、讲得粗,没有 SDK,没有 Step by step,关键细节交代不清……幸而,摸索两日,总算是探得一个靠谱的办法——PECL 的 OAuth 库访问。

特别记录于此,供众玩家观赏。

在使用 PECL 的 OAuth 库之前,尝试过包括 oauth-php 在内的一些第三方库。有些跟 QQ 的 API 不兼容(不要信什么大家都是严格按照 RFC 实现之类的浮云);有些自己正常运行都有问题;还有些我觉得作为一个 API 调用界面,本身设计的用法就太过复杂,封装层次太高……本想用熟悉的 Zend_OAuth,但是想到 Zend 的那个大块头……幸有 PECL!

不过 PECL 也不是人人都能用的,毕竟这个玩意是个要额外安装的家伙。大家酌情选择吧……

先讲讲我的运行环境。我使用的是 linode 的 VPS 主机,最便宜的那种。装的是 Ubuntu 10.4,Apache2、PHP5 这些都是 apt 装的。个人觉得,我投入的那点精力优化出来的编译参数不一定会比 ubuntu 的团队做得更好。

所以 OAuth 扩展的安装是非常的简单,首先安装 php 的编译依赖和 pear 包。libpcre3 是 OAuth 编译依赖的一个包,主要用来支持正则表达式:

sudo apt-get install php5-dev php-pear libpcre3-dev

使用 pecl 安装 OAuth:

sudo pecl install oauth

在 /etc/php5/apache2/conf.d/ 下建立文件 oauth.ini,加内容:

extension=oauth.so

重启 web 服务器:

sudo apache2ctl restart

好了,OAuth 扩展加载完成。

在演示中,只做两件事情:1、利用 OAuth 完成身份验证。2、取得身份验证后获取大厅消息。

下面是代码,不罗嗦了,注释里说明。

define.php

<?php
define('OAUTH_KEY', '应用信息里的 App Key');
define('OAUTH_SECRET', '应用信息里的 App Secret');

define('REQUEST_TOKEN', 'https://open.t.qq.com/cgi-bin/request_token');
define('AUTHORIZE', 'https://open.t.qq.com/cgi-bin/authorize');
define('ACCESS_TOKEN', 'https://open.t.qq.com/cgi-bin/access_token');

define('CALLBACK', 'http://xxiyy.com/qqt/callback.php');

session_id('XY');
session_start();

index.php

<?php
include('define.php');
try {
    $oauth = new OAuth(OAUTH_KEY, OAUTH_SECRET, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
    $oauth->enableDebug();
    // 很重要!!!在 OAuth 标准里是没有规定 nonce 的长度的,但是 QQ 对 nonce 的长度做了要求——32 字节长。如果不设置一下,会返回 400 错误。我为此纠结了一天。
    $oauth->setNonce(md5(rand()));
    // CALLBACK 一定要设置,OAuth 扩展的文档上是没设置的,但是 QQ 这里不设会报错
    $requestTokenInfo = $oauth->getRequestToken(REQUEST_TOKEN, CALLBACK);
    $_SESSION['oauth_token_secret'] = $requestTokenInfo['oauth_token_secret'];
    // header("Location: ……") 亦可
    echo "<p><a href='" . AUTHORIZE . "?oauth_token=" . $requestTokenInfo['oauth_token'] . "'>authorize</a></p>";
} catch (OAuthException $e) {
    var_dump($e);
}

callback.php

<?php
include('define.php');
try {
    $oauth = new OAuth(OAUTH_KEY, OAUTH_SECRET, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
    $oauth->enableDebug();
    // 很重要!!!如果不设置一下,会返回 401 错误。
    $oauth->setNonce(md5(rand()));
    $oauth->setToken($_GET['oauth_token'], $_SESSION['oauth_token_secret']);
    $accessTokenInfo = $oauth->getAccessToken(ACCESS_TOKEN, null, $_GET['oauth_verifier']);
    $_SESSION['access_token'] = $accessTokenInfo['oauth_token'];
    $_SESSION['access_secret'] = $accessTokenInfo['oauth_token_secret'];
    header('Location: room.php');
} catch (OAuthException $e) {
    var_dump($e);
}

room.php

<?php
include('define.php');
try {
    $url = "http://open.t.qq.com/api/statuses/public_timeline?format=json&pos=0&reqnum=10";

    $oauth = new OAuth(OAUTH_KEY, OAUTH_SECRET, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
    $oauth->enableDebug();
    $oauth->setToken($_SESSION['access_token'], $_SESSION['access_secret']);
    $oauth->fetch($url);
    $json = json_decode($oauth->getLastResponse());
    var_dump($json);
} catch (OAuthException $e) {
    var_dump($e);
}

完整代码:下载

PS:多说两句。今天微博上看到关于 QQ 开放的 API 有一些讨论,似乎认可度不高。不过,虽然腾讯这次开放的微博 API 还有很多不足,尤其是开发者支持和文档方面。但说句公道话,还远未达到“令人畏惧”的程度(你们想看看更“令人畏惧”的吗?)。按照腾讯一贯的风格:持续迭代、快速改进,应该很快会有新的支持。

尝试一下这个:

貌似有问题,带不上地址呢?我又搞错什么了?

Join the Conversation

6 Comments

  1. 楼主这是基于OAuth 1.0*的扩展
    请问下 该扩展 是否支持 OAuth2.0 协议呢
    或者目前有木有这样的扩展可以用,谢谢

Leave a comment

Your email address will not be published. Required fields are marked *