API Reference
SoloPay REST API 전체 명세입니다.
Base URL
| 환경 | URL |
|---|---|
| Production | https://gateway.solonetwork.io/api/v1 |
| Staging | https://gateway.dev.solonetwork.io/api/v1 |
| Development | http://localhost:3001/api/v1 |
인증
| 방식 | 헤더 | 사용 엔드포인트 |
|---|---|---|
| Public Key | x-public-key | POST /payments, GET /payments/:id, POST /payments/:id/relay, GET /payments/:id/relay, GET /payments/:id/gas-status, POST /payments/request-gas |
| API Key | x-api-key | GET /merchant/*, POST /merchant/payment-methods, POST /refunds |
| 없음 | - | GET /chains, GET /chains/tokens |
공통 응답 형식
성공
{
"success": true,
"data": { ... }
}에러
{
"code": "ERROR_CODE",
"message": "Human readable message",
"details": [...]
}Payments
POST /payments
결제를 생성합니다.
인증: x-public-key + Origin 헤더
Request
{
"orderId": "order-001",
"amount": 10.5,
"tokenAddress": "0xE4C687167705Abf55d709395f92e254bdF5825a2",
"successUrl": "https://example.com/success",
"failUrl": "https://example.com/fail",
"currency": "USD"
}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
orderId | string | ✓ | 가맹점 주문 ID (중복 불가) |
amount | number | ✓ | 결제 금액 (토큰 단위 또는 법정화폐 단위) |
tokenAddress | address | ✓ | ERC-20 토큰 주소 (화이트리스트 & 가맹점 활성화 필수) |
successUrl | string | ✓ | 결제 성공 시 리다이렉트 URL |
failUrl | string | ✓ | 결제 실패 시 리다이렉트 URL |
currency | string | 법정화폐 코드 (예: USD, KRW). 입력 시 가격 변환 적용 |
Response (201)
{
"success": true,
"data": {
"paymentId": "0xabc123def456...",
"orderId": "order-001",
"chainId": 80002,
"tokenAddress": "0xE4C687167705Abf55d709395f92e254bdF5825a2",
"tokenSymbol": "SUT",
"tokenDecimals": 18,
"gatewayAddress": "0x...",
"forwarderAddress": "0x...",
"amount": "10500000000000000000",
"recipientAddress": "0xMerchantWallet...",
"merchantId": "0x...",
"deadline": "1706281200",
"successUrl": "https://example.com/success",
"failUrl": "https://example.com/fail",
"expiresAt": "2024-01-26T12:35:00.000Z",
"tokenPermitSupported": true,
"isFaucetEnabled": true,
"currency": "USD",
"fiatAmount": 10.5,
"tokenPrice": 1.0
}
}GET /payments/:id
결제 상태를 조회합니다.
인증: x-public-key 헤더 (GET 요청에서 Origin 대신 x-origin 헤더 사용 가능)
상태 값: CREATED, PAID, REFUND_SUBMITTED, REFUNDED, INVALID, EXPIRED, FAILED. 결제 성공 = PAID (자금이 가맹점으로 직접 전송).
Response (200)
{
"success": true,
"data": {
"paymentId": "0xabc123...",
"orderId": "order-001",
"status": "PAID",
"chainId": 80002,
"tokenAddress": "0xE4C687167705Abf55d709395f92e254bdF5825a2",
"tokenSymbol": "SUT",
"tokenDecimals": 18,
"tokenPermitSupported": true,
"isFaucetEnabled": true,
"gatewayAddress": "0x...",
"forwarderAddress": "0x...",
"amount": "10500000000000000000",
"recipientAddress": "0xMerchantWallet...",
"merchantId": "0x...",
"deadline": "1706281200",
"successUrl": "https://example.com/success",
"failUrl": "https://example.com/fail",
"expiresAt": "2024-01-26T12:35:00.000Z",
"txHash": "0xdef789...",
"payerAddress": "0x...",
"createdAt": "2024-01-26T12:30:00Z",
"currency": "USD",
"fiatAmount": 10.5,
"tokenPrice": 1.0
}
}- txHash — 결제 트랜잭션 해시. PAID 이후 상태에서 존재합니다.
- deadline — 결제 요청 서명 만료 시각(Unix 타임스탬프). 종료 상태가 아닐 때 사용됩니다.
POST /payments/:id/relay
Gasless 결제를 제출합니다.
인증: x-public-key + Origin 헤더
Request
{
"paymentId": "0xabc123...",
"forwarderAddress": "0x...",
"forwardRequest": {
"from": "0x...",
"to": "0x...",
"value": "0",
"gas": "200000",
"nonce": "1",
"deadline": "1706281200",
"data": "0x...",
"signature": "0x..."
}
}Response (202)
{
"success": true,
"data": {
"status": "submitted",
"message": "Gasless 거래가 제출되었습니다"
}
}GET /payments/:id/relay
Relay 요청 상태를 조회합니다.
인증: x-public-key 헤더
Response (200)
{
"success": true,
"data": {
"status": "CONFIRMED",
"transactionHash": "0xdef789...",
"errorMessage": null,
"createdAt": "2024-01-26T12:34:00Z",
"updatedAt": "2024-01-26T12:35:42Z"
}
}| 상태 | 설명 |
|---|---|
QUEUED | Relay 요청 대기 중 |
SUBMITTED | 트랜잭션 제출됨 |
CONFIRMED | 트랜잭션 확정 완료 |
FAILED | 트랜잭션 실패 |
GET /payments/:id/gas-status
토큰 승인 트랜잭션에 필요한 네이티브 토큰을 지갑이 1회 지원받을 수 있는지 확인합니다. 인증: x-public-key
curl "https://gateway.dev.solonetwork.io/api/v1/payments/0xabc123.../gas-status?walletAddress=0xPayer..." \
-H "x-public-key: pk_xxxxx"{
"needsGas": true,
"hasEnoughTokenBalance": true,
"alreadyGranted": false,
"canReceiveGas": true
}가맹점에서 faucet 기능이 활성화되어 있어야 합니다(결제 응답의 isFaucetEnabled: true). 지갑은 체인별로 최대 한 번만 지원받을 수 있고, 하나의 결제는 최대 한 번의 지원만 제공할 수 있습니다.
| 필드 | 설명 |
|---|---|
needsGas | 네이티브 잔액이 예상 approve 비용보다 적음 |
hasEnoughTokenBalance | 지갑에 결제 토큰 금액 이상 보유 |
alreadyGranted | 이 지갑이 해당 체인에서 이미 지원을 받음 |
canReceiveGas | needsGas && !alreadyGranted && hasEnoughTokenBalance |
canReceiveGas는 지갑 단위 조건입니다
canReceiveGas는 이 결제가 다른 지갑에 이미 지원을 제공했는지는 반영하지 않습니다. 이후 request-gas 호출에서 PAYMENT_ALREADY_GRANTED가 반환될 수 있으므로 POST /payments/request-gas에서 해당 오류를 처리하세요.
에러 응답
| HTTP | 코드 | 원인 |
|---|---|---|
| 403 | FAUCET_DISABLED | 가맹점 faucet 비활성화 (canReceiveGas: false로 내려오지 않음) |
| 404 | NOT_FOUND | 결제가 없거나 인증된 가맹점 소유가 아님 |
전체 가스 Faucet 오류 코드는 에러 코드를 참고하세요.
POST /payments/request-gas
ERC-20 approve 트랜잭션 제출에 사용할 네이티브 토큰을 1회 요청합니다. 인증: x-public-key + Origin
curl -X POST https://gateway.dev.solonetwork.io/api/v1/payments/request-gas \
-H "x-public-key: pk_xxxxx" \
-H "Origin: https://yourshop.com" \
-H "Content-Type: application/json" \
-d '{
"paymentId": "0xabc123...",
"walletAddress": "0xPayer..."
}'{
"txHash": "0xdef789...",
"amount": "10000000000000000",
"chainId": 80002
}인증된 가맹점의 결제이고, 지갑에 결제 토큰이 충분하며, 네이티브 토큰 잔액이 예상 승인 비용보다 적을 때만 지원됩니다. 응답은 지원 트랜잭션이 온체인에서 확정된 후 반환되므로, 이 호출이 성공하면 바로 approve를 제출할 수 있습니다.
게이트웨이에 ALLOWED_WIDGET_ORIGIN이 설정된 경우 Origin이 그 값과 정확히 일치해야 합니다. 브라우저 fetch는 Origin을 자동으로 보냅니다. 서버 측 호출은 직접 설정해야 합니다. 인증 참고.
에러 응답
| HTTP | 코드 | 원인 |
|---|---|---|
| 403 | FAUCET_DISABLED | 가맹점 faucet 비활성화 |
| 403 | FORBIDDEN | Origin이 ALLOWED_WIDGET_ORIGIN과 불일치 |
| 404 | NOT_FOUND | 결제가 없거나 인증된 가맹점 소유가 아님 |
| 400 | INSUFFICIENT_TOKEN_BALANCE | 지갑 토큰 잔액이 결제 금액 미만 |
| 400 | ALREADY_HAS_GAS | approve에 필요한 네이티브 토큰이 이미 충분함 |
| 400 | ALREADY_GRANTED | 이 지갑이 해당 체인에서 이미 지원을 받음 |
| 400 | PAYMENT_ALREADY_GRANTED | 이 결제가 이미 지원을 제공함 |
| 409 | GRANT_IN_PROGRESS | 동일 결제에 대한 다른 지원 요청이 진행 중 |
자세한 내용은 에러 코드를 참고하세요.
Merchant
GET /merchant
현재 가맹점 정보를 조회합니다.
인증: x-api-key
Response (200)
{
"success": true,
"data": {
"merchant": {
"id": 1,
"merchant_key": "my-store",
"name": "My Store",
"chain_id": 80002,
"chain": { "id": 1, "network_id": 80002, "name": "Polygon Amoy", "is_testnet": true },
"webhook_url": null,
"public_key": "pk_xxx",
"is_enabled": true,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"payment_methods": [...]
},
"chainTokens": [...]
}
}GET /merchant/payment-methods
결제 수단 목록을 조회합니다.
인증: x-api-key
POST /merchant/payment-methods
결제 수단을 추가합니다.
인증: x-api-key
{
"tokenAddress": "0x...",
"is_enabled": true
}PATCH /merchant/payment-methods/:id
결제 수단을 수정합니다.
{ "is_enabled": false }GET /merchant/payments
결제 내역을 조회합니다.
인증: x-api-key
Query Parameters: orderId (특정 주문 조회)
GET /merchant/payments/:id
특정 결제 상세를 조회합니다.
인증: x-api-key
Chains
GET /chains
지원 체인 목록을 조회합니다. (인증 없음)
{
"success": true,
"data": {
"chains": [
{ "id": 1, "network_id": 80002, "name": "Polygon Amoy", "is_testnet": true },
{ "id": 2, "network_id": 97, "name": "BSC Testnet", "is_testnet": true },
{ "id": 3, "network_id": 11155111, "name": "Sepolia", "is_testnet": true }
]
}
}GET /chains/tokens
지원 체인과 토큰 전체 목록을 조회합니다. (인증 없음)
Health
GET /health
서버 상태를 확인합니다. (인증 없음)
{
"status": "ok",
"timestamp": "2024-01-26T12:00:00.000Z"
}다음 단계
- 에러 코드 - 에러 처리