FreeSWITCH中文网,电话机器人开发网 ,微信订阅号:

FreeSWITCH及VOIP,Openser,电话机器人等产品中文技术资讯、交流、沟通、培训、咨询、服务一体化网络。QQ群:293697898

FSGUI6.1.2动态座席组及推送事件的接口


tags:FreeSWITCH 排队机 ACD排队 工号 满意度 创建时间:2021-08-19 17:41:59

FSGUI6.1.2动态座席组及推送事件的接口

一、基础说明

系统架构图

a.数据表结构

`////////////////////////////////////////////////////////////////////////////////////////////////////////////////////`

```
`CREATE SEQUENCE public.ext_group_id_seq`
  `INCREMENT 1`
  `MINVALUE 1`
  `MAXVALUE 9223372036854775807`
  `START 4`
  `CACHE 1;`
`ALTER TABLE public.ext_group_id_seq`
  `OWNER TO postgres;`


`CREATE SEQUENCE public.ext_group_map_id_seq`
  `INCREMENT 1`
  `MINVALUE 1`
  `MAXVALUE 9223372036854775807`
  `START 1`
  `CACHE 1;`
`ALTER TABLE public.ext_group_map_id_seq`
  `OWNER TO postgres;`

`CREATE TABLE public.ext_group`
`(`
  `id bigint NOT NULL DEFAULT nextval('ext_group_id_seq'::regclass),`
  `group_name character varying(100), -- 组或座席组名`
  `group_number character varying(50) NOT NULL, -- 座席组短号`
  `current_ext_number character varying(50), -- 当前组里接听时找到的分机,如果找不到,则再从头开始`
  `group_call_mode integer DEFAULT 5, -- 呼叫模式  ...`
  `group_callout_timeout integer DEFAULT 15, -- 呼叫到每个号码时的超时时长,默认15秒`
  `transfer_ring character varying(255) DEFAULT '::character varying,`
  `black_list_ring character varying(255) DEFAULT '::character varying,`
  `busy_ring character varying(255) DEFAULT '::character varying,`
  `CONSTRAINT "PK_GROUP_NUMBER" PRIMARY KEY (group_number)`
`)`
`WITH (`
  `OIDS=FALSE`
`);`
`ALTER TABLE public.ext_group`
  `OWNER TO postgres;`
`COMMENT ON TABLE public.ext_group`
  `IS '分机座席分组,面向110业务';`
`COMMENT ON COLUMN public.ext_group.group_name IS '组或座席组名';`
`COMMENT ON COLUMN public.ext_group.group_number IS '座席组短号';`
`COMMENT ON COLUMN public.ext_group.current_ext_number IS '当前组里接听时找到的分机,如果找不到,则再从头开始';`
`COMMENT ON COLUMN public.ext_group.group_call_mode IS '呼叫模式  
0 顺序`
`1 随机`
`2 循环`
`3 记忆优先+ 0`
`4 记忆优先+1`
`5 记忆优先+2';`
`COMMENT ON COLUMN public.ext_group.group_callout_timeout IS '呼叫到每个号码时的超时时长,默认15秒';`



`CREATE TABLE public.ext_group_map`
`(`
  `id bigint NOT NULL DEFAULT nextval('ext_group_map_id_seq'::regclass),`
  `ext_group_id bigint, -- 分机组id`
  `ext_group_number character varying(50), -- 座席组号码`
  `ext character varying(50) -- 分机`
`)`
`WITH (`
  `OIDS=FALSE`
`);`
`ALTER TABLE public.ext_group_map`
  `OWNER TO postgres;`
`COMMENT ON COLUMN public.ext_group_map.ext_group_id IS '分机组id';`
`COMMENT ON COLUMN public.ext_group_map.ext_group_number IS '座席组号码';`
`COMMENT ON COLUMN public.ext_group_map.ext IS '分机';
```

`////////////////////////////////////////////////////////////////////////////////////////////////////////////////////`

到2020-7实现的座席组逻辑如下:

a. 在系统中预定几个组,如 110,12345,12320120,等

B. 接着由座席上线时,指定上线了哪几个组

c. 我们在路由中配置了,如 85733555是进到12320这个组,则配操作符为 16,明细是 12320这个组号

d. 优先进行和组配套的黑名单,如果是处于黑名单就挂 机或放音

e. 接着查询历史沟通记录,如果记忆中的座席空闲,那么就由该座席来处理,否则找空闲座席处理

f. 如果没有历史沟通,就直接找该组空闲座席

g. 如果没空闲座席了,则判断是vip还是普通用户来电,有一定时器,不断优先判断vip的来电,接着判断普通的来电,在查找到有空闲座席的情况下,转给该空闲座席.

h. 不同的客户,需求有所不同,在有关挂 机的要求,有的要求放音几次后挂 ,有的是,客户不挂 机,我们不主动挂 机,按实际来配.

b.相关接口

获取token

返回值: "token":"token code"

非正常返回值: "Not Authorized"

 curl -d '{"username": "admin", "password": "admin"}' -H "Content-Type:application/json" http://ip:8085/api/login

上线

让座席分机为上线或下线,即up or down

//up为上线

//down为下线

里边的组,可以为多个如: "12345,12320"

curl -H "Content-Type: application/json" -d '{"Extension":"1002","Groups":"12345,110"}'  -H "Authorization:Nway token " http://ip:8085/api/agent_up

下线

 curl -H "Content-Type: application/json" -d '{"Extension":"1002"}'  -H "Authorization:Nway token " http://ip:8085/api/agent_down

分机忙闲

让座席分机置忙或置闲 ,这里和设置呼叫状态,在不同的客户需求时,需要进行分开,否则可能只用呼叫状态一项处理不了

//ready or rest

置闲

curl -H "Content-Type: application/json" -d '{"Extension":"1002"}'  -H "Authorization:Nway token " http://ip:8085/api/agent_ready

置忙

curl -H "Content-Type: application/json" -d '{"Extension":"1002"}'  -H "Authorization:Nway token " http://ip:8085/api/agent_busy

设置呼叫状态,具体看需求要不要

​ //ring,talking,ivr,ready,typing,no_answer, no_ready

​ //ready是等待电话-置闲

​ //talking是正在通话中

​ //typing 整理态,接完电话后在整理,默认5分钟

​ //no_answer 久不应答,即响铃后座席未接

​ //busy 置忙

​ //rest 小休

curl -H "Content-Type: application/json" -d '{"Extension":"1002","Value":"ready" }'  -H "Authorization:Nway token " http://ip:8085/api/extension_callstate

获取排队中的来电

按以下的信息返回排队中的电话信息

 Uuid             string    //呼入的channel的uuid
    Number           string    //呼入的号码
    RealCallinNumber string    //实际呼入的号码
    Group            string    //进入的组
    Level            string    //保留用于normal,vip
    CallinTime       time.Time //呼入时间

bash curl -H "Authorization:Nway token " http://ip:8085/api/queues

获取所有的分机状态

按以下的信息返回所有的分机状态信息

go Extension string RegStatus string AgentState string CallState string LastStatusChangeTime string

curl  -H "Authorization:Nway token " http://ip:8085/api/get_extensions

事件和消息的推送

我们使用redis的pub/sub或rabbitmq模式推送如来电,挂 机等事件,以及来电排队等事件,以及cdr

a. 来电,振铃,接通,挂 机等事件

需要psubscribe event_*

就会将所有的event事件推过来

模式如下:

evt_name,callin_number, dest_number, domain, dtmf, gateway, originate_number, direction, auuid, buuid, origination_dest_number

其中evt_name为以下项:

 EVENT_CALLIN EVENT_NAME = 1 + iota     //呼入
    EVENT_CALLOUT     //呼出
    EVENT_RING        //回铃
    EVNET_ALERT       //振铃
    EVENT_ANSWER      //应答
    EVENT_HANGUP      //座席
    EVENT_DTMF        //按键
    EVENT_PLAYRING    //开始放音
    EVENT_PLAYSTOP    //放音结束
    EVENT_PARK        //park掉
    EVENT_UNPARK      //解决park
    EVENT_HOLD        //hold掉
    EVENT_UNHOLD      //unhold
    EVENT_BRIDGED     //已桥接
    EVENT_DESTORY     //已完全释放
    EVENT_TALKING     //正在通话中
    EVENT_DA          //回铃检测

​ Callin_number为呼入号码,或称为主叫号码

​ dest_number 目标号码

​ domain 域,先不用考虑

​ dtmf, 如果是按键,则这里有值

​ gateway, 如果是呼出,则这是呼出的gateway名称

​ originate_number, 原主叫号码

​ direction, 呼入还是呼出

​ auuid, 这条通道的uuid

​ buuid, 关联通道的uuid

​ origination_dest_number 原始被叫号码

如果是mq,则类似于以下

pushstr := "{\"type\":\"event\"," +
            "\"event_name\":\"" + strStatus + "\"," +
            "\"aleg_uuid\":\"" + auuid + "\"," +
            "\"bleg_uuid\":\"" + buuid + "\"," +
            "\"callin_number\":\"" + callin_number + "\"," +
            "\"dest_number\":\"" + dest_number + "\"," +
            "\"domain\":\"" + domain + "\"," +
            "\"dtmf\":\"" + dtmf + "\"," +
            "\"gateway\":\"" + gateway + "\"," +
            "\"originate_number\":\"" + originate_number + "\"," +
            "\"direction\":\"" + direction + "\"," +
            "\"origination_dest_number\":\"" + origination_dest_number + "\"}"

面向座席,则只需要监视以下消息

呼给座席
{
    "type":"event",
    "method":"callout",
    "cti_ip":"10.1.213.29",
    "uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
    "number":"18638737767",
    "group":"120",
    "extension":"1018",
    "level":"normal",
    "callin_time":"2021-05-30 17:00:02"
}
座席无应答
{
    "type":"event",
    "method":"noanswer",
    "cti_ip":"10.1.213.29",
    "uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
    "number":"18638737767",
    "group":"120",
    "extension":"1018",
    "level":"normal",
    "callin_time":"2021-05-30 17:00:02"
}
座席应答
{
    "type":"event",
    "method":"answered",
    "cti_ip":"10.1.213.29",
    "uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
    "number":"18638737767",
    "group":"120",
    "extension":"1018",
    "level":"normal",
    "callin_time":"2021-05-30 17:00:02"
}
座席挂断
{
    "type":"event",
    "method":"hangup",
    "cti_ip":"10.1.213.29",
    "uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
    "number":"18638737767",
    "group":"120",
    "extension":"1018",
    "level":"normal",
    "callin_time":"2021-05-30 17:00:02"
}

b. 通话详单信息

以前采用http推送模式,虽然也没什么影 响,但后来还是采用redis或进一步放个大点的mq等的来完成推送消息的过程

psubscribe cdr_*

其中,主叫,被叫,如果是呼入到座席,那么中间经过了几个没有回应或转接的信息都一起推送过来,如代码:

arr := []string{strings.Trim(uuid, " "),    //唯 一标识符
            strings.Trim(a_caller_id_number, " "),  //a路的主叫号码
            strings.Trim(a_destination_number, " "), //呼叫的目标号码,如119
            strings.Trim(a_start_stamp, " "),   //开始时间
            strings.Trim(a_answer_stamp, " "),   //应答时间
            strings.Trim(a_end_stamp, " "),     结束时间
            strings.Trim(a_duration, " "),     总持续时长
            strings.Trim(a_billsec, " "),      实际通话时间
            strings.Trim(a_sip_hangup_disposition, " "),    哪边挂边
            strings.Trim(a_record_file, " "),       录音文件
            strings.Trim(str_no_answer_agents, " "),   没有应答的座席号码

            strings.Trim(destination_number, " "),     座席号码
            strings.Trim(start_stamp, " "),       开始呼叫座席的时间
            strings.Trim(answer_stamp, " "),      座席应答的时间
            strings.Trim(end_stamp, " "),          座席挂机时间
            strings.Trim(duration, " "),         座席
            strings.Trim(billsec, " ")}
        if len(no_answer_agents) > 0 {
            var tmpstr string
            tmpstr = "{"
            for _, v := range no_answer_agents {
                tmpstr += v + ","
            }
            tmpstr = tmpstr[:len(tmpstr)-1]
            tmpstr += "}"
            arr = append(arr, tmpstr)
        } else {
            arr = append(arr, "")
        }

如果是mq,则类似于

mqstr := "{\"type\":\"cdr\"," +
        "\"uuid\":\"" + strings.Trim(uuid, " ") + "\"," +
        "\"a_caller_id_number\":\"" + strings.Trim(a_caller_id_number, " ") + "\"," +
        "\"a_destination_number\":\"" + strings.Trim(a_destination_number, " ") + "\"," +
        "\"a_start_stamp\":\"" + strings.Trim(a_start_stamp, " ") + "\"," +
        "\"a_answer_stamp\":\"" + strings.Trim(a_answer_stamp, " ") + "\"," +
        "\"a_end_stamp\":\"" + strings.Trim(a_end_stamp, " ") + "\"," +
        "\"a_duration\":\"" + strings.Trim(a_duration, " ") + "\"," +
        "\"a_billsec\":\"" + strings.Trim(a_billsec, " ") + "\"," +
        "\"a_sip_hangup_disposition\":\"" + strings.Trim(a_sip_hangup_disposition, " ") + "\"," +
        "\"a_record_file\":\"" + strings.Trim(a_record_file, " ") + "\"," +
        "\"str_no_answer_agents\":\"" + strings.Trim(str_no_answer_agents, " ") + "\"," +
        "\"destination_number\":\"" + strings.Trim(destination_number, " ") + "\"," +
        "\"start_stamp\":\"" + strings.Trim(start_stamp, " ") + "\"," +
        "\"answer_stamp\":\"" + strings.Trim(answer_stamp, " ") + "\"," +
        "\"end_stamp\":\"" + strings.Trim(end_stamp, " ") + "\"," +
        "\"duration\":\"" + strings.Trim(duration, " ") + "\"," +
        "\"billsec\":\"" + strings.Trim(billsec, " ") + "\"}"
即:
{
    "type":"cdr",
    "cti_ip":"10.1.213.29",
    "uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
    "is_callout":"false",
    "a_caller_id_number":"130****8217",
    "a_destination_number":"120",
    "a_start_stamp":"2021-05-30 16:57:10",
    "a_answer_stamp":"2021-05-30 16:57:10",
    "a_end_stamp":"2021-05-30 16:57:29",
    "a_duration":"19",
    "a_billsec":"19",
    "a_sip_hangup_disposition":"recv_bye",
    "a_record_file":"2021/May/30/18939657757_04ee30b8-c125-11eb-bb04-9180ac6fa0de.wav",
    "str_no_answer_agents":"1011",
    "destination_number":"1011",
    "start_stamp":"2021-05-30 16:57:11",
    "answer_stamp":"",
    "end_stamp":"2021-05-30 16:57:29",
    "duration":"18",
    "flag":"单座席无应答",
    "billsec":"0"
}

c. 排队信息

psubscripe queue_*

其大概信息如下:

method, uuid, number, group, level, callin_time

如果是非redis而是mq,则推送如下消息

RedisString := "{\"type\":\"queue\"," +
            "\"method\":\"" + method + "\"," +
            "\"uuid\":\"" + uuid + "\"," +
            "\"number\":\"" + number + "\"," +
            "\"group\":\"" + group + "\"," +
            "\"level\":\"" + level + "\"," +
            "\"callin_time\":\"" + callin_time + "\"}"

入队:
{
    "type":"queue",
    "method":"nway_queue_add",
    "cti_ip":"10.1.213.29",
    "uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
    "number":"130****8217",
    "group":"120",
    "level":"normal",
    "callin_time":"2021-05-30 17:00:01"
}
出队:
{
    "type":"queue",
    "method":"nway_queue_remove",
    "uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
    "number":"130****8217",
    "group":"120",
    "level":"normal",
    "callin_time":"2021-05-30 19:16:30"
}

d. 在分机发生状态变化时,由系统向外发状态变更

psubscripe agent_*

其大概信息如下:

number, status, time

如果是mq,则类似于以下:

RedisString := "{\"type\":\"agent\"," +
            "\"number\":\"" + number + "\"," +
            "\"status\":\"" + status + "\"," +
            "\"time\":\"" + nway_time + "\"}"

呼叫转移

#为了减少代码量,所以使用了和监听一样的名称
#EvdedPhone 正在通话的号码
#EvdPhone 要转出的号码
#EvdGateway 如果是外线号码,则需要指定网关
curl -H "Content-Type: application/json" -d '{"EvdedPhone":"100
2","EvdPhone":"1003","EvdGateway":""}' -H "Authorization:Nway 
token" http://ip:8085/api/transfer

让电话接通

 curl -H "Authorization:Nway token" http://ip:8085/api/answer/1002

挂断电话

curl -H "Authorization:Nway token" http://ip:8085/api/hangup/1002

监听

EvdedPhone 被监听的号码
EvdPhone 由哪个号码监听
EvdGateway 如果是外线号码进行监听,则需要指定网关
 curl -H "Content-Type: application/json" -d '{"EvdedPhone":
"1002","EvdPhone":"1003","EvdGateway":""}' -H "Authorization:N
way token " http://ip:8085/api/eavesdrop

