@bsv/payment-express-middleware

中文文档
2.1.11发布于 2026/10/28SEE LICENSE IN LICENSE.txtTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 1.6万

BSV Blockchain service monetization express middleware

原始使用文档
文档目录14 节
  1. Requirements
  2. Install
  3. Basic use
  4. Flow
  5. Options
  6. Replay storage
  7. Payment receipt
  8. Error behavior
  9. Public services and browser access
  10. Security notes
  11. API
  12. Development
  13. License
  14. SDK4 hotfix peer requirement

@bsv/payment-express-middleware

Patch candidate 2.1.11 updates packed first-party runtime or development dependency ranges. This metadata-only patch preserves public APIs, peer ranges, wire formats and defaults. No additional consumer or data migration is required; earlier migration guidance still applies.

Express middleware for the legacy authenticated x-bsv-payment JSON flow. It runs after @bsv/auth-express-middleware, issues an HTTP 402 challenge, validates an Atomic BEEF transaction, atomically rejects reused transaction IDs, internalizes output zero, and exposes a verified payment receipt.

This protocol is distinct from the newer BRC-121 implementation in @bsv/402-pay. Choose one protocol deliberately; their headers and client contracts are not interchangeable.

Version 2.1.8 removes middleware payment-header size ceilings. A header already received from the client is parsed and its payment validated regardless of size. HTTP server, CDN, proxy and WAF configuration own transport budgets; configure and validate the full route for supported payment proofs. The deprecated maxPaymentHeaderBytes option remains accepted for source compatibility but is ignored, including when an older application still supplies a value. Move any intended transport policy to the HTTP server or edge and remove the option.

Atomic BEEF validation, canonical base64, derivation verification, payment pricing, wallet acceptance and atomic replay protection still apply. Invalid payment contents are rejected. SDK 2.8.5 separately raises client header capacity; that does not constrain what this middleware accepts from other compatible clients. No BRC100 call, wire or wallet-data migration is required. Source publication is a separate protected release step.

Requirements

  • Node.js 22 or newer
  • Express 4.18 or newer, including Express 5
  • @bsv/auth-express-middleware earlier in the middleware chain
  • A BRC-100 wallet implementing internalizeAction

The package ships native ESM and CommonJS entry points with declarations for both module systems.

Install

npm install @bsv/payment-express-middleware @bsv/auth-express-middleware @bsv/sdk express

Express is a peer dependency, so the middleware uses the application's single Express runtime and type graph. This prevents duplicate Express installations from making PaymentRequest or the returned middleware incompatible with the application's route types.

Basic use

import express from 'express'
import { createAuthMiddleware } from '@bsv/auth-express-middleware'
import { createPaymentMiddleware, type PaymentRequest } from '@bsv/payment-express-middleware'

const app = express()

app.use(express.json())
app.use(createAuthMiddleware({ wallet }))
app.use(
  createPaymentMiddleware({
    wallet,
    calculateRequestPrice(req) {
      if (req.path === '/free') return 0
      if (req.path === '/premium') return 500
      return 100
    },
    replayStore
  })
)

app.get('/premium', (req: PaymentRequest, res) => {
  res.json({
    accepted: req.payment?.accepted,
    satoshisPaid: req.payment?.satoshisPaid,
    txid: req.payment?.txid
  })
})

Prices must be 0 or a positive safe integer. Zero-cost requests continue with an accepted zero-value receipt. Invalid or failed pricing returns a stable 500 response and never authorizes the request.

Flow

  1. Auth middleware verifies the peer and supplies a compressed req.auth.identityKey.

  2. calculateRequestPrice returns the required satoshis.

  3. If no x-bsv-payment header is present, the middleware returns 402 with:

    • x-bsv-payment-version: 1.0
    • x-bsv-payment-satoshis-required
    • x-bsv-payment-derivation-prefix
  4. The client retries with one JSON header:

    {
      "derivationPrefix": "<canonical-base64>",
      "derivationSuffix": "<canonical-base64>",
      "transaction": "<base64-atomic-beef>"
    }
    
  5. The middleware parses the received header, verifies the derivation prefix, parses the Atomic BEEF transaction, reduces legacy overinclusive envelopes to the declared subject and its dependency closure, and requires output zero to cover the current price.

  6. The wallet must validate and newly accept the remittance with { accepted: true } from internalizeAction. Merge/replay-like or malformed results do not authorize the route.

  7. Only after wallet validation does the middleware atomically claim the transaction ID. This prevents invalid derivation material paired with a public transaction from poisoning the replay store.

  8. next() runs with req.payment, and x-bsv-payment-satoshis-paid reports the actual output value.

Wallet verdicts must expose accepted and optional isMerge as own data properties; inherited or accessor-backed authority is rejected without invoking accessors. Malformed, duplicate, underfunded, rejected, or ambiguous payments never call next.

Options

const payment = createPaymentMiddleware({
  wallet,
  calculateRequestPrice,
  replayStore,
  logger
})
  • wallet is required and must provide internalizeAction.
  • calculateRequestPrice may be synchronous or asynchronous and defaults to 100 satoshis.
  • replayStore must implement an atomic claim(transactionId): boolean | Promise<boolean>. It returns false if the transaction has already been used.
  • maxPaymentHeaderBytes is deprecated and ignored; header budgets belong to the HTTP server or edge.
  • logger may provide error and warn methods. Internal failures are sent to it as structured context but are never exposed in HTTP responses.

Invalid option types fail during startup.

Replay storage

