npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@obeliskstudio/obelisk-usdt

v0.1.2

Published

ObeliskStudio 通用 USDT-TRC20 支付模块

Readme

ObeliskUSDT

npm version Business Contact Studio Channel

需要定制或开发支付业务,联系 Telegram:@Mhuai8(ObeliskStudio)

ObeliskUSDT 是一个专注 USDT-TRC20 的支付收款模块。
面向开发者提供可快速接入的 USDT 收款能力,支持网站与机器人双端场景。

模块定位很明确:只负责支付链路(下单、收款、链上确认、回调),不侵入宿主业务系统(商品、订单履约、会员发放等)。

私有化部署,资金直达你的钱包。
目标:让团队“少改代码、快速上线”完成 USDT 收款。

项目定位

  • 核心目标:低改造、快接入、可扩展
  • 适用对象:机器人项目、网站项目、SaaS、内容订阅、工具类付费功能
  • 设计原则:支付模块独立,宿主业务解耦,避免后续维护互相牵连

为什么选择 ObeliskUSDT

  • API 优先:通过 HTTP 路由快速接入,不绑定你的业务框架
  • 自托管可控:部署在你自己的服务环境,数据与资金链路可审计
  • 全流程闭环:下单、二维码、扫链、确认、回调一体化
  • 双端复用:网页和机器人共用一套支付核心逻辑
  • 对账友好:支持 bizOrderNo 透传,方便和宿主业务单关联

特性

  • 支持网页与机器人两种支付入口
  • 创建订单、生成二维码、链上扫描、确认回调全流程
  • 交易哈希去重,避免重复入账
  • 订单归属校验,用户仅可查询/取消自己的订单
  • 支持宿主业务订单号透传:bizOrderNo
  • 核心数据表统一 obl_ 前缀,避免与宿主冲突

适用场景

  • 你已有业务系统,只缺一个可落地的 USDT 收款能力
  • 你希望机器人和网页共用同一套支付后端
  • 你需要区分“业务订单号”和“支付订单号”,便于对账与审计
  • 你希望后续可按项目扩展,不被单体支付逻辑绑死

边界职责(非常重要)

  • 本模块负责:
    • 生成支付订单与收款金额
    • 分配收款钱包并返回支付二维码
    • 扫链确认交易并更新支付状态
    • 触发 onOrderConfirmed 回调
  • 宿主项目负责:
    • 商品、定价、库存、会员时长等业务规则
    • 权益发放(必须幂等)
    • 用户系统与权限体系
    • 财务对账策略与内部报表

依赖要求

  • Node.js 18+
  • Sequelize(推荐,模块运行依赖;宿主可继续使用 TypeORM)
  • Redis
  • TronGrid / TronScan API Key

与同类网关的定位差异

  • 我们不是通用商城系统,而是“可嵌入的支付能力模块”
  • 我们不接管你的商品与履约逻辑,只处理支付本身
  • 我们强调“稳定可维护”与“可复制接入”

安装与获取

npm 安装(推荐)

npm i @obeliskstudio/obelisk-usdt

在线使用(生产推荐)

你可以直接在宿主项目通过 npm 在线拉取并使用,不需要 clone 本仓库:

npm i @obeliskstudio/obelisk-usdt@latest

安装后可用以下命令确认版本:

npm ls @obeliskstudio/obelisk-usdt

包地址:

  • https://www.npmjs.com/package/@obeliskstudio/obelisk-usdt

5 分钟接入清单

  1. 准备数据库并执行迁移脚本(推荐使用内置迁移执行器)。
  2. 在宿主项目中初始化 initObeliskUSDT(...)
  3. 挂载 paymentRouteradminRouter
  4. 配置并启动扫描器:startScanner()
  5. 实现 onOrderConfirmed 幂等发放逻辑。
  6. 管理端先添加收款钱包,再开放支付入口。

数据库迁移(推荐)