多方通话

为了减少代码量,所以使用了和监听一样的名称
EvdedPhone 邀请加入多方通话的的号码
EvdPhone 邀请加入的多方通话里有哪个号码在通话
EvdGateway 如果是外线号码,则需要指定网关
 curl -H "Content-Type: application/json" -d '{"EvdedPhone
":"1002","EvdPhone":"1003","EvdGateway":""}' -H "Authorizatio
n:Nway token " http://192.168.1.115:8085/api/threeway

HOLD

curl -H "Authorization:Nway token" http://ip:8085/api/hold/1002

UNHOLD

bash curl -H "Authorization:Nway token" http://ip:8085/api/unhold/1002

控制话机hold

bash curl -H "Authorization:Nway token" http://ip:8085/api/phone_hold/1002

控制话机unhold

bash curl -H "Authorization:Nway token" http://ip:8085/api/phone_unhold/1002

二、配置及操作

a. 路由配置

新建一条路由,比如我们是要呼转给120

进入到路由明细

添加路由明细

但是在添加明细前,需要先添加一个动态组

这里的组id为4

那么这样就配好了一个路由,当有电话呼入时,就走该路由了,按照动态注册上来的座席号进行分配了

b. 获取的分机状态信息说明

接口为:curl -H "Authorization:Nway Token" http://192.168.1.115:8085/api/extension_info/1002

