# @crvouga/mockingbird-service-twilio 中文文档

规范地址：https://npmcn.com/package/%40crvouga/mockingbird-service-twilio/

版本：3\.11\.0
npm 元数据更新时间：2026-11-11T02:43:13.066Z
中文译文更新时间：2026-11-11T02:39:21.491Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40crvouga/mockingbird-service-twilio
原文对照：https://npmcn.com/package/%40crvouga/mockingbird-service-twilio/?lang=original
项目主页：https://github.com/crvouga/mockingbird/tree/main/packages/service/twilio#readme
源码仓库：https://github.com/crvouga/mockingbird

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：5.2 MB，28 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：7 个
- 首次发布：2026-09-23T00:03:07.342Z
- 最新版本发布：2026-11-11T02:43:12.655Z
- 近 30 天下载量：15461（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：38（近 12 个月 38 个）

## 中文简介

Twilio 的状态仿真器, Lookup v2, Messageing and Recordings 在一个端口上, 并有签名的收发短信和语音网呼(Mockingbird 服务合同).

## 安装

```sh
npm install @crvouga/mockingbird-service-twilio
```

也可以使用：`pnpm add @crvouga/mockingbird-service-twilio`、`yarn add @crvouga/mockingbird-service-twilio`、`bun add @crvouga/mockingbird-service-twilio`

## README

# @crvouga/mockingbird-service-twilio (英语)

