@jiangyifen
2017-02-26T14:34:04.000000Z
字数 12359
阅读 679
中间件
API
作者:江毅奋
手机:13391026171
邮箱:jiangyifen@rssoft.cc
QQ:1072661132
http(s)://${IP}:${PORT}/rsmw/api/${API_VERSION}/?sign=${sign}
例:
http(s)://192.168.100.100:18080/rsmw/api/2.0?sign=371d58f95967f0c87b95376b39ec2552
注意,HTTP 请求头部的 Content-Type 必须 如下设置
Content-Type: text/plain;charset=UTF-8
{
"timestamp":"1478321775260",
"command":"${commandName}"
"${keyX}":"${valueX}"
}
{
"timestamp":"1478321782349",
"errCode":"${errCode}",
"errMsg":"${errMsg}",
"${keyX}":"${valueX}"
}
{
"timestamp":"1478321785359",
"event":"${event_name}",
"${KEY-X}":"${VALUE-X}"
}
System.currentTimeMillis()
RSMW通过“校验签名”的方法对调用者的身份进行认证。
当你的应用需要向RSMW服务器端发送jsonString时,先获整个jsonString的sign:
String sign = RsmwSignUtil.sign(jsonString, apiSecret);
然后把sign在URL中带上,供rsmw服务器端校验:
String url = "http://192.168.100.100/rsmw/api/2.0?sign=" + sign;
http://192.168.100.100/rsmw/api/2.0?sign=371d58f95967f0c87b95376b39ec2552
{
"timestamp":"1478321782349",
"command":"orignate",
"xxxx":"yyyy"
}
Java签名工具类:
import java.security.MessageDigest;
public class RsmwSignUtil {
private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
private static final String md5(String s) {
try {
byte[] btInput = s.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static final String sign(String jsonString, String apiSecret){
String result = md5(jsonString + apiSecret);
return result;
}
}
{
"timestamp":"1478321782349",
"command":"helloWorld"
}
RSMW 会向你返回
{
"timestamp":1478321782349,
"errCode":"0",
"errMsg":"Hello World!"
}
勾选需要订阅的Event
用途:Agent(座席)一般对应于第三方应用的“用户”概念。第三方的用户与RSMW的Agent需要用此接口实现同步。
调用时机:第三方应用新增用户、删除用户时
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
agentAid | 第三方应用中用户的唯一标识,一般是id或用户名 | String | 64 | 是 |
agentName | 姓名 | String | 64 | |
agentJobNumber | 工号 | Long | 64 |
- 【新增Agent】
Request:
{
"timestamp":"1478321782349",
"command":"agentSave",
"agentAid":"1001",
"agentName":"张三",
"agentJobNumber":1001
}
Request:
{
"timestamp":"1478321782349",
"command":"agentDelete",
"agentAidList":["1001","1002"]
}
Request:
{
"timestamp":"1478321782349",
"command":"agentListAll"
}
Response:
{
"timestamp": 1478321782349,
"errCode": "0",
"errMsg": "SUCCESS",
"result": [
{
"agentName": "张三",
"aid": "1001",
"extColumns": {},
"id": 1,
"jobNumber": 1001
},
{
"agentName": "李四",
"aid": "1002",
"extColumns": {},
"id": 2,
"jobNumber": 1002
}
]
}
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
agentAid | 第三方应用中用户的唯一标识,一般是id或用户名 | String | 64 | 是 |
sipPhoneName | 所要绑定的SIPPHONE的分机号 | String | 64 |
- 【绑定】
Request:
{
"timestamp":"1478321782349",
"command":"bind",
"agentAid":"1001",
"sipPhoneName":"8001"
}
{
"timestamp":"1478321782349",
"command":"unBind",
"agentAid":"1001"
}
{
"timestamp":"1478321782349",
"command":"unBind",
"sipPhoneName":"8001"
}
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
agentAid | 第三方应用中用户的唯一标识,一般是id或用户名 | String | 64 | |
sipPhoneName | 所要绑定的SIPPHONE的分机号 | String | 64 |
- Request:
{
"command":"getBindInfo",
"agentAid":"1001"
}
{
"command":"getBindInfo",
"sipPhoneName":"8001"
}
{
"timestamp":"1478321782349",
"errCode":"0",
"errMsg":"SUCCESS",
"agentAid":"1001",
"sipPhoneName":"8001"
}
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
queueMemberInterface | 技能组成员所使用的设备拨号字符串,格式为:SIP/${sipPhoneName} | String | 64 | 是 |
reason | 置忙原因 | String | 64 |
- 【置忙】
Request:
{
"timestamp":"1478321782349",
"command":"queueMemberPause",
"queueMemberInterface":"SIP/8001",
"reason":"开会"
}
{
"timestamp":"1478321782349",
"command":"queueMemberUnPause",
"queueMemberInterface":"SIP/8001"
}
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
channels | 实时通道数 | Integer | 64 | |
calls | 实时通话数 | Integer | 64 |
说明:“通道”指一个设备(话机或网关)和RSMW之间的一个连接;“通话”指“一通电话”,可能包含多个“通道”
例如:8001分机呼叫8002分机(产生1个“通道”:SIP/8001-XXXXXXXX,1个通话),8002振铃(产生第2个通道:SIP/8002-XXXXXXXX),8002接起。此时系统中共有2个“通道”,1个“通话”。
Request:
{
"timestamp":"1478321782349",
"command":"getChannelCount"
}
Response:
{
"timestamp":"1478321782349",
"errCode":"0",
"errMsg":"SUCCESS",
"channels":201,
"calls":100,
}
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
absoluteTimeout | 通话超时时间(秒)。超时后自动挂断 | Integer | 32 | |
src | 第一路呼叫的号码 | String | 64 | 是 |
srcGateway | 第一路呼叫所需要走的gateway。若src为内部分机号,则此字段无需填写 | String | 64 | |
srcAccessNumber | 第一路呼叫所需要用的主叫号。若src为内部分机号,则此字段无需填写 | String | 64 | |
srcAnnounceMediaUrl | 第一路呼叫接通后所听到的提示音 | String | 64 | |
dst | 第二路呼叫的号码 | String | 64 | 是 |
dstGateway | 第二路呼叫所需要走的gateway。若dst为内部分机号,则此字段无需填写 | String | 64 | |
dstAccessNumber | 第二路呼叫所需要用的主叫号。若dst为内部分机号,则此字段无需填写 | String | 64 | |
dstAnnounceMediaUrl | 第二路呼叫接通后所听到的提示音 | String | 64 | |
queueLength | RSMW 内部呼叫队列中,当前排队的呼叫请求数量 | Integer | 64 |
Request:
{
"timestamp":"1478321782349",
"command":"originate",
"absoluteTimeout":300,
"src":"13391026171",
"srcGateway":"myGatewayName1",
"srcAccessNumber":"60172133",
"srcAnnounceMediaUrl":"http://ip:port/path",
"dst":"13761488223",
"dstGateway":"myGatewayName2",
"dstAccessNumber":"60172133",
"dstAnnounceMediaUrl":"http://ip:port/path"
}
Response:
{
"timestamp":"1478321782349",
"errCode":"0",
"errMsg":"SUCCESS",
"queueLength":10
}
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
sipPhoneName | sipPhone的分机号 | String | 64 | 是 |
channel | sipPhone的channel | String | 64 | |
connectedChannel | 正与sipPhone接通的对方channel | String | 64 |
Request:
{
"timestamp":"1478321782349",
"command":"getChannel",
"sipPhoneName":"8001"
}
Response:
{
"timestamp":"1478321782349",
"errCode":"0",
"errMsg":"SUCCESS",
"channel":"SIP/8001-XXXXXXXX",
"connectedChannel":"SIP/gw1-XXXXXXXX"
}
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
channel | 希望转接的channel名称 | String | 64 | 是 |
exten | 希望将channel转接到的目标分机号 | String | 64 | 是 |
Request:
{
"timestamp":"1478321782349",
"command":"redircet",
"channel":"SIP/8001-XXXXXXXX",
"exten":"13391026171"
}
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
channel | 希望挂断的channel名称 | String | 64 | 是 |
Request:
{
"timestamp":"1478321782349",
"command":"hangup",
"channel":"SIP/8001-XXXXXXXX"
}
用途:查询所有的sipPhone状态
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
online | sipPhone是否注册在线 | Boolean | ||
regStatus | sipPhone当前注册状态描述 | String | 64 | |
currentChannel | sipPhone当前channel名称 | String | 64 | |
channelState | sipPhone当前通话状态【READY,RINGING,RING,UP】 | String | 64 | |
connectedChannel | 正与sipPhone接通的对端channel名称 | String | 64 | |
agent | 当前绑定该sipPhone的坐席 | Object | ||
agent.id | agent的id | Long | 64 | |
agent.aid | agent的aid | String | 64 | |
agent.agentName | agent的姓名 | String | 64 | |
agent.jobNumber | agent的工号 | Long | 64 | |
sipPhone | sipPhone对象 | Object | ||
sipPhone.id | sipPhone的id | Long | 64 | |
sipPhone.name | sipPhone的分机号 | String | 64 | |
sipPhone.secret | sipPhone注册密码 | String | 64 | |
sipPhone.callerIdNumber | sipPhone主叫号 | String | 64 | |
sipPhone.canLdd | 允许呼叫本地号码 | Boolean | ||
sipPhone.canDdd | 允许呼叫国内长途 | Boolean | ||
sipPhone.canIdd | 允许呼叫国际长途 | Boolean |
Request:
{
"timestamp":"1478321782349",
"command":"getSipPhoneStatus"
}
Response:
{
"timestamp": 1486974877553,
"errMsg": "SUCCESS",
"errCode": "0",
"result": {
"8001": {
"online": true,
"currentChannel": "",
"channelState": "READY",
"regStatus": "OK (29 ms)",
"connectedChannel": "",
"agent": {
"id": 1,
"aid": "1001",
"agentName": "1001",
"jobNumber": 1001,
"extColumns": {}
},
"sipPhone": {
"id": 1,
"name": "8001",
"secret": "aaa111",
"callerIdNumber": "",
"canLdd": true,
"canDdd": true,
"canIdd": false,
"extColumns": {}
}
},
"8002":{
...
}
}
}
用途:查询手机号归属地信息
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
mobilePhoneNumber | 手机号 | String | 64 | 是 |
areaCode | 区号 | String | 64 | |
province | 省 | String | 64 | |
city | 市 | String | 64 | |
operator | 运营商 | String | 64 |
Request:
{
"timestamp":"1478321782349",
"command":"getMobileInfo",
"mobilePhoneNumber":"13391026171"
}
Response:
{
"timestamp": 1486974877553,
"errMsg": "SUCCESS",
"errCode": "0",
"areaCode":"021",
"province":"上海",
"city":"上海",
"operator":"电信"
}
触发时机:两个channel接通或断开时
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
bridge | 接通或挂断(true,false) | Boolean | 64 | |
areaCode | 区号 | String | 64 | |
province | 省 | String | 64 | |
city | 市 | String | 64 | |
operator | 运营商 | String | 64 |
{
"timestamp":"1478321782349",
"event":"bridgeEvent",
"bridge":true,
"channel1":"SIP/8001-XXXXXXXX",
"uniqueId1":"1486973220.28",
"callerIdNumber1":"8001",
"channel2":"SIP/gw1-XXXXXXXX",
"uniqueId2":"1486973221.00",
"callerIdNumber2":"13391026171"
}
触发时机:channel的状态改变时
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
channel | 通道名称 | String | 64 | |
uniqueId | 通道id | String | 64 | |
channelState | 通道状态【RING,RINGING,UP,DOWN】 | String | 64 | |
callerIdName | 主叫号callerIdName | String | 64 | |
callerIdNumber | 主叫名callerIdNumber | String | 64 | |
connectedLineName | 对端主叫号 | String | 64 | |
connectedLineNumber | 对端主叫名 | String | 64 |
{
"timestamp":"1478321782349",
"event":"newStateEvent",
"channel":"SIP/8001-XXXXXXXX",
"uniqueId":"1486973220.28",
"channelState":"RINGING",
"callerIdName":"8001",
"callerIdNumber":"8001",
"connectedLineName":"13391026171",
"connectedLineNumber":"13391026171"
}
触发时机:channel被路由到新的exten时
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
accessDate | 日期 | String | 64 | |
uniqueId | channel唯一标识 | String | 64 | |
channel | channel名称 | String | 64 | |
callerIdNumber | 主叫号 | String | 64 | |
srcGateway | 本channel的来源网关 | String | 64 | |
srcAccessNumber | 本channel的来源接入号 | String | 64 | |
dstGateway | 本channel的目标网关 | String | 64 | |
dstAccessNumber | 本channel的目标接入号 | String | 64 | |
exten | 本channel当前路由到的分机号 | String | 64 | |
extenType | 本channel当前路由到的分机号类型 | String | 64 | |
extenDescription | 本channel当前路由到的分机号描述 | String | 64 |
{
"timestamp":"1478321782349",
"event":"channelRouteEvent",
"accessDate":"2017-11-22 01:23:45",
"uniqueId":"1486973220.28",
"channel":"SIP/gw1-XXXXXXXX",
"callerIdNumber":"13391026171",
"srcGateway":"gw1",
"srcAccessNumber":"60000000",
"dstGateway":"gw2",
"dstAccessNumber":"61111111",
"exten":"7001",
"extenType":"QUEUE",
"extenDescription":"客服组"
}
触发时机:通话结束时
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
startTime | 通话开始时间 | String | 64 | 是 |
answerTime | 通话应答时间 | String | 64 | |
endTime | 通话结束时间 | String | 64 | 是 |
answered | 是否应答 | Boolean | 是 | |
duration | 持续时长 | Integer | 64 | 是 |
billSeconds | 接通时长 | Integer | 64 | 是 |
callDirection | 呼叫方向【INNER, OUTER, INBOUND, OUTBOUND, ORIGINATE】 | String | 64 | 是 |
callerId | 主叫字符串(包括callerIdNumber和callerIdName) | String | 64 | 是 |
src | 主叫 | String | 64 | 是 |
srcGateway | 主叫网关 | String | 64 | |
srcAccessNumber | 主叫接入号 | String | 64 | |
srcAgentAid | 主叫agentAid | String | 64 | |
srcAgentname | 主叫agent姓名 | String | 64 | |
srcChannel | 主叫channel | String | 64 | 是 |
dst | 被叫 | String | 64 | 是 |
dstGateway | 被叫网关 | String | 64 | |
dstAccessNumber | 被叫接入号 | String | 64 | |
dstAgentAid | 被叫agentAid | String | 64 | |
dstAgentname | 被叫agent姓名 | String | 64 | |
dstChannel | 被叫channel | String | 64 | 是 |
serverId | 产生本话单的服务器id | String | 64 | 是 |
recordUrl | 录音相对路径 | String | 64 | 是 |
uniqueId | 本通话的唯一标识 | String | 64 | 是 |
{
"timestamp":1486972748511,
"event":"cdrEvent",
"startTime":"2017-02-13 15:58:59",
"answerTime":"",
"endTime":"2017-02-13 15:59:07",
"answered":false,
"duration":8,
"billSeconds":0,
"callDirection":"INNER",
"callerId":"8002 <8002>",
"src":"8002",
"srcGateway":"",
"srcAccessNumber":"",
"srcAgentAid":"",
"srcAgentname":"",
"srcChannel":"SIP/8002-00000010",
"dst":"8001",
"dstGateway":"",
"dstAccessNumber":"",
"dstAgentAid":"",
"dstAgentName":"",
"dstChannel":"SIP/8001-00000011",
"dstContext":"SIPPHONE",
"serverId":"asterisk1",
"recordUrl":"/2017/02/13/1486972739.26.wav",
"uniqueId":"1486973220.28"
}
【API 路由】用来让第三方应用决定呼入通话的路由:RSMW会在有电话呼入时向第三方URL发起请求,告知关键参数。第三方应用可以通过这些参数结合自身的业务数据来决定将该通电话路由到哪里。
“API路由”功能在“呼入路由”或“IVR”中进行配置
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
channel | 通道名称 | String | 64 | 是 |
src | 主叫 | String | 64 | 是 |
srcAccessNumber | 主叫接入号 | String | 64 | |
ivrExten | 当前IVR分机号 | String | 64 | |
ivrKeyPressed | IVR中的按键 | String | 64 |
- Request:
{
"timestamp":"1478321782349",
"event":"apiRoute",
"channel":"SIP/8002-00001111",
"src":"13391026171",
"srcAccessNumber":"60172133",
"ivrExten":"6001",
"ivrKeyPressed":"654321"
}
路由到内部Exten或自定义Dialplan的Exten
字段 | 说明 | 类型 | 长度 | 必填 |
---|---|---|---|---|
dst | 目标号码(希望把该通电话路由到哪里去 | String | 64 | 是 |
dstGateway | 目标网关(如果dst需要从网关呼出,则从该网关呼出) | String | 64 | 是 |
dstAccessNumber | 目标接入号(如果dst需要从网关呼出,则用该号码作为主叫) | String | 64 |
- Response:
{
"timestamp":"1478321782349",
"errCode":"0",
"dst":"8001"
}
路由到外部号码
{
"timestamp":"1478321782349",
"errCode":"0",
"dst":"13391026171",
"dstGateway":"gw1",
"dstAccessNumber":"60172133"
}
Git: https://git.oschina.net/jiangyifen/rsmw-java
我们推荐使用Chrome或Firefox上的HTTP插件:
Chrome上的Postman:postman
Firefox上的REST Client:REST Client
他们会简化你的调试工作。
当然,你完全可以直接写代码调试
联系江毅奋(13391026171)获取商业支持
如何调用RSMW API ?
通过发送HTTP POST请求来调用Api Command
通过接收HTTP POST请求来接收Api Event
通过接收HTTP POST请求并给出HTTP响应来使用Api路由
调用 API 时,为何返回的是HTML而不是JSON
Http头部Content-Type字段必须如下设置。请检查
Content-Type: text/plain;charset=UTF-8
参考 【2.2 URL 及 HTTP POST JSON格式】
是否提供OCX控件 ?
不提供。OCX是Windows平台的技术,且相对封闭和陈旧,无法适配大部分主流浏览器。
RSMW所采用跨平台的、更标准、更流行、更简单易用的HTTP API。
RSMW 支持什么开发语言 ?
RSMW 对于第三方应用采用什么语言开发没有任何要求。任何语言都可以调用RSMW API
RSMW 是否支持高可用和横向扩展?
支持。
联系江毅奋(13391026171)获取商业支持