Bloque 付款 SDK
官方TypeScript/JavaScript SDK用于整合Bloque支付.
安装
bun add @bloque/payments
认证
SDK支持三证模式:
| 证书 | 前缀 | 何处 | 目的 |
|---|---|---|---|
| 密钥 | sk_test_ 编号 : sk_live_ | 只有服务器 | 以短寿命 JWT 交换 /origins/api-keys/exchange |
| 可公布的密钥 | pk_test_ 编号 : pk_live_ | 浏览器 | 识别商家; 只读( 查看推车) |
| 客户端秘密 | 日本 | 浏览器 | JWT范围为单一的退出会议(checkout.pay(中文(简体) ) |
初始化( 建议)
import { Bloque } from '@bloque/payments';
const bloque = new Bloque({
mode: 'sandbox',
secretKey: process.env.BLOQUE_SECRET_KEY!,
webhookSecret: process.env.BLOQUE_WEBHOOK_SECRET, // optional
});
SDK自动交换JWT的秘密密钥并缓存(在过期前刷新出1分).
初始化( 遗留)
const bloque = new Bloque({
mode: 'sandbox',
accessToken: process.env.BLOQUE_ACCESS_TOKEN!, // deprecated — use secretKey
});
快速启动: 创建退出
import { Bloque } from '@bloque/payments';
const bloque = new Bloque({
mode: 'sandbox',
secretKey: process.env.BLOQUE_SECRET_KEY!,
});
const checkout = await bloque.checkout.create({
name: 'Pack Profesional de Productividad',
description:
'Periféricos premium para trabajo intensivo y alto rendimiento',
asset: 'COPM/2',
image_url: 'https://cdn.bloque.app/checkouts/productivity-pack.png',
items: [
{
name: 'Teclado mecánico Keychron K2',
description: 'Wireless, RGB, switches Blue',
amount: 450_000_00,
quantity: 2,
image_url: 'https://cdn.bloque.app/items/keychron-k2.png',
},
{
name: 'Mouse Logitech MX Master 3S',
description: 'Inalámbrico, sensor 8K DPI',
amount: 380_000_00,
quantity: 1,
image_url: 'https://cdn.bloque.app/items/mx-master-3s.png',
},
],
success_url: 'https://bloque.app/success',
cancel_url: 'https://bloque.app/cancel',
merchant: {
name: 'Bloque',
theme: {
primary: '#10b981',
primary_foreground: '#ffffff',
background: '#f8fafc',
surface: '#ffffff',
border: '#d1d5db',
input_border: '#10b98166',
},
},
payment_methods: ['card', 'pse', 'cash'],
payeer: {
name: 'Nestor Cortina',
email: '[email protected]',
},
});
console.log('Checkout URL:', checkout.url);
API 密码
Bloque 配置
type BloqueConfig = {
mode: 'sandbox' | 'production';
secretKey: string; // sk_test_... or sk_live_...
timeout?: number; // request timeout in ms (default 10_000)
maxRetries?: number; // retry count (default 2)
webhookSecret?: string;
};
/** @deprecated Use BloqueConfig with secretKey instead */
type BloqueConfigLegacy = {
mode: 'sandbox' | 'production';
accessToken: string;
timeout?: number;
maxRetries?: number;
webhookSecret?: string;
};
离职
bloque.checkout.create(params)
type CheckoutParams = {
name: string;
description?: string;
image_url?: string;
asset?: 'COPM/2' | 'DUSD/6';
items: {
name: string;
description?: string;
amount: number;
quantity: number;
image_url?: string;
}[];
success_url: string;
cancel_url: string;
metadata?: Record<string, string | number | boolean>;
merchant?: {
name: string;
theme: {
primary: string;
primary_foreground: string;
background: string;
surface: string;
border: string;
input_border: string;
};
};
payment_methods?: ('card' | 'pse' | 'cash')[];
expires_at?: string;
};
注释:
asset默认为DUSD/6当省略时.- 创建请求使用
redirect_url来源于success_url。 。 。 .
响应形状 :
type Checkout = {
id: string;
urn: string;
object: 'checkout';
url: string;
client_secret: string; // scoped JWT for browser-side checkout
status: 'pending' | 'paid' | 'expired' | 'deposited' | 'cancelled';
amount_total: number;
amount_subtotal: number;
asset: 'COPM/2' | 'DUSD/6';
items: {
name: string;
description?: string;
amount: number;
quantity: number;
image_url?: string;
}[];
metadata?: Record<string, string | number | boolean>;
created_at: string;
updated_at: string;
expires_at: string | null;
};
通过 client_secret 改为 @bloque/payments-core 或者说 @bloque/payments-react 在浏览器上授权执行付款.
bloque.checkout.retrieve(checkoutId)
const checkout = await bloque.checkout.retrieve('checkout_123');
bloque.checkout.cancel(checkoutId)
const checkout = await bloque.checkout.cancel('checkout_123');
付款
bloque.payments.create(params)
支持的直接支付方法是 card, (中文(简体) ), pse,以及 cash (图 POST /payments/:type 在服务器上).
const payment = await bloque.payments.create({
paymentUrn: 'did:bloque:payments:123e4567-e89b-12d3-a456-426614174000',
payment: {
type: 'card',
data: {
cardNumber: '4111111111111111',
cardholderName: 'John Doe',
expiryMonth: '12',
expiryYear: '2028',
cvv: '123',
email: '[email protected]',
installments: 1,
currency: 'COP',
},
},
});
付款答复:
type PaymentResponse = {
id: string;
object: 'payment';
status: 'approved' | 'rejected' | 'pending';
amount: number;
currency: string;
created_at: string;
three_ds?: { current_step: string; iframe: string };
};
bloque.payments.getStatus(paymentId)
由URN(如:. did:bloque:payments:...)在3DS挑战后.
const latest = await bloque.payments.getStatus(payment.id);
3D 安全( 直接 API)
当您用 3DS 处理卡片支付服务器侧面时, 通过浏览器指纹字段和可选的沙盒方案:
import type { BrowserInfo } from '@bloque/payments';
function browserInfoFromRequest(req: {
headers: Record<string, string | string[] | undefined>;
}): BrowserInfo {
const ua = String(req.headers['user-agent'] ?? '');
const accept = String(req.headers['accept'] ?? '*/*');
const lang = String(req.headers['accept-language'] ?? 'en');
return {
browser_user_agent: ua,
browser_language: lang,
browser_color_depth: '24',
browser_screen_height: '900',
browser_screen_width: '1440',
browser_tz: '0',
};
}
const payment = await bloque.payments.create({
checkoutId: 'checkout_123',
payment: {
type: 'card',
data: {
cardNumber: '4111111111111111',
cardholderName: 'John Doe',
expiryMonth: '12',
expiryYear: '2028',
cvv: '123',
email: '[email protected]',
is_three_ds: true,
browser_info: browserInfoFromRequest(req),
three_ds_auth_type: 'challenge_v2', // sandbox only; omit in production
},
},
});
if (payment.three_ds?.iframe) {
// 1) Decode HTML entities if the gateway returns escaped HTML
// 2) If iframe is a URL (https://...), use <iframe src="...">
// 3) Otherwise use <iframe srcdoc={decodedHtml}> with sandbox allow-scripts allow-forms allow-popups
// 4) Show Mastercard ID Check branding before/around the challenge where required
// 5) Poll until terminal state:
let status = payment.status;
while (status === 'pending') {
await new Promise((r) => setTimeout(r, 3000));
const next = await bloque.payments.getStatus(payment.id);
status = next.status;
}
}
字段名称 BrowserInfo 匹配 Bloque 付款 API (browser_user_agent, (中文(简体) ), browser_language(见a/c.5/49/70,附件).
网络呼号
校验webhook 签名( I)HMAC-SHA256:
const isValid = bloque.webhooks.verify(
rawBody,
signature,
{ secret: process.env.BLOQUE_WEBHOOK_SECRET! },
);
您也可以设置 webhookSecret 期间 Bloque 初始化和省略 options 内 verify。 。 。 .
示例
完整的例子见:
examples/basic-checkout.ts