@crvouga/mockingbird-service-flex

中文文档
4.1.0发布于 2026/11/11MITTypeScriptES Module构建来源已验证近 30 天下载 1.7万

Flex HSA / FSA 付款的状态模拟器 API: 产品(已录入目录),付款的离职会话,订阅,停会和设置模式,订阅,客户,设置意图,退款,主机的离职页面,以及Svix签名的We

中文使用文档
文档目录11 节
  1. 安装
  2. 使用量
  3. 浏览器 E2E 套件
  4. 路线
  5. 主机页面
  6. 网络呼号
  7. 管理员(超过标准合同)
  8. 命名空间
  9. 企业
  10. 故意不模拟
  11. API 密码

@crvouga/嘲笑鸟-服务-flex

本地模拟器。 真正的API合同. 部分 嘲笑鸟。 。 。 .

国家模拟器 弹性 (withflex.com) HSA/FSA支付测试套件API:产品 (从记录的目录中回答) payment (一次), subscription, (中文(简体) ), off_session 财务报告和审定财务报表 setup 模式,订阅,客户,设置意图, 退款,即 主机退出页面,而由 Svix 签名的 Webhooks Flex 贴出回。 驱动真实的UI检出 checkout.withflex.com 然后在5分钟的调和器上等在这里 毫秒:页面是本地的,签名的webhook一卡通即可到达应用程序 已接受.

  • 行动范围: 支助
  • Flex没有公布机器可读规格:合同(openapi.yaml)是手写自 电线塑造了消费者的阅读和写作B/billing/flex/),和每一个字段的zod 满足了计划要求。 订阅模式, price_data.recurring 和订阅 对象跟随 Flex API 参考文献 (这里) 没有沙盒记录).

安装

npm install -D @crvouga/mockingbird-service-flex

仅限无害环境管理。 节点 22或 Bun 1.2. 无土生属地. 给它服务 npx mockingbird-flex serve, (中文(简体) ), createServer 从 ./server (节点),或 createRuntime 带有任意 获取服务器 .

使用量

将应用程序指向模拟器:

信封数值
FLEX_API_BASE_URLhttp://127.0.0.1:8792 (或 …/__admin/ns/<namespace>(中文(简体) )
FLEX_API_KEY任意 fsk_test_… 键(测试模式); fsk_… 是活模式; 其他格式获得401
FLEX_WEBHOOK_SECRET与 --webhook-secret数字 : fwhsec_<base64> 或者说 whsec_<base64>
npx mockingbird-flex serve --port 8792 \
  --webhook-url http://127.0.0.1:3000/billing/webhooks/flex \
  --webhook-secret "$FLEX_WEBHOOK_SECRET"
import { createServer } from "@crvouga/mockingbird-service-flex/server"

// Test setup: the emulator, posting signed webhooks to the app's handler.
const server = await createServer({
  webhooks: {
    url: "http://127.0.0.1:3000/billing/webhooks/flex",
    secret: "fwhsec_ZmxleC1tb2NrLXNpZ25pbmcta2V5",
  },
})

// Application code: FLEX_API_BASE_URL is server.url, FLEX_API_KEY any fsk_test_ key.
const baseUrl = server.url
const created = await fetch(`${baseUrl}/v1/checkout/sessions`, {
  method: "POST",
  headers: { "content-type": "application/json", authorization: "Bearer fsk_test_suite" },
  body: JSON.stringify({
    checkout_session: {
      success_url: "https://app.test/done?session_id={CHECKOUT_SESSION_ID}",
      cancel_url: "https://app.test/cart",
      client_reference_id: "attempt-1",
      line_items: [
        { price_data: { product: "fprod_01m0tgysj4ahvf8fas60c2ef2d", unit_amount: 4500 }, quantity: 1 },
      ],
    },
  }),
})
const { checkout_session } = (await created.json()) as {
  checkout_session: { checkout_session_id: string; url: string }
}

// Test control: open checkout_session.url in the browser and pay with 4000 0512 3000 0072, or:
await fetch(`${baseUrl}/__admin/sessions/${checkout_session.checkout_session_id}/complete`, {
  method: "POST",
})
await server.close()

浏览器 E2E 套件

