API 레퍼런스

완전한 ChainPay 연동 가이드. 몇 분 만에 암호화폐 결제를 받으세요.

Next.js 스타터 템플릿

인증, 요금제 페이지, ChainPay 결제가 사전 연동된 완전한 Next.js 앱입니다. 클론하고 5분 만에 실행하세요.

GitHub에서 보기

빠른 시작

세 단계로 암호화폐 결제를 받으세요 — 블록체인 지식이 필요 없습니다.

1

결제 주문을 생성합니다

Node.js
const response = await fetch("https://chainpay.pro/api/v1/orders", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    amount: 29.99,
    currency: "USDT",
    chain: "trc20",
    externalId: "order_abc123",           // your internal order ID
    metadata: { userId: "user_456" }      // arbitrary JSON, returned in webhook
  })
});

const order = await response.json();
// order.checkoutUrl  → redirect user here
// order.payAddress   → or show the address directly
2

사용자를 결제 페이지로 리디렉션합니다

JavaScript
// Server-side redirect
res.redirect(order.checkoutUrl);

// Or client-side
window.location.href = order.checkoutUrl;
3

결제가 확인되면 Webhook을 수신합니다

Webhook 페이로드(서버로 POST)
{
  "event": "payment.completed",
  "orderId": "ord_a1b2c3d4e5f6",
  "externalId": "order_abc123",
  "amount": "29.99",
  "netAmount": "29.75",          // after 0.8% fee
  "currency": "USDT",
  "chain": "trc20",
  "txHash": "e3b0c44298fc1c149afb...",
  "completedAt": "2026-03-22T08:15:00Z",
  "metadata": { "userId": "user_456" }
}

처리하기 전에 X-ChainPay-Signature 헤더를 검증하세요. 검증 코드는 섹션을 참고하세요.

인증

모든 API 요청에는 API 키를 Bearer 토큰으로 포함해야 합니다.

HTTP 헤더
Authorization: Bearer sk_live_YOUR_API_KEY
cURL 예제
curl -X POST https://chainpay.pro/api/v1/orders \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount": 10, "currency": "USDT", "chain": "trc20"}'
키 접두사환경블록체인
sk_live_…프로덕션실제 거래
sk_test_…샌드박스실제 자금 이동 없음
보안: 클라이언트 측 코드나 공개 저장소에 API 키를 절대 노출하지 마세요. 환경 변수로 저장하고 백엔드에서만 API를 호출하세요.

주문 생성

POSThttps://chainpay.pro/api/v1/orders

요청 매개변수

매개변수타입필수 여부설명
amountnumber필수USD 기준 결제 금액(예: 29.99). 이에 상응하는 암호화폐 금액은 현재 시세로 계산됩니다.
currencystring필수받을 암호화폐. 다음 중 하나: "USDT", "ETH", "BTC", "SOL".
chainstring필수블록체인 네트워크. 다음 중 하나: "trc20", "erc20", "btc", "sol". 선택한 통화와 호환되어야 합니다.
externalIdstring선택내부 주문 식별자. Webhook에서 변경 없이 반환됩니다. 가맹점별로 고유해야 합니다.
metadataobject선택임의의 JSON 객체(최대 2 KB). 이 주문의 모든 Webhook에서 반환됩니다 — 사용자 ID, 장바구니 참조 등을 전달하는 데 유용합니다.

지원되는 통화 + 체인 조합

currencychain네트워크평균 확인 시간
USDTtrc20TRON (TRC-20)약 1분
USDTerc20Ethereum (ERC-20)약 2분
ETHerc20Ethereum약 2분
BTCbtcBitcoin약 30분
SOLsolSolana5초 미만

응답

201 Created
{
  "orderId":      "ord_a1b2c3d4e5f6g7h8",
  "payAddress":   "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "cryptoAmount": "29.99",
  "currency":     "USDT",
  "chain":        "trc20",
  "checkoutUrl":  "https://chainpay.pro/pay/ord_a1b2c3d4",
  "expiresAt":    "2026-03-22T09:00:00Z",
  "createdAt":    "2026-03-22T08:30:00Z"
}

결제 흐름

호스팅형 결제 페이지의 작동 방식입니다.

  1. 1
    리디렉션서버는 주문 생성 시 반환된 checkoutUrl로 사용자를 리디렉션합니다.
  2. 2
    결제 페이지호스팅형 페이지에는 정확한 암호화폐 금액이 미리 입력된 QR 코드와 지갑 주소가 표시됩니다. 사용자는 QR을 스캔하거나 주소를 지갑 앱에 복사합니다.
  3. 3
    확인ChainPay가 블록체인을 모니터링합니다. 필요한 확인 횟수에 도달하면 주문 상태가 confirming으로, 이어서 completed로 변경됩니다.
  4. 4
    돌아가기 리디렉션결제 페이지에 성공 화면이 표시됩니다. 대시보드에 successUrl을 설정해 두었다면 사용자가 자동으로 그곳으로 리디렉션됩니다.
  5. 5
    Webhook서버가 payment.completed Webhook을 수신합니다. Webhook 서명을 검증한 후에만 주문을 이행하세요.
