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

@qzsy/unipay-sdk

v0.1.3

Published

统一支付网关服务端 TypeScript SDK

Downloads

385

Readme

@qzsy/unipay-sdk

统一支付网关的服务端 TypeScript SDK。其他应用只放 应用密钥标识 + 服务端密钥,由本包处理访问令牌、防重放键和 application/problem+json

业务对接步骤、参数、出入包和 Agent 集成指令见 docs/业务对接.md,控制台可交互版在 /user/docs

金额单位是 CNY 分。密钥和通知签名密钥只能放业务服务端,不要进浏览器或小程序。

安装

npm i @qzsy/unipay-sdk

bun add @qzsy/unipay-sdk

两条接入路径

托管收银台: 业务只建单,用户跳到网关页面选方式并付款。适合网站、多业务共用一个公众号支付目录。

直连调起: 业务自己的 H5 / 小程序 / App 调起支付。网关返回 next_action(微信 JSAPI / 小程序 / App、支付宝 trade_no / order_string)。这是微信统一下单的等价物,不必跳收银台

import { UnifiedPay } from '@qzsy/unipay-sdk'

const pay = new UnifiedPay({
  baseUrl: process.env.UNIFIEDPAY_BASE_URL!, // 例如 http://127.0.0.1:3000
  clientId: process.env.UNIFIEDPAY_CLIENT_ID!,
  clientSecret: process.env.UNIFIEDPAY_CLIENT_SECRET!,
})

// 路径 A:打开托管收银台
const { checkout } = await pay.createHostedCheckout({
  intent: {
    merchant_order_no: 'ord_1001',
    amount: { value: 199 },
    subject: '会员充值',
    return_url: `https://shop.example.com/pay/result?order=ord_1001`,
    notify_url: 'https://shop.example.com/webhooks/pay',
  },
})
// 把 checkout.checkout_url 发给用户打开

// 路径 B:业务前端自己调起(小程序 / JSAPI / App)
const { attempt } = await pay.createDirectPayment({
  intent: {
    merchant_order_no: 'ord_1002',
    amount: { value: 199 },
    subject: '会员充值',
    notify_url: 'https://shop.example.com/webhooks/pay',
  },
  payer: {
    provider: 'WECHAT',
    identifier: openid, // 业务后端用 code 换到的身份
  },
  attempt: {
    provider: 'WECHAT',
    interaction: 'MINI_PROGRAM',
  },
})
// 把 attempt.next_action 交给前端:executeAction 或 wx.requestPayment / my.tradePay

先在控制台登记回跳和通知的站点前缀。下单传完整 return_url / notify_url(可带查询参数),须与已登记地址同协议、同主机,路径落在前缀下。有 notify_url 时只投这一单指定地址,签名仍用匹配端点那把密钥。不传 URL 且应用只有一条登记时,网关用那一条。币种默认 CNY,订单默认 30 分钟过期。

写操作会自动带 Idempotency-Key。同一笔业务重试时请自己传入同一个键(不要含 :):

import { createIdempotencyKey } from '@qzsy/unipay-sdk'

await pay.createIntent(input, { idempotencyKey: createIdempotencyKey() })

通知验签

网关请求头:webhook-id / webhook-timestamp / webhook-signaturev1, + HMAC-SHA256 base64)。

import { verifyWebhook } from '@qzsy/unipay-sdk'

const event = verifyWebhook({
  secret: process.env.UNIFIEDPAY_WEBHOOK_SECRET!,
  headers: request.headers,
  rawBody: await request.text(),
})

if (event.type === 'com.unifiedpay.payment.succeeded.v1') {
  // 先按 event.id 去重,再查自己的订单并履约
}

验签只证明报文真实完整,不代替业务去重和查单。notify_url 即使带了查询参数,密钥也不变。

createRefund 也可传 notify_url;不传则用原单地址。公众号授权回跳用 oauth_return_url,规则与 return_url 相同。

其它常用方法

| 方法 | 对应接口 | | --- | --- | | capabilities | GET /api/v1/payment-capabilities | | createIntent / getIntent / listIntents | /api/v1/payment-intents | | createDirectPayment | 建意图 + 可选导入身份 + 发起尝试,返回 next_action | | createCheckoutSession | POST /api/v1/checkout-sessions | | createAttempt / getAttempt | 支付尝试 | | cancelIntent / reverseAttempt | 关单 / 付款码撤销 | | createRefund / getRefund | 退款 | | readCheckout | 用收银台只读令牌查状态 |

浏览器 / 小程序侧用 @qzsy/unipay-sdk/browseropenCheckout 打开托管页;executeAction(next_action)sdk 调起微信 JSAPI、wx.requestPayment、支付宝 H5 / my.tradePay。App 参数(WECHAT_APP / ALIPAY_APP)交给原生 SDK,浏览器里会返回 UNSUPPORTED。不要把 clientSecret 带到前端。

微信内 H5 若要在业务自己的页面调 JSAPI,该页必须在微信支付授权目录里;否则请走托管收银台。小程序和 App 没有这个限制。

错误

失败会抛 GatewayErrorcodedetailretryablerequestIdretryable === true 时只能用同一防重放键 / 同一业务单号重试,不能另开一笔扣款。

本地试跑

开发服务起来后:

UNIFIEDPAY_CLIENT_SECRET=演示服务端密钥 bun packages/sdk/examples/checkout.ts
UNIFIEDPAY_CLIENT_SECRET=演示服务端密钥 bun packages/sdk/examples/direct-pay.ts

密钥在管理端「支付网关 → 开发者中心」复制。本机优先 http://127.0.0.1:3000;若只监听了 IPv6,改用 http://localhost:3000