# @firmhouse/firmhouse-sdk 中文文档

规范地址：https://npmcn.com/package/%40firmhouse/firmhouse-sdk/

版本：1\.2\.0
npm 元数据更新时间：2026-09-04T08:14:45.947Z
中文译文更新时间：2026-11-14T20:05:41.317Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40firmhouse/firmhouse-sdk
原文对照：https://npmcn.com/package/%40firmhouse/firmhouse-sdk/?lang=original
项目主页：https://github.com/firmhouse/firmhouse-sdk#readme
源码仓库：https://github.com/firmhouse/firmhouse-sdk

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

- 包体积（解压后）：3.2 MB，133 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.0\.0
- 运行依赖：2 个
- 首次发布：2024-06-26T22:36:02.710Z
- 最新版本发布：2026-09-04T08:14:45.633Z
- 近 30 天下载量：6575（2026-10-15 至 2026-11-13，npm 官方下载统计）
- 已发布版本数：8（近 12 个月 4 个）

## 中文简介

一个 JavaScript / TypeScript SDK 用于以结构化和类型安全的方式与 Firmhouse GraphQL API 交互.

## 安装

```sh
npm install @firmhouse/firmhouse-sdk
```

也可以使用：`pnpm add @firmhouse/firmhouse-sdk`、`yarn add @firmhouse/firmhouse-sdk`、`bun add @firmhouse/firmhouse-sdk`

## README

# 事务所 SDK

一个 JavaScript / TypeScript SDK 用于以结构化和类型安全的方式与 Firmhouse GraphQL API 交互.

Firmhouse SDK的设计是为了通过提供完全打入的接口和以有条理的方式处理出错,使开发者更容易与Firmhouse API互动.

## 特征

-   用 TypeScript 完全打入了 SDK,所以不需要担心字段名称和类型.
-   以自动补全和类型提示提供平滑的IDE体验.
-   以结构化的方式处理错误 .
-   支持 Storefront 和 Write 访问符并基于访问类型限制操作.
-   给予您在回复中包含/排除相关资源的选项,而不写入杂乱的 GraphQL 查询 .
-   支持采用贴现码并计算贴现车总数.
-   提供订阅、订购产品和额外字段的帮助.
-   提供嵌入式的 Adyen 取出, 这样您就可以在自己的存储前端进行支付步骤, 而不是重定向到主机支付页面 .

## 安装

```bash
npm install @firmhouse/firmhouse-sdk
```

## 文档