返回说明:

reg_state : 分机是不是注册在线:reged 在线,unreg 不在线

seat_status:座席状态:idle是空闲, busy是置忙

call_state:呼叫状态, ready 是可以接听,talking是正在通话,ring是振铃

三、宁卫软电话操作

  1. 宁卫软电话基于开源产品改造

配置项

  1. 对应的调用接口

    call ,直接呼叫 http://127.0.0.1:8899/?method=call&phone=018621575908

    hangup,直接挂断

    http://127.0.0.1:8899/?method=hangup

    answer ,直接接通 http://127.0.0.1:8899/?method=answer

四、ESL操作配置

a. ESL api/app列表

在nwayacd模块中,支持大量的esl配置操作,从而避免还要去操作操作界面等,这样方便相关的开发使用。

freeswitch@internal> show modules mod_nwayacd
type,name,ikey,filename
api,nway_add_ext,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_add_group,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_busy,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_list_exts,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_list_groups,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_login,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_logout,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_ready,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_rm_ext,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_rm_group,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_set_ext_jobnumber,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_set_reged_ext,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_set_ring_group,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_set_unreg_ext,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_threeway,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_uuid_hold,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_uuid_unhold,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nwayacd,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nwayacd_transfer,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nwayacd_version,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
application,nway_bridge,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
application,nwayacd,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
application,nwaycallout,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so

