码迷,mamicode.com
首页 > Windows程序 > 详细

容联云通讯API的学习过程及 RestAPI Node.js 封装

时间:2015-05-14 11:38:17      阅读:2468      评论:0      收藏:0      [点我收藏+]

标签:

进入正文~ 公司最近有个活动,会用到云通讯的功能。作为一个全栈工程师自然是对 JavaScript 比较熟一点,所以决定选择 Nodejs 来进行开发。看了一下云通讯的文档,没有 Nodejs 的 SDK (´°????????ω°????????`) 好在 Rest API 是基于 HTTP 协议的,用其他语言也能很容易地实现接口 (?>?<?) 

可能是因为对云通讯这种功能没什么概念吧,看了一遍文档还是云里雾里的。怎么办呢……于是决定对着文档一个一个接口试,试下来以后对云通讯的功能也有了个大概了解了。

理解下来,云通讯大概有三种接口:

  • 1. voip 客户端,包括安卓、iOS、Windows 的 Client SDK 和基于 Flash 的 Web SDK,可以分配一个 voip 电话号码,实现类似落地电话一样的功能
  • 2. 应用主动发起的 RestAPI,由应用向云通讯发起请求,可以实现子帐号、短信、双向回拨、语音验证码、话单下载以及创建电话会议等等操作
  • 3. 云通讯向应用服务器发起请求,根据返回结果做出相应的操作。一般用于 ivr 相关功能


下面从第二种开说吧,因为这种操作比较能掌握主动权 ?(‾??)? 

首先是子帐号,可以用来在 voip 客户端进行登录。对 RestAPI 的请求大部分需要通过主帐号发起,但是还有一些 API 是需要通过子帐号发起的。所以我们首先尝试来发起一个创建子帐号的请求吧。

创建子账户的文档在
http://docs.cloopen.com/index.php/%E5%88%9B%E5%BB%BA%E5%AD%90%E8%B4%A6%E6%88%B7

看文档上说请求地址是:

/{SoftVersion}/Accounts/{accountSid}/SubAccounts


额,这些是个嘛呢,看不懂啊…… 别急,文档下面还有一个关于“统一请求包头”的链接:
http://docs.cloopen.com/index.php/Rest%E4%BB%8B%E7%BB%8D#2_.E7.BB.9F.E4.B8.80.E8.AF.B7.E6.B1.82.E5.8C.85.E5.A4.B4

首先有一个 BaseURL:

https://sandboxapp.cloopen.com:8883/2013-12-26


从 sandboxapp 可以看出这个是测试用的 BaseURL(从云通讯控制台里可以看到生产的 BaseURL 前面是 https://app.cloopen.com:8883 ),而“2013-12-26”就是请求地址里的 {SoftVersion} 部分。
这个就是请求地址前面的部分,于是上面的请求的完整地址就是:

https://sandboxapp.cloopen.com:8883/2013-12-26/Accounts/{accountSid}/SubAccounts



接下来可以看到有两种 URL 格式:

/Accounts/{accountSid}/{func}/{funcdes}?sig={SigParameter}
/SubAccounts/{subAccountSid}/{func}/{funcdes}?sig={SigParameter}


第一种是通过主帐号发起,第二种是通过子帐号发起的。我们要实现的创建子帐号接口就是第一种,需要传递主帐号信息。大家登录云通讯控制台以后可以看到有一个 ACCOUNT SID, 就是这里的 {accountSid} 了。假设我的 ACCOUNT SID 是 xxxxxx,那请求地址就是:

https://sandboxapp.cloopen.com:8883/2013-12-26/Accounts/xxxxxx/SubAccounts



为了拼出个请求地址就罗里吧嗦写了这么多,是不是很烦?好了好了,下面进入比较重要的部分,就是统一请求包头。
云通讯的接口可能两种格式,即 xml 和 json。作为一个 JS 开发人员当然希望全都用 json 了,可惜有很多接口比如 ivr 相关接口只支持 xml。
在请求头里必须包括 Content-Type,Accept,和 Content-Length。 Content-Type 字段表示发起请求体的格式,Accept 表示希望返回的格式。如果你发出的是 xml,希望返回的也是 xml,那请求头就需要是

Accept:application/xml;
Content-Type:application/xml;charset=utf-8;


Content-Length 是请求体的长度,一般用到的请求库应该会帮忙算出来。我这里用到了 Node.js 的 request 库。

然后还里还必须带另外两个参数: SigParameter 和 Authorization。这两个就需要自己算了,根据文档说明:

  2. SigParameter是REST API 验证参数
       •  URL后必须带有sig参数,例如:sig=ABCDEFG。
       •  使用MD5加密(账户Id + 账户授权令牌 + 时间戳)。其中账户Id和账户授权令牌根据url的验证级别对应主账户或子账户。
       •  时间戳是当前系统时间,格式"yyyyMMddHHmmss"。时间戳有效时间为24小时,如:20140416142030
       •  SigParameter参数需要大写  


下面是实现:


// 实现一个计算md5的方法
crypto = require(‘crypto‘)
md5 = function(str, type=‘hex‘){
  md5sum = crypto.createHash(‘md5‘)
  md5sum.update(str)
  return md5sum.digest(type)
}
//计算 sig
// sid 即主账户或子账户的 sid, 本例中为主账户即上面提到的 xxxxxx
// token 是主账户或子账户的 token,本例中为主账户 token, 即控制台里看到的 AUTH TOKEN,假设我的为 yyyyyy
// timestamp 是格式为 yyyyMMddHHmmss 的时间戳,这里就不写生成 timestamp 的函数了
getSig = function(sid, token, timestamp){
  return md5(sid + token + timestamp).toUpperCase()
}

看文档还以为 SigParameter 也需要加在请求头里,实践后发现在 querystring 里加一个 sig 参数就可以了
于是请求地址变为

https://sandboxapp.cloopen.com:8883/2013-12-26/Accounts/xxxxxx/SubAccounts?sig=算出来的结果



继续:


3. Authorization是包头验证信息
         •  使用Base64编码(账户Id + 冒号 + 时间戳)其中账户Id根据url的验证级别对应主账户或子账户
         •  冒号为英文冒号
         •  时间戳是当前系统时间,格式"yyyyMMddHHmmss",需与SigParameter中时间戳相同。



Authorization 是需要加在请求头里的。实现:

//实现一个计算 base64 编码的方法
base64 = function(str){
  return (new Buffer(str)).toString(‘base64‘)
}
getAuthorization = function(sid, timestamp){
  return base64(sid + ‘:‘ + timestamp)
}

再回头看创建子帐号接口的文档,需要使用 POST 方法,并传递 appId 和 friendlyName。
要创建子帐号,需要先在云通讯控制台创建一个应用,这个 appId 就是创建过的应用的 id。friendlyName 算是子帐号的昵称吧,必填,每个子帐号的 friendlyName 是唯一的。

最后我们希望使用 json 格式来进行交互,于是发起请求的方法大概就是:


request = require(‘request‘)
sid = ‘xxxxxx‘
token = ‘yyyyyy‘
appId = ‘zzzzzz‘
friendlyName = ‘newuser‘
timestamp = getTimestamp()
request({
  uri: ‘https://sandboxapp.cloopen.com:8883/2013-12-26/Accounts/xxxxxx/SubAccounts‘,
  qs: {sig: getSig(sid, token, timestamp)},
  header: {
    Accept: ‘application/json;‘,
    ‘Content-Type‘: ‘application/json;charset=utf-8;‘
    Authorization: getAuthorization(sid, timestamp)
  },
  body: {
    appId: appId,
    friendlyName: friendlyName
  }
}, function(err, response, body){
  //回调函数
  console.log(body)
})


结果:

{ statusCode: ‘000000‘,
  SubAccount:
   { subAccountSid: ‘cdxxxxxxxxxxxxxx90‘,
     voipAccount: ‘8xxxxxxxx7‘,
     dateCreated: ‘2014-06-01 12:40:06‘,
     voipPwd: ‘Hxxxxv‘,
     subToken: ‘0xxxxxxxxxxxxxxxa‘ } }

大功告成!

接下来的接口都类似,于是就很容易了。但试到 ivr 相关的接口,却总是报错,一直不明所以,直到发现 ivr 的文档上没有 json 相应格式说明,这才想到:我勒个去,ivr 接口不支持 json!
于是就需要把 js 的对象序列化成 xml 了。放狗搜了一下,发现一个 js2xmlparser,使用也蛮简单的。比方说我们希望得到这样的 xml:

<?xml version=‘1.0‘ encoding=‘utf-8‘?>
<Request>
  <Appid>111222333444555666777888</Appid>        
  <CreateConf action="createconfresult.jsp" maxmember="5"/>
</Request>

序列化方法和传入对象格式就是:

js2xmlparser = require(‘js2xmlparser‘)
js2xmlparser(‘Request‘, {
  Appid: ‘111222333444555666777888‘,
  CreateConf:{
    ‘@‘: {
      ‘action‘: ‘createconfresult.jsp‘,
      ‘maxmember‘: ‘5‘
    }
  }
})


js2xmlparser 详细的用法大家可以去官网看看:
https://github.com/michaelkourlas/node-js2xmlparser

好在返回的结果仍然可以指定为 ‘application/json;‘,这样会返回一个 json 字符串,需要自己调用 JSON.parse 解析一下。

最后把云通讯一些常用的接口封装了一下,写成了一个 Node.js 模块。还没来得及写文档和逐一测试,有兴趣的同学可以先看一下代码,欢迎各种砸砖报 bug~
https://github.com/ipy/yuntongxun

容联云通讯API的学习过程及 RestAPI Node.js 封装

标签:

原文地址:http://www.cnblogs.com/yuntongxun/p/4502697.html

(0)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!