运行 npx mockingbird-flex serve 在端口上,点 FLEX_API_BASE_URL 和浏览器 在模拟器的页面上登陆而不是 checkout.withflex.com: 没有网络, 没有共享 Flex 账户,而签名的webhook一旦点击Pay就立即到达了应用程序. 页面 URL 需要 模拟者的出处,或 --public-url 当给予。 按主机查找 Flex 标签的套件 (单位:千美元)/\bcheckout\.withflex\.com\b/与 --public-url http://checkout.withflex.com.localhost:8792:铬溶解于每个 *.localhost 名称以回转。 其他浏览器可能需要主机条目.

路线

所有API体被包裹: {product: {…}}, (中文(简体) ), {checkout_session: {…}}, (中文(简体) ), {customer: {…}}, (中文(简体) ), {setup_intent: {…}}, (中文(简体) ), {products: […], has_more}, (中文(简体) ), {checkout_sessions: […], has_more}。 。 。 . 错误是 {error: {type, message, param?}}。 。 。 .

路线行为
GET /v1/products?limit=&starting_after=古老的第一; limit 1–100(默认 10). 药丸先出,再出出产.
POST /v1/products{product: {name, description?, url?, client_reference_id?, metadata?}}新产品活跃, hsa_fsa_eligibility: null 直至保密(PUT /__admin/products/:id) (中文(简体) ).
GET /v1/products/{id}product_id, name, description, url, client_reference_id, hsa_fsa_eligibility, visit_type, active, test_mode, metadata, created_at。 。 。 .
PATCH /v1/products/{id}{product: {active?, name?, description?, url?, metadata?}}; 发射 product.updated。 。 。 .
POST /v1/checkout/sessionsIdempotency-Key 很荣幸. mode payment (第1行项目), subscription (1行项目: price_data.recurring 实值 {interval: day|week|month|year, interval_count?}, 其他 400; 可选 subscription_data: {cancel_at_period_end?, metadata?}, (中文(简体) ), setup (客户和无细列项目,其他400个), off_session (客户+已保存) payment_method,在回答前充电:答复已经 complete,或者其扩大的付款意向是 requires_payment_method 编号 : requires_action 百分比 offSessionOutcome) (中文(简体) ). 未知或不活跃的产品、客户和支付方法为400个. redirect_url 财务报告和审定财务报表 url 是主机页面.
GET /v1/checkout/sessions/{id}?expand_customer=true&expand_payment_intent=true会话; 扩展返回 customer 编号 : payment_intent 对象而不是标识.
GET /v1/checkout/sessions?client_reference_id=&limit=&starting_after=最新第一(我们的模棱两可的恢复).
POST /v1/checkout/sessions/{id}/refundIdempotency-Key 很荣幸. {checkout_session: {}} (全文)或 {checkout_session: {amount}};400 当未付或资金过多时.
POST /v1/customersIdempotency-Key 很荣幸. {customer: {first_name, last_name, email, phone}} (所有要求).
GET /v1/setup_intents/{id}?expand=customer,payment_methodsetup_intent_id, status, customer, payment_method。 。 。 .
GET /v1/subscriptions/{id}{subscription: {subscription_id, status, items, customer, default_payment_method, cancel_at_period_end, current_period_start, current_period_end, canceled_at, metadata, test_mode, created_at}}。付费订阅模式会开始一个: active, (中文(简体) ), items = 其经常性细列项目,第一个经常性项目的间隔期(月/年步骤夹住月份的最后一天),记入刚刚使用的卡片 subscription 持有其身份证明.

认证 : Authorization: Bearer fsk_test_… 或者说 fsk_…; 缺少密钥,或任何其他格式 (单位:千美元)sk_test_…, (中文(简体) ), whsec_…,为 401 authentication_error。 。 。 . test_mode 在创建对象上 钥匙 相同的密钥 + 相同的正体重放存储的响应; 相同的密钥 + 不同的正体是 400 idempotency_error;飞行中键同时提出的请求为409个.

主机页面

GET /pay/{sessionId} 制作一个普通形式( 无脚本) , 使用 data-testid编号 flex-mock-email, (中文(简体) ), -first-name, (中文(简体) ), -last-name, (中文(简体) ), -phone, (中文(简体) ), -card, (中文(简体) ), -exp, (中文(简体) ), -cvc, (中文(简体) ), -zip, (中文(简体) ), -pay, (中文(简体) ), -cancel, (中文(简体) ), -error, (中文(简体) ), -amount,并在字母步骤上 -lmn-submit输入还携带 页:1 name和占位器 我们的密码定位器寻找(cardNumber, (中文(简体) ), expiry, (中文(简体) ), cvc, (中文(简体) ), postalCode, (中文(简体) ), email(中文(简体) ). POST /pay/{sessionId} 提出:

纸牌结果
4000 0512 3000 0072HSA卡:成功.
4242 4242 4242 4242 (或任何其他有效卡)成功; 如果行项目的产品是 letter_of_medical_necessity,会话得到 next_action: {type: "collect_letter_of_medical_necessity", collect_letter_of_medical_necessity: {url}} 和浏览器跳到该步骤;提交它完成支付.
4000 0000 0000 0002缩写: 402页 <div role="alert">Your card was declined.</div>; 付款意向为 requires_payment_method。 。 。 .

成功 302 个 success_url 与 {CHECKOUT_SESSION_ID} 替换( 绘图和 %7BCHECKOUT_SESSION_ID%7D(三); GET /pay/{id}/cancel (取消链接) cancel_url, (中文(简体) ), 会话开始。 在一个没有客户的会话上建立联系电子邮件 。 在一个 页面 URL 包含的命名空间 /__admin/ns/<name> (浏览器不发送信头); publicUrl 覆盖来源.

网络呼号

签署(svix-id, (中文(简体) ), svix-timestamp =墙钟, svix-signature: v1,<base64 HMAC-SHA256(key, "<id>.<ts>.<body>")>,密钥 = base64-解码后的秘密 fwhsec_编号 :whsec_) (中文(简体) ). 车身 : {event: {event_id, event_type, object, event_dt, test_mode, created_at}}。与Flex一样 OpenAPI (英语:EventObject和生产交付, object 持有一个键 资源: 退出事件 {checkout_session} (这样) object.checkout_session.checkout_session_id, (中文(简体) ), 付款意向事件 {payment_intent}, (中文(简体) ), charge.* 事件 {charge} (其意图是: charge.payment_intent, (中文(简体) ), refund.* 财务报告和审定财务报表 charge.refund.updated 事件 {refund} (其意图是: refund.payment_intent_id, (中文(简体) ), customer.subscription.* {subscription} 财务报告和审定财务报表 product.updated {product}。付款意向、收费和退款对象名称为“不退出会话”:接收者 通过付款意向找到付款.

活动何时
payment_intent.succeeded,则 checkout.session.completed页面(或 …/complete或非会期收费)
customer.subscription.created (订阅),在这之前订阅模式会话解决
checkout.session.async_payment_succeeded解决会议的意图 processing
checkout.session.async_payment_faileda 减少(页数、行政、会外)
checkout.session.expired…/expire,或 expires_at 传递到模拟器时钟( 默认 24 h)
checkout.session.refunded (会话,每笔退款在 refunds,则 refund.created (两次), charge.refunded, (中文(简体) ), refund.updated, (中文(简体) ), charge.refund.updated每次退款,通过API或仪表板(POST /__admin/sessions/:id/refund) (中文(简体) ). 退货和收费事项是按订单生产的,提供一份仪表盘退货;每份退货 items 标明其付款意向
product.updatedPATCH /v1/products/{id} 财务报告和审定财务报表 PUT /__admin/products/:id
checkout_session.completed, (中文(简体) ), checkout_session.expired别名,用: PUT /__admin/settings {"eventNaming": "underscored"}

端点只接收它所订阅的事件类型, 如Flex的仪表板: pass webhooks: {events: [...]} (默认:每类)或 PUT /__admin/webhook-endpoints订阅 所以测试不能通过事件制作 从来没有收到.

POST /__admin/events {type, session | product} 需要时会发出任何类型的信号。 非-2xx的答案是: 重审(即5秒、5分、30分、2小时); GET /__admin/webhooks, (中文(简体) ), …/events, (中文(简体) ), POST /__admin/webhooks/flush, (中文(简体) ), …/:id/replay, (中文(简体) ), PUT /__admin/webhook-endpoints 和往常一样.

管理员(超过标准合同)

路线效果
PUT /__admin/products/:id{hsa_fsa_eligibility?, active?, test_mode?, visit_type?, client_reference_id?, name?, metadata?}; 发射 product.updated。 。 。 .
POST /__admin/sessions/:id/complete{card?}: 结算如已支付(HSA卡,除非 card 实值 4242…) (中文(简体) ).
POST /__admin/sessions/:id/decline付款意向 requires_payment_method。 。 。 .
POST /__admin/sessions/:id/expire届会议 ∗∗ expired。 。 。 .
POST /__admin/sessions/:id/refund{amount?}:在Flex的仪表板(默认全额)中退款;出出退事. 409,当未付时,400美元超过未注资的数额.
POST /__admin/sessions/:id/require_action{next_action_type?}数字 : collect_letter_of_medical_necessity (违约), provide_second_payment_method, (中文(简体) ), provide_alternative_payment_method, (中文(简体) ), payment_failed。 。 。 .
PUT /__admin/sessions/:id/payment-intent{status, amount_received?}数字 : requires_payment_method, (中文(简体) ), requires_action, (中文(简体) ), processing, (中文(简体) ), succeeded, (中文(简体) ), canceled。 。 。 .
GET /__admin/sessions, (中文(简体) ), GET /__admin/sessions/:id命名空间的会话.
POST /__admin/events为会话或产品发送任意事件类型 .
GET/PUT /__admin/settings{eventNaming, offSessionOutcome, sessionTtlSeconds, lmnOnRegularCard, publicUrl}。 。 。 .
POST /__admin/tick现在到期的会话( 模拟器每100 ms 计时) .

每个管弦乐团状态都可以达到:待定(开放),行动(需要)require_action,或一个 意图 requires_action),处理,取消(意图) canceled,或已过期),失败 (单位:千美元)decline),成功,退款(全额退款),隔离(部分退款, amount_mismatch,重复会议).

错误预设( E)POST /__admin/faults {"preset": "<name>", "count"?: n}· ; GET /__admin/faults/presets: create_4xx 四百个, create_5xx (创造,然后500:恢复通过), create_5xx_not_created, (中文(简体) ), timeout (创建, 16 s后答案, 超过客户端的 15 s 中止 ; params.delayMs 超过, invalid_shape (无) redirect_url编号 :url, (中文(简体) ), amount_mismatch (单位:千美元)amount_total +100), (中文(简体) ), duplicate_sessions_for_client_reference (两会,然后500), refund_4xx, (中文(简体) ), server_error, (中文(简体) ), webhook_duplicate, (中文(简体) ), webhook_reorder, (中文(简体) ), webhook_drop。 。 。 .

命名空间

x-mockingbird-namespace页:1 /__admin/ns/<name> 前缀在 FLEX_API_BASE_URL,或用 API 键: PUT /__admin/credentials {"credentials": {"<FLEX_API_KEY>": "<namespace>"}}。 。 。 .

企业

src/corpus/products.ts 是消费者每一行的产品方面 flexCatalogMappings 参考固定图 (663行,以 bun scripts/corpus.ts <fixture.json>:产品代号、客户参考、 acme_purpose 编号 : acme_merchant_product_id 编号 : acme_client_reference_id 元数据我们的目录验证 比较、资格和访问类型。 每个产品都是活性的 测试模式,所以我们的验证 复制每个绘图行自己的 active 旗帜。 没有沙盒记录( 没有证书) , 所以产品名称被合成.

故意不模拟

  • 真实的卡片处理,花旗iframes和分价支付:页面是一个平面形式,以及 只能以 next_action: provide_second_payment_method。 。 。 .
  • 医疗需要函调查表:一个提交按钮就位.
  • 测试/活数据分离:活键看到相同的对象(仅限 test_mode 页:1.
  • 离职后订阅生命周期:续订、发票和 invoice.* 事件, 审判, customer.subscription.updated 编号 : .deleted,以及订阅更新/取消 路线。 订户留下来 active 其第一个时期。 价格price 编号在 使用内线 price_data。 。 。 .
  • 债券、晋升守则allow_promotion_codes 部分捕捉, 争议.
  • Flex的准确错误文本和ID:形状跟随我们的消费者所读;ID长相像 fprod_01z…, (中文(简体) ), fcs_01z…, (中文(简体) ), fcus_…, (中文(简体) ), fpi_…, (中文(简体) ), fseti_…, (中文(简体) ), fpm_…, (中文(简体) ), fevt_…。 。 。 .

API 密码

导出仁爱说明
FlexAPI类进程模拟器 : fetch(request), (中文(简体) ), reset(), (中文(简体) ), settle(id), (中文(简体) ), decline(id), (中文(简体) ), expire(id), (中文(简体) ), requireAction(id, type), (中文(简体) ), setPaymentIntent(id, patch), (中文(简体) ), applyRefund(id, amount), (中文(简体) ), dashboardRefund(id, amount?), (中文(简体) ), putProduct(product), (中文(简体) ), emitFor(type, target), (中文(简体) ), tick(), (中文(简体) ), sessions(), (中文(简体) ), subscriptions(), (中文(简体) ), present(session, view)选项: sqlite, (中文(简体) ), now, (中文(简体) ), namespace, (中文(简体) ), publicNamespace, (中文(简体) ), products, (中文(简体) ), settings, (中文(简体) ), onEvent。 。 。 .
createRuntime函数服务合同的模拟者。 选项 : webhooks: {url, secret, events?, retryDelaysMs?, fetch?}, (中文(简体) ), products, (中文(简体) ), settings, (中文(简体) ), tickMs, (中文(简体) ), clock, (中文(简体) ), seed, (中文(简体) ), adminKey, (中文(简体) ), onLog。 。 。 .
FLEX_PRESETS对象每个命名的断层预设.
FLEX_NAMESPACE字符串服务名称, "flex"。 。 。 .
FLEX_EVENT_TYPES数组包括了每个网络事件类型,别名.
eventObjectKey函数事件类型的密钥 object 被嵌入(refund.created → refund, (中文(简体) ), charge.refund.updated → refund) (中文(简体) ).
keyMode函数"test" 页:1 fsk_test_…, (中文(简体) ), "live" 页:1 fsk_…,否则 undefined。 。 。 .
isNextActionType函数字符串是否为下一个动作类型 .
CARDS, (中文(简体) ), classifyCard, (中文(简体) ), substituteSessionId数值主机页面的测试卡,它的卡分类器,以及 {CHECKOUT_SESSION_ID} 替换.
CORPUS_ROWS, (中文(简体) ), corpusProduct数值记录的产品体及其行-产品映射.
DEFAULT_SETTINGS, (中文(简体) ), ELIGIBILITIES, (中文(简体) ), NEXT_ACTION_TYPES, (中文(简体) ), PAYMENT_INTENT_STATUSES, (中文(简体) ), SUBSCRIPTION_STATUSES数值默认和enums.
periodEnd函数periodEnd(startMs, {interval, interval_count?}): 计费期的结束(划时代 ms).
document, (中文(简体) ), operationIds, (中文(简体) ), supportedOperationIds数值销售商为OpenAPI合同及其业务代号.
createServer, (中文(简体) ), serveTarget, (中文(简体) ), DEFAULT_PORT (单位:千美元)./server(中文(简体) )节点服务过来 node:http (过期时每100毫秒划勾) serve CLI目标(--webhook-url, (中文(简体) ), --webhook-secret, (中文(简体) ), --public-url, (中文(简体) ), --event-naming; 港口8792.

部分 嘲笑鸟。 。 。 .

版本与发布记录

@crvouga/mockingbird-service-flex 共发布 45 个版本,首次发布于 2026/09/23;过去 12 个月发布了 45 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
4.1.0latest2026/11/11今天
4.0.92026/11/038 天前
4.0.82026/11/038 天前
4.0.72026/11/038 天前
4.0.62026/11/038 天前
4.0.52026/11/038 天前

关于 @crvouga/mockingbird-service-flex 的常见问题

@crvouga/mockingbird-service-flex 是什么?

Flex HSA / FSA 付款的状态模拟器 API: 产品(已录入目录),付款的离职会话,订阅,停会和设置模式,订阅,客户,设置意图,退款,主机的离职页面,以及Svix签名的We

如何安装 @crvouga/mockingbird-service-flex?

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

@crvouga/mockingbird-service-flex 支持 TypeScript 吗?

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

@crvouga/mockingbird-service-flex 支持 ESM 还是 CommonJS?

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

@crvouga/mockingbird-service-flex 可以商用吗?

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

@crvouga/mockingbird-service-flex 的下载量有多少?

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

@crvouga/mockingbird-service-flex 还在维护吗?

最新版本 4.1.0 发布于 2026/11/11(今天);至今共发布 45 个版本,其中过去 12 个月发布了 45 个;首次发布于 2026/09/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。