你可以找到SDK的文档 [这里](https://developer.firmhouse.com/sdks/firmhouse-sdk)。 。 。 .

## 使用量

```typescript
import { Access, FirmhouseClient } from '@firmhouse/firmhouse-sdk';
import { assignSubscriptionUtils, calculateCartTotals, mapExtraFieldsByFieldId } from '@firmhouse/firmhouse-sdk/utils';

const apiToken = 'YOUR_PROJECT_ACCESS_TOKEN';

const client = new FirmhouseClient({
  apiToken,
});

const { results: products } = await client.products.fetchAll();
const { results: plans } = await client.plans.fetchAll();
const product = await client.products.fetchById('123');
const cartToken = await client.carts.createCartToken();
await client.carts.addProduct(cartToken, {
  productId: products[0].id,
  quantity: 2,
});

// Apply a discount code and calculate the discounted cart totals.
await client.carts.applyDiscountCode(cartToken, 'WELCOME10');
const cart = await client.carts.get(cartToken, {
  appliedPromotions: {
    includeRelations: {
      promotion: true,
      discountCode: true,
    },
  },
});
const {
  payNowSubtotalCents, // Signup amount before discount.
  payNowDiscountCents, // Discount applied at signup.
  payNowTotalCents, // Signup amount after discount.
  monthlySubtotalCents, // Monthly amount before discount.
  monthlyDiscountCents, // Discount applied each month.
  monthlyTotalCents, // Monthly amount after discount.
} = calculateCartTotals(cart);
await client.carts.removeDiscountCode(cartToken);

const writeAccessApiToken = 'YOUR_PROJECT_ACCESS_TOKEN_WITH_WRITE_ACCESS';
const writeAccessClient = new FirmhouseClient({
  apiToken: writeAccessApiToken,
  accessType: Access.write,
});

const project = await writeAccessClient.projects.getCurrent({
  extraFields: true,
  promotions: true,
  taxRates: true,
});

const invoices = await writeAccessClient.invoices.fetchAll();

await client.selfServiceCenterToken.create('subscriber@example.com', 'https://myapp.com/ssc/token-login');
const selfServiceCenterLoginToken = 'TOKEN_RECEIVED_FROM_THE_LOGIN_LINK';
const subscription = await writeAccessClient.subscriptions.getBySelfServiceCenterLoginToken(selfServiceCenterLoginToken);

const subscriptionWithUtils = assignSubscriptionUtils(subscription);
const upcomingOrderDate = subscriptionWithUtils.getClosestUpcomingOrderDate();
const upcomingOrderProducts = subscriptionWithUtils.getClosestUpcomingOrderOrderedProducts();

const extraFieldsById = mapExtraFieldsByFieldId(subscription.extraFields);
const extraFieldAnswer = extraFieldsById['EXTRA_FIELD_ID'];
```

`calculateCartTotals` 多次使用最大活动升级 晋级是存在的;晋级不堆叠. 贴现额在 小计,不包括运费.

## 内嵌 Adyen 报到

Adyen 工程可以在您的商店前端实现支付步骤 [阿迪恩网络 下潜](https://docs.adyen.com/online-payments/build-your-integration/) 改为 发送客户到主机支付页面. `client.payments` 返回浏览器安全 会话配置,帮助者将其转换为 Drop-in期望的选项.

安装 `@adyen/adyen-web` 自己; SDK 不依赖它.

```typescript
import { AdyenCheckout, Dropin } from '@adyen/adyen-web';
import { buildAdyenCheckoutOptions, buildAdyenDropinOptions, resolveAdyenCheckoutEntry } from '@firmhouse/firmhouse-sdk/utils';

const entry = resolveAdyenCheckoutEntry(new URLSearchParams(window.location.search));
let paymentToken = sessionStorage.getItem(`paymentToken:${cartToken}`);

// The customer is back from a redirect, so the payment is already with Adyen.
if (entry.mode === 'redirect' && paymentToken) {
  const status = await client.payments.waitForCheckoutStatus(cartToken, paymentToken);
  if (status.paymentStatus === 'PAID' && status.successUrl) {
    window.location.assign(status.successUrl);
    return;
  }
  // The payment was refused or expired. It is reopened, so Drop-in can be mounted again.
}

if (!paymentToken) {
  // `payment` is null when the checkout has nothing to pay for.
  const { payment } = await client.carts.createSubscription(cartToken, 'https://myshop.com/checkout', 'https://myshop.com/thanks');
  if (!payment) return;
  paymentToken = payment.token;
  sessionStorage.setItem(`paymentToken:${cartToken}`, paymentToken);
}

const session = await client.payments.createAdyenSession(cartToken, paymentToken);
const checkout = await AdyenCheckout(buildAdyenCheckoutOptions(session));
new Dropin(checkout, buildAdyenDropinOptions(session)).mount('#dropin-container');
```

IDEAL、Ban Contact和3D安全挑战等支付方法将客户带到 另一页,Adyen 返回到您的报到 `sessionId` 财务报告和审定财务报表 `redirectResult` 查询参数. `resolveAdyenCheckoutEntry` 检测到 读取 重定向返回时,先确定结果: 经常在客户回来之前登陆的网游, 无法创建会话 已经支付的款项.

保持支付符从 `createSubscription` 某处能活过转机, 例如 `sessionStorage`。不要在重定向返回时再次完成推车:一旦 支付, `createSubscription` 不再返回它,所以没有标志 读取结果.

要比 Webhook 更快地向浏览器报告结果,你可以将结果交给 当支付尚未打开时, 结果返回 Adyen :

```typescript
const checkout = await AdyenCheckout(buildAdyenCheckoutOptions(session, entry));
checkout.submitDetails({ details: { redirectResult: entry.redirectResult } });
```

请求同一付款的会话再次返回仍在运行的会话, 所以重新装入取出页面 使客户保持同样的付款, 和拒绝 付款可以重新审理.

全体 `client.payments` 方法需要存储前置访问符和订阅符 检查. `buildAdyenDropinOptions` 映射卡片、 PayPal 和 Google 付费设置 ,因此,需要持卡人姓名等设置适用于您的退出 无需硬编码 会话存储支付方法。 将您的演示文稿选项合并到结果中 样式 Drop- in.

## 常见问题

### @firmhouse/firmhouse-sdk 是什么？

一个 JavaScript / TypeScript SDK 用于以结构化和类型安全的方式与 Firmhouse GraphQL API 交互\.

### 如何安装 @firmhouse/firmhouse-sdk？

在项目目录运行 npm install @firmhouse/firmhouse-sdk，或使用 pnpm add / yarn add / bun add。

### @firmhouse/firmhouse-sdk 支持 TypeScript 吗？

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

### @firmhouse/firmhouse-sdk 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @firmhouse/firmhouse-sdk 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @firmhouse/firmhouse-sdk 可以商用吗？

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

### @firmhouse/firmhouse-sdk 的下载量有多少？

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

### @firmhouse/firmhouse-sdk 还在维护吗？

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

