FreeSWITCH 简单图形化界面40 - 使用mod_curl模块进行http请求
- 0、界面预览
- 00、简介
- 1、编译安装
-
- [1.1 编辑模块配置文件](#1.1 编辑模块配置文件)
- 2、使用
-
- [2.1 拨号规则](#2.1 拨号规则)
-
- [GET 请求](#GET 请求)
- [POST 请求](#POST 请求)
- [JSON 数据](#JSON 数据)
- [2.2 Lua 脚本](#2.2 Lua 脚本)
-
- [GET 请求](#GET 请求)
- [POST 请求](#POST 请求)
- [JSON 数据](#JSON 数据)
- [3 、示例](#3 、示例)
-
- [3.1 示例 1:提交 CDR 到第三方接口](#3.1 示例 1:提交 CDR 到第三方接口)
- [3.2 示例 2:提交外呼状态到第三方接口](#3.2 示例 2:提交外呼状态到第三方接口)
0、界面预览
用户名:admin,密码:admin
FreeSWITCH界面安装参考:https://blog.csdn.net/jia198810/article/details/137820796
00、简介
mod_curl
是 FreeSWITCH 的一个强大模块,它允许用户通过 HTTP 请求与外部服务进行交互,从而实现数据的获取和提交。无论是简单的 GET 请求,还是复杂的 POST 请求和文件传输,mod_curl
都能轻松应对。
1、编译安装
在使用mod_curl
之前,需要确保该模块已正确编译并加载到 FreeSWITCH 中。以下是详细的编译和安装步骤:
1.1 编辑模块配置文件
- 打开 FreeSWITCH 源代码目录下的
modules.conf
文件,找到以下行并取消注释:
bash
#applications/mod_curl
保存文件并退出。
- 重新编译 FreeSWITCH
在终端中执行以下命令,重新编译 FreeSWITCH:
bash
make
make install
- 加载模块
编辑 FreeSWITCH 的模块加载配置文件modules.conf.xml
(路劲为/usr/local/freeswitch/conf/autoload_configs
),添加以下内容:
xml
<load module="mod_curl"/>
保存文件后,重新加载 FreeSWITCH 以使模块生效。
- 验证模块加载
启动 FreeSWITCH 并进入 CLI,执行以下命令以验证mod_curl
是否已正确加载:
bash
module_exists mod_curl
如果返回true
,则表示模块加载成功。
2、使用
2.1 拨号规则
mod_curl
提供了两种主要的应用方式:curl
和curl_sendfile
(不常用)。
在拨号规则中,可以通过以下方式调用curl
应用:
xml
<action application="curl" data="http://example.com/api?param=value"/>
curl应用的请求,会生成两个通道变量 curl_response_data 和curl_response_code,可以使用${}获取。
GET 请求
通过 URL 参数发送 GET 请求:
xml
<action application="curl" data="http://example.com/api?param=value"/>
POST 请求
发送 POST 请求并携带数据:
xml
<action application="curl" data="http://example.com/api post param=value"/>
JSON 数据
发送 JSON 格式的数据:
xml
<action application="curl" data="http://example.com/api content-type application/json post {\"key\":\"value\"}"/>
2.2 Lua 脚本
mod_curl
也可以在 Lua 脚本中使用,通过 FreeSWITCH 的 API 接口调用 HTTP 请求。
GET 请求
在 Lua 脚本中发起 GET 请求的示例如下:
lua
local api = freeswitch.API()
local url = "http://example.com/api?param=value"
local response = api:execute("curl", url)
freeswitch.consoleLog("INFO", "Response: " .. response .. "\n")
POST 请求
发送 POST 请求的示例如下:
lua
local api = freeswitch.API()
local url = "http://example.com/api"
local data = "param=value"
local response = api:execute("curl", url .. " post " .. data)
freeswitch.consoleLog("INFO", "Response: " .. response .. "\n")
JSON 数据
发送 JSON 格式数据的示例如下:
lua
local api = freeswitch.API()
local url = "http://example.com/api"
local json_data = "{ \"key\": \"value\" }"
local response = api:execute("curl", url .. " content-type application/json post " .. json_data)
freeswitch.consoleLog("INFO", "Response: " .. response .. "\n")
3 、示例
3.1 示例 1:提交 CDR 到第三方接口
在呼叫结束后,将通话详情记录(CDR)提交到第三方接口。以下是 Lua 脚本的实现示例:
lua
#!/usr/bin/env lua
-- upload_cdr.lua
-- 2024年6月29日
-- 提交话单信息到第三方接口
-- 拨号规则,提前设置挂机回调
-- session:execute("set", string.format("api_hangup_hook=lua upload_cdr.lua")
-- 序列化并打印env对象的所有通话信息,调试专用
-- local call_info = env:serialize()
-- freeswitch.consoleLog("INFO", "所有通话信息:\n" .. call_info)
local mobile = env:getHeader("destination_number") or ""
local caller_ani = env:getHeader("Caller-ANI") or ""
local sip_account = env:getHeader("sip_from_user") or ""
local start_time = env:getHeader("start_stamp") or ""
-- local start_time = env:getHeader("answer_stamp") or ""
local end_time = env:getHeader("end_stamp") or ""
local use_time_length = env:getHeader("billsec") or "0"
local order_no = string.format("freeSWITCH%s%s", sip_account, mobile)
local mobile_hangup_api = env:getHeader("mobile_hangup_api") or ""
local api_timeout = env:getHeader("api_timeout") or "3"
-- 打印详细信息,确保变量不为空
if sip_account == mobile then
freeswitch.consoleLog("INFO", "异常呼叫主叫=被叫,再次获取SIP账号为 : " .. caller_ani .. "\n")
sip_account = caller_ani
end
freeswitch.consoleLog("INFO", "CallerANI : " .. caller_ani .. "\n")
freeswitch.consoleLog("INFO", "SIP账号 : " .. sip_account .. "\n")
freeswitch.consoleLog("INFO", "被叫号码 : " .. mobile .. "\n")
freeswitch.consoleLog("INFO", "开始时间 : " .. start_time .. "\n")
freeswitch.consoleLog("INFO", "结束时间 : " .. end_time .. "\n")
freeswitch.consoleLog("INFO", "通话时长 : " .. use_time_length .. "\n")
freeswitch.consoleLog("INFO", "订单号 : " .. order_no .. "\n")
freeswitch.consoleLog("INFO", "CDR推送接口 : " .. mobile_hangup_api .. "\n")
freeswitch.consoleLog("INFO", "接口超时时间 : " .. api_timeout .. "\n")
-- 准备执行命令
local api = freeswitch.API();
--[[
-- 使用python提交
local cmd = string.format(
"/usr/local/python310/bin/python /usr/local/freeswitch/scripts/upload_cdr.py '%s' '%s' '%s' '%s' '%s' '%s' '%s'",
mobile, sip_account, start_time, end_time, use_time_length, order_no, mobile_hangup_api)
local response = api:execute("bg_system", cmd)
]]
-- 使用curl提交
local cmd = string.format(
"%s connect-timeout %s timeout %s post mobile=%s&sip_account=%s&start_time='%s'&end_time='%s'&use_time_length=%s&order_no=%s",
mobile_hangup_api, api_timeout, api_timeout, mobile, sip_account, start_time, end_time, use_time_length, order_no)
freeswitch.consoleLog("INFO", "推送命令: " .. cmd .. "\n")
local response = api:execute("curl", cmd)
if (response == "") then
freeswitch.consoleLog("INFO", "推送结果: 无响应,可能连接接口失败!")
else
freeswitch.consoleLog("INFO", "推送结果: " .. response .. "\n")
end
3.2 示例 2:提交外呼状态到第三方接口
在外呼结束后,将外呼状态提交到第三方接口。以下是 Lua 脚本的实现示例:
lua
#!/usr/bin/env lua
-- handle-callout-result.lua
-- 2025年2月26日
-- 处理外呼结果
-- 外呼api设置挂机回调。originate {origination_caller_id_number=300,orgination_caller_id_name=outcall,api_hangup_hook='lua handle-callout-result.lua'}sofia/gateway/gw01/172xxxx2122 401 xml Local-Extensions
-- local env
-- local freeswitch
local call_info = env:serialize()
-- -- 序列化并打印env对象的所有通话信息,调试专用
-- freeswitch.consoleLog("INFO", "所有通话信息:\n" .. call_info)
-- 开始时间
local start_time = env:getHeader("start_stamp") or ""
-- 结束时间
local end_time = env:getHeader("end_stamp") or ""
-- 通话时间
local duration = env:getHeader("billsec") or "0"
-- SIP中继名称
local trunk_name = env:getHeader("trunk_name") or ""
-- 被叫号码
local destination_number = env:getHeader("destination_number") or ""
-- 本地号码
local local_number = env:getHeader("rdnis") or ""
-- 备用被叫号码
local sip_to_user = env:getHeader("sip_to_user") or ""
-- 呼出主叫号码
local outgoing_caller_id_number = env:getHeader("origination_caller_id_number") or ""
-- answer api
local answer_api = env:getHeader("answer_api") or ""
-- no_answer api
local no_answer_api = env:getHeader("no_answer_api") or ""
-- api 超时时间
local api_timeout = 3
-- 通话结果
local hangup_cause = env:getHeader("hangup_cause") or ""
-- 是否检查主叫号码被占用
local check_number_in_use = env:getHeader("check_number_in_use") or "false"
local response
local result
local temp_string
-- 打印详细信息,确保变量不为空
if destination_number == "" then
freeswitch.consoleLog("INFO", string.format("# destination_number未空,使用sip_to_user的值%s\n",sip_to_user))
destination_number = sip_to_user
end
freeswitch.consoleLog("INFO", "# ==============API接口外呼挂机处理============= \n")
freeswitch.consoleLog("INFO", "# ------------------外呼呼叫信息---------------- \n")
freeswitch.consoleLog("INFO", "# 开始时间 : " .. start_time .. "\n")
freeswitch.consoleLog("INFO", "# 结束时间 : " .. end_time .. "\n")
freeswitch.consoleLog("INFO", "# 通话时长 : " .. duration .. "\n")
freeswitch.consoleLog("INFO", "# 外呼号码 : " .. destination_number .. "\n")
freeswitch.consoleLog("INFO", "# 本地号码 : " .. local_number .. "\n")
freeswitch.consoleLog("INFO", "# 呼出主叫 : " .. outgoing_caller_id_number .. "\n")
freeswitch.consoleLog("INFO", "# 挂机接口 : " .. no_answer_api .. "\n")
freeswitch.consoleLog("INFO", "# ---------------------------------------------\n\n")
-- 执行fs api命令
local api = freeswitch.API();
-- 应答提交api,在401 xml Local-Extensions中。
-- if (hangup_cause == "ANSWER" or hangup_cause == "NORMAL_CLEARING") then
-- -- 呼叫应答提交
-- freeswitch.consoleLog("INFO", "# 呼叫结果 : 呼叫已经应答,推送应答接口\n")
-- if (answer_api == "") then
-- freeswitch.consoleLog("INFO", "# 推送结果 : 应答接口为空,不提交!\n")
-- return
-- else
-- -- 提交无应答结果
-- temp_string = string.format(
-- "%s connect-timeout %s timeout %s post destination_number=%s",
-- no_answer_api, api_timeout, api_timeout, destination_number)
-- freeswitch.consoleLog("INFO", string.format("# 推送结果 : 请求地址:%s\n",temp_string))
-- -- 执行推送
-- response = api:execute("curl",temp_string)
-- if (response == "") then
-- freeswitch.consoleLog("INFO", "# 推送结果 : 接口无响应,可能连接接口失败!\n")
-- else
-- freeswitch.consoleLog("INFO", "# 推送结果 : " .. response .. "\n")
-- end
-- end
freeswitch.consoleLog("INFO", "# ----------------外呼挂机处理-----------------\n")
if (hangup_cause == "BUSY" or hangup_cause == "USER_BUSY" or hangup_cause == "NO_USER_RESPONSE" or hangup_cause == "NO_ROUTE_DESTINATION" or hangup_cause == "CALL_REJECTED" or hangup_cause == "NO_ANSWER") then
freeswitch.consoleLog("INFO", "# 挂机结果 : " .. hangup_cause .. "\n")
-- 呼叫未应答提交
freeswitch.consoleLog("INFO", "# 呼叫结果 : 呼叫未应答,推送未应答接口\n")
if (no_answer_api == "") then
freeswitch.consoleLog("INFO", "# 推送结果 : 未应答接口为空,不提交!\n")
return
else
-- 提交无应答结果
temp_string = string.format(
"%s content-type application/json connect-timeout %s timeout %s post {\"destination_number\":\"%s\"}",
no_answer_api, api_timeout, api_timeout, destination_number)
freeswitch.consoleLog("INFO", string.format("# 推送结果 : 请求地址:%s\n",temp_string))
-- 执行推送
response = api:execute("curl", temp_string)
if (response == "") then
freeswitch.consoleLog("INFO", "# 推送结果 : 接口无响应,可能连接接口失败!\n")
else
freeswitch.consoleLog("INFO", "# 推送结果 : ".. response.. "\n")
end
end
elseif (hangup_cause == "NORMAL_CLEARING") then
freeswitch.consoleLog("INFO", "# 挂机结果 : " .. hangup_cause .. "\n")
freeswitch.consoleLog("INFO", "# 挂机结果 : 通话正常挂断\n")
else
freeswitch.consoleLog("INFO", "# 挂机结果 : " .. hangup_cause .. "\n")
end
freeswitch.consoleLog("INFO", "# ----------------------------------------------\n")
-- 如果要检查主叫号码是否被占用,则呼叫结束后,删除正在使用的主叫号码
if (check_number_in_use == "true") then
freeswitch.consoleLog("INFO", string.format("# 通话已结束 : 开启了检查主叫号码占用,将释放主叫%s\n",outgoing_caller_id_number))
-- 检查号码是否被占用
temp_string = string.format(
"delete/%s/number_in_use_%s",
trunk_name, outgoing_caller_id_number)
freeswitch.consoleLog("INFO", string.format("# 通话已结束 : 释放正在使用的主叫号码:%s\n",temp_string))
result = api:execute("hash",temp_string)
freeswitch.consoleLog("INFO", string.format("# 通话已结束 : 释放正在使用的主叫号码:%s\n",result))
end
freeswitch.consoleLog("INFO", "# ===============================================\n\n")
return
祝君好运