腾讯微博API之发送带图片的微博 (JavaScript/HTA)

今天 (严格地讲是昨天) 下午开始写发送图片的部分, 其实整个代码的结构都变了, 现在调用也更加方便.

注意, 本文所讲的JavaScript是指在HTA或者其他能够自由创建ActiveXObject对象的环境中的JavaScript, 并不是指普通权限的浏览器中运行的JavaScript.

发送图片等文件需要使用multipart/form-data类型的数据, 偷偷懒地话, 可以用form来提交, 但是想全程XMLHTTP, 就绕了下.

这次遇到的问题主要有两个, 然而这两个问题如果通过form来提交, 则都能轻松搞定.

第一个问题是字节文件的读取. 我使用了ADODB.Stream对象. 详细方法请Google或者参照我的代码.

第二个问题是multipart/form-data的boundary.

当时调用API的时候一直返回file size error这个错误. 一开始我一直以为是图片的问题, 毕竟它是说的file… 但后来, 下意识地修改了一些重要参数, 甚至直接点开API, 都是这个错误. 这才意识到, 或许参数根本没有成功传递.

一开始我使用xmlhttp发送的是string, 但貌似一闪而过, 没有 “上传” 的动作在其中, 毕竟文件也有些大小, 上传是需要一定的时间的. 这时开始就起了疑心, 后来改成了stream, 先把stream改成文本模式, 写入文本, 再改成字节模式, 写入文件内容, 再改回来, 再改过去. 如此反复后, 使用xmlhttp发送了这个stream. 这时总算是有点等待的意思了. 但之后的返回内容依旧提示file size error.

这里纠结了很久, 又去查了很多资料, 最后看到这样一个.

在程序中定义了一个变量boundary,大部分例子中这个boundary变量的起始字符是”–“,因为在HTTP消息体中要使用”–“,但是,如果这样定义,那么调用
xhr.setRequestHeader(‘Content-Type’, ‘multipart/form-data; boundary=’ + boundary);
设置HTTP消息头的时候,就将”–“也声明进去了,我发现在我的运行环境中这样不行,如果定义的变量boundary中没有起始字符”–“就可以了。当然此时要注意在整个消息的结尾需要在boundary字符串前后都加”–“,可以参照HTML规范构造符合规范的消息体。

说实在的我没读懂他的意思… 但是直觉告诉我, 难道是后面的分隔符必须在定义的boundary的基础之上, 前面再加一个 “–” ? 于是试了试… 于是成功了!

具体的操作我也不多说了, 感兴趣的话可以看我的代码.

http://www.vilic.info/demo/vt.rar

 

腾讯微博API OAuth验证及微博发送 (JavaScript)

首先, 道路是曲折的… 之前曾小试过 Basic 验证, 一开是也是不得要领, 不过悟透那个就显然快多了.

这是第一次做 OAuth 的验证, 在此实在想狠狠地骂腾讯的 API 说明文档, 不清不楚, 害得我到处查, 到处试… 总算, 经过一个上午的奋斗, 成功获取了 Request Token, 下午再稍加努力, 终于把 Access Token 拿到了手, 晚上又继续奋战, 搞定了微博发送, 至此, 也算对 OAuth 及腾讯微博的 API 有了个基本的了解.

JavaScript 实现腾讯微博的 OAuth 的难点在于 HMAC-SHA1 加密, 而且之后还得转换成 Base64, 最变态的是, 获取 Request Token 的时候, 加密时 AppKey 后面还得跟上个 “&”!!! 比如原来 AppKey 是 “123456”, 那么加密时的 Key 就是 “123456&”

好吧, 既然大家在看这篇文章, 相信关于 XMLHttpRequest 这些也比较熟悉了, 我就说说重点 (因为我是第一次真正接触 OAuth, 所以对里面一些约定俗成的东西可能还不清楚, 所以高手看了不要笑我这些 “重点” 太幼稚).

HMAC-SHA1 加密的 JavaScript 实现

在网上搜这个搜了很久, 最后找到了一个叫 Crypto-JS 的东西, 一看, 果然是好家伙, 里面提供了非常丰富的加密方式, 值得收藏. http://code.google.com/p/crypto-js/ 下载后引用 crypto.js, sha1.js, hmac.js 三个文件, 加密方式如下:

var message = “Message to be encoded”;
var secret = “Secret phrase”;

var bytes = Crypto.HMAC(Crypto.SHA1, message, secret, { asBytes: true }) ;
//但仅仅这样还不行, 还得转换成Base64.
//在Crypto.util下找到相应的方法.
var signature = Crypto.util.bytesToBase64(bytes);

这样就搞定啦. 需要注意的是 (前面我也有提到), 在获取 Request Token 的时候, secret需要在 App Secret 后面加上 “&”. 获取 Access Token 的时候, 则是用 “&” 把 App Secret 和 Token Secret连起来.

参数编码

按说这个是算不上重点的, 不过实在找不到东西写, 就把这个算上去吧.

方法很简单, 使用JavaScript内置的encodeURIComponent()方法即可.

看来这里还真是重点, 编码要求要什么 [RFC3986], 在 encodeURIComponent() 的基础上, 还要额外编码 ! * ( ) ‘ 这5个字符.

否则当添加微博的内容中出现这些字符的时候, oauth_signature 参数会有误, 导致鉴权失败.

时间戳

注意单位是哦! new Date().getTime()的单位是毫秒, 所以注意先除以1000再取整.

要签名的Base String

里面的参数要排序, 当然这个文档中也强调了. 另外就是这些参数中是不包括 oauth_signature 的. 显然, 也没法包含这个参数, 不过我这样点明下, 免得大家心生疑惑.

 

最后, 这个是我用 HTA (JavaScript) 实现的一个验证和发微博的小Demo, http://www.vilic.info/demo/vt.rar . 源码是基于 vejis 的, 如果有看不太明白的可以参考 vejis.js 文件中的说明. (补充, 后来发现有个小Bug, 其实不算Bug, 我一开始以为所有的API都可以用POST方法, 就全部使用的是POST, 对应的稍微小改就可以了)

关于腾讯和360

所以, 最近腾讯和360玩得很火, 到今天, 已经基本玩成了闹剧.

当您看到这封信的时候,我们刚刚作出了一个非常艰难的决定。在360公司停止对QQ进行外挂侵犯和恶意诋毁之前,我们决定将在装有360软件的电脑上停止运行QQ软件。

腾讯也忍不住了, 终于摆出了决战的态势, 不过就最近发生的事, 我想讲讲自己的看法.

首先, 腾讯一直没有处于主动, 一切都是360在进攻. 包括今天腾讯的这封信, 肯定是360早已经预料到了的结果之一. 所以, 如果不究其对错, 我想360的目的是为了与腾讯划分出一个互斥的市场, 虽然它们其中一个是做”安全”的, 一个是什么都做的. 很显然, 360的目的已经达到了, 一个互斥的用户群必然形成. 在这样的两个用户群中, 慢慢上演的将会是互相蚕食. 只是”安全”市场吗? 或者, 360真会如一些”网友”所言推出IM产品? 这个, 我相信360内部早就规划好了路线, 只是等着一步一步实现而已.

就商业而言, 无所谓对错, 或者说, 360似乎很英明. 假设它以后真的会推出IM, 那他的路明显要比百度Hi要高效一些. 就如我之前所说, 360在创造互斥的市场, 而百度Hi是在并行的市场与腾讯较量. 这个很值得思考.

然后, 回到个人. 这个问题上我更倾向于腾讯. 虽然它有很多附和天朝的做法我看不惯, 但这毕竟是国内企业的通病, 暂时也没法改变. 除此之外, 关于各种”模仿”, 我保持中立, 这个东西, 不好说的.