<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>语音验证码 on 豆子技术站</title><link>https://blog.91demo.top/tags/%E8%AF%AD%E9%9F%B3%E9%AA%8C%E8%AF%81%E7%A0%81/</link><description>Recent content in 语音验证码 on 豆子技术站</description><generator>Hugo -- 0.155.1</generator><language>zh-cn</language><lastBuildDate>Tue, 13 Jan 2026 12:40:16 +0800</lastBuildDate><atom:link href="https://blog.91demo.top/tags/%E8%AF%AD%E9%9F%B3%E9%AA%8C%E8%AF%81%E7%A0%81/index.xml" rel="self" type="application/rss+xml"/><item><title>实战笔记：实现一个语音验证码远程呼叫版本</title><link>https://blog.91demo.top/voice-call/</link><pubDate>Tue, 13 Jan 2026 12:40:16 +0800</pubDate><guid>https://blog.91demo.top/voice-call/</guid><description>&lt;p&gt;在实现了主动使用VOIP客户端拨打&lt;code&gt;8000&lt;/code&gt;号码播报语音验证码的功能后，我发现了一个最大的缺点，就是这需要用户主动去操作。这对于想使用API集成的第三方应用来说根本无法实现。&lt;/p&gt;
&lt;p&gt;在思考之后，我决定实现一个可以调用API就呼叫VOIP客户端的版本，当呼叫用户并且用户接通后，自动播报语音验证码的功能。当实现这个功能后，它的好处是显而易见的。比如，可以集成到嵌入式，集成到第三方网站，直接调用API就可以呼叫出去。&lt;/p&gt;
&lt;p&gt;那么该如何实现它呢？&lt;/p&gt;
&lt;h2 id="一-系统原理"&gt;一、 系统原理&lt;/h2&gt;
&lt;p&gt;传统的拨号方案（Dialplan）是静态的，而 ARI 允许我们动态控制。整个“API 触发呼叫并播报”的流程如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;触发阶段：第三方系统通过 API 向 Go 服务发送呼叫请求（包含目标 ID 和验证码）。&lt;/li&gt;
&lt;li&gt;呼叫发起（Originate）：Go 服务调用 Asterisk ARI 的 /channels 接口。此时 Asterisk 会尝试向 PJSIP 终端（或通过中继向手机）发起呼叫。&lt;/li&gt;
&lt;li&gt;接通监听（Stasis Start）：一旦用户接起电话，该通道会被移交给一个名为 Stasis 的应用。此时 Go 服务会收到一个“通道已接通”的 WebSocket 事件。&lt;/li&gt;
&lt;li&gt;语音合成与播放：Go 服务识别到接通后，调用播报指令（可以播放预录音文件，或对接 TTS 引擎生成的语音流）。&lt;/li&gt;
&lt;li&gt;挂断处理：播报完毕后，服务发送挂断指令，释放资源。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二系统架构"&gt;二、系统架构&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[第三方API] --&amp;gt; [Go 后端服务] --(REST API)--&amp;gt; [Asterisk ARI]
| |
(WebSocket) (PJSIP/IMS)
| |
[接通状态回调] &amp;lt;--- [用户终端接听]
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="三-核心代码实现-golang"&gt;三、 核心代码实现 (Golang)&lt;/h2&gt;
&lt;p&gt;这里使用了 GitHub 上的 &lt;code&gt;go-ari&lt;/code&gt; 库。&lt;/p&gt;
&lt;h3 id="1-初始化-ari-客户端"&gt;1. 初始化 ARI 客户端&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/v5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/v5/client/native&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 连接到 Asterisk ARI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;cl&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;native&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Connect&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;native&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Options&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Application&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;voice-verify&amp;#34;&lt;/span&gt;, &lt;span style="color:#75715e"&gt;// 必须与 asterisk.conf 配置一致&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Username&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;URL&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:8088/ari&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-实现呼叫并播报语音验证码"&gt;2. 实现呼叫并播报语音验证码&lt;/h3&gt;
&lt;p&gt;这是核心逻辑：接收参数 -&amp;gt; 发起呼叫 -&amp;gt; 监听接通 -&amp;gt; 播放语音。&lt;/p&gt;</description></item><item><title>实战笔记：实现一个语音验证码自助拨打版本</title><link>https://blog.91demo.top/voice-code/</link><pubDate>Fri, 19 Aug 2022 12:40:16 +0800</pubDate><guid>https://blog.91demo.top/voice-code/</guid><description>&lt;p&gt;自助语音验证码是通过拨打VOIP电话自动获取验证码，验证码可用来豆子笔记网站认证。这个纯粹是自己的兴趣驱动的。掌握了此项技术，你也可以应用于其它地方。&lt;/p&gt;
&lt;p&gt;我是使用Asterisk实现的，Asterisk 是一个流行的开源通信平台，它提供了构建各种通信应用的灵活而强大的解决方案。它被广泛应用于企业内部电话系统、呼叫中心、语音邮件等场景。Asterisk 支持多种通信协议，包括 SIP、H.323、MGCP 和 SCCP，并且能够与传统的 PSTN 线路深度兼容。此外，Asterisk 还支持通过 Inter-Asterisk eXchange (IAX)协议进行语音 IP 传输，允许数据和语音同时在网络上传输。&lt;/p&gt;
&lt;h2 id="自助语音验证码使用说明"&gt;自助语音验证码使用说明&lt;/h2&gt;
&lt;p&gt;你需要准备：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;软电话，或者支持 VOIP 的电话机&lt;/li&gt;
&lt;li&gt;AST 账户，AST 账户从豆子工具小程序中获取，功能菜单为获取 AST 账户。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;注意：该功能目前已经下架，这里仅作为备忘记录。&lt;/p&gt;
&lt;p&gt;首先，使用获取到的账户配置你的电话。然后拨打 8000，即可自动获取验证码。如果您有什么问题，欢迎关注公众号【技术源泉】私信我。&lt;/p&gt;
&lt;h2 id="技术实现"&gt;技术实现&lt;/h2&gt;
&lt;p&gt;它的工作原理是：用户通过 VOIP 电话连接到 Asterisk，当拨打固定的数字 8000时，Asterisk 将调用 AGI 接口获取服务端的API生成验证码，然后将获取到的验证码拆分通过语音文件播报给用户，播报完毕后自动挂断。&lt;/p&gt;
&lt;p&gt;我们根据自助语音验证码原理，将自助验证码实现分解为以下几个技术要点，只要我们解决以下技术要点，就可以实现自助语音验证码。&lt;/p&gt;
&lt;p&gt;技术要点：&lt;/p&gt;
&lt;p&gt;1，如何播放音频文件？音频文件从哪里来？如何播放动态数据？&lt;br&gt;
2，如何存储用户信息？如何使用数据库存储用户信息？&lt;br&gt;
3，如何获取验证码？&lt;/p&gt;
&lt;p&gt;下面内容是我对各个技术点的对应解决方案。&lt;/p&gt;
&lt;p&gt;1，Asterisk 自带 Playback 应用，可以通过它播放音频文件。音频文件需要我们提前录制好，并且转换为对应的音频格式，最简单的方法就是使用手机上的录音机。当在拨号计划中多次执行 Playback 应用，Asterisk 会将音频流自动连接起来。所以我们可以使用循环多次执行 Playback 应用即可。&lt;br&gt;
2，Asterisk 使用配置文件写入 SIP 用户信息，但当写入新的 SIP 用户信息后，需要重新加载配置文件。为了方便和第三方对接，我们推荐使用数据库。Asterisk 支持数据库，并且可以实时获取用户信息。&lt;br&gt;
3，Asterisk 支持 AGI 接口，我们可以使用 AGI 获取第三方应用的验证码，获取后和提前录制好的文件结合起来进行播放。&lt;/p&gt;
&lt;p&gt;当掌握了这些技术点后，我们就可以灵活应用到其它解决方案。&lt;/p&gt;
&lt;p&gt;下面我们来看具体实现：&lt;br&gt;
1，音频文件处理。我们使用手机上的录音机来录制音频文件。Android 录音机录制的音频文件格式为 mp3，如果是 amr 格式，请使用豆子工具音频格式转换功能，转成 mp3 格式文件。IOS 录音机录制的音频文件格式为 m4a，请使用豆子工具音频格式转换功能，转成 mp3 格式文件。我们还需要使用 ffmpeg 将 mp3 文件转成 g711a 格式文件。这个 mp3 转 g711a 功能也可以在豆子工具中使用。&lt;/p&gt;</description></item></channel></rss>