API tương thích Coinbase Commerce
Các endpoint charge, header X-CC-Api-Key, đối tượng charge và webhook ký bằng X-CC-Webhook-Signature đều theo tài liệu của Coinbase Commerce, nên các SDK chính thức hoạt động sau khi đổi một dòng. Coinbase Commerce đã ngừng phục vụ người bán ngoài Hoa Kỳ và Singapore từ ngày 2026-03-31. Đến từ nơi khác? Xem tổng quan chuyển đổi.
Bên dưới đó là một hóa đơn blockwallets bình thường: địa chỉ nhận tiền là của bạn, trang thanh toán là trang thanh toán do chúng tôi lưu trữ, và một khoản thanh toán chỉ được tính khi đã được xác nhận trên chuỗi và đối chiếu với node thứ hai. Phần dưới gồm: ba bước, rồi từng API hỗ trợ gì và khác bản gốc ở đâu — tham số chúng tôi không triển khai sẽ trả về lỗi chứ không bị bỏ qua âm thầm.
Ba bước
- Có tài khoản người bán (đăng ký dùng ở trang chủ) và thêm tên miền của bạn trong “Tên miền website” ở “Nhà phát triển › Tích hợp & khóa” trong trang quản trị. URL callback (
ipn_callback_url) và URL chuyển hướng (success_url/cancel_url/redirect_url) phải thuộc các tên miền đó hoặc tên miền của URL callback của bạn — khóa bị lộ cũng không thể trỏ webhook sang nơi khác. - Tạo thông tin xác thực tương thích trong trang quản trị ở mục “Nhà phát triển › Tích hợp & khóa”, một bộ cho live và một bộ cho thử nghiệm: NOWPayments dùng API key + IPN secret, Coinbase Commerce dùng API key + webhook shared secret. Chúng chỉ hiển thị một lần; chúng tôi chỉ lưu giá trị băm / bản mã hóa.
- Trỏ code của bạn đến URL gốc bên dưới và dùng khóa mới. Chạy thử trên testnet bằng thông tin xác thực thử nghiệm trước, rồi mới chuyển sang live.
| Trước | Sau | Header xác thực | Chữ ký webhook |
|---|---|---|---|
https://api.commerce.coinbase.com | https://blockwallets.io/coinbase/ | X-CC-Api-Key | X-CC-Webhook-Signature (HMAC-SHA256) |
Coinbase Commerce
Mọi SDK chính thức đều nhận một URL gốc — chỉ đổi một dòng (chú ý dấu / ở cuối):
// Node(coinbase-commerce-node)
const { Client } = require("coinbase-commerce-node");
- Client.init(process.env.COINBASE_COMMERCE_API_KEY);
+ Client.init(process.env.COINBASE_COMMERCE_API_KEY, "https://blockwallets.io/coinbase/");
# Python(coinbase-commerce)
- client = Client(api_key=API_KEY)
+ client = Client(api_key=API_KEY, base_api_uri="https://blockwallets.io/coinbase/")
// PHP(coinbase/coinbase-commerce)
- ApiClient::init($apiKey);
+ ApiClient::init($apiKey, 'https://blockwallets.io/coinbase/');curl -X POST https://blockwallets.io/coinbase/charges \
-H "X-CC-Api-Key: $COINBASE_COMMERCE_API_KEY" -H "X-CC-Version: 2018-03-22" \
-H "content-type: application/json" \
-d '{"name":"Order #12345","description":"Pro plan","pricing_type":"fixed_price",
"local_price":{"amount":"100.00","currency":"USD"},
"redirect_url":"https://shop.example/success","cancel_url":"https://shop.example/cancel",
"metadata":{"order_id":"12345"}}'
# → 201 {"data": {"id": "…", "code": "7C7V5ECK", "hosted_url": "https://blockwallets.io/pay/inv_…", "timeline": [{"status": "NEW", …}], …}}Endpoint được hỗ trợ
| Endpoint | Ghi chú |
|---|---|
POST /charges | Tạo charge; hosted_url là trang thanh toán do chúng tôi lưu trữ; có hiệu lực 1 giờ |
GET /charges/:code_or_id | Tra cứu theo mã 8 ký tự hoặc id |
GET /charges | Danh sách: limit (≤100) / starting_after / ending_before / order, với cùng đối tượng pagination |
POST /charges/:code_or_id/cancel | Hủy charge chưa thấy khoản thanh toán nào |
Không có: /charges/:code/resolve (400 — hãy xử lý charge trả thiếu trong trang quản trị), /checkouts, /events, /invoices (404).
Webhook
Webhook của Coinbase ở cấp tài khoản, và của chúng tôi cũng vậy: chúng đến URL callback đặt trong trang quản trị của bạn (charge tạo bằng thông tin xác thực thử nghiệm đến URL callback thử nghiệm). Nội dung là {id, scheduled_for, attempt_number, event: {id, type, api_version, created_at, data}} của Coinbase, với charge đầy đủ trong data; X-CC-Webhook-Signature = HMAC-SHA256(shared secret, nội dung thô), nên Webhook.verifyEventBody của các SDK dùng được nguyên trạng. Khi thử lại, event.id giữ nguyên còn attempt_number tăng lên — hãy loại trùng theo event.id.
import crypto from "node:crypto";
// Same as the SDK's Webhook.verifySigHeader: HMAC-SHA256(shared secret, raw body)
function verifyWebhook(rawBody, sig, sharedSecret) {
const hmac = crypto.createHmac("sha256", sharedSecret).update(rawBody, "utf8").digest("hex");
return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(sig || ""));
}
// verifyWebhook(rawBody, req.headers["x-cc-webhook-signature"], process.env.COINBASE_WEBHOOK_SECRET)
// or with the official SDK:Webhook.verifyEventBody(rawBody, signature, sharedSecret)| Sự kiện | Khi nào | Mục cuối trong timeline |
|---|---|---|
charge:confirmed | Đã thanh toán (được xác nhận trên chuỗi và đối chiếu; trả dư vẫn tính) | COMPLETED |
charge:failed | Hết hạn chưa thanh toán / bạn đã hủy / hết hạn khi trả thiếu | EXPIRED / CANCELED / UNRESOLVED (context UNDERPAID) |
Khi truy vấn bạn còn thấy NEW (chờ thanh toán) và PENDING (đã thấy thanh toán trên chuỗi, đang xác nhận). Hãy giao hàng khi nhận charge:confirmed: chúng tôi không gửi charge:created, charge:pending, charge:delayed hay charge:resolved.
Khác biệt so với Coinbase Commerce
pricing_typephải làfixed_price;local_price.currencyphải là USD (USDC / USDT theo 1:1).no_pricevà tiền pháp định khác trả về 400.- Địa chỉ xuất hiện khi khách chọn coin và mạng tại trang thanh toán:
addresseschỉ chứa mạng đó,pricingchỉ cólocalcùngsettlementsau khi đã chọn; không cóexchange_rates,checkouthay các trường thương hiệu. metadatađược lưu và trả lại nguyên vẹn (tối đa 4 KB).- Hoàn tiền không xuất hiện trong timeline; hãy xem trong trang quản trị.
Chế độ thử nghiệm
Charge và thanh toán tạo bằng thông tin xác thực thử nghiệm chạy trên testnet của từng chuỗi và webhook của chúng được ký bằng IPN secret / shared secret thử nghiệm — tách biệt hoàn toàn với live: khóa thử nghiệm không thấy được các khoản thanh toán live.
Mọi thứ còn lại (trang thanh toán, xác nhận, mạng và mức tối thiểu, hoàn tiền) hoạt động như trong tài liệu chính.