만료: 주문은 생성 후 30분이 지나면 만료됩니다. 해당 시간 내에 결제가 감지되지 않으면 상태가 expired로 변경되고 payment.expired Webhook이 전송됩니다. 다시 시도하려면 새 주문을 생성하세요.

Webhook

ChainPay는 주문 상태가 변경되면 서명된 HTTP POST 요청을 Webhook URL로 전송합니다.

설정

1

대시보드 → 앱 → 새 앱으로 이동합니다

2

Webhook URL을 입력합니다(예: https://yourapp.com/api/webhooks/chainpay)

3

생성된 Webhook Secret을 복사합니다 — 서명 검증에 사용합니다

Webhook 이벤트

현재 지원되는 이벤트:

이벤트발생 시점
payment.completed주문이 결제되고 온체인에서 확인됨
payment.expired주문이 결제 없이 만료됨

페이로드 형식

JSON
{
  "event": "payment.completed",
  "orderId": "ord_xxxxxxxx",
  "amount": "9.99",
  "currency": "USDT",
  "chain": "trc20",
  "txHash": "abc123...",
  "netAmount": "9.92",
  "completedAt": "2026-01-01T00:00:00.000Z",
  "metadata": {
    "userId": "your-user-id",
    "plan": "monthly"
  }
}

서명 검증

모든 Webhook 요청에는 X-ChainPay-Signature 헤더가 포함됩니다. 앱의 Webhook Secret으로 HMAC-SHA256을 사용해 검증하세요:

Node.js / TypeScript
import crypto from 'crypto'

function verifyWebhook(rawBody: string, signature: string, secret: string): boolean {
  const computed = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(computed),
    Buffer.from(signature)
  )
}

// In your webhook handler:
export async function POST(req: Request) {
  const rawBody = await req.text()
  const signature = req.headers.get('x-chainpay-signature') ?? ''

  if (!verifyWebhook(rawBody, signature, process.env.CHAINPAY_WEBHOOK_SECRET!)) {
    return new Response('Unauthorized', { status: 401 })
  }

  const event = JSON.parse(rawBody)
  if (event.event === 'payment.completed') {
    const { userId, plan } = event.metadata
    // activate user's plan
  }

  return new Response('OK')
}
Python
import hmac, hashlib

def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
    computed = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(computed, signature)

Webhook 테스트

1

대시보드 → 앱으로 이동하여 앱을 선택합니다

2

"테스트 이벤트 전송"을 클릭합니다

3

서버가 요청을 수신했는지 확인합니다(HTTP 200 예상)

재시도 정책

전송에 실패하면 지수 백오프로 재시도합니다: 1분 → 5분 → 30분 → 2시간 → 24시간(총 5회 시도).

5회 시도가 모두 실패하면 Webhook은 실패로 표시됩니다. 전송 실패 내역은 대시보드 → 알림에서 확인하세요.

모범 사례

  • 처리하기 전에 항상 서명을 검증하세요
  • HTTP 200을 빠르게 반환하세요 — 무거운 처리는 비동기로 수행하세요
  • 이벤트 중복 제거에 orderId를 사용하세요(Webhook은 두 번 이상 전송될 수 있습니다)
  • 정확한 서명 검증을 위해 파싱하기 전에 원본 본문을 저장하세요

주문 조회

GEThttps://chainpay.pro/api/v1/orders/:id
응답
{
  "id":          "ord_a1b2c3d4e5f6g7h8",
  "amount":      "29.99",
  "cryptoAmount":"29.99",
  "netAmount":   "29.75",
  "currency":    "USDT",
  "chain":       "trc20",
  "status":      "completed",
  "payAddress":  "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "txHash":      "e3b0c44298fc1c149afbf4c8996fb92...",
  "externalId":  "order_abc123",
  "metadata":    { "userId": "user_456" },
  "createdAt":   "2026-03-22T08:30:00Z",
  "expiresAt":   "2026-03-22T09:00:00Z",
  "completedAt": "2026-03-22T08:45:00Z"
}

주문 상태 값

