SDK Integration (V2)
Quick Reference
The A55Pay JavaScript SDK V2 runs in the buyer's browser: it collects card data, runs Device Data Collection (DDC), handles 3DS authentication, processes the payment, and surfaces callbacks. Raw card data does not pass through your origin servers.
Why SDK
| Benefit | Detail |
|---|---|
| Secure by default | Card data stays in browser — A55 handles encryption |
| Fastest integration | One script tag + one function call |
| Built-in DDC & 3DS | SDK runs device fingerprinting and authentication automatically |
| Event callbacks | onSuccess, onError, onReady / onClose for full control |
How it works
Step-by-step integration
Load the SDK
Add the script tag to your checkout page:
<script src="https://cdn.jsdelivr.net/npm/a55pay-sdk"></script>
Pin a minor version in production (e.g., a55pay-sdk@1.2.x) for reproducible behavior across deploys.
Create a charge on your backend
Your backend creates a charge without card data — the SDK will collect and submit card data from the browser.
- cURL
- Python
- Node.js
- Go
- Java
- PHP
curl -sS -X POST "https://sandbox.api.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": "Jane Doe",
"payer_email": "jane@example.com",
"payer_tax_id": "12345678901",
"currency": "BRL",
"installment_value": 10000,
"installment_count": 1,
"type_charge": "credit_card",
"description": "SDK charge",
"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://sandbox.api.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": "Jane Doe", "payer_email": "jane@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://sandbox.api.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: "Jane Doe", payer_email: "jane@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://sandbox.api.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://sandbox.api.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://sandbox.api.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;
Call A55Pay.payV2() from the browser
Pass the chargeUuid from your backend and the card data collected in the browser:
A55Pay.payV2({
charge_uuid: chargeUuid,
userData: {
name: 'Jane Doe',
email: 'jane@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) => {
// Payment confirmed — show success to buyer
console.log('Charge confirmed:', payload);
},
onError: (err) => {
// Decline or error — show appropriate message
console.error('Charge failed:', err);
},
onReady: () => {
// SDK initialized — you can show the payment form
},
});
The SDK will automatically: run DDC -> submit payment -> handle 3DS challenge (if needed) -> call onSuccess or onError.
Handle callbacks
| Callback | When it fires | What to do |
|---|---|---|
onSuccess(payload) | Payment completed (confirmed or paid) | Show success, redirect to order page |
onError(err) | Decline, error, or authentication failure | Show user-friendly error message |
onReady() | SDK initialized and ready | Optionally show the card form |
Expected onSuccess payload:
{
"chargeUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "confirmed",
"reference_external_id": "sdk_001"
}
Expected onError payload:
{
"chargeUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "error",
"message": "Card declined by issuer"
}
Confirm via webhook
Always use the webhook as the source of truth. The buyer might close the browser before onSuccess fires.
{
"charge_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "paid",
"transaction_reference": "txn_ref_001"
}
A55Pay.open(config) — iframe checkout
For a fully hosted checkout experience inside an iframe or modal:
const { close } = A55Pay.open({
checkoutUuid: chargeUuid,
display: 'modal', // 'modal' or 'inline'
containerId: 'checkout', // required for 'inline'
onSuccess: (payload) => {
console.log('Payment confirmed:', payload);
},
onError: (err) => {
console.error('Payment error:', err);
},
onClose: () => {
console.log('Checkout closed by user');
},
onEvent: (event) => {
console.log('Checkout event:', event);
},
});
| Callback | payV2 | open |
|---|---|---|
onSuccess | Yes | Yes |
onError | Yes | Yes |
onReady | Yes | No |
onClose | No | Yes |
onEvent | No | Yes |
A55Pay.startApplePay(config) — Apple Pay button
Use A55Pay.startApplePay() to process Apple Pay payments natively in Safari without handling Apple Pay tokens on your backend.
Apple Pay requires prior registration of your merchant in A55's Apple Pay account and hosting a domain verification file. Contact tech.services@a55.tech before integrating.
Step 1 — Create a charge (no card data)
Create a charge on your backend with type_charge: "applepay" but without card fields. The charge returns status: "issued" and a charge_uuid.
curl -X POST https://sandbox.api.a55.tech/api/v1/bank/wallet/charge/ \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "YOUR_MERCHANT_UUID",
"wallet_uuid": "YOUR_WALLET_UUID",
"payer_name": "John Does",
"description": "Order #123",
"due_date": "2025-10-31",
"installment_count": 1,
"installment_value": 100.00,
"currency": "BRL",
"webhook_url": "https://yoursite.com/webhook",
"type_charge": "applepay"
}'
{
"charge_uuid": "58e6dabd-71fe-49ed-8f55-ec055648dae7",
"status": "issued",
"type": "applepay",
"charge_payment_url": "https://pay.a55.tech/charge/v2/58e6dabd-71fe-49ed-8f55-ec055648dae7"
}
Step 2 — Render the Apple Pay button
Host the domain verification file at /.well-known/apple-developer-merchantid-domain-association, then pass the charge_uuid to A55Pay.startApplePay():
<apple-pay-button
id="apple-pay-btn"
buttonstyle="black"
type="pay"
locale="en-US"
style="display:none; --apple-pay-button-width:240px; --apple-pay-button-height:44px; --apple-pay-button-border-radius:8px;"
></apple-pay-button>
<script src="https://cdn.jsdelivr.net/npm/a55pay-sdk/dist/a55pay-sdk.min.js"></script>
<script>
var btn = document.getElementById('apple-pay-btn');
if (A55Pay.isApplePayAvailable()) {
btn.style.display = 'inline-block';
}
btn.addEventListener('click', function () {
A55Pay.startApplePay({
chargeUuid: 'CHARGE_UUID_FROM_STEP_1',
countryCode: 'US',
amount: 100.00,
currencyCode: 'BRL', // default: 'BRL'
merchantDomain: 'pay.a55.tech', // default: 'pay.a55.tech'
displayName: 'Your Company', // default: 'A55Pay'
supportedNetworks: ['visa', 'masterCard', 'elo', 'amex'],
onSuccess: function (result) { console.log('Approved:', result); },
onError: function (error) { console.error('Error:', error.message); },
onClose: function () { console.log('Cancelled by user'); },
});
});
</script>
| Callback | When it fires | What to do |
|---|---|---|
onSuccess(result) | Payment approved | Show success, redirect to order page |
onError(error) | Decline or error | Show user-friendly error message |
onClose() | User cancelled Apple Pay sheet | Restore UI to initial state |
| Method | payV2 | open | startApplePay |
|---|---|---|---|
| Payment method | Credit/debit card | Credit/debit card | Apple Pay |
| Card data collected by | Your form | A55 (hosted) | Apple Pay (device) |
| Requires Apple registration | No | No | Yes |
| Safari only | No | No | Yes |
Full Apple Pay documentation →
Test with sandbox cards
| Card Number | Brand | Scenario | Expected Status |
|---|---|---|---|
4111 1111 1111 1111 | Visa | Successful payment | confirmed |
5500 0000 0000 0004 | Mastercard | Successful payment | confirmed |
4000 0000 0000 0002 | Visa | Card declined | declined |
4000 0000 0000 0101 | Visa | 3DS challenge required | confirmed |
4000 0000 0000 0069 | Visa | Processing error | error |
Never log PAN, CVV, or cryptograms from callback payloads. The SDK handles card data in the browser context — keep it there.
Want higher approval rates?
Visa Data Only shares enriched data with issuers through 3DS rails — without any challenge. Square's pilot showed up to +646 basis points improvement.
If you use payV2, the SDK already collects device data via DDC. You can combine this with data_only: true on the backend charge to maximize approvals without adding friction.