InMemoryPaymentReplayStore is the safe single-process default. It:

  • atomically claims each transaction ID once within one process;
  • records only transactions the wallet reported as newly accepted;
  • refuses new claims when its fixed capacity is reached rather than evicting an older replay marker; and
  • loses all claims when the process restarts.

Its default capacity is 100,000 claims. It is appropriate for tests and bounded single-process services, not a horizontally scaled or durable deployment.

Production services should inject a shared durable store backed by a database or cache primitive with atomic insert-if-absent semantics:

const replayStore = {
  async claim(transactionId: string) {
    return await database.insertPaymentClaimIfAbsent(transactionId)
  }
}

Do not implement claim as separate read and write operations. Keep replay claims for at least as long as a transaction could otherwise be accepted again. A derivation nonce proves that the server created the prefix; it is not an expiring, single-use replay database.

Payment receipt

After authorization:

interface PaymentReceipt {
  satoshisPaid: number
  accepted: true
  tx: string
  txid: string
}

satoshisPaid is the actual value of output zero, which may be greater than the required price. For free requests it is zero and tx/txid are empty.

Error behavior

StatusCodeMeaning
400ERR_MALFORMED_PAYMENTThe header is duplicated, oversized, invalid JSON, or has invalid fields
400ERR_INVALID_DERIVATION_PREFIXThe server did not create the supplied prefix
400ERR_INVALID_PAYMENTAtomic BEEF is invalid or output zero is underfunded
400ERR_PAYMENT_FAILEDThe wallet could not accept the payment
402ERR_PAYMENT_REQUIREDA payment challenge was issued
409ERR_PAYMENT_REPLAYEDThe transaction was already claimed or was not newly accepted
500ERR_SERVER_MISCONFIGUREDAuth middleware did not provide a valid identity
500ERR_PAYMENT_INTERNALPricing failed or returned an invalid value
503ERR_PAYMENT_UNAVAILABLEChallenge creation or replay storage is unavailable

Public errors deliberately omit wallet, replay-store, and pricing exception messages.

Public services and browser access

This middleware does not impose CORS or CSP. Public payment services can remain cross-origin by default while operators optionally configure an allowlist at the application or edge layer. Browser clients need the x-bsv-payment-* response headers exposed through CORS. Never pair a wildcard origin with credentialed CORS.

Security notes

  • Use HTTPS; payment and identity headers are not a confidentiality layer.
  • Run authentication first and authorization/payment routes after both middleware functions.
  • Use a durable atomic replay store for multiple processes or replicas.
  • Wallet errors and rejected remittances are never inserted into the replay store; investigate an unavailable replay store promptly because the wallet may already have accepted the transaction before that independent gate.
  • Monitor 409 and 503 rates and replay-store capacity.
  • Treat pricing as security-sensitive, deterministic request policy.
  • The wallet remains responsible for validating and safely internalizing the supplied BRC-29 remittance.
  • Apply normal request/header limits and rate limiting at the service edge.
  • Logger failures are contained and cannot interrupt payment authorization or change the HTTP result.

API

Runtime exports:

  • createPaymentMiddleware
  • InMemoryPaymentReplayStore

Type exports:

  • BSVPayment
  • PaymentLogger
  • PaymentMiddlewareOptions
  • PaymentReceipt
  • PaymentReplayStore
  • PaymentRequest

See API.md for generated signatures.

Development

pnpm typecheck
pnpm lint
pnpm format:check
pnpm test:coverage
pnpm pack:check

The test suite is deterministic and does not call public APIs. pack:check builds and validates the exact npm tarball in ESM and CommonJS consumer probes. Tests do not rebuild the package as a side effect.

License

Current TS Stack changes are licensed under the Open BSV License Version 6; see LICENSE.txt. This package also retains pre-uniformization code under the Open BSV License Version 4. Redistributors must preserve THIRD_PARTY_NOTICES.md and the applicable text in LICENSES/.

SDK4 hotfix peer requirement

The SDK4 peer alternative starts at @bsv/sdk ^4.0.1, which restores numeric wallet results and legacy wire compatibility. Existing SDK2/3 alternatives and lower bounds remain unchanged. SDK4 users should install the 4.0.1 hotfix; no application-wallet wire or data migration is required.

版本与发布记录

@bsv/payment-express-middleware 共发布 27 个版本,首次发布于 2025/01/07;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.1.11latest2026/10/2811 天前
2.1.102026/10/2415 天前
2.1.92026/10/031 个月前
2.1.82026/09/251 个月前
2.1.72026/09/231 个月前
2.1.62026/08/282 个月前

其他发布通道:next → 2.0.0-beta.0。

关于 @bsv/payment-express-middleware 的常见问题

@bsv/payment-express-middleware 是什么?

BSV Blockchain service monetization express middleware

如何安装 @bsv/payment-express-middleware?

在项目目录运行 npm install @bsv/payment-express-middleware,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:express(>=4.18.0 <6)、@bsv/sdk(^2.1.6 || ^3.0.0 || ^4.0.1)、@types/express(>=4.17.0 <6)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@bsv/payment-express-middleware 支持 TypeScript 吗?

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

@bsv/payment-express-middleware 支持 ESM 还是 CommonJS?

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

@bsv/payment-express-middleware 需要什么版本的 Node.js?

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

@bsv/payment-express-middleware 可以商用吗?

@bsv/payment-express-middleware 使用 SEE LICENSE IN LICENSE.txt 许可。许可条款写在包内的独立文件中,请阅读该文件确认可否商用。以上为概括,不构成法律意见,请以许可原文为准。

@bsv/payment-express-middleware 的下载量有多少?

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

@bsv/payment-express-middleware 还在维护吗?

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