@x-money/core

中文文档
0.2.0发布于 2026/10/30MITTypeScriptES Module零依赖

用于Node.js的X Money API客户端

中文使用文档
文档目录12 节
  1. 快速启动
  2. 资源
  3. 分页
  4. 幂等性
  5. 测试模式
  6. 人则
  7. 快速结账回调
  8. 错误
  9. 关于int64的注释
  10. 文档
  11. 支持
  12. 许可证

@x-money /核心

X Money API的TypeScript服务器SDK。创建结帐会话,收费链接帐户,发出退款和付款,并验证webhook。

零运行时依赖,仅限ESM, Node 24或更新版本。

npm install @x-money/core

快速启动

import { XMoney } from "@x-money/core";

// The key is always explicit. Read it from wherever you keep secrets; the SDK
// will not pick one up from the environment on its own.
const apiKey = process.env.XMONEY_API_KEY;
if (!apiKey) throw new Error("Missing XMONEY_API_KEY");
const xmoney = new XMoney(apiKey);

const session = await xmoney.checkouts.create({
  line_items: [
    { name: "PlayStation 5", amount: 49999, currency: "USD", quantity: 1 },
  ],
  success_url: "https://example.com/success",
  failure_url: "https://example.com/failure",
  reference: "order-2481",
});

// Send the customer to session.url, or hand it to @x-money/checkout in the
// browser to open it in a popup instead of redirecting.

金额是以货币最小单位表示的整数,所以 49999 是499.99美元。

资源

checkouts, exchanges, accounts, customers, payments, refunds, payouts, settlements, webhooks.

API公开的每个端点在这里都有一个方法。SDK自己的测试套件在两个方向上相互检查,因此如果在下一个版本中没有匹配的方法,就不能将端点添加到API中。

分页

可列出的资源有 list 方法。等待一页,或者 for await 走完每一页。签出会话和帐户交换在API中没有列表。

const firstPage = await xmoney.payouts.list({ limit: 100 });

for await (const payout of xmoney.payouts.list({ limit: 100 })) {
  console.log(payout.id);
}

幂等性

每个POST都携带一个生成的等幂键。传递您自己的命令以确保跨进程重启的重试是安全的,这是您想要的任何由订单id驱动的重试。

await xmoney.refunds.create(
  { payment: "xmpy_...", reference: "refund-order-8471" },
  { idempotencyKey: "refund-order-8471" },
);

测试模式

有了测试钥匙, testOutcome 发送 Xm-Test-Outcome 头强制该请求发生拒绝、过期或授权错误。数量永远不会决定结果。

await xmoney.payments.create(
  { customer_id: "xmcu_...", account_id: "xmac_...", amount: 2437, currency: "USD" },
  { testOutcome: "INSUFFICIENT_FUNDS" },
);

人则

constructEvent 验证 xm-signature 头并返回一个类型化事件。它把 XMoneySignatureVerificationError 错误的签名、格式错误的报头或300秒重放窗口之外的时间戳。

import { XMoney, XMoneyUnknownEventError, XMoneySignatureVerificationError } from "@x-money/core";

app.post("/webhooks", express.raw({ type: "*/*" }), async (req, res) => {
  let event;
  try {
    event = xmoney.webhooks.constructEvent(
      req.body,
      req.headers["xm-signature"],
      process.env.XMONEY_WEBHOOK_SECRET,
    );
  } catch (err) {
    if (err instanceof XMoneyUnknownEventError) return res.status(200).end();
    if (err instanceof XMoneySignatureVerificationError) return res.status(400).end();
    throw err;
  }

  if (event.type === "checkout_session_completed") {
    await fulfillOrder(event.event.merchant_reference);
  }
  res.status(200).end();
});

req.body 必须是未解析的请求体。经过json解析和重新序列化的正文将不匹配签名。表达的需要 express.raw() 在这条路上,而不是 express.json().

无法识别的事件类型是比此包更老的真实投递。抓 XMoneyUnknownEventError 并返回200,否则将重试端点,直到老化为止。

要在测试中签署有效载荷, generateTestHeader 返回一个 xm-signature 价值 constructEvent 将接受:

const header = xmoney.webhooks.generateTestHeader(rawBody, secret);
const event = xmoney.webhooks.constructEvent(rawBody, header, secret);

constructEvent 使用 node:crypto 它是同步的。 constructEventAsync hmac -sign与Web加密(crypto.subtle)而不是 createHmac。相同的参数,相同的错误,并且它接受标头 generateTestHeader 生产。取回 Request 仍然需要 await request.text()。这个包的其余部分仍然是导入的 node:crypto 对于HTTP客户端,所以在Node上运行webhook路由,直到webhook -only导出存在。

const event = await xmoney.webhooks.constructEventAsync(
  await request.text(),
  request.headers.get("xm-signature"),
  process.env.XMONEY_WEBHOOK_SECRET,
);

快速结账回调

结帐会话可以询问客户详细信息,并让您在客户仍在结帐时回答:

const session = await xmoney.checkouts.create({
  line_items: [{ name: "Starter kit", amount: 1986, currency: "USD", quantity: 1 }],
  reference: "order-2481",
  requested_customer_details: ["EMAIL", "SHIPPING_ADDRESS"],
  allowed_shipping_countries: ["US"],
  callback_events: ["CUSTOMER_DETAILS_UPDATED", "CONFIRMATION_REQUESTED"],
});

X Money然后发送到你的回调端点,它与你的webhook端点分开注册,并有自己的回调端点 xmcbsk_ 签署的秘密。 checkout_session_customer_details_updated 当结帐打开时,当客户改变他们的送货地址或电子邮件时,到达;回答这个地址,或者拒绝它。 checkout_session_confirmation_requested 付款时到达,在任何资金流动之前;批准或拒绝订单。客户在等待你的答复,所以在5秒内回复。超时、非200状态或非决策的消息体使该步骤失败,客户可以重试。

app.post("/xmoney/callbacks", express.raw({ type: "*/*" }), (req, res) => {
  let callback;
  try {
    callback = xmoney.callbacks.constructEvent(
      req.body,
      req.headers["xm-signature"],
      process.env.XMONEY_CALLBACK_SECRET,
    );
  } catch {
    return res.status(400).end();
  }

  const address = callback.event.customer_details?.shipping_address;
  if (callback.type === "checkout_session_customer_details_updated") {
    if (address && /^p\.?\s*o\.?\s*box/i.test(address.street)) {
      return res.json(xmoney.callbacks.reject({ field: "SHIPPING_ADDRESS", message: "We can't ship to PO boxes" }));
    }
    return res.json(xmoney.callbacks.approve({ tax_line_items: [{ name: "Sales tax", amount: taxFor(address), currency: "USD" }] }));
  }
  res.json(xmoney.callbacks.approve());
});

approve() 没有税,会议的税不变,只有 checkout_session_customer_details_updated 接受税收。 reject() 没有字段拒绝整个订单。一个 rejected_message 显示给客户,限制为100个字符。 constructEventAsync 和 generateTestHeader 就像他们为webhook做的那样。

错误

错误提出当
XMoneyError基类。每个SDK错误都是一个。
XMoneyMissingApiKeyError没有向构造函数传递API密钥。
XMoneyInvalidApiKeyError关键不是一个 xmsk_test_ / xmsk_prod_ 密钥。
XMoneyInvalidBaseUrlErrorbaseUrl 不是一个绝对URL。
XMoneyAPIErrorAPI返回一个非2xx。带一个标准化的 code, HTTP status, requestId.
XMoneyConnectionError该请求从未得到回应。 code 是 timeout, aborted,或者 network.
XMoneySignatureVerificationError未验证webhook或回调签名,或者签名密钥类型错误(xmwhsk_ 人, xmcbsk_ 回调)。
XMoneyUnknownEventError签名已验证,但此包没有事件的类型。抓住它并返回200。

请求在30秒后超时,并在429秒、5xx秒和网络故障时重试两次,并伴有指数级的回退 Retry-After。两者都是可配置的,每个客户端和每个请求的超时。

const xmoney = new XMoney({
  apiKey,
  timeoutMs: 10_000,
  maxRetries: 5,
  onResponse: ({ requestId, status, method, path }) => {
    console.log(method, path, status, requestId);
  },
});

该包附带了一个嵌入TypeScript源的源映射。节点仅在开始时将其应用于堆栈跟踪 --enable-source-maps,或之后 process.setSourceMapsEnabled(true)。如果没有这些,SDK内部的跟踪就会指向缩小的bundle。

关于int64的注释

API将64位整数序列化为JSON字符串,因为JavaScript数字无法保存较大的值。SDK在输出时将已知的int64字段转换回数字,因此数量和时间戳将如您所期望的那样到达。

metadata 跳过,因此永远不会重写您自己的数据。

文档

指南、API参考和webhook目录在 xmoney.mintlify.site /文档.

让AI编码代理使用此包收集付款:

npx skills add https://xmoney.mintlify.site/docs

浏览器是SDK的一半, @x-money /结帐,呈现Pay with X按钮并打开此包创建的会话。

支持

报告错误并提出问题 X帮助中心。安全问题也是如此;请不要公开发布。

许可证

麻省理工学院。全文在包中作为 LICENSE.

版本与发布记录

@x-money/core 共发布 2 个版本,首次发布于 2026/10/03;过去 12 个月发布了 2 个版本。

版本发布日期距今
0.2.0latest2026/10/304 天前
0.1.02026/10/031 个月前

关于 @x-money/core 的常见问题

@x-money/core 是什么?

用于Node.js的X Money API客户端

如何安装 @x-money/core?

在项目目录运行 npm install @x-money/core,或使用 pnpm add / yarn add / bun add。

@x-money/core 支持 TypeScript 吗?

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

@x-money/core 支持 ESM 还是 CommonJS?

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

@x-money/core 需要什么版本的 Node.js?

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

@x-money/core 可以商用吗?

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

@x-money/core 还在维护吗?

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