🚀 PayBySquare 生成器
PayBySquare 生成器是一个全面的 Node.js/TypeScript 库,用于生成、解码和验证支付二维码。PayBySquare 是斯洛伐克银行协会(SBA)采用的支付二维码国家标准。

✨ 主要特性
生成功能
- ✅ 基于简单的 JSON 接口
- ✅ 生成 PNG 格式的二维码缓冲区或文件
- ✅ 支持所有 PayBySquare 支付字段
- ✅ 可自定义二维码样式(尺寸、颜色、纠错级别)
解码功能
- ✅ 从 PNG 缓冲区解码 PayBySquare 二维码
- ✅ 将支付数据提取为 JSON 格式
- ✅ 往返验证(无损编码/解码)
合规性与验证
- ✅ IBAN 校验和验证(mod - 97 算法)
- ✅ 字段格式合规性检查
- ✅ 银行标准验证(BIC/SWIFT、货币代码)
- ✅ 带有错误严重程度级别的详细合规性报告
开发特性
- ✅ 完全支持 TypeScript 并提供类型定义
- ✅ 零 UI 依赖 - 纯基于函数的接口
- ✅ ESM 模块格式(Node.js >= 18)
- ✅ 经过全面测试(96 个单元测试,覆盖率超过 90%)
- ✅ MCP 服务器 - 可与 Claude Desktop 和其他 MCP 客户端配合使用
📦 安装指南
npm install paybysquare-generator
要求
- Node.js >= 18.0.0
- 支持 ESM 模块
🚀 快速开始
import { generatePayBySquare } from 'paybysquare-generator';
const buffer = await generatePayBySquare({
iban: 'SK9611000000002918599669',
beneficiaryName: 'John Doe',
amount: 100.50,
currency: 'EUR',
variableSymbol: '123456',
paymentNote: 'Invoice payment'
});
📚 详细文档
API 参考
generatePayBySquare(input, options?)
根据支付数据生成 PayBySquare 二维码 PNG 图像。
参数:
input: PayBySquareInput - 支付数据(见下文)
options?: GenerationOptions - 可选的二维码生成选项
返回值: Promise<Buffer> - 以 Node.js Buffer 形式的 PNG 图像
抛出错误:
ValidationError - 如果输入数据无效
EncodingError - 如果支付数据编码失败
GenerationError - 如果二维码 PNG 生成失败
generatePayBySquareToFile(input, filePath, options?)
生成 PayBySquare 二维码并保存到文件。
参数:
input: PayBySquareInput - 支付数据
filePath: string - 保存 PNG 文件的路径
options?: GenerationOptions - 可选的二维码生成选项
返回值: Promise<void>
decodePayBySquare(buffer)
从 PNG 缓冲区解码 PayBySquare 二维码,还原为支付数据。
参数:
buffer: Buffer - 包含 PayBySquare 二维码的 PNG 图像缓冲区
返回值: Promise<PayBySquareInput> - 解码后的支付数据
抛出错误:
DecodingError - 如果二维码无法读取或解码
示例:
import { readFile } from 'fs/promises';
import { decodePayBySquare } from 'paybysquare-generator';
const qrBuffer = await readFile('./payment-qr.png');
const paymentData = await decodePayBySquare(qrBuffer);
console.log(paymentData.iban, paymentData.amount);
isCompliant(input)
对支付数据进行简单的合规性检查,返回通过或失败结果。
参数:
input: PayBySquareInput - 要验证的支付数据
返回值: boolean - 如果完全合规返回 true,否则返回 false
示例:
import { isCompliant } from 'paybysquare-generator';
const isValid = isCompliant({
iban: 'SK9611000000002918599669',
beneficiaryName: 'Test'
});
console.log(isValid);
checkCompliance(input)
提供详细的合规性报告,包含错误、警告和严重程度级别。
参数:
input: PayBySquareInput - 要验证的支付数据
返回值: Promise<ComplianceResult> - 结构化的合规性报告
示例:
import { checkCompliance } from 'paybysquare-generator';
const report = await checkCompliance(paymentData);
if (!report.isCompliant) {
console.log('错误:', report.errors);
console.log('警告:', report.warnings);
console.log('详情:', report.details);
}
ComplianceResult 接口:
interface ComplianceResult {
isCompliant: boolean;
errors: ComplianceIssue[];
warnings: ComplianceIssue[];
details: {
ibanValid: boolean;
fieldsValid: boolean;
bankingStandardsValid: boolean;
totalIssues: number;
};
}
interface ComplianceIssue {
type: 'error' | 'warning';
field: string;
message: string;
severity: 'critical' | 'major' | 'minor';
}
checkQRCompliance(buffer)
直接从 PNG 缓冲区检查二维码的合规性。
参数:
buffer: Buffer - 包含二维码的 PNG 图像缓冲区
返回值: Promise<ComplianceResult> - 解码数据的合规性报告
verifyRoundTrip(input)
验证支付数据在编码和解码过程中是否无损。
参数:
input: PayBySquareInput - 原始支付数据
返回值: Promise<RoundTripResult> - 往返验证结果
示例:
import { verifyRoundTrip } from 'paybysquare-generator';
const result = await verifyRoundTrip(originalData);
if (!result.isLossless) {
console.log('检测到数据丢失:', result.differences);
}
RoundTripResult 接口:
interface RoundTripResult {
isLossless: boolean;
differences: FieldDifference[];
input: PayBySquareInput;
decoded: PayBySquareInput;
}
interface FieldDifference {
field: string;
original: any;
decoded: any;
}
输入数据格式
PayBySquareInput
interface PayBySquareInput {
iban: string;
beneficiaryName: string;
amount?: number;
currency?: string;
variableSymbol?: string;
constantSymbol?: string;
specificSymbol?: string;
paymentNote?: string;
dueDate?: string;
swift?: string;
originatorReference?: string;
beneficiaryAddress?: {
street?: string;
city?: string;
};
}
GenerationOptions
interface GenerationOptions {
width?: number;
margin?: number;
errorCorrectionLevel?: 'L' | 'M' | 'Q' | 'H';
color?: {
dark?: string;
light?: string;
};
removeAccents?: boolean;
}
💻 使用示例
最小支付示例
import { generatePayBySquare } from 'paybysquare-generator';
import { writeFile } from 'fs/promises';
const buffer = await generatePayBySquare({
iban: 'SK9611000000002918599669',
beneficiaryName: 'John Doe'
});
await writeFile('payment.png', buffer);
包含所有字段的完整支付示例
const buffer = await generatePayBySquare({
iban: 'SK9611000000002918599669',
beneficiaryName: 'Acme Corporation',
amount: 150.50,
currency: 'EUR',
variableSymbol: '2026001',
constantSymbol: '0308',
paymentNote: 'Invoice #2026001',
dueDate: '2026-02-15',
swift: 'TATRSKBX',
originatorReference: 'REF-2026-001',
beneficiaryAddress: {
street: 'Business Street 123',
city: 'Bratislava 81108'
}
});
捐赠示例(无固定金额)
const buffer = await generatePayBySquare({
iban: 'SK9611000000002918599669',
beneficiaryName: 'Charity Organization',
paymentNote: 'Voluntary donation'
});
自定义二维码样式示例
const buffer = await generatePayBySquare(
{
iban: 'SK9611000000002918599669',
beneficiaryName: 'Shop Name',
amount: 99.99
},
{
width: 500,
margin: 2,
errorCorrectionLevel: 'H',
color: {
dark: '#1E40AF',
light: '#FFFFFF'
}
}
);
直接保存到文件示例
import { generatePayBySquareToFile } from 'paybysquare-generator';
await generatePayBySquareToFile(
{
iban: 'SK9611000000002918599669',
beneficiaryName: 'Recipient',
amount: 25.00
},
'./payment.png'
);
错误处理示例
import {
generatePayBySquare,
ValidationError,
EncodingError,
GenerationError
} from 'paybysquare-generator';
try {
const buffer = await generatePayBySquare({
iban: 'INVALID',
beneficiaryName: 'Test'
});
} catch (error) {
if (error instanceof ValidationError) {
console.error('输入无效:', error.message);
} else if (error instanceof EncodingError) {
console.error('编码失败:', error.message);
} else if (error instanceof GenerationError) {
console.error('二维码生成失败:', error.message);
}
}
解码二维码示例
import { decodePayBySquare } from 'paybysquare-generator';
import { readFile } from 'fs/promises';
const qrBuffer = await readFile('./payment-qr.png');
const paymentData = await decodePayBySquare(qrBuffer);
console.log('IBAN:', paymentData.iban);
console.log('收款人:', paymentData.beneficiaryName);
console.log('金额:', paymentData.amount, paymentData.currency);
console.log('可变符号:', paymentData.variableSymbol);
简单合规性检查示例
import { isCompliant } from 'paybysquare-generator';
const paymentData = {
iban: 'SK9611000000002918599669',
beneficiaryName: 'Test Merchant',
amount: 100,
currency: 'EUR'
};
if (isCompliant(paymentData)) {
console.log('✓ 支付数据有效');
} else {
console.log('✗ 支付数据存在问题');
}
详细合规性报告示例
import { checkCompliance } from 'paybysquare-generator';
const paymentData = {
iban: 'SK9999999999999999999999',
beneficiaryName: 'Test',
amount: -50,
variableSymbol: 'ABC123',
swift: 'INVALID'
};
const report = await checkCompliance(paymentData);
console.log('是否合规:', report.isCompliant);
console.log('\n错误:');
report.errors.forEach(err => {
console.log(` [${err.severity}] ${err.field}: ${err.message}`);
});
console.log('\n验证详情:');
console.log(' IBAN 是否有效:', report.details.ibanValid);
console.log(' 字段是否有效:', report.details.fieldsValid);
console.log(' 银行标准是否有效:', report.details.bankingStandardsValid);
console.log(' 总问题数:', report.details.totalIssues);
往返验证示例
import { verifyRoundTrip } from 'paybysquare-generator';
const originalData = {
iban: 'SK9611000000002918599669',
beneficiaryName: 'Test Company',
amount: 250.75,
currency: 'EUR',
variableSymbol: '123456',
paymentNote: 'Testing round-trip'
};
const result = await verifyRoundTrip(originalData);
if (result.isLossless) {
console.log('✓ 数据在编码/解码循环中完美保留!');
} else {
console.log('✗ 检测到数据丢失:');
result.differences.forEach(diff => {
console.log(` ${diff.field}:`);
console.log(` 原始值: ${diff.original}`);
console.log(` 解码后的值: ${diff.decoded}`);
});
}
🔧 技术细节
验证规则
该库对所有输入进行全面验证:
- IBAN:必需,必须是有效格式(2 位国家代码 + 2 位数字 + 11 - 30 位字母数字)
- 收款人姓名:必需,最多 70 个字符
- 金额:可选,提供时必须为正数且有限
- 货币:可选,必须是 3 位 ISO 4217 代码(默认: EUR)
- 可变符号:可选,仅 1 - 10 位数字
- 常量符号:可选,仅 1 - 4 位数字
- 特定符号:可选,仅 1 - 10 位数字
- 支付备注:可选,最多 140 个字符
- 到期日期:可选,必须是 ISO 8601 格式(YYYY - MM - DD)
- 地址字段:可选,每个最多 70 个字符
运行示例
仓库中包含完整的示例:
git clone https://github.com/yourusername/paybysquare-generator
cd paybysquare-generator
npm install
npm run example
这将生成几个不同用例的示例二维码。
运行测试
npm test
npm run test:watch
npm run test:coverage
从源代码构建
npm run build
PayBySquare 标准
该库实现了斯洛伐克银行协会(SBA)定义的 PayBySquare 标准 1.1.0 版本。更多信息:
依赖项
生产环境依赖
TypeScript 支持
该库使用 TypeScript 编写,并包含完整的类型定义。所有类型都已导出,方便使用:
import type {
PayBySquareInput,
BeneficiaryAddress,
GenerationOptions,
ComplianceResult,
ComplianceIssue,
ComplianceDetails,
RoundTripResult,
FieldDifference
} from 'paybysquare-generator';
import {
PayBySquareError,
ValidationError,
EncodingError,
GenerationError,
DecodingError
} from 'paybysquare-generator';
MCP 服务器
该库包含一个 模型上下文协议(MCP)服务器,可将所有功能暴露给 Claude 和其他 MCP 客户端。
可用工具
generate_paybysquare - 根据支付数据生成二维码(保存到文件,返回文件路径)
- 必需参数:
beneficiaryName(收款人的全名)
- 建议参数:
swift(国际转账的 BIC 代码)
- 可选参数:
outputDirectory(自定义保存位置,默认: ~/paybysquare-qr-codes/)
decode_paybysquare - 将二维码解码为支付数据(从 base64 编码的 PNG 图像)
check_compliance - 验证支付数据的合规性,并提供详细的错误报告
verify_roundtrip - 验证无损编码/解码(数据完整性检查)
快速设置
- 构建服务器:
npm run build:mcp
- 配置 Claude Desktop:
在
claude_desktop_config.json 中添加以下内容:{
"mcpServers": {
"paybysquare": {
"command": "node",
"args": ["/absolute/path/to/paybysquare/dist/mcp-server/index.js"]
}
}
}
- 重启 Claude Desktop
在 Claude 中的示例用法
配置完成后,你可以使用自然语言进行操作:
为以下信息生成 PayBySquare 二维码:
- IBAN: SK9611000000002918599669
- 收款人: John Doe
- 金额: 100.50 EUR
- SWIFT: TATRSKBX
- 支付备注: Invoice #12345
Claude 将生成二维码并保存到文件,返回:
✓ 二维码生成成功!
文件保存路径: /Users/username/paybysquare-qr-codes/paybysquare-1705331234567-a3f2.png
解码这个 PayBySquare 二维码并告诉我支付详情
[上传图像]
检查以下支付数据是否符合银行标准:
- IBAN: SK9611000000002918599669
- 收款人: Test Company
- 金额: 250 EUR
- SWIFT: TATRSKBX
注意: 二维码默认自动保存到 ~/paybysquare-qr-codes/ 目录。你可以使用 outputDirectory 选项指定自定义目录。
详细的 MCP 服务器文档请参阅 mcp-server/README.md。
📄 许可证
本项目采用 MIT 许可证。
贡献
欢迎贡献代码!请随时提交拉取请求。
相关项目
支持
如果你遇到任何问题或有疑问,请在 GitHub 上 提交问题。
为斯洛伐克开发者社区用心打造 ❤️