23 total.

b. 配置项 api的使用

  1. 添加分机

bgapi nway_add_ext 1000 1234

  1. 分机工号设定

bgapi nway_set_ext_jobnumber 1000 1234 true //最后一项为true或false,代表是否启用,1000为分机,1234为工号

  1. 删除分机

bgapi nway_rm_ext 1000

  1. 设定分机为注册

bgapi nway_set_reged_ext 1000

  1. 设定分机为未注册

bgapi nway_set_unreg_ext 1000

  1. 添加组

bgapi nway_add_group group mode

Usage:bgapi nway_add_group 110 4

mode选项:0,sequence;1,random;2,crycle;3,remember+0;4,remember+1;5,remember+2;

  1. 删除组

nway_rm_group 110

  1. 设定每个分组的不同的语音

bgapi nway_set_ring_group group welcome_ring blacklist_ring busy_ring transfer_ring

Usage:bgapi nway_set_ring_group 110 /nway/welcome.wav /nway/black.wav /nway/busy.wav /nway/transfer.wav

  1. 列出所有分机

bgapi nway_list_exts

  1. 列出所有分组

    bgapi nway_list_groups

  2. 让某分机上线并加入多个组中

    bgapi nway_login extension group_list

    Usage:bgapi nway_login 1000 120,119,110

  3. 让某分机登出,并中止和各组的关联关系

    bgapi nway_logout extension

    Usage: bgapi nway_logout 1000

  4. 呼叫转移

    bgapi nwayacd_transfer [uuid] [extension]

    Usage: bgapi nwayacd_transfer uuid 1002

  5. 将座席置忙

    bgapi nway_busy extension

    Usage:bgapi nway_busy 1000

  6. 将座席置闲

    bgapi nway_ready extension

    Usage:bgapi nway_ready 1000

  7. 输出排队模块的版本

    bgapi nwayacd_version

  8. 将通话unHold

    bgapi nway_uuid_unhold [uuid]

    Usage: bgapi nway_uuid_unhold uuid

  9. 将通话hold

    bgapi nway_uuid_hold [uuid]

  10. 三方通话

    bgapi nway_threeway [uuid] phone gateway Usage:bgapi nway_uuid_hold ex009-4333444-988kk 018621575908 gw1

c. 配置项 app的使用

  1. 通过app实现外呼

nwaycallout

Usage:nwaycallout 18621575908 gw1 110

xml中配置

  <action application="nwaycallout" data="$0 test 110"/>
  1. 配置排队机排队

nwayacd

Usage:nwayacd 110

xml中配置

<action application="nwayacd" data="110"/>


上海老李,QQ:1354608370,FreeSWITCH QQ群: