自助语音验证码介绍

版本:v1.0 创作时间:2024-08-19 21:40:00 自助语音验证码是通过 拨打 VOIP 电话自动获取验证码,验证码可用来豆子笔记网站认证。掌握了此项技术,你也可以应用于其它地方。 Asterisk 是一个流行的开源通信平台,它提供了构建各种通信应用的灵活而强大的解决方案。它被广泛应用于企业内部电话系统、呼叫中心、语音邮件等场景。 Asterisk 支持多种通信协议,包括 SIP、H.323、MGCP 和 SCCP,并且能够与传统的 PSTN 线路深度兼容。 此外,Asterisk 还支持通过 Inter-Asterisk eXchange (IAX)协议进行语音过 IP 传输,允许数据和语音同时在网络上传输。 我们使用 Asterisk 实现了自助语音验证码功能。 常用 VOIP 软件 手机端推荐:zoiper,linphone PC 端推荐:microsip,eyebeam,zoiper,linphone 自助语音验证码使用说明 你需要准备: 软电话,或者支持 VOIP 的电话机 AST 账户,AST 账户从豆子工具小程序中获取,功能菜单为获取 AST 账户。 注意:AST 账户获取后,需在次日才可以使用,因为申请账号的库和 Asterisk 不是同一个库。它会在凌晨进行自动同步。 首先,使用获取到的账户配置你的电话。 然后,拨打 8000,即可自动获取验证码。 如果您有什么问题,欢迎关注公众号【技术源泉】私信我。

2022-08-19 · 1 min · Eagle

如何实现自助语音验证码?

用户通过 VOIP 电话连接到 Asterisk,拨打固定的数字 8000,Asterisk 将调用 AGI 接口获取验证码,然后将获取到的验证码播报给用户,播报完毕后自动挂断。 我们根据自助语音验证码原理,将自助验证码实现分解为以下几个技术要点,只要我们解决以下技术要点,就可以实现自助语音验证码。 技术要点: 1,如何播放音频文件?音频文件从哪里来?如何播放动态数据? 2,如何存储用户信息?如何使用数据库存储用户信息? 3,如何获取验证码? 下面内容是我对各个技术点的对应解决方案。 1,Asterisk 自带 Playback 应用,可以通过它播放音频文件。音频文件需要我们提前录制好,并且转换为对应的音频格式,最简单的方法就是使用手机上的录音机。当在拨号计划中多次执行 Playback 应用,Asterisk 会将音频流自动连接起来。所以我们可以使用循环多次执行 Playback 应用即可。 2,Asterisk 使用配置文件写入 SIP 用户信息,但当写入新的 SIP 用户信息后,需要重新加载配置文件。为了方便和第三方对接,我们推荐使用数据库。Asterisk 支持数据库,并且可以实时获取用户信息。 3,Asterisk 支持 AGI 接口,我们可以使用 AGI 获取第三方应用的验证码,获取后和提前录制好的文件结合起来进行播放。 当掌握了这些技术点后,我们就可以灵活应用到其它解决方案。

2022-08-20 · 1 min · Eagle

语音验证码完整实现流程

音频文件处理 我们使用手机上的录音机来录制音频文件。 Android 录音机录制的音频文件格式为 mp3,如果是 amr 格式,请使用豆子工具音频格式转换功能,转成 mp3 格式文件。 IOS 录音机录制的音频文件格式为 m4a,请使用豆子工具音频格式转换功能,转成 mp3 格式文件。 我们还需要使用 ffmpeg 将 mp3 文件转成 g711a 格式文件。这个 mp3 转 g711a 功能后续会集成到豆子工具中。 mp3 转 g711a 命令: ffmpeg -i test.mp3 -acodec pcm_alaw -f alaw -ac 1 -ar 8000 -vn test.alaw 使用 ffplay 播放测试 ffplay -i test.alaw -f alaw -ac 1 -ar 8000 将制作好的音频文件存放在 asterisk sounds 目录,就可以在拨号计划中使用 Playback 应用调用它了。 配置实时数据库 今天讲解 Asterisk 如何实时将 SIP 用户写入 sqlite3 数据库。 先定义数据库表结构,我当前使用的 PJSIP 协议。 CREATE TABLE ps_endpoints ( id VARCHAR(40) NOT NULL, transport VARCHAR(40), aors VARCHAR(200), auth VARCHAR(40), context VARCHAR(40), disallow VARCHAR(200), allow VARCHAR(200), direct_media varchar(5) check(direct_media in ('yes','no')), connected_line_method varchar(10) check(connected_line_method in ('invite','reinvite','update')), direct_media_method varchar(10) check(direct_media_method in ('invite','reinvite','update')), direct_media_glare_mitigation varchar(20) check(direct_media_glare_mitigation in ('none','outgoing','incoming')), disable_direct_media_on_nat varchar(5) check(disable_direct_media_on_nat in ('yes','no')), dtmf_mode varchar(20) check(dtmf_mode in ('rfc4733','inband','info')), external_media_address VARCHAR(40), force_rport varchar(5) check(force_rport in ('yes','no')), ice_support varchar(5) check(ice_support in ('yes','no')), identify_by varchar(10) check(identify_by in ('username')), mailboxes VARCHAR(40), moh_suggest VARCHAR(40), outbound_auth VARCHAR(40), outbound_proxy VARCHAR(40), rewrite_contact varchar(5) check(rewrite_contact in ('yes','no')), rtp_ipv6 varchar(5) check(rtp_ipv6 in ('yes','no')), rtp_symmetric varchar(5) check(rtp_symmetric in ('yes','no')), send_diversion varchar(5) check(send_diversion in ('yes','no')), send_pai varchar(5) check(send_pai in ('yes','no')), send_rpid varchar(5) check(send_rpid in ('yes','no')), timers_min_se INTEGER, timers varchar(20) check(timers in ('forced','no','required','yes')), timers_sess_expires INTEGER, callerid VARCHAR(40), callerid_privacy varchar(40) check(callerid_privacy in ('allowed_not_screened','allowed_passed_screened','allowed_failed_screened','allowed','prohib_not_screened','prohib_passed_screened','prohib_failed_screened','prohib','unavailable')), callerid_tag VARCHAR(40), `100rel` varchar(20) check(`100rel` in ('no','required','yes')), aggregate_mwi varchar(5) check(aggregate_mwi in ('yes','no')), trust_id_inbound varchar(5) check(trust_id_inbound in ('yes','no')), trust_id_outbound varchar(5) check(trust_id_outbound in ('yes','no')), use_ptime varchar(5) check(use_ptime in ('yes','no')), use_avpf varchar(5) check(use_avpf in ('yes','no')), media_encryption varchar(10) check(media_encryption in ('no','sdes','dtls')), inband_progress varchar(5) check(inband_progress in ('yes','no')), call_group VARCHAR(40), pickup_group VARCHAR(40), named_call_group VARCHAR(40), named_pickup_group VARCHAR(40), device_state_busy_at INTEGER, fax_detect varchar(5) check(fax_detect in ('yes','no')), t38_udptl varchar(5) check(t38_udptl in ('yes','no')), t38_udptl_ec varchar(20) check(t38_udptl_ec in ('none','fec','redundancy')), t38_udptl_maxdatagram INTEGER, t38_udptl_nat varchar(5) check(t38_udptl_nat in ('yes','no')), t38_udptl_ipv6 varchar(5) check(t38_udptl_ipv6 in ('yes','no')), tone_zone VARCHAR(40), language VARCHAR(40), one_touch_recording varchar(5) check(one_touch_recording in ('yes','no')), record_on_feature VARCHAR(40), record_off_feature VARCHAR(40), rtp_engine VARCHAR(40), allow_transfer varchar(5) check(allow_transfer in ('yes','no')), allow_subscribe varchar(5) check(allow_subscribe in ('yes','no')), sdp_owner VARCHAR(40), sdp_session VARCHAR(40), tos_audio INTEGER, tos_video INTEGER, cos_audio INTEGER, cos_video INTEGER, sub_min_expiry INTEGER, from_domain VARCHAR(40), from_user VARCHAR(40), mwi_fromuser VARCHAR(40), dtls_verify VARCHAR(40), dtls_rekey VARCHAR(40), dtls_cert_file VARCHAR(200), dtls_private_key VARCHAR(200), dtls_cipher VARCHAR(200), dtls_ca_file VARCHAR(200), dtls_ca_path VARCHAR(200), dtls_setup varchar(20) check(dtls_setup in ('active','passive','actpass')), srtp_tag_32 varchar(5) check(srtp_tag_32 in ('yes','no')), UNIQUE (id) ); CREATE INDEX ps_endpoints_id ON ps_endpoints (id); CREATE TABLE ps_auths ( id VARCHAR(40) NOT NULL, auth_type varchar(10) check(auth_type in ('md5','userpass')), nonce_lifetime INTEGER, md5_cred VARCHAR(40), password VARCHAR(80), realm VARCHAR(40), username VARCHAR(40), UNIQUE (id) ); CREATE INDEX ps_auths_id ON ps_auths (id); CREATE TABLE ps_aors ( id VARCHAR(40) NOT NULL, contact VARCHAR(40), default_expiration INTEGER, mailboxes VARCHAR(80), max_contacts INTEGER, minimum_expiration INTEGER, remove_existing varchar(5) check(remove_existing in ('yes','no')), qualify_frequency INTEGER, authenticate_qualify varchar(5) check(authenticate_qualify in ('yes','no')), UNIQUE (id) ); CREATE INDEX ps_aors_id ON ps_aors (id); PJSIP 测试数据: ...