> 本地模拟器。 真正的API合同. 部分 [嘲笑鸟](https://github.com/crvouga/mockingbird)。 。 。 .

状态模拟器 **特维利奥** 测试套房: 查看 v2 手机验证, 校验 v2 手机 OTP (与真实的状态机器:错误的代码,尝试限制,在模拟器时钟上10分钟的过期), 可编程事件与发件箱,并呼叫录音。 也签下Twilio的字 输入短消息和语音网呼到你的应用程序。 每个产品都在一个港口上服务。 一个套房读取 检察官办公室来自行政飞机,而不是绕过核查(`E2E_OTP_BYPASS_*`) (中文(简体) ).

-   行动范围: [支助](https://github.com/crvouga/mockingbird/blob/main/packages/service/twilio/SUPPORT.md)
-   合同`openapi.yaml`由Twilio的API 引用我们的消费者 打电话 搜索 v2 响应会被对照活的 API 检查字节 (单位:千美元)`scripts/parity.ts`,录入 `test/fixtures/lookups.live.json`) (中文(简体) ).

## 安装

```bash
npm install -D @crvouga/mockingbird-service-twilio
```

仅限无害环境管理。 节点 22或 Bun 1.2. 查询验证用途 `libphonenumber-js` (Twilio的电话) 寻找是libphone数字。 给它服务 `npx mockingbird-twilio serve`,与 `createServer` 从 `./server` (节点),或与 `createRuntime` 在任何获取服务器中.

## 使用量

```bash
npx mockingbird-twilio serve --port 8798 \
  --app-url http://127.0.0.1:3000 \
  --public-base-url "$TWILIO_VOICE_WEBHOOK_BASE_URL" \
  --account-sid "$TWILIO_ACCOUNT_SID" --auth-token "$TWILIO_AUTH_TOKEN" \
  --caller-id "$TWILIO_VOICE_CALLER_ID"
```

### 对准应用软件(G-T1)

twilio-node为每种产品建立主机(`api.twilio.com`, (中文(简体) ), `verify.twilio.com`, (中文(简体) ), `lookups.twilio.com`) (中文(简体) ). 模拟器将主机作为第一个路径段 : `{emulator}/api/2010-04-01/…`, (中文(简体) ), `{emulator}/verify/v2/…`, (中文(简体) ), `{emulator}/lookups/v2/…`。通过时 `new Twilio(...)` a 一个 `httpClient` 重写 URL. `twilioMockUrl` 重写 :

```ts
import twilio from "twilio"
import { twilioMockUrl } from "@crvouga/mockingbird-service-twilio"
import { createServer } from "@crvouga/mockingbird-service-twilio/server"

const server = await createServer() // or process.env.TWILIO_API_BASE_URL, e.g. http://127.0.0.1:8798

type RequestOptions = Parameters<twilio.RequestClient["request"]>[0]

/** https://verify.twilio.com/v2/Services/VA…/Verifications → {base}/verify/v2/Services/VA…/Verifications */
class MockRequestClient extends twilio.RequestClient {
  override request(opts: RequestOptions): Promise<never> {
    const uri = twilioMockUrl(opts.uri, server.url)
    return super.request({ ...opts, uri }) as Promise<never>
  }
}

// The app's own Twilio client. Only its HTTP client changes.
const client = twilio("AC00000000000000000000000000000000", "fixture-token", {
  httpClient: new MockRequestClient(),
})
const lookup = await client.lookups.v2.phoneNumbers("+12025550123").fetch()
// lookup.valid === true, lookup.nationalFormat === "(202) 555-0123"
await server.close()
```

示例类型检查用twilio 5.13.1 或 后; 5.1.0 运行方式相同,但是它的 `exports` 地图隐藏打字方式 `moduleResolution: nodenext`。 。 。 .

模拟器也通过 `Host` 头曰. 满足它的要求 `lookups.twilio.com` (通过 DNS 覆盖或代理) 且没有前缀 `/lookups/…`。录音 适配器为生 `fetch` 联 合 国 `https://api.twilio.com/2010-04-01/…` 变成 `twilioMockUrl(url, TWILIO_API_BASE_URL)`。 。 。 . `RecordingUrl` 在网络呼声中保持犬形 `https://api.twilio.com` 格式,适配器检查.

### 在测试中读取检察官办公室

```ts
import twilio from "twilio"
import { twilioMockUrl } from "@crvouga/mockingbird-service-twilio"
import { createServer } from "@crvouga/mockingbird-service-twilio/server"

// Test setup: the emulator, and the app's Twilio client pointed at it as above.
const server = await createServer()
type RequestOptions = Parameters<twilio.RequestClient["request"]>[0]
class MockRequestClient extends twilio.RequestClient {
  override request(opts: RequestOptions): Promise<never> {
    const uri = twilioMockUrl(opts.uri, server.url)
    return super.request({ ...opts, uri }) as Promise<never>
  }
}
const client = twilio("AC00000000000000000000000000000000", "fixture-token", {
  httpClient: new MockRequestClient(),
})
const verify = client.verify.v2.services("VA00000000000000000000000000000000")

// The app sends the code.
const verification = await verify.verifications.create({ to: "+12025550123", channel: "sms" })

// The test reads it from the admin plane, the way a user reads the SMS.
const latest = await fetch(`${server.url}/__admin/verify/+12025550123/latest`)
const { code } = (await latest.json()) as { code: string; sid: string; status: string }

// The app checks it.
const check = await verify.verificationChecks.create({ verificationSid: verification.sid, code })
// check.status === "approved"
await server.close()
```

### 路线

| 路线 | 行为 |
| --- | --- |
| `GET /lookups/v2/PhoneNumbers/{PhoneNumber}` | 验证活 API 的编号( libphone number ) : `valid`, (中文(简体) ), `validation_errors` (单位:千美元)`TOO_SHORT`, (中文(简体) ), `TOO_LONG`, (中文(简体) ), `INVALID_BUT_POSSIBLE`, (中文(简体) ), `INVALID_COUNTRY_CODE`, (中文(简体) ), `INVALID_LENGTH`, (中文(简体) ), `NOT_A_NUMBER`, (中文(简体) ), `phone_number`, (中文(简体) ), `national_format`, (中文(简体) ), `calling_country_code`, (中文(简体) ), `country_code`, (中文(简体) ), `url`。每个数据包都是 `null`国家编号,无 `CountryCode` 必须是有效的美国号码,否则答案是 `INVALID_COUNTRY_CODE`. 虚构555-01xx数字有效. |
| `POST /verify/v2/Services/{VA}/Verifications` | `To` (有效E.164,或 `Channel=email`, (中文(简体) ), `Channel`选项 `CustomCode`创建 `VE…` 使用6位码(或 `fixedCode`) (中文(简体) ). 再次发送到同一待核查的核查中,保留其编号和代码,并添加一个 `send_code_attempts` 输入。 第6局在10分钟内发送到一个号码是429 `60203`一个坏 `To` 为 400 `60200`不明服务编号(不是) `VA` + 32 十六进制)为 404 `20404`。 。 。 . |
| `POST /verify/v2/Services/{VA}/VerificationCheck` | `Code` 加号 `VerificationSid` 或者说 `To`。右侧代码返回 200 `approved`, (中文(简体) ), `valid: true`。错误的代码返回 200 `pending` 并计数尝试。 第六张支票是429 `60202`。缺失、核准、取消或过期(模拟钟上10分钟)的核查为404 `20404`。 。 。 . |
| `GET` 编号 : `POST /verify/v2/Services/{VA}/Verifications/{VE}` | 获取验证,或设置 `Status=canceled|approved` 在一个. |
| `POST /api/2010-04-01/Accounts/{AC}/Messages.json` | `To`, (中文(简体) ), `Body` 或者说 `MediaUrl`,以及 `From` 或者说 `MessagingServiceSid`返回 201 `SM…` 锡德 (`MM…` rFC 2822 日期. `MessagingServiceSid` 只有状态 `accepted`, (中文(简体) ), `from: null`, (中文(简体) ), `num_segments: "0"` (尚未选择发件人). `From` 只有状态 `queued`。两者均保留,状态为 `queued` (Twilio在特定的发送器上排队). 没有一能键:同一体产生出另一个自相id. 出错:21604(无到发),21602(无到发),21603(无到发),21211(无效到发),21617(超过1600个字符). 消息被录入收发箱. |
| `GET /api/2010-04-01/Accounts/{AC}/Messages/{SM}.json` | 读取回函. |
| `GET /api/2010-04-01/Accounts/{AC}/Messages.json` | 该账户的最新第一信息资源 . `PageSize` 默认为50 (1-1000), `PageToken` 如下 `next_page_uri`编号 :`previous_page_uri`· ; `Page` 是客户状态。 链接保持供应商路径没有 `/api`,因此应用普通产品前缀重写. `To` 财务报告和审定财务报表 `From` 过滤存储的资源 . |
| `GET /api/2010-04-01/Accounts/{AC}/Recordings/{RE}.wav` | 录音为RIFF WAV. 与 `RequestedChannels=2` 你有两个渠道 否则双道录音被混为一谈,就像Twilio那样. |
| `GET` 编号 : `DELETE /api/2010-04-01/Accounts/{AC}/Recordings/{RE}.json` | 元数据,或删除(204;第二个删除是404,我们的消费者容忍它). |

错误使用Twilio的身体, `{code, message, more_info, status}`,与 `X-Twilio-Error-Code`。 。 。 . 认证为 HTTP Basic: a `AC…` (或 `SK…`)用户名和不空密码. 与 `accounts` (或 `--account-sid` 加号 `--auth-token`只有这些对被接受。 失踪或 错误的证书是401 `20003`。对于错误的符号,信息匹配活的: `authentication failed, auth token is not valid for account AC…`。 。 。 .

### 网络呼声(S8.4)

模拟器标志进入了网络 `X-Twilio-Signature`。签名为基数64 HMAC- SHA1( 自动令牌, 公共 URL + 排序) `key+value` 参数),与 `twilio.validateRequest`它的标志反对 **公共基础 URL 应用程序配置** (单位:千美元)`--public-base-url`,也就是说. `TWILIO_VOICE_WEBHOOK_BASE_URL`),而不是本地主机地址它帖子 改为: Twilio不重试这些webhooks,所以仿真器每发一次.

| 触发 | 员额 | 有效载荷 |
| --- | --- | --- |
| `POST /__admin/inbound/sms {from, body, to?, media?, messageSid?, params?}` | `/messaging/inbound/sms` | `MessageSid`编号 :`SmsSid` (单位:千美元)`SM…`,或 `MM…` 与媒体), `AccountSid`, (中文(简体) ), `From`, (中文(简体) ), `To` (默认 : `--caller-id`, (中文(简体) ), `Body`, (中文(简体) ), `NumMedia`, (中文(简体) ), `MediaUrl{i}`, (中文(简体) ), `MediaContentType{i}`, (中文(简体) ), `SmsStatus=received`,, , , , , , , , |
| `POST /__admin/voice/twiml` | `/admin/messaging/voice/twiml` | `CallSid`, (中文(简体) ), `From=client:<uuid>`, (中文(简体) ), `To`, (中文(简体) ), `CallStatus=ringing` 外加身体的田地(如:. `conversationId`(中文(简体) ) |
| `POST /__admin/voice/disclosure` | `/admin/messaging/voice/disclosure` | `CallSid`, (中文(简体) ), `CallStatus=in-progress` |
| `POST /__admin/voice/status` | `/admin/messaging/voice/status` | `CallSid`, (中文(简体) ), `CallStatus=completed`, (中文(简体) ), `CallDuration` |
| `POST /__admin/voice/recording` | `/admin/messaging/voice/recording` | `RecordingSid`,犬类 `RecordingUrl`, (中文(简体) ), `RecordingStatus=completed`, (中文(简体) ), `RecordingDuration`, (中文(简体) ), `RecordingChannels=2`。它也存储一个双通道的WAV,所以下载工作. |

每个体域都覆盖默认值. 管理员的回答列出了每个发送的应用程序状态 和反应机构(如:. `<Response/>`) (中文(简体) ). 事件类型 `PUT /__admin/webhook-endpoints` 过滤器是 `sms.inbound` 财务报告和审定财务报表 `voice.{twiml,disclosure,status,recording}`。 。 。 .

### 管理员(超过标准合同)

| 路线 | 效果 |
| --- | --- |
| `GET /__admin/verify/:e164/latest` | `{code, sid, status, to, channel, serviceSid, attempts, sendAttempts, createdAt, expiresAt}` 最新核查到这个号码 这是测试如何读取检察官办公室. |
| `GET` 编号 : `PUT /__admin/verify` | `{fixedCode: "000000" | null, ttlSeconds, maxCheckAttempts, maxSendAttempts, sendWindowSeconds}` 呼叫的命名空间. |
| `PUT /__admin/lookups/:e164` | `{valid, validationErrors?}` 覆盖该号码的搜索( 验证和信件也使用它) . `DELETE` 删除覆盖 . |
| `PUT /__admin/recordings/:RE` | 上传一段录音:一个生的WAV体(`content-type: audio/wav`, (中文(简体) ), `{"wavBase64": …}`,或 `{channels?, seconds?}` 用于合成8千赫16位音调. |
| `GET /__admin/outbox?to=&since=&kind=sms|verify` | 所有"同意":简讯`{to, from, messagingServiceSid, body, sid}`)和每一次验证代码发送(`{code, body: "Your verification code is: …"}`) (中文(简体) ). |
| `GET /__admin/messages` | 命名空间中的信件资源 . |

错误预设( E)`POST /__admin/faults {"preset": "<name>", "count"?: n, "latencyMs"?: n}`; 以 `GET /__admin/faults/presets`,并读 `hits` 编号 : `remaining` 从 `GET /__admin/faults`) (中文(简体) ). 预设适用于调用命名空间. `verify_5xx` (开始和检查答案) `20500`, (中文(简体) ), `sms_drop_before_accept` (Messages.json在信件存在前将套接字放下;仍然注册为 `sms_socket_drop`, (中文(简体) ), `sms_accepted_then_socket_drop` (信件和发件箱项被存储,然后套接字在任何响应字节之前关闭), `sms_4xx` (400个) `21211`, (中文(简体) ), `sms_429` (429个) `20429` 与 `Retry-After: 1`, (中文(简体) ), `sms_5xx` (500个) `20500`,没有 `Retry-After`, (中文(简体) ), `sms_missing_sid` (201人,其身体省略) `sid`收发箱里还有留言, `lookup_5xx` (503个) `20503`; EMR 未打开), `webhook_duplicate`, (中文(简体) ), `webhook_drop`. Messages.json上的503是同一个有代码的信封 `20503` 财务报告和审定财务报表 `Retry-After` (标准过失,不是单独的预设). 状态断层没有存储信息.

### 命名空间

Twilio SDK 无法添加信头, 所以套房会选择命名空间 **账户**数字 : `PUT /__admin/credentials {"credentials": {"<TWILIO_ACCOUNT_SID>": "<namespace>"}}`名称空间 也可以来自 `x-mockingbird-namespace` 标题或一个 `/__admin/ns/<name>` 基础 URL 前缀 (单位:千美元)`twilioMockUrl` 保留前缀).

