@douyinpay_sdk/douyinpay-nodejs
v1.0.1
Published
Douyin Pay server-side SDK for Node.js
Readme
douyinpay-nodejs
抖音支付 Node.js 服务端 SDK。
本 SDK 使用 TypeScript 实现,HTTP Client 基于 urllib,同时支持 CommonJS 与 ESM 引入方式。
安装
npm install @douyinpay_sdk/douyinpay-nodejs快速开始
ESM
import { createAutoClientRSA } from '@douyinpay_sdk/douyinpay-nodejs';
const sdk = await createAutoClientRSA({
mchid: 'your_mchid',
serial: 'your_merchant_cert_serial',
privateKey: process.env.DOUYINPAY_PRIVATE_KEY!,
encryptKey: process.env.DOUYINPAY_API_ENCRYPT_KEY!,
});CommonJS
const { createClientRSA } = require('@douyinpay_sdk/douyinpay-nodejs');
const { readFileSync } = require('node:fs');
const sdk = createClientRSA({
mchid: 'your_mchid',
serial: 'your_merchant_cert_serial',
privateKey: process.env.DOUYINPAY_PRIVATE_KEY,
platformCertificate: readFileSync('/path/to/douyinpay_platform_certificate.pem', 'utf8'),
});核心入口与依赖关系
SDK 对外入口统一从包根导出。业务代码通常只需要关注三类入口:初始化 client、调用 API、处理证书/回调。
| 入口 | 作用 | 依赖 | 说明 |
| --- | --- | --- | --- |
| createClientRSA(options) | 用本地平台证书/平台公钥初始化 client | mchid、商户证书 serial、商户 privateKey、platformCertificate | 本地已持有平台证书,或希望自己管理证书文件 |
| createAutoClientRSA(options) | 自动下载平台证书后初始化 client,并支持后台刷新 | mchid、商户证书 serial、商户 privateKey、接口加密 encryptKey | 希望 SDK 管理平台证书下载、缓存和刷新 |
| sdk.getClient(path) | 获取某个接口路径的请求 client | 已初始化的 sdk | 下单、查单、退款等接口都通过它发起请求 |
| downloadPlatformCertificates(options) | 单独下载平台证书 | mchid、商户证书 serial、商户 privateKey、接口加密 encryptKey | 只想下载证书并自行管理时使用 |
| parseCallback(...) / CallbackHandler | 回调通知验签与解密 | 平台证书或自动证书管理器、接口加密 encryptKey、原始 headers/body | 支付、退款等异步通知处理 |
依赖关系简述:
商户配置
├─ 本地证书模式:createClientRSA
│ └─ 使用传入的平台证书/公钥做响应验签
│ └─ sdk.getClient(path) 调用下单、查单、退款等 API
│
└─ 自动证书模式:createAutoClientRSA
└─ AutoCertificateManager
├─ downloadPlatformCertificates 下载并解密平台证书
├─ 内存缓存平台证书
└─ sdk.getClient(path) 调用 API 时使用最新证书做响应验签
回调处理
└─ parseCallback / CallbackHandler
├─ 使用平台证书验签回调原始 body
└─ 使用接口加密密钥 encryptKey 解密 resource说明:
DouyinPaySdk是底层 SDK 对象,推荐业务代码优先使用createClientRSA或createAutoClientRSA初始化。
Client 初始化方式
SDK 目前提供两种 RSA client 初始化方式。两种方式创建出的 sdk 都是同一个调用入口,后续下单、查单、退款等 API 调用方式完全一致。
1. 本地单证书初始化
适合你已经在本地持有抖音支付平台证书,或希望证书文件完全由业务系统自行管理的场景。
必填项:
mchid:商户号serial:商户证书序列号,用于请求签名头privateKey:商户私钥 PEM 内容platformCertificate:抖音支付平台证书 PEM 内容;也支持平台公钥内容
如果 platformCertificate 是完整证书 PEM,SDK 会自动解析平台证书序列号;如果传入的是平台公钥内容,则必须额外传 platformSerial。
import { readFileSync } from 'node:fs';
import { createClientRSA } from '@douyinpay_sdk/douyinpay-nodejs';
const sdk = createClientRSA({
mchid: 'your_mchid',
serial: 'your_merchant_cert_serial',
privateKey: readFileSync('/path/to/merchant_private_key.pem', 'utf8'),
platformCertificate: readFileSync('/path/to/douyinpay_platform_certificate.pem', 'utf8'),
});如果只传平台公钥,需要同时指定平台证书序列号:
const sdk = createClientRSA({
mchid: 'your_mchid',
serial: 'your_merchant_cert_serial',
privateKey: process.env.DOUYINPAY_PRIVATE_KEY!,
platformCertificate: process.env.DOUYINPAY_PLATFORM_PUBLIC_KEY!,
platformSerial: 'your_platform_cert_serial',
});这种方式不会自动下载平台证书;响应验签使用初始化时传入的证书或公钥。
2. 自动下载平台证书初始化
适合服务端长期运行使用。初始化时不需要传平台证书,SDK 会调用平台证书下载接口,用接口加密密钥解密平台证书,并按配置定时刷新证书。响应验签失败时会直接抛错,不会在验签链路中触发证书下载补偿。
必填项:
mchid:商户号serial:商户证书序列号,用于请求签名头privateKey:商户私钥 PEM 内容encryptKey:接口加密密钥,用于解密平台证书下载接口返回的证书内容
import { readFileSync } from 'node:fs';
import { createAutoClientRSA } from '@douyinpay_sdk/douyinpay-nodejs';
const sdk = await createAutoClientRSA({
mchid: 'your_mchid',
serial: 'your_merchant_cert_serial',
privateKey: readFileSync('/path/to/merchant_private_key.pem', 'utf8'),
encryptKey: 'your_api_encrypt_key',
// 可选:默认 24 小时后台刷新一次;传 0 可关闭定时刷新。
refreshIntervalMs: 24 * 60 * 60 * 1000,
});自动下载的证书会缓存在当前进程内存中,不会由 SDK 自动写入本地文件。
两种初始化方式创建出的 sdk 调用 API 的方式完全一致:
const response = await sdk
.getClient('/v1/trade/transactions/native')
.post(requestBody);API 调用
SDK 的接口调用方式与常见 Node.js 支付 SDK 类似:先创建 client,然后通过 getClient(path) 获取指定接口客户端。
const client = sdk.getClient('/your/api/path');
await client.get(options);
await client.post(data, options);
await client.put(data, options);
await client.patch(data, options);
await client.delete(options);SDK 会自动完成:
- 请求签名
Authorization头生成Douyinpay-Sdk-Agent客户端版本上报- HTTP 请求发送
- 抖音支付响应验签
回调通知验签与解密
收到抖音支付回调后,应先使用平台证书对原始请求体进行验签,验签通过后再解密 resource。SDK 提供 parseCallback 和 CallbackHandler 两种入口。
使用本地平台证书
import { parseCallback } from '@douyinpay_sdk/douyinpay-nodejs';
const notify = await parseCallback(
request.headers,
rawBody,
{
encryptKey: 'your_api_encrypt_key',
certs: {
your_platform_cert_serial: platformCertificatePem,
},
},
);
console.log(notify.event_type);
console.log(notify.content); // resource 解密后的业务内容使用自动证书管理器
如果传入 certificateProvider,SDK 会使用其中当前已缓存的平台证书参与回调验签;回调验签失败会直接抛错,不会触发证书下载补偿。
import { CallbackHandler, createAutoClientRSAWithManager } from '@douyinpay_sdk/douyinpay-nodejs';
const { sdk, certificateManager } = await createAutoClientRSAWithManager({
mchid: 'your_mchid',
serial: 'your_merchant_cert_serial',
privateKey: merchantPrivateKeyPem,
encryptKey: 'your_api_encrypt_key',
});
const handler = new CallbackHandler({
encryptKey: 'your_api_encrypt_key',
certificateProvider: certificateManager,
});
const notify = await handler.parse(request.headers, rawBody);createAutoClientRSAWithManager 与 createAutoClientRSA 使用同一套 AutoClient 初始化逻辑,只是额外返回 certificateManager,便于回调验签复用已初始化并定时刷新的平台证书。
sdk 可继续用于下单、查单、退款等 API 调用。
验签使用的原文格式为:
timestamp + "\n" + nonce + "\n" + body + "\n"当前 Node.js SDK 支持 AEAD_AES_256_GCM 回调资源解密。
1. 下单
当前示例使用 Native 下单接口:
POST /v1/trade/transactions/nativeconst outTradeNo = `ORDER_${Date.now()}`;
const response = await sdk
.getClient('/v1/trade/transactions/native')
.post({
mchid: 'your_mchid',
appid: 'your_appid',
description: '抖音支付测试订单',
out_trade_no: outTradeNo,
time_expire: new Date(Date.now() + 10 * 60 * 1000).toISOString(),
notify_url: 'https://www.example.com/douyinpay/notify',
attach: '',
amount: {
currency: 'CNY',
total: 1,
},
ip: '127.0.0.1',
});
console.log(response.status);
console.log(response.data);返回示例:
{
"code_url": "https://qr.douyinpay.com/xxxxx"
}2. 查单
通过商户订单号查询订单:
GET /v1/trade/transactions/out-trade-no/{out_trade_no}?mchid={mchid}const response = await sdk
.getClient(`/v1/trade/transactions/out-trade-no/${encodeURIComponent(outTradeNo)}`)
.get({
query: {
mchid: 'your_mchid',
},
});
console.log(response.status);
console.log(response.data);返回示例:
{
"mchid": "your_mchid",
"appid": "your_appid",
"out_trade_no": "ORDER_123456",
"trade_state": "NOTPAY",
"trade_state_desc": "未支付"
}3. 平台证书下载
平台证书用于校验抖音支付响应签名。证书下载接口本身也需要商户私钥签名,请求成功后返回加密证书,SDK 会使用接口加密密钥进行 AES-256-GCM 解密。
import { readFileSync } from 'node:fs';
import { downloadPlatformCertificates } from '@douyinpay_sdk/douyinpay-nodejs';
const certificates = await downloadPlatformCertificates({
mchid: 'your_mchid',
serial: 'your_merchant_cert_serial',
privateKey: readFileSync('/path/to/merchant_private_key.pem', 'utf8'),
// 首次下载证书时还没有可信平台证书,可传 bootstrap 占位,并显式关闭本次下载响应验签。
// 后续已有平台证书后,请传入实际 certs 并保持 verifyResponse 为默认 true。
certs: { bootstrap: '' },
verifyResponse: false,
encryptKey: 'your_api_encrypt_key',
});
console.log(certificates);返回结构:
[
{
serialNo: 'platform_cert_serial',
certificate: '-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----',
effectiveTime: '2026-01-01T00:00:00+08:00',
expireTime: '2031-01-01T00:00:00+08:00'
}
]下载完成后,SDK 只返回证书内容,不会自动落盘。你可以自行保存,或将平台证书配置到 createClientRSA 中使用;如果使用 createAutoClientRSA,通常不需要手动调用本接口。
TypeScript 支持
SDK 内置 TypeScript 类型声明,无需额外安装 @types/*。
import type { DouYinPayConfig, DouYinPayResponse } from '@douyinpay_sdk/douyinpay-nodejs';错误处理
try {
const response = await sdk
.getClient('/v1/trade/transactions/native')
.post(requestBody);
console.log(response.data);
} catch (error) {
console.error('DouyinPay request failed:', error);
}常见错误包括:
- 商户号、证书序列号、私钥或平台证书缺失
- 请求签名失败
- HTTP 请求失败
- 响应缺少验签头
- 平台证书序列号不匹配
- 响应签名验签失败
- 回调验签失败或 resource 解密失败
安全建议
- 不要把商户私钥、接口加密密钥、平台证书本地配置提交到 GitHub
- 不要在日志中打印商户私钥和接口加密密钥
- 回调处理必须先验签,再解密和处理业务
- 平台证书可能轮换,建议使用自动下载证书模式或定期更新本地证书
License
MIT
