Cryptomus 호환 API
blockwallets로 USDT와 USDC, 그리고 BTC, LTC, DOGE, BCH와 각 체인의 네이티브 코인(고정 환율의 미국 달러로 정산)을 받을 수 있습니다. 고객이 결제하면 저희가 체인에서 확인하고 당신에게 알려 드립니다. API, 서명, 웹훅은 Cryptomus와 같아서, Cryptomus를 연동해 두었다면 도메인만 바꾸면 끝입니다. 먼저 동작 방식을, 그다음 API를 설명합니다.
돈을 받는 두 가지 방법
둘 다 금액에 제한이 없어 고정 가격 주문도, 고객이 금액을 직접 입력하는 충전도 받을 수 있습니다. 결제가 끝나면 상품을 발송하거나 고객의 잔액을 충전하세요. 차이는 결제마다 새 주소를 쓰느냐 하나뿐입니다.
고객이 당신의 페이지에서 상품을 고르거나 금액을 입력하면 청구서를 만들고, 고객은 결제 페이지에 표시된 금액을 보냅니다. 청구서마다 새 주소와 카운트다운이 있고, 입금되면 실제로 받은 금액과 함께 알려 드립니다.
POST /v1/payment → 웹훅 type: payment
금액을 미리 정하지 않습니다. 고객마다 네트워크별로 영구 주소를 하나씩 주고, 고객은 그 주소를 지갑에 저장해 두었다가 언제든 보낼 수 있습니다. 송금할 때마다 웹훅이 한 번씩 갑니다.
POST /v1/wallet → 웹훅 type: wallet
잘 모르겠다면 청구서를 쓰세요. 코드 없이 쓰려면 관리 화면의 결제 링크가 대신 청구서를 만들어 줍니다. 아직 가맹점이 아니라면 홈페이지에서 이용을 신청하세요. 승인되면 가맹점 관리 화면에 로그인해 먼저 관리 화면 홈의 “한 건 시험 결제”로 소액을 보내 보세요(돈은 당신의 잔액으로 들어갑니다).
청구서의 흐름
결제에는 고객, 당신의 사이트, blockwallets, 블록체인 네 주체가 참여합니다. 다이어그램은 위에서 아래로 시간순이며, 오른쪽 열은 각 단계에서의 청구서 상태입니다.
다이어그램이 넓으니 옆으로 스크롤하세요.
요약하면 다섯 단계입니다.
- 청구서를 만들고(결제 링크가 대신 해 주거나 서버가
/v1/payment를 호출), 결제 페이지url을 받아 고객을 그곳으로 보냅니다. - 고객은 결제 페이지에서 코인과 네트워크를 고르고, 전용 주소와 금액을 받아 지갑이나 거래소에서 송금합니다.
- 체인에서 송금을 확인하고 컨펌이 충분히 쌓일 때까지 기다린 뒤, 다른 노드 제공자로 한 번 더 대조합니다(노드 하나가 거짓 데이터를 줄 수 없게).
- 청구서가
paid가 되면 즉시 서명된 웹훅을url_callback으로 POST하고, 몇 초 뒤 결제 페이지가 고객을url_success로 돌려보냅니다. - 돈이 잔액에 들어오고, 가맹점 관리 화면에서 내 지갑으로 출금할 수 있습니다.
청구서 상태
| status | 의미 | 할 일 |
|---|---|---|
check | 결제 대기 | — |
confirm_check | 송금이 보이고 컨펌을 기다리는 중 | — |
wrong_amount_waiting | 받았지만 부족함. 고객이 같은 주소로 추가 송금 가능(is_payment_multiple이 true일 때, 알림은 한 번) | — (추가 송금이 끝나면 paid가 옵니다) |
paid | 결제 완료 | payment_amount_usd 기준으로 발송 / 충전 |
paid_over | 결제 완료, 초과 결제 | 동일(payment_amount_usd는 받은 금액) |
wrong_amount | 전액을 받지 못한 채 만료됨(is_payment_multiple이 false면 처음 부족하게 송금한 시점) | 충전형 서비스는 받은 payment_amount_usd만큼 충전할 수 있고, 쇼핑몰은 고객에게 나머지 결제를 안내 |
cancel | 받은 금액 없이 만료됨 | — (나중에 도착한 돈도 입금 처리되고 알림이 갑니다) |
is_final이 true이면 상태가 더 바뀌지 않습니다(늦게 도착한 결제 제외).
결제 링크 (코드 없음)
가맹점 관리 화면 → “결제 › 결제 링크” → 설명과 금액 입력(네트워크를 고정하거나 고객이 고르게 함) → 만들기. 링크마다 URL과 QR 코드가 생깁니다.
- 링크를 열 때마다 새 청구서가 만들어지므로 링크 하나를 계속 재사용할 수 있습니다(예: “회원권 $99”).
- 모든 결제는 “결제 › 결제 내역” 아래에 표시되고, “자금 › 잔액과 출금”에서 내 지갑으로 출금합니다.
- “개발자 › 연동 및 키”에서 자격 증명과 웹훅 URL을 만들어 두었다면, 링크로 들어온 결제도 아래 형식으로 알려 드립니다.
- 받기를 멈추려면 “비활성화”를 누르세요. 링크는 즉시 작동을 멈춥니다.
API 연동
1. 자격 증명과 서명
가맹점 관리 화면 → “개발자 › 연동 및 키” → merchant(UUID)와 API key를 생성합니다. Live용과 Test용이 각각 한 세트씩 있습니다. Live는 실제 돈을 받고 Test는 테스트넷에서 동작합니다. 웹사이트 도메인도 등록하세요. url_callback, url_return, url_success는 이 도메인에 속해야 합니다. API key는 한 번만 표시되므로 안전하게 보관하고 서버에서만 사용하세요.
기본 URL은 https://blockwallets.io입니다. 모든 엔드포인트는 POST + JSON이고 다음 헤더를 보냅니다.
merchant: 가맹점 UUID(Live인지 Test인지가 여기서 결정됩니다)sign:md5(base64(요청 본문) + API key). 본문은 보내는 JSON 문자열 그대로입니다
성공하면 {"state": 0, "result": {…}}, 실패하면 {"state": 1, "message": "…"}를 돌려줍니다(오류 참고).
아래 주요 엔드포인트에는 “직접 해보기” 패널이 있습니다. Test용 merchant와 API key를 입력하면 페이지가 브라우저에서 요청에 서명하고 엔드포인트를 호출한 뒤 요청과 응답 전체를 보여 줍니다(자격 증명은 페이지 메모리에만 있습니다). 서명이 맞지 않으면 서명 검사기로 단계별로 대조해 보세요.
import crypto from "node:crypto";
async function call(path, data) {
const body = JSON.stringify(data);
const sign = crypto.createHash("md5").update(Buffer.from(body).toString("base64") + process.env.BW_API_KEY).digest("hex");
const res = await fetch("https://blockwallets.io" + path, {
method: "POST",
headers: { merchant: process.env.BW_MERCHANT, sign, "Content-Type": "application/json" },
body,
});
return res.json();
}function bw_call(string $path, array $data): array {
$body = json_encode($data, JSON_UNESCAPED_UNICODE);
$sign = md5(base64_encode($body) . getenv('BW_API_KEY'));
$ch = curl_init('https://blockwallets.io' . $path);
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['merchant: ' . getenv('BW_MERCHANT'), 'sign: ' . $sign, 'Content-Type: application/json'],
]);
return json_decode(curl_exec($ch), true);
}import base64, hashlib, json, os, requests
def bw_call(path: str, data: dict) -> dict:
body = json.dumps(data, separators=(",", ":"), ensure_ascii=False)
sign = hashlib.md5((base64.b64encode(body.encode()).decode() + os.environ["BW_API_KEY"]).encode()).hexdigest()
headers = {"merchant": os.environ["BW_MERCHANT"], "sign": sign, "Content-Type": "application/json"}
return requests.post("https://blockwallets.io" + path, data=body.encode(), headers=headers).json()2. 청구서 만들기 POST /v1/payment
고객이 주문하거나 충전 페이지에서 금액을 입력하면 https://blockwallets.io/v1/payment를 호출하고, 응답의 result.url로 고객을 보냅니다.
{
"amount": "42.00",
"currency": "USD",
"order_id": "order_1042",
"url_callback": "https://shop.example/webhooks/crypto",
"url_return": "https://shop.example/cart",
"url_success": "https://shop.example/thanks?order=1042"
}| 매개변수 | 필수 | 설명 |
|---|---|---|
amount | 예 | 문자열로 된 금액, 소수점 둘째 자리까지: "42.00". 당신이 정한 가격 또는 고객이 입력한 숫자이며, 선택한 네트워크의 최소 금액보다 작으면 안 됩니다(네트워크 참고) |
currency | 예 | USD, USDT, USDC, 모두 1:1 |
order_id | 예 | 주문 번호: 영문자, 숫자, -, _, 100자 이하. 같은 order_id로 다시 호출하면 기존 청구서를 돌려줍니다(주문이 중복 생성되지 않음) |
url_callback | 아니요 | 웹훅 URL. 생략하면 웹훅을 보내지 않습니다 |
url_return | 아니요 | 결제 전에 “뒤로”를 누르면 이동할 주소 |
url_success | 아니요 | 결제 후 고객이 이동할 주소 |
network | 아니요 | 네트워크를 미리 지정: tron / bsc / eth / base / polygon / arbitrum / optimism / avalanche / xlayer / btc / ltc / doge / bch / sol / ton. 생략하면 고객이 결제 페이지에서 고릅니다 |
to_currency | 아니요 | 해당 네트워크의 코인: USDT / USDC. btc / ltc / doge / bch에서는 BTC / LTC / DOGE / BCH(선택) |
lifetime | 아니요 | 청구서 유효 시간(초), 300 – 43200, 기본값 3600. 600 미만은 600으로 처리됩니다 |
accuracy_payment_percent | 아니요 | 부족 결제를 어디까지 결제 완료로 볼지, 0 – 5, 기본값 0. 100 = 도착하는 대로 인정: 컨펌되자마자 paid(더 받았으면 paid_over)이며, 웹훅의 payment_amount_usd 기준으로 충전하면 됩니다. 충전형 서비스에 알맞습니다. 생략하면 관리 화면 “설정 › 결제 규칙 및 수수료율”의 “수취 금액 규칙”이 적용되고, “도착한 만큼 충전”은 100을 뜻합니다 |
subtract | 아니요 | 플랫폼 수수료 중 고객이 내는 비율, 0 – 100. payer_amount에 더해집니다(플랫폼 수수료는 1%이며 거래액이 많을수록 낮아집니다. 1%일 때 100으로 설정하면 $100 청구서의 고객 결제액은 $101.00. 요금 참고). 생략하면 관리 화면 “설정 › 결제 규칙 및 수수료율”의 “수수료와 부족 결제” 설정이 적용됩니다(기본값 0) |
is_payment_multiple | 아니요 | 부족 결제에 추가 송금을 허용할지, 기본값 true: 상태는 wrong_amount_waiting이며 나머지를 같은 주소로 보내면 paid가 됩니다(처음 부족하게 송금한 시점에 남은 시간이 30분 미만이면 만료 시각이 그때부터 30분 뒤로 늦춰짐). false: 처음 부족하게 송금하는 즉시 wrong_amount가 됩니다. 생략하면 관리 화면 설정이 적용됩니다 |
additional_data | 아니요 | 임의의 문자열(255자 이하), 조회와 웹훅에서 그대로 돌려줍니다 |
{
"state": 0,
"result": {
"uuid": "6f1c2a7e-…",
"order_id": "order_1042",
"amount": "42.00",
"currency": "USD",
"network": null,
"address": null,
"payer_amount": null,
"payment_amount": null,
"url": "https://blockwallets.io/pay/inv_01J8…",
"expired_at": 1760965200,
"status": "check",
"is_final": false
}
}network, address, payer_amount는 고객이 네트워크를 고른 뒤에 채워집니다.
3. 청구서 조회
POST /v1/payment/info{"order_id": "…"}또는{"uuid": "…"}: 청구서 한 건을 가져오며 그 과정에서 체인도 확인합니다(10초에 최대 한 번).POST /v1/payment/list: 목록, 페이지당 15건,date_from/date_to는 선택. 다음 페이지는 응답의paginate.nextCursor로 요청합니다(?cursor=…).POST /v1/payment/services: 사용 가능한 네트워크와 네트워크별 최소 금액.POST /v1/payment/resend{"order_id": "…"}: 결제 완료 / 부족 결제된 청구서의 웹훅을 다시 보냅니다.
웹훅이 기본 경로이고, 조회는 보조 수단입니다(예: 서버가 꺼져 있어 웹훅을 놓쳤을 때).
4. 고정 지갑 POST /v1/wallet
고객 한 명에게 네트워크 하나당 영구 주소를 만들어 줍니다. 같은 order_id(보통 당신의 사용자 id) + 네트워크는 항상 같은 주소를 돌려줍니다. 모든 EVM 체인(BNB Chain, Ethereum, Base, Polygon, Arbitrum, Optimism, Avalanche, X Layer)은 주소 하나를 공유하고, TRON, BTC, LTC, DOGE, BCH, Solana, TON은 각각 자기 주소가 있습니다. 고객이 보내는 금액은 모두 입금 처리되고 송금마다 웹훅이 한 번씩 갑니다. BTC / LTC / DOGE / BCH / TRX / BNB / ETH / POL / AVAX / OKB / SOL / TON 송금은 각 송금이 확인된 시점의 환율로 미국 달러로 환산됩니다(payment_amount_usd).
{
"order_id": "user_42",
"currency": "USDT",
"network": "tron",
"url_callback": "https://shop.example/webhooks/crypto"
}{
"state": 0,
"result": {
"wallet_uuid": "0b9d…",
"uuid": "5e2f…",
"order_id": "user_42",
"currency": "USDT",
"network": "tron",
"address": "TXy4…8kQ2",
"url": "https://blockwallets.io/deposit/dac_01J8…"
}
}result.url은 고객에게 건넬 수 있는 입금 전용 페이지입니다(주소 + QR 코드 + 최근 입금 내역). 해당 네트워크의 최소 금액(보통 $1, BTC $5) 미만 송금은 자동으로 입금 처리되지 않습니다. 입금 처리가 필요하면 문의해 주세요. 주소 차단(/v1/wallet/block-address)은 아직 지원하지 않습니다.
웹훅
청구서 상태가 바뀔 때(paid, paid_over, wrong_amount_waiting, wrong_amount, cancel)와 고정 지갑으로 송금이 들어올 때마다 url_callback으로 JSON을 POST합니다. 2xx 응답이면 전달된 것으로 보고, 그렇지 않으면 1분, 5분, 30분, 2시간, 12시간, 24시간, 24시간 뒤에 다시 시도합니다. 관리 화면이나 /v1/payment/resend로 다시 보낼 수도 있습니다.
{
"type": "payment",
"uuid": "6f1c2a7e-…",
"order_id": "order_1042",
"amount": "42.00",
"payment_amount": "42",
"payment_amount_usd": "42.00",
"merchant_amount": "41.58",
"commission": "0.42",
"is_final": true,
"status": "paid",
"from": "TQ8m…",
"wallet_address_uuid": null,
"network": "tron",
"currency": "USD",
"payer_currency": "USDT",
"payer_amount": "42",
"payer_amount_exchange_rate": "1",
"additional_data": null,
"txid": "9c1e…",
"sign": "5f0c9b…"
}| type | 언제 | 입금 처리 |
|---|---|---|
payment | 청구서 상태가 바뀜 — status 참고 | paid / paid_over일 때 payment_amount_usd만큼 충전하고, uuid로 중복을 제거합니다 |
wallet | 고정 지갑으로 송금이 들어옴(status는 항상 paid, order_id는 지갑을 만들 때 쓴 값) | payment_amount_usd만큼 충전합니다. 송금마다 고유한 uuid가 있으니 그것으로 중복을 제거하세요 |
서명 검증 (필수)
서명은 웹훅 본문의 sign 필드입니다. sign을 제거하고 나머지를 PHP json_encode처럼 다시 인코딩한 뒤(공백 없이, /는 \/로 이스케이프, 비 ASCII 문자는 이스케이프하지 않음) md5(base64(인코딩한 문자열) + API key)가 sign과 같아야 합니다. 같은 모드의 API key를 쓰세요. 같은 웹훅이 두 번 이상 올 수 있으니 uuid + status로 중복을 제거하세요.
검증에 실패하면 받은 웹훅 본문 원문을 서명 검사기에 붙여 넣으세요. 모든 단계의 결과를 보여 주고 어디서 달라지는지 표시해 줍니다(전부 브라우저에서 실행되며 API key는 업로드되지 않습니다). 관리 화면 “개발자 › 웹훅 로그”의 모든 웹훅은 한 번의 클릭으로 검사기에서 열립니다.
import crypto from "node:crypto";
function verify(rawBody, apiKey) {
const { sign, ...data } = JSON.parse(rawBody);
const json = JSON.stringify(data).replaceAll("/", "\\/");
const expected = crypto.createHash("md5").update(Buffer.from(json).toString("base64") + apiKey).digest("hex");
return typeof sign === "string" && sign.length === expected.length && crypto.timingSafeEqual(Buffer.from(sign), Buffer.from(expected));
}$data = json_decode(file_get_contents('php://input'), true);
$sign = $data['sign'] ?? '';
unset($data['sign']);
$expected = md5(base64_encode(json_encode($data, JSON_UNESCAPED_UNICODE)) . $apiKey);
if (!hash_equals($expected, $sign)) {
http_response_code(401); exit;
}import base64, hashlib, hmac, json
def verify(raw_body: bytes, api_key: str) -> bool:
data = json.loads(raw_body)
sign = data.pop("sign", "")
encoded = json.dumps(data, separators=(",", ":"), ensure_ascii=False).replace("/", "\\/")
expected = hashlib.md5((base64.b64encode(encoded.encode()).decode() + api_key).encode()).hexdigest()
return hmac.compare_digest(expected, sign)테스트 모드
Test용 merchant와 API key로 만든 청구서는 테스트넷에서 동작하며 실제 돈이 오가지 않습니다. 결제 페이지에 “결제 시뮬레이션” 버튼(전액 / 절반 / 초과)이 표시되므로 테스트넷 코인 없이도 상태 변화와 웹훅을 확인할 수 있습니다.
POST /v1/test-webhook/payment,/v1/test-webhook/wallet: 서명된 샘플 웹훅을url_callback으로 보냅니다(필수인url_callback(등록한 웹사이트 도메인의 주소)과currency,network를 넘기고, 선택으로status,order_id). 검증 코드를 디버깅할 때 쓰세요.- 관리 화면 “개발자 › 연동 및 키” → “테스트 알림 보내기”: 웹훅 URL로 샘플을 보냅니다.
- 관리 화면 “개발자 › 웹훅 로그”: 전달 시도마다 시각, 대상 URL, HTTP 상태, 소요 시간, 요청 본문, 서버의 응답(처음 4 KB)을 보여 주며 주문이나 상태로 필터링하고 한 번의 클릭으로 다시 보낼 수 있습니다. 30일간 보관합니다.
Cryptomus에서 이전하기
- 관리 화면 “개발자 › 연동 및 키” → merchant와 API key를 생성합니다.
- 코드의
https://api.cryptomus.com을https://blockwallets.io로 바꾸고 새 merchant와 API key를 사용합니다. - “웹사이트 도메인”에 도메인을 추가합니다(
url_callback/url_return/url_success는 이 도메인만 허용).
지원: /v1/payment, /v1/payment/info, /v1/payment/list, /v1/payment/services, /v1/payment/resend, /v1/wallet, /v1/test-webhook/payment, /v1/test-webhook/wallet.
차이점: 청구서는 USD / USDT / USDC로만 가격을 매기며(모두 1:1, 환율 스프레드 없음), commission은 저희 플랫폼 수수료(받은 금액 × 청구서를 만든 시점의 가맹점 요율. 표준 1%, 거래액에 따라 최저 0.5%까지. 고객이 부담한 부분에 수수료가 두 번 붙지는 않습니다)이고 merchant_amount = 받은 금액 − commission입니다. 고객이 BTC / LTC / DOGE / BCH / TRX / BNB / ETH / POL / AVAX / OKB / SOL / TON로 결제하면 여러 거래소의 중간값으로 견적을 내 30분간 고정합니다. payer_amount는 보낼 코인 수량, payer_amount_exchange_rate는 코인 1개의 USD 가치이며, 결제 금액은 고정된 환율로 payment_amount_usd로 환산됩니다(코인은 저희가 보유하며 따로 교환하지 않습니다). 네트워크는 tron / bsc / eth / base / polygon / arbitrum / optimism / avalanche / xlayer / btc / ltc / doge / bch / sol / ton. 청구서 최소 유효 시간은 10분. is_refresh는 없고 고정 지갑 차단도 없습니다. 웹훅은 기본적으로 바뀌는 IP에서 오며, IP로 허용 목록을 쓴다면 관리 화면 “개발자 › 연동 및 키”에서 “고정 IP 웹훅”을 켜세요. 그러면 웹훅은 18.163.145.41에서만 옵니다. 허용 목록은 추가 보호 장치일 뿐이니 sign 검증은 계속 하세요.
NOWPayments나 Coinbase Commerce에서 오셨나요? 둘 다 호환 API가 있으니 기본 URL과 키만 바꾸면 됩니다. 이전 가이드를 참고하세요.
네트워크와 금액
| 코인 | 네트워크 | network 매개변수 | 최소 금액 | 도착 시간 |
|---|---|---|---|---|
| USDT | TRON | tron | $1 | 약 1분 |
| USDT | BNB Chain | bsc | $1 | 약 1분 |
| USDC | BNB Chain | bsc | $1 | 약 1분 |
| USDT | Ethereum | eth | $5 | 약 1분 |
| USDC | Ethereum | eth | $5 | 약 1분 |
| USDC | Base | base | $1 | 약 1분 |
| USDT | Polygon | polygon | $1 | 약 1분 |
| USDC | Polygon | polygon | $1 | 약 1분 |
| USDT | Arbitrum | arbitrum | $1 | 약 1분 |
| USDC | Arbitrum | arbitrum | $1 | 약 1분 |
| USDT | Optimism | optimism | $1 | 약 1분 |
| USDC | Optimism | optimism | $1 | 약 1분 |
| USDT | Avalanche | avalanche | $1 | 약 1분 |
| USDC | Avalanche | avalanche | $1 | 약 1분 |
| USDT | X Layer | xlayer | $1 | 약 1분 |
| USDC | X Layer | xlayer | $1 | 약 1분 |
| USD1 | BNB Chain | bsc | $1 | 약 1분 |
| FDUSD | BNB Chain | bsc | $1 | 약 1분 |
| DAI | Ethereum | eth | $5 | 약 1분 |
| DAI | Arbitrum | arbitrum | $1 | 약 1분 |
| DAI | Base | base | $1 | 약 1분 |
| BTC | Bitcoin | btc | $5 | 약 10분 |
| LTC | Litecoin | ltc | $1 | 약 3분 |
| DOGE | Dogecoin | doge | $1 | 약 1분 |
| BCH | Bitcoin Cash | bch | $1 | 약 10분 |
| TRX | TRON | tron | $1 | 약 1분 |
| BNB | BNB Chain | bsc | $1 | 약 1분 |
| ETH | Ethereum | eth | $5 | 약 1분 |
| ETH | Base | base | $1 | 약 1분 |
| ETH | Arbitrum | arbitrum | $1 | 약 1분 |
| ETH | Optimism | optimism | $1 | 약 1분 |
| POL | Polygon | polygon | $1 | 약 1분 |
| AVAX | Avalanche | avalanche | $1 | 약 1분 |
| OKB | X Layer | xlayer | $1 | 약 1분 |
| USDT | Solana | sol | $1 | 약 1분 |
| USDC | Solana | sol | $1 | 약 1분 |
| SOL | Solana | sol | $1 | 약 1분 |
| USDT | TON | ton | $1 | 약 1분 |
| TON | TON | ton | $1 | 약 1분 |
ERC-20은 수수료가 높아 최소 금액이 $5이고, 비트코인도 수수료가 낮지 않아 최소 $5입니다. 나머지는 모두 $1입니다. 고객은 반드시 결제 페이지에 표시된 네트워크로 보내야 합니다. 다른 네트워크로 보낸 돈은 자동으로 입금 처리되지 않습니다.
BTC / LTC / DOGE / BCH는 멤풀에 들어오면 곧바로 “감지됨”으로 표시되고, 컨펌이 충분히 쌓여야 인정됩니다. 교체(RBF)되거나 사라진 트랜잭션은 인정되지 않습니다.
네이티브 코인(TRX, BNB, ETH, POL, AVAX, OKB, SOL, TON)은 BTC / LTC / DOGE / BCH처럼 고정 환율로 견적을 내고 미국 달러로 입금 처리됩니다. 네트워크와 코인을 모두 지정하세요. 청구서는 network: "bsc", to_currency: "BNB", 고정 지갑은 network: "bsc", currency: "BNB"입니다. 네트워크만 지정하면 해당 체인의 USDT가 기본값입니다(Base는 USDC).
컨트랙트가 보낸 송금(멀티시그, 일괄 지급)도 받을 수 있습니다. 일부 체인에서는 트랜잭션 해시를 알 수 없어 웹훅의 txid가 null일 수 있습니다.
오류
{ "state": 1, "message": "amount must be a number like 10.28" }| HTTP | 흔한 원인 |
|---|---|
| 422 | 매개변수가 없거나 형식이 잘못됨, 금액이 네트워크 최소 금액 미만, 콜백 / 리디렉션 URL이 등록한 도메인에 속하지 않음, /v1/payment에서 지원하지 않는 코인 / 네트워크를 지정함 |
| 401 | 잘못된 merchant, 잘못된 sign(Invalid Sign.), 또는 재발급되어 바뀐 API key |
| 404 | 청구서가 없거나 당신의 것이 아님(Payment not found), /v1/wallet에서 지원하지 않는 코인 / 네트워크 조합(The service was not found) |
| 503 | 네트워크를 일시적으로 쓸 수 없음 — 다른 네트워크를 고르거나 미리 지정하지 마세요 |
서명이 틀리면(Invalid Sign.) 응답에 debug 객체가 들어갑니다. body_base64는 저희가 받은 요청 본문의 base64(당신이 보낸 내용이며 API key는 절대 포함되지 않음)이고 body_bytes는 그 길이입니다. 서명할 때 만든 base64와 비교해 보세요. 다르면 보낸 본문이 서명한 문자열과 다른 것입니다(프레임워크가 다시 직렬화했거나, 프록시가 인코딩을 바꿨거나, 끝에 줄바꿈이 붙은 경우). 같다면 API key가 틀린 것입니다. 서명 검사기에 붙여 넣으면 처음 달라지는 곳을 볼 수 있습니다.
{
"state": 1,
"message": "Invalid Sign.",
"debug": {
"body_base64": "eyJhbW91bnQiOiI0Mi4wMCIsImN1cnJlbmN5IjoiVVNEIiwi…",
"body_bytes": 158,
"sign_formula": "md5(body_base64 + API key)"
}
}자주 묻는 질문
고객이 원하는 금액을 충전하게 하려면 어느 방식이 맞나요?
청구서입니다. 충전 페이지에서 고객이 금액을 입력하게 하고 그 금액으로 청구서를 만든 뒤, 도착하면 payment_amount_usd만큼 충전하세요. 고객이 주소 하나를 저장해 두고 반복해서 보내게 하고 싶을 때만 고정 지갑을 쓰세요.
고객이 부족하게 결제하면 어떻게 되나요?
만료 전에 고객이 결제 페이지에서 차액을 보낼 수 있습니다(남은 금액이 표시되며 상태는 wrong_amount_waiting이고, 처음 부족하게 송금한 시점에 남은 시간이 30분 미만이면 만료 시각이 그때부터 30분 뒤로 늦춰집니다). 만료 시점에도 부족하면 청구서는 wrong_amount가 되고 웹훅의 payment_amount_usd는 받은 금액입니다. 충전형 서비스는 그 금액만큼 충전하면 됩니다.
고객이 늦게 결제하거나 두 번 결제하면요?
만료 후에 도착한 돈도 입금 처리되고 알림이 갑니다. 청구서가 전액 결제된 뒤에 도착한 돈도 기록되어 관리 화면에서 볼 수 있습니다.
고객이 다른 네트워크로 보내면요?
예를 들어 청구서는 TRON인데 BNB Chain에서 보낸 경우입니다. 자동으로 입금 처리되지 않으니 저희에게 연락하시면 직접 처리해 드립니다.
비용은 얼마인가요?
받은 결제 건당 1%이며 지난달 거래액에 따라 자동으로 내려갑니다($50,000 이상 0.9%, $100,000 이상 0.8%, $250,000 이상 0.7%, $500,000 이상 0.6% 및 $1,000,000 이상 0.5%). 월 이용료와 가입비는 없습니다. 네트워크 수수료는 고객이 송금할 때 부담합니다. 고객에게 수수료를 넘기려면 청구서를 만들 때 subtract를 설정하거나 관리 화면에서 기본값을 정하세요. 출금에는 추가 수수료가 없습니다. 요금을 참고하세요.
돈은 언제 받나요?
결제가 컨펌되는 즉시 잔액에 들어옵니다. “자금 › 잔액과 출금”에서 내 지갑으로 출금을 신청하면, 저희가 승인한 뒤 지급하고 체인상 트랜잭션이 출금 내역에 표시됩니다.
자동 출금도 켤 수 있습니다. 출금 가능한 잔액이 정해 둔 금액에 도달하거나 매일 00:00 UTC가 되면 출금 가능한 잔액 전체를 출금합니다. 자동 출금도 같은 방식으로 검토하며, 설정을 바꿀 때마다 이메일로 알림이 갑니다.