包内提供 runObeliskUSDTMigrations(),用于自动执行 database/migrations/*.sql

import { runObeliskUSDTMigrations } from '@obeliskstudio/obelisk-usdt';

await runObeliskUSDTMigrations({
  sequelize,
  logger,
});

说明:

  • 会自动创建迁移记录表:obl_usdt_schema_migrations
  • 已执行迁移会自动跳过
  • 不会在 initObeliskUSDT() 时自动改库,需由宿主在部署/启动阶段主动调用

示例目录(当前状态)

仓库提供与当前接口契约一致的最小示例:

  • examples/backend/host-init.ts:宿主后端初始化与路由挂载
  • examples/backend/payment-api-client.ts:服务端创建/查询/取消支付订单
  • examples/web/create-and-poll.ts:网页端创建订单并轮询支付状态
  • examples/bot/create-order-with-qr.ts:机器人创建订单并发送二维码
  • examples/README.md:示例使用说明

示例按当前字段与路由编写,可直接作为接入参考。

快速接入

import { initObeliskUSDT } from '@obeliskstudio/obelisk-usdt';

const usdt = initObeliskUSDT({
  sequelize,
  redis,
  logger,
  config: {
    network: 'mainnet',
    webUrl: process.env.WEB_URL || '',
    botUsername: process.env.BOT_USERNAME || '',
    trongridApiKey: process.env.TRONGRID_API_KEY,
    tronscanApiKey: process.env.TRONSCAN_API_KEY,
    apiAuthToken: process.env.OBL_USDT_API_AUTH_TOKEN || '',
  },
  authMiddleware: {
    optional: optionalAuth,
    required: requireAuth,
    admin: requireAdminAuth,
  },
  onOrderConfirmed: async (order) => {
    // 宿主发放逻辑(必须幂等)
    await benefitService.grantByOrderNo(order.orderNo);
  },
});

app.use('/api', usdt.paymentRouter);
app.use('/api', usdt.adminRouter);

await usdt.startScanner();
usdt.registerScheduledTasks(cron);

完整支付流程(宿主视角)

  1. 宿主先创建业务订单,得到 bizOrderNo
  2. 调用 POST /payment/create 创建支付订单,返回 orderNo、金额、钱包地址、二维码。
  3. 用户转账后,扫描器监听链上交易并匹配订单。
  4. 状态按 pending -> paid -> confirmed -> completed 推进。
  5. 到达确认阈值后触发 onOrderConfirmed
  6. 宿主在回调里做幂等发放,并记录发放日志。

支付接口

用户接口:

  • POST /payment/create
  • GET /payment/status/:orderNo
  • POST /payment/cancel/:orderNo

管理接口:

  • /admin/payment/wallets/*
  • /admin/payment/orders/*
  • /admin/payment/network*

创建订单参数

{
  "bizOrderNo": "HOST-ORDER-10001",
  "baseAmount": "99.00",
  "ts": 1700000000,
  "nonce": "e1b4f0f3b7d24e62a3d6c9f78b7a4b12",
  "metadata": { "biz": "obeliskcard", "plan": "vip_year" },
  "signature": "请看下方签名算法"
}

字段说明:

  • bizOrderNo:必填,宿主业务订单号(用于对账与幂等发放)
  • baseAmount:必填,支付基准金额(> 0,最多 2 位小数,建议用字符串传)
  • ts:必填,签名时间戳(支持秒或毫秒)
  • nonce:必填,签名随机串(建议 16-32 字节 hex)
  • metadata:可选,宿主自定义字段(用于对账与回调发放)
  • signature:必填,HMAC-SHA256 签名

说明:

  • POST /payment/create 会返回 orderToken
  • bizOrderNo 幂等:同一 bizOrderNo 在“未过期 + 状态仍在支付中”时重复调用创建接口,会返回同一笔订单,不会重复创建与重复占用金额。
  • 查询/取消订单时,需要带上 orderToken
    • Header:x-obl-order-token: <orderToken>
    • 或 Query:?token=<orderToken>

签名算法(HMAC-SHA256)

POST /payment/create 默认要求签名,防止创建接口被刷单与参数被篡改。

同时启用 ts + nonce 防重放:

  • ts 超出允许时间窗口会拒绝(默认 300 秒,可通过 apiSignMaxSkewSeconds 调整)
  • nonce 会写入 Redis(SET NX EX),按 bizOrderNo + nonce 作用域防重放
  • 签名比较使用 crypto.timingSafeEqual,降低时序侧信道风险

签名步骤:

  1. 从请求体中取这些字段参与签名(字段不存在或为空字符串则跳过):

bizOrderNo, baseAmount, ts, nonce, metadata

  1. 将参与签名字段按 key 的 ASCII 字典序排序,拼成 key=value&key=value 的字符串。
  2. value 会做 encodeURIComponent,其中 metadata 会先做稳定 JSON 序列化。
  3. 使用 apiAuthToken 作为密钥,对拼接后的字符串做 HMAC-SHA256,输出 hex 小写,作为 signature。 签名示例(Node.js):
import crypto from 'crypto';

function stableStringify(value: any): string {
  if (value === null || value === undefined) return '';
  if (typeof value === 'string') return JSON.stringify(value);
  if (typeof value === 'number') return JSON.stringify(Number.isFinite(value) ? value : null);
  if (typeof value === 'boolean') return JSON.stringify(value);
  if (Array.isArray(value)) return `[${value.map((v) => stableStringify(v)).join(',')}]`;
  if (typeof value === 'object') {
    const keys = Object.keys(value).sort();
    return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(',')}}`;
  }
  return JSON.stringify(String(value));
}

export function buildSignature(payload: any, apiAuthToken: string) {
  const picked: Record<string, string> = {};
  const fields = ['bizOrderNo', 'baseAmount', 'ts', 'nonce'];
  for (const f of fields) {
    const v = payload?.[f];
    const s = v === undefined || v === null ? '' : String(v).trim();
    if (s) picked[f] = s;
  }
  if (payload?.metadata && typeof payload.metadata === 'object') {
    const raw = stableStringify(payload.metadata);
    if (raw && raw !== '{}' && raw !== '[]') picked.metadata = raw;
  }

  const canonical = Object.keys(picked)
    .sort()
    .map((k) => `${k}=${encodeURIComponent(picked[k])}`)
    .join('&');

  return crypto.createHmac('sha256', apiAuthToken).update(canonical).digest('hex');
}

网页接入建议

  • 前端创建订单后展示二维码和倒计时
  • 轮询 GET /payment/status/:orderNo 刷新状态
  • 超时后提供“重新下单”与“联系客服”入口
  • 支付成功页展示 orderNobizOrderNo 便于排查

机器人接入示例

const result = await usdt.bot.createOrderWithQR({
  bizOrderNo: 'HOST-ORDER-10001',
  baseAmount: '99.00',
  metadata: { scene: 'bot' },
});

await bot.sendPhoto(chatId, result.qrPngBuffer, {
  caption: `订单号: ${result.orderNo}\n金额: ${result.actualAmount} USDT\n地址: ${result.walletAddress}`,
});

上线前检查清单

  • 已添加至少 2 个可用收款钱包(避免单点故障)
  • onOrderConfirmed 已做幂等保护(防重复发放)
  • 扫描器、任务调度已启动并可观测
  • .env 已配置 API Key,代码中无硬编码密钥
  • 对外查询/取消订单时,orderToken 必须作为校验凭证

安全基线

  • 查询/取消接口必须校验订单归属
  • onOrderConfirmed 发放逻辑必须幂等
  • 密钥必须使用环境变量,禁止硬编码
  • 扫描器对第三方链上接口启用短熔断降频,避免外部抖动拖垮主流程

性能与稳定性优化

  • 钱包扫描启用固定并发池,提升多钱包场景吞吐。
  • 扫描配置启用短缓存,减少高频配置读取开销。
  • 扫描间隔自适应:有交易提速,无交易降频。
  • 订单确认使用异步回调队列(重试 + 死信),避免慢回调阻塞主扫描链路。
  • 管理统计接口 GET /admin/payment/stats 返回扫描器健康指标(熔断与队列状态)。

数据表

  • obl_payment_wallets
  • obl_payment_orders
  • obl_payment_transactions

订单状态流转

pending -> paid -> confirmed -> completed

使用说明

  • 详细接入文档:docs/使用说明-接入文档.md
  • 建议先看“用户使用流程(含加钱包)”章节再上线

版权与联系

  • Copyright © 2026 ObeliskStudio. All rights reserved.
  • 维护者:@Mhuai8(ObeliskStudio)
  • 作者邮箱:[email protected] / [email protected]
  • 工作室 Telegram:@ObeliskStudio
  • 工作室业务:承接定制开发、支付系统、机器人、网站与各类技术外包合作
  • 业务合作:需要定制或开发,联系 @Mhuai8