SDK 集成(V2)
Quick Reference
WhatA55Pay JS SDK V2
Why卡数据留在浏览器中——内置 DDC 与 3DS(3D Secure 验证)的最快路径
Reading Time15 分钟
Difficulty初级
Prerequisites身份验证 → 创建收款
A55Pay JavaScript SDK V2 在买家浏览器中运行:采集卡数据、执行设备数据采集(Device Data Collection,DDC)、处理 3DS 认证、完成支付并触发回调。原始卡数据不会经过您的源站服务器。
为何使用 SDK
| 优势 | 说明 |
|---|---|
| 默认安全 | 卡数据留在浏览器——A55 全面处理卡数据安全 |
| 最快集成 | 一个 script 标签 + 一次函数调用 |
| 内置 DDC 与 3DS | SDK 自动运行设备指纹与认证 |
| 事件回调 | onSuccess、onError、onReady / onClose 供您完全掌控 |
工作原理
分步集成
1
加载 SDK
在结账页加入 script 标签:
<script src="https://cdn.jsdelivr.net/npm/a55pay-sdk"></script>
版本固定
生产环境请固定次版本(例如 a55pay-sdk@1.2.x),以便各次部署行为可复现。
2
在后端创建收费
后端创建不含卡数据的收费——SDK 将在浏览器中采集并提交卡数据。
- cURL
- Python
- Node.js
- Go
- Java
- PHP
curl -sS -X POST "https://core-manager.a55.tech/api/v1/bank/wallet/charge/" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"merchant_id": "merchant_123",
"payer_name": "张伟",
"payer_email": "zhangwei@example.com",
"payer_tax_id": "12345678901",
"currency": "BRL",
"installment_value": 10000,
"installment_count": 1,
"type_charge": "credit_card",
"description": "SDK 测试收费",
"reference_external_id": "sdk_001",
"webhook_url": "https://merchant.example/webhooks/a55",
"redirect_url": "https://merchant.example/return"
}'
import os, requests
r = requests.post(
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/",
headers={"Authorization": f"Bearer {os.environ['ACCESS_TOKEN']}",
"Content-Type": "application/json"},
json={
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"merchant_id": "merchant_123",
"payer_name": "张伟", "payer_email": "zhangwei@example.com",
"payer_tax_id": "12345678901",
"currency": "BRL", "installment_value": 10000, "installment_count": 1,
"type_charge": "credit_card",
"reference_external_id": "sdk_001",
"webhook_url": "https://merchant.example/webhooks/a55",
},
)
charge_uuid = r.json()["uuid"]
const res = await fetch(
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
wallet_uuid: "00000000-0000-4000-8000-000000000001",
merchant_id: "merchant_123",
payer_name: "张伟", payer_email: "zhangwei@example.com",
payer_tax_id: "12345678901",
currency: "BRL", installment_value: 10000, installment_count: 1,
type_charge: "credit_card",
reference_external_id: "sdk_001",
webhook_url: "https://merchant.example/webhooks/a55",
}),
}
);
const { uuid: chargeUuid } = await res.json();
payload := map[string]interface{}{
"wallet_uuid": "00000000-0000-4000-8000-000000000001",
"type_charge": "credit_card", "currency": "BRL",
"installment_value": 10000, "installment_count": 1,
"reference_external_id": "sdk_001",
"webhook_url": "https://merchant.example/webhooks/a55",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://core-manager.a55.tech/api/v1/bank/wallet/charge/", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ACCESS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var result struct{ UUID string `json:"uuid"` }
json.NewDecoder(resp.Body).Decode(&result)
String json = """
{"wallet_uuid":"00000000-0000-4000-8000-000000000001",
"type_charge":"credit_card","currency":"BRL",
"installment_value":10000,"installment_count":1,
"reference_external_id":"sdk_001",
"webhook_url":"https://merchant.example/webhooks/a55"}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://core-manager.a55.tech/api/v1/bank/wallet/charge/"))
.header("Authorization", "Bearer " + System.getenv("ACCESS_TOKEN"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json)).build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
String chargeUuid = new JSONObject(resp.body()).getString("uuid");
$payload = [
"wallet_uuid" => "00000000-0000-4000-8000-000000000001",
"type_charge" => "credit_card", "currency" => "BRL",
"installment_value" => 10000, "installment_count" => 1,
"reference_external_id" => "sdk_001",
"webhook_url" => "https://merchant.example/webhooks/a55",
];
$ch = curl_init("https://core-manager.a55.tech/api/v1/bank/wallet/charge/");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("ACCESS_TOKEN"),
"Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$chargeUuid = json_decode(curl_exec($ch))->uuid;
3
在浏览器中调用 A55Pay.payV2()
传入后端返回的 chargeUuid 以及在浏览器中采集的卡数据:
A55Pay.payV2({
charge_uuid: chargeUuid,
userData: {
name: '张伟',
email: 'zhangwei@example.com',
document: '12345678901',
card_number: '4111111111111111',
card_expiry_month: '12',
card_expiry_year: '2030',
card_cvv: '123',
address: {
street: 'Av. Paulista 1000',
city: 'São Paulo',
state: 'SP',
zip_code: '01310100',
country: 'BR',
},
},
onSuccess: (payload) => {
// 支付已确认——向买家展示成功
console.log('收费已确认:', payload);
},
onError: (err) => {
// 拒绝或错误——展示适当的错误信息
console.error('收费失败:', err);
},
onReady: () => {
// SDK 已初始化——可以显示支付表单
},
});
SDK 将自动:运行 DDC → 提交支付 → 处理 3DS 挑战(如需要)→ 调用 onSuccess 或 onError。
4
处理回调
| 回调 | 触发时机 | 建议操作 |
|---|---|---|
onSuccess(payload) | 支付完成(confirmed 或 paid) | 展示成功,跳转订单页 |
onError(err) | 拒绝、错误或认证失败 | 展示用户可理解的错误信息 |
onReady() | SDK 已初始化并就绪 | 可选:显示卡表单 |
onSuccess 预期载荷:
{
"chargeUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "confirmed",
"reference_external_id": "sdk_001"
}
onError 预期载荷:
{
"chargeUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "error",
"message": "Card declined by issuer"
}
5
通过 Webhook 确认
请始终将 Webhook(网络钩子)作为最终事实来源(source of truth)。买家可能在 onSuccess 触发前关闭浏览器。
{
"charge_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "paid",
"transaction_reference": "txn_ref_001"
}
A55Pay.open(config)——iframe 结账
若要在 iframe 或弹层中获得完全托管的结账体验:
const { close } = A55Pay.open({
checkoutUuid: chargeUuid,
display: 'modal', // 'modal' 或 'inline'
containerId: 'checkout', // 'inline' 模式下必填
onSuccess: (payload) => {
console.log('支付已确认:', payload);
},
onError: (err) => {
console.error('支付错误:', err);
},
onClose: () => {
console.log('用户关闭了结账');
},
onEvent: (event) => {
console.log('结账事件:', event);
},
});
| 回调 | payV2 | open |
|---|---|---|
onSuccess | 是 | 是 |
onError | 是 | 是 |
onReady | 是 | 否 |
onClose | 否 | 是 |
onEvent | 否 | 是 |
使用沙箱测试卡
| Card Number | Brand | Scenario | Expected Status |
|---|---|---|---|
4111 1111 1111 1111 | Visa | 支付成功 | confirmed |
5500 0000 0000 0004 | Mastercard | 支付成功 | confirmed |
4000 0000 0000 0002 | Visa | 卡被拒绝 | declined |
4000 0000 0000 0101 | Visa | 需要 3DS 挑战 | confirmed |
4000 0000 0000 0069 | Visa | 处理错误 | error |
日志
切勿记录回调载荷中的 PAN、CVV 或密码文(cryptogram)。SDK 在浏览器上下文中处理卡数据——请保持在该环境中。
希望提高通过率?
Visa Data Only 通过 3DS 通道与发卡行共享丰富数据——无需任何挑战。Square 的试点显示最高可达 +646 个基点 的提升。
若使用 payV2,SDK 已通过 DDC 采集设备数据。您可在后端收费请求上同时设置 data_only: true,在几乎不增加摩擦的情况下尽量提高通过率。