상태설명
pending주문이 생성되었으며, 사용자가 결제를 보내기를 기다리는 중입니다.
confirming온체인에서 거래가 감지되었으며, 충분한 블록 확인을 기다리는 중입니다.
completed결제가 완전히 확인되었습니다. 주문을 이행해도 안전합니다.
expired결제가 감지되지 않은 채 30분이 경과했습니다.
failed예상치 못한 오류가 발생했습니다. orderId와 함께 지원팀에 문의하세요.

환율 API

현재 USD 환율을 가져옵니다. API 키가 필요 없습니다.

GEThttps://chainpay.pro/api/v1/rates
응답
{
  "USDT": 1.0,
  "ETH":  3450.00,
  "BTC":  87500.00,
  "SOL":  145.00,
  "updatedAt": "2026-03-22T08:00:00Z"
}

환율은 집계된 시장 데이터로부터 60초마다 업데이트됩니다. 주문 생성 엔드포인트에 전달하는 amount는 항상 USD로 해석되며, API는 주문 생성 시점의 환율로 암호화폐로 변환합니다.

샌드박스 모드

실제 자금을 이동하지 않고 전체 연동을 테스트하세요.

?mode=test로 가입하면 sk_test_ API 키를 받게 됩니다. 모든 표준 엔드포인트는 샌드박스 모드에서 동일하게 작동합니다 — 블록체인 폴링은 생략되며 확인은 수동으로 트리거합니다.

1단계 — 샌드박스 API 키 받기

cURL
curl -X POST "https://chainpay.pro/api/auth/register?mode=test" \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "yourpassword"}'

# Response includes:
# { "merchant": { "apiKey": "sk_test_xxxxxxxxxxxxxxxx" } }

2단계 — 테스트 키로 주문 생성하기

cURL
curl -X POST https://chainpay.pro/api/v1/orders \
  -H "Authorization: Bearer sk_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount": 10, "currency": "USDT", "chain": "trc20", "externalId": "test_order_1"}'

3단계 — 결제 시뮬레이션하기

cURL
curl -X POST https://chainpay.pro/api/v1/sandbox/simulate-payment \
  -H "Authorization: Bearer sk_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"orderId": "ord_abc123"}'

# Response:
{
  "success":   true,
  "orderId":   "ord_abc123",
  "txHash":    "sandbox_ord_abc123_1711000000000",
  "netAmount": "9.92000000"
}
# The order status is now "completed" and your webhook is fired.
샌드박스 거래 해시에는 sandbox_ 접두사가 붙습니다. simulate-payment 엔드포인트는 sk_test_ 키에서만 사용할 수 있습니다. 라이브 키로 시도하면 403을 반환합니다.

오류 코드

모든 오류 응답은 일관된 JSON 형식을 사용합니다:

오류 응답 형식
{
  "error": "INVALID_CHAIN",
  "message": "chain 'foo' is not supported for currency USDT",
  "status": 400
}
HTTP 상태일반적인 오류 코드원인 및 해결
400INVALID_AMOUNT, INVALID_CURRENCY, INVALID_CHAIN, MISSING_FIELD요청 본문이 잘못되었거나 필수 필드가 누락되었습니다. 위의 요청 매개변수 표를 확인하세요.
401UNAUTHORIZED, INVALID_API_KEYAuthorization 헤더가 누락되었거나 유효하지 않습니다. Bearer <key>를 전송하고 있는지 확인하세요.
403FORBIDDEN, SANDBOX_ONLYAPI 키에 이 작업에 대한 권한이 없습니다(예: 라이브 키로 simulate-payment 사용).
404ORDER_NOT_FOUND주어진 ID의 주문이 존재하지 않거나, 귀하의 가맹점 계정에 속하지 않습니다.
429RATE_LIMITED요청이 너무 많습니다. 기본 한도는 API 키당 60 req/min입니다. 속도를 줄이고 Retry-After 헤더 값만큼 기다린 후 재시도하세요.
500INTERNAL_ERROR예상치 못한 서버 측 오류입니다. 지수 백오프로 재시도하세요. 지속되면 요청 ID와 함께 지원팀에 문의하세요.

정산

ChainPay가 수집한 자금을 지갑으로 보내는 방식과 시점입니다.

정산 일정
매일 02:00 UTC
처리 수수료
거래당 0.8%
최소 지급액
$10 상당

정산은 완료되었으나 아직 정산되지 않은 모든 금액을 대시보드의 설정 → 정산 지갑에서 설정한 지갑 주소로 보냅니다. 통화별로 별도의 지급 주소를 설정할 수 있습니다.

팁: 처리 수수료는 주문별로 차감됩니다 — Webhook의 netAmount는 이미 수수료가 차감된 금액을 반영합니다. 정산은 해당일의 모든 netAmount 값의 합계를 전송합니다.

연동할 준비가 되셨나요?

계정을 만들고 몇 초 만에 API 키를 받으세요.