2022-08-21 · 5 min · Eagle

语音验证码实现中常见错误

403 登录失败 解决:等待 1 分钟,等超时之后重新连接即可。一般是切换 IP 时或者换软电话登录会碰到。 401 登录失败 解决:检查账户和密码是否正确?检查连接地址是否正确?检查 Asterisk 是否启动?检查防火墙端口是否打开? 408 连接超时 解决:一般是 Asterisk 服务不通,检查 Asterisk 服务是否启动,检查防火墙是否打开? 可以拨通,没有声音? 一般是 NAT 造成,配置这三个参数:rtp_symmetric,force_rport,rewrite_contact。 SIP 客户端没有自动挂机? 一般是没有设置 stun 造成的,在 SIP 客户端,设置 stun 即可。如果没有 stun server,可以设置这个stun.l.google.com:19302 AGI 脚本返回状态 4,正常应该为 0? 查看网上资料,是 AGI 脚本中调用 Hangup 导致,将脚本中的 Hangup 去掉,放在拨号计划配置文件中执行 Hangup,可以解决这个问题。 AGI Script agidemo completed, returning 0 查看客户端是否在线? pjsip show endpoints 要求最大一个客户端在线,请在aors配置中使用配置 max_contacts 设置为 1 MicroSIP客户端配置后还显示IDLE? SIP SERVER字段必须填写,和域名地址保持一致。这样状态IDLE会变为ONline。 MicroSIP客户端连接后,Asterisk不显示在线? 如果是服务器在公网,客户端在局域网的网络结构: 我的Asterisk显示的客户端Contact是局域网地址,针对这种情况。 1,临时解决方法:请在账户配置中,勾选IP REWRITE或ICE,具体选择哪个看服务端的配置。他们分别表示IP地址重写和启用更智能的 NAT 穿透技术。如果需要向好友显示在线状态,请勾选Publish Presence。 2,更推荐的解决方法:检查Asterisk的PJSIP配置,需要添加 rewrite_contact=yes这是解决 NAT 的“银弹”。它告诉 Asterisk:“忽略报文里写的内网 IP,直接回复给数据包发过来的那个公网地址和端口。” 设置 rtp_symmetric=yes:确保语音流(RTP)也走同样的路径,防止通话时单通(没声音)。

2022-08-24 · 1 min · Eagle

语音验证码远程呼叫

在实现了使用VOIP客户端拨打8000号码后,播报语音验证码的功能后,我发现了一个最大的缺点,就是这需要用户主动去操作。这对于想使用API集成无法实现。 在思考之后,我决定使用一个可以调用API就呼叫VOIP客户端,当用户接通后,播报语音验证码的功能。当实现这个功能后,它的好处是显而易见的。比如,可以集成到嵌入式,集成到第三方网站。 那么该如何实现它呢? 一、 系统原理 传统的拨号方案(Dialplan)是静态的,而 ARI 允许我们动态控制。整个“API 触发呼叫并播报”的流程如下: 触发阶段:第三方系统通过 API 向 Go 服务发送呼叫请求(包含目标 ID 和验证码)。 呼叫发起(Originate):Go 服务调用 Asterisk ARI 的 /channels 接口。此时 Asterisk 会尝试向 PJSIP 终端(或通过中继向手机)发起呼叫。 接通监听(Stasis Start):一旦用户接起电话,该通道会被移交给一个名为 Stasis 的应用。此时 Go 服务会收到一个“通道已接通”的 WebSocket 事件。 语音合成与播放:Go 服务识别到接通后,调用播报指令(可以播放预录音文件,或对接 TTS 引擎生成的语音流)。 挂断处理:播报完毕后,服务发送挂断指令,释放资源。 二、系统架构 [第三方API] --> [Go 后端服务] --(REST API)--> [Asterisk ARI] | | (WebSocket) (PJSIP/IMS) | | [接通状态回调] <--- [用户终端接听] 三、 核心代码实现 (Golang) 假设你使用了 GitHub 上的 go-ari 库。 1. 初始化 ARI 客户端 import ( "github.com/v5" "github.com/v5/client/native" ) // 连接到 Asterisk ARI cl, err := native.Connect(&native.Options{ Application: "voice-verify", // 必须与 asterisk.conf 配置一致 Username: "admin", Password: "password", URL: "http://localhost:8088/ari", }) 2. 实现呼叫并播报逻辑 这是核心逻辑:接收参数 -> 发起呼叫 -> 监听接通 -> 播放语音。 ...

2026-01-13 · 3 min · Eagle