### 故意不模拟

-   发送: 保留信息 `queued`编号 :`accepted`,没有发送状态回调(我们的消费者集没有) `statusCallback`),并且没有出现语音通话,会议或媒体流.
-   信件收藏 `DateSent` 过滤器(模拟器从未发送消息).
-   付费的搜索数据包( E)`Fields=line_type_intelligence`, (中文(简体) ), `caller_name`,)总是 `null`。 。 。 .
-   接受和记录除短信以外的核查频道,但无任何消息。 校验 服务配置(代码长度、友好名称、速率限制桶)是全局的,设置为 `PUT /__admin/verify`。 。 。 .
-   账户:任何 `AC…` sid是它自己的账户,而路径的 `{AccountSid}` 没有 与证书核对.
-   libphonenumber-js从它的元数据中去掉"局部"长度. 模拟器恢复它们 NANP (7)和 GB (4–6,8),这足以用于虚构的数字测试. 其他国家 可能回答 `TOO_SHORT` 特维利奥回答的地方 `INVALID_BUT_POSSIBLE`。 。 。 .

## API 密码

| 导出 | 仁爱 | 说明 |
| --- | --- | --- |
| `TwilioAPI` | 类 | 进程模拟器 : `fetch(request)`, (中文(简体) ), `reset()`, (中文(简体) ), `latestVerification(to)`, (中文(简体) ), `resolveLookup(raw, country?)`, (中文(简体) ), `setLookup(e164, override)`, (中文(简体) ), `putRecording(sid, input)`, (中文(简体) ), `outbox()`, (中文(简体) ), `messages()`选项: `sqlite`, (中文(简体) ), `now`, (中文(简体) ), `namespace`, (中文(简体) ), `verify`, (中文(简体) ), `accounts`。 。 。 . |
| `createRuntime` | 函数 | 具有完整服务合同的仿真器(健康,管理员,取名空间,证书,预设,出柜,网络呼号),外加主机路由. 选项 : `app: {url, publicBaseUrl?, authToken, accountSid?, callerId?, messagingServiceSid?}`, (中文(简体) ), `verify`, (中文(简体) ), `accounts`, (中文(简体) ), `retryDelaysMs`, (中文(简体) ), `fetch`, (中文(简体) ), `clock`, (中文(简体) ), `seed`, (中文(简体) ), `adminKey`, (中文(简体) ), `onLog`。返回的运行时间也有 `inboundSms(input)` 财务报告和审定财务报表 `voiceWebhook(kind, params)`。 。 。 . |
| `TWILIO_PRESETS` | 对象 | 每个命名的断层预设. |
| `TWILIO_WEBHOOK_EVENTS` | 对象 | Webhook 事件类型 – 它所张贴的应用路径 . |
| `twilioMockUrl` | 函数 | 重写上游 `https://<product>.twilio.com/…` URL 在模拟器基址上( 对于 G- T1 ) `httpClient`) (中文(简体) ). |
| `TWILIO_PRODUCTS` | 数组 | 产品前缀服务于: `api`, (中文(简体) ), `verify`, (中文(简体) ), `lookups`。 。 。 . |
| `lookup` | 函数 | 查找 v2 原始输入的验证( 选择在 a 中) `CountryCode` (b) 建立区域网络. |
| `e164Key` | 函数 | `+` 和数字 : 管理员超过使用的密钥. |
| `twilioError` | 函数 | Twilio错误反应, `{code, message, more_info, status}`。 。 。 . |
| `DEFAULT_VERIFY_SETTINGS` | 对象 | 验证缺省:10分钟过期,5次核对,每10分钟发出5个,随机编码. |
| `DEFAULT_ACCOUNT_SID` | 字符串 | 证书为 API 密钥时使用的账户 . |
| `TWILIO_NAMESPACE` | 字符串 | 服务名称, `"twilio"`。 。 。 . |
| `synthesizeWav`, (中文(简体) ), `readWav`, (中文(简体) ), `mixDownToMono` | 函数 | 制作一款PCM WAV,读取其格式,将多通道的WAV混合到单相. |
| `document`, (中文(简体) ), `operationIds`, (中文(简体) ), `supportedOperationIds` | 数值 | 销售商为OpenAPI合同及其业务代号. |
| `createServer`, (中文(简体) ), `serveTarget`, (中文(简体) ), `DEFAULT_PORT` (单位:千美元)`./server`(中文(简体) ) | 节点 | 服务过来 `node:http`; 数据 `serve` CLI目标; 第8798口. |

部分 [嘲笑鸟](https://github.com/crvouga/mockingbird)。 。 。 .

## 常见问题

### @crvouga/mockingbird-service-twilio 是什么？

Twilio 的状态仿真器, Lookup v2, Messageing and Recordings 在一个端口上, 并有签名的收发短信和语音网呼\(Mockingbird 服务合同\)\.

### 如何安装 @crvouga/mockingbird-service-twilio？

在项目目录运行 npm install @crvouga/mockingbird-service-twilio，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 mockingbird-twilio，可以用 npx mockingbird-twilio 直接运行。

### @crvouga/mockingbird-service-twilio 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @crvouga/mockingbird-service-twilio 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @crvouga/mockingbird-service-twilio 可以商用吗？

@crvouga/mockingbird-service-twilio 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @crvouga/mockingbird-service-twilio 的下载量有多少？

根据 npm 官方下载统计，@crvouga/mockingbird-service-twilio 在 2026/10/11 – 2026/11/09 这 30 天内被下载 15,461 次，日均约 515 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @crvouga/mockingbird-service-twilio 还在维护吗？

最新版本 3\.11\.0 发布于 2026/11/11（今天）；至今共发布 38 个版本，其中过去 12 个月发布了 38 个；首次发布于 2026/09/23。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

