Payment Kit Vendor SDK - Signature verification, lifecycle management, and type definition integration solution
npm install @blocklet/payment-vendorPayment Kit 供应商集成软件开发工具包,为供应商提供标准化的认证、签名验证和安全通信解决方案。
本 SDK 旨在简化供应商与 Payment Kit 的集成过程,提供标准化的接口和安全机制。主要解决供应商在接收、验证和处理来自中介请求时面临的技术挑战。
- 签名验证:基于 Ed25519 算法的请求签名验证
- 白名单管理:中介访问控制和权限管理
- 时间戳验证:防重放攻击机制
- 认证中间件:自动验证请求合法性
- 日志中间件:记录请求和响应信息
- 错误处理中间件:统一的错误响应格式
- 限流中间件:防止接口滥用
- 健康检查中间件:系统状态监控
``bash`
npm install @blocklet/payment-vendor
本 SDK 支持两种使用场景,请根据你的角色选择对应的集成方式:
| 角色 | 身份 | 主要职责 | 使用的 SDK 功能 | 典型场景 |
|------|------|----------|----------------|----------|
| 🏪 Vendor
(供应商) | 商品/服务提供方 | • 接收发货请求
• 处理用户订单
• 提供服务实例 | • 中间件验证
• 白名单管理
• 请求解析 | Blocklet 开发者、
SaaS 服务商、
API 提供商 |
| 🔄 Broker
(中介) | Payment Kit 等平台 | • 发送发货请求
• 管理支付流程
• 协调供应商 | • 请求签名
• 认证生成
• 通信协议 | Payment Kit、
电商平台、
分发平台 |
适用场景: 你是商品/服务的提供方,需要接收并处理来自 Payment Kit 的发货请求。
核心能力:
- ✅ 请求验证:自动验证来自 Payment Kit 的签名请求
- ✅ 白名单管理:控制哪些中介可以访问你的服务
- ✅ 安全防护:防重放攻击、限流保护、错误处理
- ✅ 监控运维:健康检查、请求日志、系统状态
#### 基础集成(5分钟快速上手)
`typescript
import VendorSDK from '@blocklet/payment-vendor';
import express from 'express';
const app = express();
app.use(express.json());
// 1. 配置信任的中介白名单(Payment Kit 等)
VendorSDK.setBrokers([
{
id: 'payment-kit',
name: 'Payment Kit Service',
publicKey: process.env.PAYMENT_KIT_PUBLIC_KEY, // Payment Kit 提供给你的公钥
status: 'active',
rateLimit: 100 // 每分钟最多100次请求
}
]);
// 2. 应用安全中间件(自动验证所有请求)
app.use('/api/vendor', VendorSDK.middleware.ensureAuth());
// 3. 实现发货端点(这是你的核心业务逻辑)
app.post('/api/vendor/deliveries', async (req, res) => {
const { userInfo, deliveryParams, description } = req.body;
try {
// 你的发货逻辑:创建实例、分配资源、发送邮件等
const result = await createInstanceForUser(userInfo, deliveryParams);
res.json({
success: true,
status: 'completed',
message: '发货成功',
data: {
instanceId: result.instanceId,
serviceUrl: result.serviceUrl,
installUrl: result.installUrl
}
});
} catch (error) {
res.status(500).json({
success: false,
status: 'failed',
message: error.message
});
}
});
// 4. 健康检查端点(供 Payment Kit 监控)
app.get('/health', VendorSDK.middleware.healthCheck({
service: 'my-vendor-service',
version: '1.0.0'
}));
// 你的业务逻辑实现
async function createInstanceForUser(userInfo, deliveryParams) {
console.log(为用户 ${userInfo.userDid} 创建实例: ${deliveryParams.instanceName});inst_${Date.now()}
// 这里实现你的具体业务逻辑
// 例如:调用云服务API、创建数据库记录、发送通知等
return {
instanceId: ,https://my-service.com/${deliveryParams.instanceName}
serviceUrl: ,https://my-service.com/install/${deliveryParams.instanceName}
installUrl:
};
}
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(🏪 供应商服务运行在端口 ${port});`
});
适用场景: 你是 Payment Kit 或其他中介服务,需要向供应商发送发货请求。
核心能力:
- ✅ 请求签名:使用 Ed25519 算法为发送给供应商的请求签名
- ✅ 安全通信:确保请求的完整性和来源可信性
- ✅ 协议标准化:统一的请求格式和响应处理
- ✅ 错误处理:完善的异常情况处理机制
#### 基础发货请求
`typescript
import { VendorAuth } from '@blocklet/payment-vendor';
// 1. 准备发货请求数据(符合 DeliveryRequest 接口)
const deliveryRequest = {
path: '/api/vendor/deliveries',
method: 'POST',
timestamp: Date.now(),
userInfo: {
userDid: 'z1muQ3xqHQK2uiACHyZ7G5S1scgbZiEdB',
email: 'user@example.com',
description: '用户购买了 Blocklet 实例'
},
deliveryParams: {
instanceName: 'my-awesome-app',
productId: 'blocklet_001',
blockletMetaUrl: 'https://registry.blocklet.io/blocklets/my-app',
customParams: {
region: 'us-west-2',
tier: 'standard'
}
},
description: '为用户创建 Blocklet 实例'
};
// 2. 生成签名请求(推荐方式:使用 Header 签名)
const { headers, body } = VendorAuth.signRequestWithHeaders(
deliveryRequest,
);
// 3. 发送到供应商
const response = await fetch('https://vendor.example.com/api/vendor/deliveries', {
method: 'POST',
headers, // 自动包含 x-broker-vendor-sig 和 x-broker-did
body // JSON 字符串
});
const result = await response.json();
if (result.success) {
console.log('✅ 发货成功:', result.data);
// 保存 instanceId 和 serviceUrl 供后续使用
} else {
console.error('❌ 发货失败:', result.message);
}
`
#### 完整的中介服务示例
`typescript
import { VendorAuth } from '@blocklet/payment-vendor';
import express from 'express';
const app = express();
app.use(express.json());
// 发货管理端点(Payment Kit 内部使用)
app.post('/api/internal/fulfill-order', async (req, res) => {
try {
const { orderId, userId, productId, vendorEndpoint } = req.body;
// 构建发货请求
const deliveryRequest = {
path: '/api/vendor/deliveries',
method: 'POST',
timestamp: Date.now(),
userInfo: {
userDid: userId,
email: req.body.userEmail,
description: 订单 ${orderId} 的发货请求${productId}-${userId.slice(-8)}
},
deliveryParams: {
instanceName: ,处理订单 ${orderId} 的发货
productId,
customParams: req.body.customParams || {}
},
description:
};
// 签名并发送请求
const { headers, body } = VendorAuth.signRequestWithHeaders(
deliveryRequest,
);
const vendorResponse = await fetch(${vendorEndpoint}/api/vendor/deliveries, {
method: 'POST',
headers,
body
});
const result = await vendorResponse.json();
// 返回处理结果
res.json({
orderId,
fulfilled: result.success,
vendorResponse: result,
timestamp: new Date().toISOString()
});
} catch (error: any) {
console.error('发货请求失败:', error);
res.status(500).json({
error: '发货处理失败',
message: error.message
});
}
});
`
`typescript
import VendorSDK from '@blocklet/payment-vendor';
import express from 'express';
const app = express();
// 基础中间件
app.use(express.json());
// 配置信任的中介白名单(动态配置)
VendorSDK.setBrokers(() => {
const configSource = process.env.VENDOR_DISTRIBUTORS || '[]';
return JSON.parse(configSource);
});
// 应用安全中间件
app.use('/api/vendor', VendorSDK.middleware.rateLimiter({
windowMs: 60000,
defaultLimit: 100
}));
app.use('/api/vendor', VendorSDK.middleware.ensureAuth({
skipTimestamp: false,
maxAge: 300000
}));
// 核心发货端点
app.post('/api/vendor/deliveries', async (req, res) => {
try {
const { userInfo, deliveryParams, description } = req.body;
// 处理发货逻辑
const result = await processFulfillment(userInfo, deliveryParams, description);
res.json({
success: result.success,
status: result.success ? 'completed' : 'failed',
data: result.data,
message: result.message
});
} catch (error) {
console.error('处理请求失败:', error);
res.status(500).json({
success: false,
error: '内部服务器错误',
message: error.message
});
}
});
// 管理接口:查看中介状态
app.get('/api/admin/brokers', async (req, res) => {
try {
const brokers = await VendorSDK.getWhitelist();
res.json({
total: brokers.length,
active: brokers.filter(d => d.status === 'active').length,
brokers: brokers.map(d => ({
id: d.id,
name: d.name,
status: d.status,
rateLimit: d.rateLimit
}))
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 错误处理中间件
app.use(VendorSDK.middleware.errorHandler);
// 业务逻辑函数(供应商实现)
async function processFulfillment(userInfo: any, deliveryParams: any, description: string) {
console.log(处理发货请求 - 用户: ${userInfo.userDid}, 实例: ${deliveryParams.instanceName});inst_${Date.now()}_${Math.random().toString(36).substr(2, 9)}
try {
// 你的具体业务逻辑:
// 1. 创建服务实例
// 2. 分配资源
// 3. 发送通知邮件
// 4. 更新数据库等
const instanceId = ;https://my-service.com/service/${deliveryParams.instanceName}
return {
success: true,
data: {
instanceId,
serviceUrl: ,https://my-service.com/install/${instanceId}
installUrl: ,发货失败: ${error.message}
expiresAt: new Date(Date.now() + 24 60 60 * 1000).toISOString()
},
message: '发货成功'
};
} catch (error: any) {
return {
success: false,
data: null,
message:
};
}
}
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(🏪 供应商服务运行在端口 ${port});`
});
`typescript
import { VendorAuth } from '@blocklet/payment-vendor';
import express from 'express';
const app = express();
app.use(express.json());
// Payment Kit 内部的发货管理服务
class VendorFulfillmentService {
private brokerSecretKey: string;
private brokerPublicKey: string;
constructor() {
this.brokerSecretKey = process.env.BROKER_SECRET_KEY!;
this.brokerPublicKey = process.env.BROKER_PUBLIC_KEY!;
}
// 向供应商发送发货请求
async fulfillOrder(orderData: {
orderId: string;
userId: string;
userEmail: string;
productId: string;
instanceName: string;
vendorEndpoint: string;
customParams?: Record
}) {
try {
// 构建标准化的发货请求
const deliveryRequest = {
path: '/api/vendor/deliveries',
method: 'POST',
timestamp: Date.now(),
userInfo: {
userDid: orderData.userId,
email: orderData.userEmail,
description: 订单 ${orderData.orderId} 的发货请求处理订单 ${orderData.orderId} 的发货
},
deliveryParams: {
instanceName: orderData.instanceName,
productId: orderData.productId,
customParams: orderData.customParams || {}
},
description:
};
// 签名请求
const { headers, body } = VendorAuth.signRequestWithHeaders(
deliveryRequest,
);
// 发送到供应商
const response = await fetch(${orderData.vendorEndpoint}/api/vendor/deliveries, {
method: 'POST',
headers,
body,
timeout: 30000 // 30秒超时
});
if (!response.ok) {
throw new Error(Vendor responded with status: ${response.status});
}
const result = await response.json();
return {
orderId: orderData.orderId,
fulfilled: result.success,
vendorResponse: result,
timestamp: new Date().toISOString()
};
} catch (error: any) {
console.error(发货请求失败 - 订单: ${orderData.orderId}, error);Vendor fulfillment failed: ${error.message}
throw new Error();
}
}
// 查询发货状态
async checkFulfillmentStatus(instanceId: string, vendorEndpoint: string) {
try {
const statusRequest = {
path: '/api/vendor/status',
method: 'GET',
timestamp: Date.now(),
params: { instanceId }
};
const { headers, body } = VendorAuth.signRequestWithHeaders(
statusRequest,
);
const response = await fetch(${vendorEndpoint}/api/vendor/status, {
method: 'POST',
headers,
body
});
return await response.json();
} catch (error: any) {
throw new Error(Status check failed: ${error.message});
}
}
}
// Payment Kit 使用示例
const fulfillmentService = new VendorFulfillmentService();
app.post('/api/internal/fulfill-order', async (req, res) => {
try {
const result = await fulfillmentService.fulfillOrder(req.body);
res.json(result);
} catch (error: any) {
res.status(500).json({
error: '发货处理失败',
message: error.message
});
}
});
app.listen(3000, () => {
console.log('🔄 Payment Kit 中介服务运行在端口 3000');
});
`
| 对比项 | 🏪 供应商端 | 🔄 中介端 |
|--------|----------------|---------------|
| 主要用途 | 接收并处理发货请求 | 发送发货请求给供应商 |
| 核心导入 | import VendorSDK from '@blocklet/payment-vendor' | import { VendorAuth } from '@blocklet/payment-vendor' |VendorSDK.setBrokers([...])
| 关键配置 | 设置信任的中介 | process.env.BROKER_SECRET_KEY 配置自己的私钥 |middleware.ensureAuth()
| 核心功能 | 使用 验证请求 | 使用 VendorAuth.signRequestWithHeaders() 签名请求 |POST /api/vendor/deliveries
| 请求方向 | 被动接收来自 Payment Kit 的请求 | 主动向供应商发送请求 |
| 典型端点 | (接收) | 调用供应商的 /api/vendor/deliveries |
| 安全职责 | 验证请求签名,防止未授权访问 | 生成请求签名,证明身份合法 |
SDK 支持两种配置模式:
#### 静态配置模式
适用于中介列表相对稳定的场景:
`typescript`
VendorSDK.setBrokers([
{
id: 'payment-kit',
name: 'Payment Kit Service',
publicKey: '0x680688a033b86da179f39018e074410439ae82a97c4cb8e1ad16c26eabcc1795',
status: 'active',
rateLimit: 100
}
]);
#### 动态配置模式
适用于需要实时更新中介配置的场景:
`typescript`
VendorSDK.setBrokers(() => {
// 从环境变量、配置文件或数据库读取
const configSource = process.env.VENDOR_DISTRIBUTORS || '[]';
const brokers = JSON.parse(configSource);
return brokers.map(item => ({
id: item.brokerId,
name: item.name,
publicKey: item.publicKey,
status: item.enabled ? 'active' : 'inactive',
rateLimit: item.rateLimit || 100
}));
});
`bash中介配置
export VENDOR_DISTRIBUTORS='[{
"brokerId": "payment-kit",
"name": "Payment Kit Service",
"publicKey": "0x680688a033b86da179f39018e074410439ae82a97c4cb8e1ad16c26eabcc1795",
"enabled": true,
"rateLimit": 100
}]'
API 文档
$3
#### VendorSDK.setBrokers(brokersOrGetter)
设置中介白名单配置。
参数:
-
brokersOrGetter: BrokerConfig[] | () => BrokerConfig[] | PromiseBrokerConfig 接口:
| 字段 | 类型 | 必需 | 描述 |
|------|------|------|------|
|
id | string | ✅ | 中介唯一标识符 |
| name | string | ✅ | 中介显示名称 |
| publicKey | string | ✅ | 用于验证签名的公钥 |
| status | 'active' \| 'inactive' | ✅ | 中介状态,仅 active 状态可通过验证 |
| rateLimit | number | ❌ | 可选的请求频率限制 |#### VendorSDK.getWhitelist()
返回当前配置的中介白名单。
返回:
Promise$3
#### VendorSDK.middleware.ensureAuth(options?)
Express 认证中间件,验证请求签名和中介权限。
可选参数:
-
skipTimestamp: boolean - 是否跳过时间戳验证
- maxAge: number - 时间戳最大有效期(毫秒)`typescript
// 基础用法
app.use('/api/vendor', VendorSDK.middleware.ensureAuth());// 自定义配置
app.use('/api/vendor', VendorSDK.middleware.ensureAuth({
skipTimestamp: false,
maxAge: 300000 // 5分钟
}));
`#### VendorSDK.middleware.rateLimiter(options?)
请求频率限制中间件。
可选参数:
-
windowMs: number - 时间窗口(毫秒)
- defaultLimit: number - 默认最大请求次数
- skipSuccessfulRequests: boolean - 是否跳过成功请求计数`typescript
// 使用默认配置
app.use('/api/vendor', VendorSDK.middleware.rateLimiter());// 自定义配置
app.use('/api/vendor', VendorSDK.middleware.rateLimiter({
windowMs: 60000, // 1分钟
defaultLimit: 100, // 默认最多100次请求
skipSuccessfulRequests: false
}));
`#### VendorSDK.middleware.healthCheck(options?)
健康检查中间件。
可选参数:
-
service: string - 服务名称
- version: string - 版本信息
- includeDetails: boolean - 是否包含详细系统信息`typescript
// 基础用法
app.get('/health', VendorSDK.middleware.healthCheck());// 自定义配置
app.get('/health', VendorSDK.middleware.healthCheck({
service: 'launcher-vendor',
version: '1.0.0',
includeDetails: true
}));
`#### VendorSDK.middleware.errorHandler
统一错误处理中间件。
`typescript
// 应该放在所有路由的最后
app.use(VendorSDK.middleware.errorHandler);
`$3
#### VendorAuth.signRequestWithHeaders(request)
生成包含签名头部的完整请求对象,适用于 header 签名验证场景。
参数:
-
request: Record - 请求数据对象
- brokerSk: string - 中介私钥
- brokerDid: string - 中介公钥/DID返回:
{ headers: Record`typescript
import { VendorAuth } from '@blocklet/payment-vendor';const requestData = {
path: '/api/vendor/deliveries',
method: 'POST',
timestamp: Date.now(),
userInfo: {
userDid: 'user_did_123',
email: 'user@example.com'
},
body: { appName: 'test-app' }
};
const { headers, body } = VendorAuth.signRequestWithHeaders(
requestData,
);
// 发送请求
const response = await fetch('https://vendor.example.com/api/deliveries', {
method: 'POST',
headers, // 包含 x-broker-vendor-sig 和 x-broker-vendor-did
body // JSON 字符串
});
`#### VendorAuth.signAndSerialize(data, secretKey)
签名并序列化请求数据,用于 body 签名验证场景。
参数:
-
data: VendorRequest - 请求数据对象
- secretKey: string - 请求方私钥返回:
string - 序列化的签名请求`typescript
const signedBody = VendorAuth.signAndSerialize(requestData, secretKey);const response = await fetch('https://vendor.example.com/api/deliveries', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: signedBody
});
`错误处理
$3
#### "Brokers must be an array"
原因: 传入
setBrokers 的参数类型不正确。解决方案:
`typescript
// ❌ 错误用法
VendorSDK.setBrokers(undefined);
VendorSDK.setBrokers("invalid");// ✅ 正确用法
VendorSDK.setBrokers([]); // 空数组
VendorSDK.setBrokers([{
id: 'test',
name: 'Test',
publicKey: 'xxx',
status: 'active'
}]);
VendorSDK.setBrokers(() => parseConfigFromEnv()); // 函数
`#### "Missing signature header"
原因: 使用了不正确的签名方式。
解决方案:
`typescript
// ❌ 错误用法(缺少签名头部)
const signedBody = VendorAuth.signAndSerialize(data, secretKey);
fetch(url, { body: signedBody });// ✅ 正确用法(包含签名头部)
const { headers, body } = VendorAuth.signRequestWithHeaders(data);
fetch(url, { method: 'POST', headers, body });
`#### "Broker not in whitelist"
原因: 请求的中介不在白名单中或状态为 inactive。
解决方案:
1. 检查中介 ID 是否正确
2. 确认中介状态为 'active'
3. 验证白名单配置是否正确加载
#### "Request timestamp too old"
原因: 请求时间戳过期(超过5分钟)。
解决方案:
`typescript
// 确保时间戳是当前时间
const requestData = {
// ...其他字段
timestamp: Date.now() // 使用当前时间戳
};
`调试和监控
$3
`typescript
// 添加请求日志中间件
app.use('/api/vendor', VendorSDK.middleware.ensureAuth());
`$3
`typescript
import { VendorAuth } from '@blocklet/payment-vendor';async function debugSignature(requestBody, expectedBrokerId) {
try {
const brokers = await VendorSDK.getWhitelist();
const broker = brokers.find(d => d.id === expectedBrokerId);
if (!broker) {
console.log('中介不存在:', expectedBrokerId);
return false;
}
const isValid = await VendorAuth.verifyRequest(requestBody, broker);
console.log('签名验证结果:', isValid);
return isValid;
} catch (error) {
console.error('签名验证失败:', error);
return false;
}
}
`$3
`typescript
// 健康检查
app.get('/health', VendorSDK.middleware.healthCheck());// 中介状态查询
app.get('/api/admin/brokers', async (req, res) => {
try {
const brokers = await VendorSDK.getWhitelist();
res.json({
total: brokers.length,
active: brokers.filter(d => d.status === 'active').length,
brokers: brokers.map(d => ({
id: d.id,
name: d.name,
status: d.status,
rateLimit: d.rateLimit
}))
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 系统信息
app.get('/api/admin/info', (req, res) => {
res.json({
version: require('../package.json').version,
uptime: process.uptime(),
memory: process.memoryUsage(),
nodeVersion: process.version
});
});
`最佳实践
$3
1. 使用环境变量管理敏感信息
`bash
export PAYMENT_KIT_PUBLIC_KEY="your_public_key_here"
export VENDOR_DISTRIBUTORS='[...]'
`2. 配置适当的限流和超时设置
`typescript
app.use('/api/vendor', VendorSDK.middleware.rateLimiter({
windowMs: 60000,
max: 1000 // 根据实际需要调整
}));
`3. 定期轮换密钥和证书
- 建议每季度更新一次密钥对
- 使用配置热重载功能平滑切换
$3
1. 验证所有入站请求的签名
`typescript
app.use('/api/vendor', VendorSDK.middleware.ensureAuth());
`2. 使用 HTTPS 传输敏感数据
`typescript
// 强制 HTTPS
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
res.redirect(https://${req.header('host')}${req.url});
} else {
next();
}
});
`3. 实施适当的错误处理
`typescript
app.use(VendorSDK.middleware.errorHandler);
`4. 定期审查和更新中介列表
- 使用动态配置模式便于管理
- 定期检查并移除不活跃的中介
$3
1. 使用缓存减少重复计算
2. 合理设置限流参数
3. 定期清理日志文件
4. 监控内存使用情况
示例代码
完整的集成示例请参考
examples/usage-example.ts` 文件。如需技术支持或报告问题,请访问项目的 GitHub 仓库提交 Issue。
本项目采用 Apache-2.0 许可证。详细信息请参阅 LICENSE 文件。