Unifi Pay Direct API 레퍼런스
Unifi Pay API를 연동하는 개발자를 위한 API 레퍼런스 입니다.
SDK 없이 REST API만으로 결제 연동 완료
API 요청 시 HMAC 서명 인증 적용
비동기 Webhook으로 실시간 결제 상태 수신
AI 연동 가이드
AI 코딩 어시스턴트에 제공하면 API 연동 작업에 참고 자료로 활용할 수 있습니다.
1. API 연동 다이어그램
결제 링크 발급 방식의 가맹점 서버·고객·Unifi Pay 간 데이터 흐름입니다.
1.1 결제 다이어그램
결제 링크 발급부터 Webhook 수신까지의 전체 흐름입니다.
Your Server: apiKey와 HMAC Signature를 이용해 Unifi Pay에 결제 링크 발급을 요청합니다.
결제 링크: 발급받은 linkUrl을 고객에게 공유합니다. 공유 채널에는 제한이 없습니다.
Customer: 링크에 접속해 결제를 진행하면 결제 요청이 생성되고, 지갑 연결 및 서명으로 결제가 완료됩니다.
Webhook: 결제 링크 발급 시 callbackUrl을 등록한 경우에만 전송됩니다. PAID 시점에 1차, CONFIRMED 시점에 2차로 결제 결과를 비동기 전송합니다. 결제 결과를 전달받는 유일한 경로이므로 반드시 등록하십시오.
2. API 상세 소개
https://app-api-pay.unifi.me
https://api-pay.unifi.me
2.1 인증 (Authentication)
서버 간 API 요청은 기본적으로 HMAC 인증이 필수입니다. X-Authorization-Hmac 헤더에 서명값을 포함해야 합니다.
X-Authorization-Hmac
HMAC 생성 공식
BASE64(HMACSHA256(apiSecret, {HTTP_METHOD}{URI}{X-API-Key}{X-Timestamp}{REQUEST_BODY}))
/api/seller/v2/payment/link
request header:
X-API-Key: "b6ef2f7c-3e74-438c-b456-689e821992be"
X-Timestamp: 1773017787000
X-Authorization-Hmac: "some-hmac-signature"
request body:
{
"requestId": "REQ-20260304-0001",
"storeId": "123",
"serviceName": "MyShop",
"itemName": "ITEM-GAME-001",
"itemPrice": 12.34,
"orderCurrencyCode": "USD",
"returnUrl": "https://myshop.com/payment/returnUrl",
"callbackUrl": "https://myshop.com/payment/callbackUrl",
"expiresAt": "2026-08-31T00:00:00Z"
}
X-Authorization-Hmac = Base64(
HmacSHA256(
apiSecret,
"POST" ← HTTP_METHOD
+ "/api/seller/v2/payment/link" ← URI
+ "b6ef2f7c-3e74-438c-b456-689e821992be" ← X-API-Key
+ "1773017787000" ← X-Timestamp
+ "{"requestId":"REQ-20260304-0001","storeId":"123","serviceName":"MyShop","itemName":"ITEM-GAME-001","itemPrice":12.34,"orderCurrencyCode":"USD","returnUrl":"https://myshop.com/payment/returnUrl","callbackUrl":"https://myshop.com/payment/callbackUrl","expiresAt":"2026-08-31T00:00:00Z"}" ← REQUEST_BODY (공백 없이)
)
)
/api/seller/v2/payment/123
request header:
X-API-Key: "b6ef2f7c-3e74-438c-b456-689e821992be"
X-Timestamp: 1773017787000
X-Authorization-Hmac: "some-hmac-signature"
X-Authorization-Hmac = Base64(
HmacSHA256(
apiSecret,
"GET" ← HTTP_METHOD
+ "/api/seller/v2/payment/123" ← URI
+ "b6ef2f7c-3e74-438c-b456-689e821992be" ← X-API-Key
+ "1773017787000" ← X-Timestamp
← REQUEST_BODY 없음 (생략)
)
)
/api/seller/v2/payment/settlement/transaction
request url:
GET /api/seller/v2/payment/settlement/transaction?from=2026-03-01T00:00:00Z&to=2026-03-31T23:59:59Z&paymentType=PURCHASE&page=0&size=20
request header:
X-API-Key: "b6ef2f7c-3e74-438c-b456-689e821992be"
X-Timestamp: 1773017787000
X-Authorization-Hmac: "some-hmac-signature"
X-Authorization-Hmac = Base64(
HmacSHA256(
apiSecret,
"GET" ← HTTP_METHOD
+ "/api/seller/v2/payment/settlement/transaction" ← URI (쿼리스트링 제외)
+ "b6ef2f7c-3e74-438c-b456-689e821992be" ← X-API-Key
+ "1773017787000" ← X-Timestamp
← REQUEST_BODY 없음 (생략)
)
)
URI 에는 경로(path)만 포함하며, 쿼리스트링(? 이후)은 포함하지 않습니다. 쿼리스트링을 포함해 서명하면 인증에 실패합니다.요청 헤더 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| X-Authorization-Hmac | STRING | 필수 | 생성된 HMAC 서명값. 모든 서버 간 API 요청에 필수입니다. |
| X-API-Key | STRING | 필수 | Unifi Pay에서 발급받은 apiKey. |
| X-Timestamp | STRING | 필수 | 밀리초 단위 Unix 타임스탬프. 현재 시각과 5분 이상 차이 시 요청이 거부됩니다. |
Unifi Pay 서버의 timestamp를 조회하여 서버 상태를 확인하고, 응답의 timestamp 값을 HMAC 서명에 활용합니다.
X-API-Key · X-Timestamp · X-Authorization-Hmac 헤더 없이 호출합니다. HMAC 서명에 사용할 timestamp 를 얻기 위한 API 이므로 위 기본 인증 규칙에서 제외됩니다.응답 필드
| 필드 이름 | 타입 | 설명 |
|---|---|---|
| timestamp | INTEGER(INT64) | 서버의 timestamp 밀리초 단위 값 |
응답 예시
{
"timestamp": 1773017787000
}
{
"code": "INTERNAL_SERVER_ERROR",
"message": ""
}
2.2 결제 링크 발급 API
고정된 금액과 상품의 결제 링크를 발급합니다. 응답으로 받은 링크를 고객에게 공유하면 별도 연동 없이 결제 페이지로 진입합니다.
요청 바디 파라미터
| 파라미터 | 타입 | 길이 | 필수 | 설명 |
|---|---|---|---|---|
| requestId | STRING | 64 | 필수 | 발급 요청에 대한 고유 식별자(멱등키). 영문·숫자·하이픈·언더스코어만 사용합니다. 동일한 requestId로 재요청하면 중복 발급으로 거부됩니다. |
| storeId | STRING | 128 | 필수 | 요청자가 제공하는 가맹점 ID 정보. |
| serviceName | STRING | 40 | 필수 | 링크 화면과 결제창에 노출될 서비스 또는 가맹점 정보. |
| itemName | STRING | 100 | 필수 | 판매 상품의 이름(상품명). |
| itemPrice | DOUBLE | — | 필수 | 판매 상품의 가격. 주문 통화 기준이며 0보다 커야 합니다. |
| orderCurrencyCode | STRING | 8 | 필수 | ISO 4217을 따르는 주문 통화 코드. USD 또는 JPY를 지원합니다. |
| returnUrl | STRING | 2048 | 선택 | 결제 완료 후 사용자가 복귀할 URL. 지정하지 않으면 복귀 버튼 없이 결제를 진행합니다. |
| callbackUrl | STRING | 2048 | 선택 | 결제 결과를 수신할 Webhook URL. 결제 링크 방식은 결제가 발생하기 전까지 거래 식별자가 생성되지 않아 상태 조회로 결과를 확인할 수 없으므로, 반드시 지정해 주십시오. |
| expiresAt | STRING | — | 필수 | 결제 링크의 만료 시각. ISO-8601 형식이며 미래 시점이어야 합니다. 만료 후 링크에 접속하면 만료 오류로 응답합니다. |
응답 필드
| 필드 이름 | 타입 | 설명 |
|---|---|---|
| linkUrl | STRING | 발급된 결제 링크 URL. 고객에게 공유합니다. |
| linkId | STRING | 링크 식별자. 가맹점이 보관하며, 링크를 만료시킬 때는 콘솔의 결제 링크 목록에서 강제 만료 버튼을 사용합니다. 2.9 결제 링크 강제 만료 API로도 만료시킬 수 있습니다. |
요청 / 응답 예시
{
"requestId": "REQ-20260304-0001",
"storeId": "123",
"serviceName": "MyShop",
"itemName": "ITEM-GAME-001",
"itemPrice": 12.34,
"orderCurrencyCode": "USD",
"returnUrl": "https://myshop.com/payment/returnUrl",
"callbackUrl": "https://myshop.com/payment/callbackUrl",
"expiresAt": "2026-08-31T00:00:00Z"
}
{
"linkUrl": "https://unifipay.example.com/pay/links/3f1d0a549c1e4f6a8a5b2f",
"linkId": "3f1d0a549c1e4f6a8a5b2f"
}
linkUrl을 고객에게 공유하면 별도 연동 없이 결제가 진행됩니다. requestId는 멱등키이므로 동일한 값으로 재요청하면 중복 발급이 거부됩니다.
오류 응답
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 (형식 오류, 필수 값 누락, 과거 시점의 expiresAt 등) |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 503 | MAINTENANCE | 점검 중 |
| 406 | PAYMENT_INVALID_REQUEST | 동일한 requestId로 재요청한 경우 또는 callbackUrl이 허용 목록에 없는 경우 |
| 406 | PAYMENT_UNSUPPORTED_POLICY | 지원하지 않는 주문 통화 또는 금액 정책 (orderCurrencyCode, itemPrice) |
| 406 | PAYMENT_STORE_INACTIVE | 요청한 storeId가 ACTIVE 상태가 아닐 때 |
| 406 | PAYMENT_WALLET_NOT_REGISTERED | 정산 지갑 주소가 등록되지 않은 경우 |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
2.3 결제 상태 확인 API
생성된 결제 건의 현재 상태를 확인합니다.
아래 응답 필드와 예시는 v2 응답 기준입니다. v2 응답에만 있는 필드에는 v2 전용 배지를 표시했습니다.
응답 필드
| 필드 이름 | 타입 | 설명 |
|---|---|---|
| transactionId | STRING | Unifi Pay에서 생성한 거래 번호. |
| orderId | STRING | Unifi Pay에서 생성한 주문 id. 결제 링크를 통한 거래는 LINK-{linkId}-{12문자 랜덤 문자열} 형식으로 발급됩니다. |
| storeId | STRING | 요청자가 제공하는 가맹점 ID 정보. |
| serviceName | STRING | 결제창에 노출될 서비스 또는 가맹점 정보. |
| paymentType | STRING | v2 전용 결제: PURCHASE / 환불: REFUND |
| status | STRING | CREATED결제 생성 완료 PENDING결제 진행 중 PAID결제 성공 CONFIRMED정산 완료 (종결) FAILED결제 실패 (종결) CANCELED결제 취소 (종결) |
| failType | STRING | status가 FAILED일 때 설정됩니다. WALLET_PURCHASE_BLOCKCHAIN_FAILEDunifi wallet에서 blockchain 출고 과정 중 실패 WALLET_PURCHASE_INSUFFICIENT_BALANCE사용자 지갑의 잔고 부족 PAYMENT_PURCHASE_BLACKLISTED사용자의 지갑이 payment 블랙리스트에 포함되어 실패 PAYMENT_STORE_INACTIVE결제 시점에 스토어가 비활성 상태 WALLET_SESSION_EXPIRED결제 요청 단계에서 Unifi 계정 세션 검증 실패 WALLET_TRANSFER_IN_PROGRESS같은 지갑과 토큰에 대해 출금 또는 전송이 이미 진행 중이어서 중복 처리 거절 UNKNOWN결제 과정 중 알 수 없는 오류 |
|
items
Array — 결제 상품 목록
최대 1건
|
||
| ↳ name | STRING | 판매 상품의 식별 정보. |
| ↳ price | DOUBLE | 판매 상품의 가격. |
| countryCode | STRING | ISO Alpha-3를 따르는 국가 코드 (예: KOR). |
| orderCurrencyCode | STRING | ISO 4217를 따르는 주문 통화 코드 (USD, JPY). |
| orderAmount | DOUBLE | 주문한 금액. |
| payCurrencyCode | STRING | 결제한 스테이블 코인 종류. |
| payAmount | DOUBLE | 결제된 금액. |
| buyerWalletAddress | STRING | 구매자 지갑 주소. 서명 전(CREATED)에는 null 입니다. |
| netAmount | DOUBLE | v2 전용 파트너 실수령액 (결제 통화 기준). CONFIRMED 이후 제공 |
| blockchainTxId | STRING | 블록체인 트랜잭션 해시. 블록체인 확정 이후(CONFIRMED)이거나, 블록체인 네트워크에 전파된 후 실패(FAILED)한 경우에 반환됩니다. |
| blockchainNetworkFee | DOUBLE | 블록체인 네트워크 수수료. 블록체인 확정 이후(CONFIRMED) 및 네트워크 전파 후 실패(FAILED) 시점에 실제로 소모된 수수료 금액이 반환됩니다. (Unifi가 전액 대납하여 사용자 부담은 없습니다.) |
| createdAt | INSTANT | v2 전용 주문 결제 요청 일시 |
| capturedAt | INSTANT | v2 전용 체인 이벤트가 관측된 시각. 관측 전에는 null 입니다. 값이 있어도 결제 성공을 뜻하지 않으므로 성공 여부는 status 로 판단하십시오. |
| finalizedAt | INSTANT | v2 전용 결제가 종료(확정, 실패, 취소)된 시각. 종결 전에는 null 입니다. |
PAID 상태는 결제 건이 v2로 생성되고 v2 API로 조회·수신하는 경우에만 노출됩니다. 생성 또는 조회 중 하나라도 v1이면 PAID 없이 기존과 동일하게 CONFIRMED로 안내됩니다.
PAID 시점에는 blockchainTxId·blockchainNetworkFee가 반환되지 않습니다. 결제 금액(payAmount)은 CONFIRMED 시점에 확정되므로, 금액·블록체인 정보는 CONFIRMED 이후 조회한 값을 사용하시기 바랍니다.
응답 예시
{
"transactionId": "<transactionId>",
"orderId": "<orderId>",
"storeId": "<storeId>",
"serviceName": "<serviceName>",
"paymentType": "PURCHASE",
"items": [
{
"name": "ITEM-GAME-001",
"price": 50000
}
],
"status": "CONFIRMED",
"failType": null,
"countryCode": "KOR",
"payAmount": 49000,
"netAmount": 48510,
"payCurrencyCode": "USDT",
"orderAmount": 50000,
"orderCurrencyCode": "USD",
"buyerWalletAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
"blockchainTxId": "0x4fce0d72ff7f4b9f4ba0cf58d30119924bea3811d85a830c762e1d87b3e1ee17",
"blockchainNetworkFee": 0.00253778,
"createdAt": "2026-09-07T04:00:00.000Z",
"capturedAt": "2026-09-07T04:01:28.000Z",
"finalizedAt": "2026-09-07T04:01:30.000Z"
}
결제가 확정되고 정산까지 완료되어 종결된 상태입니다.
결제가 실패한 상태입니다.
오류 응답
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC일 경우 |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path 일 경우 |
| 503 | MAINTENANCE | 점검 중일 경우 |
| 406 | PAYMENT_TRANSACTION_NOT_FOUND | 유효하지 않은 transactionId |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
2.4 결제 Webhook
결제 건에 대한 처리 결과를 비동기로 수신합니다. Webhook은 PAID 시점에 1차, CONFIRMED 시점에 2차로 총 2회 발송됩니다. 두 Webhook 모두 동일한 transactionId로 전송되므로 중복 수신에 대비해 멱등하게 처리해 주십시오. 1차(PAID) 수신 시점부터 결제 완료 화면으로 전환할 수 있습니다.
Webhook 바디 필드
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| transactionId | STRING | 필수 | Unifi Pay에서 생성한 거래 번호. |
| orderId | STRING | 필수 | Unifi Pay에서 생성한 주문 id. 결제 링크를 통한 거래는 LINK-{linkId}-{12문자 랜덤 문자열} 형식으로 발급되며, 고객이 결제 링크에서 결제를 진행한 시점에 결정됩니다. |
| status | STRING | 필수 | 결제 처리 결과. PAID: 결제 성공 (1차 Webhook), CONFIRMED: 정산 완료 (2차 Webhook), FAILED: 실패, CANCELED: CREATED 상태로 약 30분 이상 유지되거나 사용자가 결제창을 이탈한 경우 취소. |
| type | STRING | 필수 | 거래 유형. PURCHASE 또는 REFUND입니다. 환불도 같은 Webhook으로 통지되며, 이때 transactionId와 orderId는 환불 거래의 값입니다 (orderId는 원결제의 orderId를 승계하므로 구매 건과 같은 값입니다). 조회 응답의 paymentType 필드와 같은 값을 뜻합니다. |
요청 예시 (JSON) — 1차 Webhook (PAID)
{
"transactionId": "<transactionId>",
"orderId": "LINK-3f1d0a549c1e4f6a8a5b2f-a1b2c3d4e5f6",
"status": "PAID",
"type": "PURCHASE"
}
요청 예시 (JSON) — 2차 Webhook (CONFIRMED)
{
"transactionId": "<transactionId>",
"orderId": "LINK-3f1d0a549c1e4f6a8a5b2f-a1b2c3d4e5f6",
"status": "CONFIRMED",
"type": "PURCHASE"
}
HTTP 200 OK 응답 코드를 반환해야 합니다.
PAID 시점에는 blockchainTxId·blockchainNetworkFee가 반환되지 않습니다. 결제 금액(payAmount)은 CONFIRMED 시점에 확정되므로, 금액·블록체인 정보는 CONFIRMED 이후 조회한 값을 사용하시기 바랍니다.
재시도 정책
가맹점 서버에서 5xx 오류 또는 응답이 없을 경우, 아래 정책에 따라 재전송됩니다.
| 순서 | 재시도 시점 |
|---|---|
| 1차 재시도 | 3초 후 |
| 2차 재시도 | 30초 후 |
| 3차 재시도 | 10분 후 |
| 4차 재시도 | 1시간 후 |
| 5차 재시도 | 3시간 후 |
2.5 환불 API (DIRECT)
환불은 판매자 API 로 접수할 수 있습니다. 접수와 조회는 v1 과 v2 두 경로를 제공하며, 본 문서는 v2 경로를 기준으로 기재합니다.
startPageUrl 페이지에서 판매자가 본인 명의의 Unifi Wallet으로 직접 서명해야 환불이 실행됩니다 (billing 미경유). Unifi Pay 콘솔의 환불 관리 메뉴에서 접수하는 방법도 그대로 사용할 수 있습니다.
CONFIRMED 상태인 경우에만 진행할 수 있습니다.PAID(판매자 서명 직후), CONFIRMED(체인 수집 완료), FAILED 세 가지 상태를 가집니다. PENDING 구간은 없습니다.환불 접수 API
원결제에 대한 환불을 접수합니다. 응답으로 받은 서명 페이지에서 판매자가 서명해야 환불이 진행됩니다.
요청 바디 파라미터
| 파라미터 | 타입 | 길이 | 필수 | 설명 |
|---|---|---|---|---|
| requestId | STRING | 128 | 필수 | 환불 요청 식별자. 파트너 안에서 전역 유니크해야 합니다. |
| orderId | STRING | 128 | 필수 | 원결제 주문 ID. 아래 환불 사전 조회 API 응답의 orderId 를 그대로 사용합니다. |
| orderCurrencyCode | STRING | 8 | 필수 | 주문 통화 코드. 원결제와 일치해야 합니다. |
| orderAmount | DOUBLE | — | 필수 | 환불 금액. 0보다 커야 합니다. |
| isPartial | BOOLEAN | — | 필수 | 부분 환불 여부. true: 부분 환불, false: 전액 환불. |
응답 필드
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| transactionId | STRING | 필수 | 생성된 환불 거래 ID. 아래 환불 단건 조회 API 로 상태를 추적합니다. |
| startPageUrl | STRING | 필수 | 판매자 서명 페이지 URL. 이 페이지에서 서명해야 환불이 진행됩니다. |
요청 예시 (JSON)
{
"requestId": "RFD-20260907-0001",
"orderId": "LINK-3kQ9xR2mN7pLw8vBc1dEfH-a1B2c3D4e5F6",
"orderCurrencyCode": "USD",
"orderAmount": 30.0,
"isPartial": true
}
응답 예시
{
"transactionId": "20260907QH4MX9KV7RDB2NT",
"startPageUrl": "https://unifipay.example.com/refund/start?token=<token>"
}
오류 응답
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 406 | PAYMENT_TRANSACTION_NOT_FOUND | 원결제를 찾을 수 없음 |
| 406 | PAYMENT_INVALID_REQUEST | 원결제가 DIRECT 수취가 아니거나 CONFIRMED 상태가 아님, 같은 원결제에 진행 중 환불 존재, 잔여 환불 가능액 초과, requestId 중복, 통화 또는 금액 정책 위반 |
| 406 | PAYMENT_REFUND_BLACKLISTED | 구매자 지갑이 환불 차단 대상 |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
환불 사전 조회 API
환불 접수 전에 환불 가능 여부와 잔여 환불 가능액을 확인합니다. 접수 전 안내용이며 접수를 보장하지 않으므로, 접수 실패를 정상 흐름으로 처리해 주십시오.
URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| transactionId | STRING | 필수 | 원결제 거래 ID. |
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| transactionId | STRING | 필수 | 원결제 거래 ID. |
| orderId | STRING | 필수 | 원결제 주문 ID. 환불 접수 API 의 orderId 로 그대로 사용합니다. |
| status | STRING | 필수 | 원결제 상태 (공개 표기). |
| orderAmount | DOUBLE | 필수 | 원결제 주문 금액. |
| refundedAmount | DOUBLE | 필수 | 확정된 환불과 진행 중인 환불의 합계. 서명하지 않은 초안은 제외됩니다. |
| refundableAmount | DOUBLE | 필수 | 남은 환불 가능액. orderAmount 에서 refundedAmount 를 뺀 값입니다. |
| refundable | BOOLEAN | 필수 | 지금 접수할 수 있는지에 대한 사전 판정 결과. |
| reason | STRING | 선택 | 접수 불가 사유 코드. 접수할 수 있으면 null 입니다. |
ORIGINAL_NOT_CONFIRMED 원결제가 아직 확정 전, ORIGINAL_NOT_REFUNDABLE 실패 또는 취소로 종료, FULLY_REFUNDED 전액 환불 완료, NOT_DIRECT_PAYOUT DIRECT 수취가 아님.응답 예시
{
"transactionId": "20260820HV7QX2MK9RDBN4T",
"orderId": "LINK-3kQ9xR2mN7pLw8vBc1dEfH-a1B2c3D4e5F6",
"status": "CONFIRMED",
"orderAmount": 100.0,
"refundedAmount": 30.0,
"refundableAmount": 70.0,
"refundable": true,
"reason": null
}
오류 응답
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
환불 단건 조회 API
접수한 환불 1건의 상태를 조회합니다. 경로 변수 transactionId 는 원결제 ID 가 아니라 환불 접수 응답으로 받은 환불 거래 ID 입니다.
URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| transactionId | STRING | 필수 | 환불 거래 ID. |
| orderId | STRING | 필수 | 원결제 주문 ID. |
| status | STRING | 필수 | 환불 상태 (공개 표기). PAID, CONFIRMED, FAILED 3종입니다. |
| failType | STRING | 선택 | 환불 실패 사유. |
| orderAmount | DOUBLE | 필수 | 환불 주문 금액. |
| orderCurrencyCode | STRING | 필수 | 주문 통화 코드. |
| refundAmount | DOUBLE | 필수 | 실제 환불된 금액. |
| refundCurrencyCode | STRING | 필수 | 실제 환불 통화. |
| blockchainTxId | STRING | 선택 | 블록체인 트랜잭션 해시. 블록체인 확정 이후(CONFIRMED)이거나, 블록체인 네트워크에 전파된 후 실패(FAILED)한 경우에 반환됩니다. |
| blockchainNetworkFee | DOUBLE | 선택 | 블록체인 네트워크 수수료. 블록체인 확정 이후(CONFIRMED) 및 네트워크 전파 후 실패(FAILED) 시점에 실제로 소모된 수수료 금액이 반환됩니다. (Unifi가 전액 대납하여 사용자 부담은 없습니다.) |
응답 예시
{
"transactionId": "20260907QH4MX9KV7RDB2NT",
"orderId": "LINK-3kQ9xR2mN7pLw8vBc1dEfH-a1B2c3D4e5F6",
"status": "CONFIRMED",
"failType": null,
"orderAmount": 30.0,
"orderCurrencyCode": "USD",
"refundAmount": 30.0,
"refundCurrencyCode": "USDT",
"blockchainTxId": "0xdef456...",
"blockchainNetworkFee": 0.0018
}
오류 응답
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
연동 시 참고 사항
| 항목 | 설명 |
|---|---|
| 환불 Webhook | 결제 결과 Webhook과 같은 callbackUrl로 type가 REFUND인 통지가 발송됩니다. 이때 transactionId와 orderId는 환불 거래의 값이며, orderId는 원결제의 값을 승계합니다. |
| 환불 내역 조회 | 아래 2.6 정산 내역 API에서 paymentType=REFUND 로 조회하거나, 2.11 결제 내역 조회 API를 사용합니다. |
| 원결제 연결 | 환불 건의 originTransactionId 가 원결제의 transactionId 를 가리킵니다. |
2.6 정산 내역 API
결제, 환불 내역을 확인합니다.
요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| from | STRING | 조건부 | 조회 시작일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-01T00:00:00Z). transactionId/settlementId 미지정 시 필수이며, to보다 이전 시점 설정 필수. |
| to | STRING | 조건부 | 조회 종료일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-31T23:59:59Z). transactionId/settlementId 미지정 시 필수이며, 조회 기간은 최대 90일까지 허용. |
| paymentType | STRING | 선택 | 결제 타입 필터 (PURCHASE / REFUND). 미지정 시 전체 |
| transactionId | STRING | 선택 | Unifi Pay에서 생성한 거래 번호. from/to/settlementId 미지정 시 필수. |
| settlementId | STRING | 선택 | Unifi Pay 지급 명세서 ID 정보. from/to/transactionId 미지정 시 필수. |
| page | INTEGER | 선택 | 페이지 번호 (0부터 시작, 기본값: 0) |
| size | INTEGER | 선택 | 페이지 크기 (기본 50, 1 이상 100 이하) |
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| content | List | 필수 | 결제 데이터 목록 |
| ↳ partnerCorpName | STRING | 필수 | 법인명 (EN) |
| ↳ storeId | STRING | 선택 | 가맹점 ID 정보 |
| ↳ orderId | STRING | 필수 | 거래에 대한 ID 정보 |
| ↳ itemName | STRING | 필수 | 상품의 식별 정보 |
| ↳ serviceName | STRING | 선택 | 서비스 또는 가맹점명 (EN) |
| ↳ orderCountryCode | STRING | 필수 | 구매자 국가 코드 |
| ↳ orderCurrencyCode | STRING | 필수 | ISO 4217를 따르는 주문 통화 코드 |
| ↳ orderAmount | DOUBLE | 필수 | 주문 금액 |
| ↳ createdAt | INSTANT | 필수 | 주문 결제 요청 일시 |
| ↳ transactionId | STRING | 필수 | Unifi Pay에서 생성한 거래 번호. |
| ↳ blockchainTxId | STRING | 필수 | KaiaScan TxID |
| ↳ paymentType | STRING | 필수 | 결제: PURCHASE / 환불: REFUND |
| ↳ originTransactionId | STRING | 선택 | 환불 시 원 거래 번호 (REFUND인 경우 필수, PURCHASE인 경우 Null) |
| ↳ status | STRING | 필수 | CONFIRMED 고정 (CONFIRMED건만 조회) |
| ↳ finalizedAt | INSTANT | 필수 | 주문 결제 최종 상태 일시 |
| ↳ capturedAt | INSTANT | 필수 | 주문 결제 완료 일시 (블록체인 확정 시각) |
| ↳ failType | STRING | 선택 | 주문 결제 실패 사유 |
| ↳ payCurrencyCode | STRING | 필수 | 실 결제 통화 USDT |
| ↳ payAmount | DOUBLE | 필수 | 실 결제 금액 |
| ↳ netAmount | DOUBLE | 선택 | v2 전용 파트너 실수령액 (결제 통화 기준). 환불 거래는 수령액이 없어 null 입니다. |
| ↳ paymentExchangeRate | DOUBLE | 필수 | 결제 시점 환율. 결제 통화와 주문 통화가 다를 때 적용되며, 같으면 1입니다. (기준 통화: payCurrencyCode) |
| ↳ buyerWalletAddress | STRING | 필수 | 구매자 결제 지갑 주소 |
| ↳ variableFeeRate | DOUBLE | 선택 | 결제 수수료율 (%). Unifi Pay 지급 명세서 번호 생성 전인 경우 Null |
| ↳ protocolFeeRate | DOUBLE | 필수 | v2 전용 프로토콜 수수료율 (퍼센트, 1 은 1%). netAmount 공제에 쓰인 요율이며 판매자 (MERCHANT_LITE) 는 현재 항상 1 입니다. |
| ↳ settlementId | STRING | 선택 | Unifi Pay 지급 명세서 ID 정보. 생성 전인 경우 Null |
| ↳ settlementCurrencyCode | STRING | 선택 | 정산 통화 코드 (USDT, JPYC). 정산 전인 경우 Null |
| ↳ settlementExchangeRate | DOUBLE | 선택 | 정산 시점 환율. 정산 전인 경우 Null |
| totalElements | LONG | 필수 | 전체 건수 |
| totalPages | INTEGER | 필수 | 전체 페이지수 |
| pageNumber | INTEGER | 필수 | 현재 페이지 번호 |
| first | BOOLEAN | 필수 | 첫 페이지 여부 |
| last | BOOLEAN | 필수 | 마지막 페이지 여부 |
응답 예시 — 성공
{
"content": [
{
"partnerCorpName": "ABC Corporation",
"storeId": "store_001",
"orderId": "ORD-20260301-0001",
"itemName": "Premium Subscription",
"serviceName": "ABC Service",
"orderCountryCode": "KOR",
"orderCurrencyCode": "USD",
"orderAmount": 50000,
"createdAt": "2026-03-01T10:00:00Z",
"transactionId": "20260301TQ9XM4HKV2RDB7N",
"blockchainTxId": "0xabcdef1234567890abcdef1234567890abcdef12",
"paymentType": "PURCHASE",
"originTransactionId": null,
"status": "CONFIRMED",
"finalizedAt": "2026-03-01T10:01:30Z",
"capturedAt": "2026-03-01T10:01:25Z",
"failType": null,
"payCurrencyCode": "USDT",
"payAmount": 10.87,
"netAmount": 10.76,
"paymentExchangeRate": 1.0,
"buyerWalletAddress": "0x1234567890abcdef1234567890abcdef12345678",
"variableFeeRate": 0,
"protocolFeeRate": 1,
"settlementId": "stl_xyz789",
"settlementCurrencyCode": "USDT",
"settlementExchangeRate": 1.0
}
],
"totalElements": 1,
"totalPages": 1,
"pageNumber": 0,
"first": true,
"last": true
}
응답 예시 — 실패
{
"code": "PAYMENT_INVALID_REQUEST",
"message": "Date range must not exceed 90 days"
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 (page/size 범위 등) |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 503 | MAINTENANCE | 점검 중 |
| 406 | PAYMENT_INVALID_REQUEST | from/to 누락 (단건 또는 정산 id 미지정 시) 또는 조회 기간 제약 위반 |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
2.7 정산 내역 API (cursor)
2.6 정산 내역 API (offset) 의 keyset(cursor) 방식 버전입니다. 전량 순회(CSV 내보내기 등)에 사용하며, transactionId 와 settlementId 단건 필터는 지원하지 않습니다.
URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| from | STRING | 필수 | 조회 시작일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-01T00:00:00Z). 필수이며, to보다 이전 시점 설정 필수. |
| to | STRING | 필수 | 조회 종료일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-31T23:59:59Z). 필수이며, 조회 기간은 최대 90일. 현재보다 최소 1시간 이전이어야 함. |
| paymentType | STRING | 선택 | 결제 타입 필터 (PURCHASE / REFUND). 미지정 시 전체 |
| cursor | STRING | 선택 | 이전 응답의 nextCursor를 그대로 전달. 미지정 시 첫 페이지 (불투명 base64 토큰). |
| size | INTEGER | 선택 | 페이지 크기 (기본값: 50, 최대: 100) |
| order | STRING | 선택 | 정렬 방향 DESC(기본) / ASC. capturedAt 기준. |
요청 예시
GET /api/seller/v2/payment/settlement/transaction/cursor
?from=2026-08-01T00:00:00Z
&to=2026-08-24T23:59:59Z
&paymentType=PURCHASE
&size=50
&order=DESC
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| content | List | 필수 | 결제 데이터 목록. 항목 필드는 2.6 정산 내역 API 의 content 와 동일하며, 이 엔드포인트는 v2 전용이라 netAmount 와 protocolFeeRate 가 항상 포함됩니다. |
| nextCursor | STRING | 선택 | 다음 페이지 cursor. 다음 요청의 cursor로 그대로 전달. 마지막 페이지면 null. |
| hasNext | BOOLEAN | 필수 | 다음 페이지 존재 여부 |
응답 예시 — 성공
{
"content": [
{
"partnerCorpName": "Example Corp",
"storeId": "123",
"orderId": "LINK-3kQ9xR2mN7pLw8vBc1dEfH-a1B2c3D4e5F6",
"itemName": "Premium Package",
"serviceName": "GameShop",
"orderCountryCode": "KOR",
"orderCurrencyCode": "USD",
"orderAmount": 100.0,
"createdAt": "2026-08-20T10:04:50.000Z",
"transactionId": "20260820HV7QX2MK9RDBN4T",
"blockchainTxId": "0x7ad1c93ff2e4b8a0cf58d3011992abc...",
"paymentType": "PURCHASE",
"originTransactionId": null,
"status": "CONFIRMED",
"finalizedAt": "2026-08-20T10:05:32.000Z",
"capturedAt": "2026-08-20T10:05:30.000Z",
"failType": null,
"payCurrencyCode": "USDT",
"payAmount": 99.95,
"netAmount": 98.95,
"buyerWalletAddress": "0xabc...123",
"paymentExchangeRate": 1.0,
"variableFeeRate": 0,
"protocolFeeRate": 1,
"settlementId": "SETTLE-20260821-004",
"settlementCurrencyCode": "USDT",
"settlementExchangeRate": 1.0
}
],
"nextCursor": "MTc4NzIyMDMzMDAwMDoyMDI2MDgyMEhWN1FYMk1LOVJEQk40VA",
"hasNext": true
}
Cursor 토큰
offset 방식과의 차이
| 항목 | 2.6 offset | 2.7 cursor |
|---|---|---|
| 페이지 이동 | page / size | cursor / size |
| 전체 건수 | totalElements 제공 | 미제공 |
| 단건 필터 | transactionId / settlementId 지원 | 미지원 |
| 대용량 성능 | deep offset 에서 저하 | 일정 (O(size)) |
| 용도 | 화면 페이지네이션 | 파일 다운로드, 대량 순회 |
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 406 | PAYMENT_INVALID_REQUEST | 날짜 형식 오류, from 또는 to 누락, 조회 기간 90일 초과, to 가 현재로부터 1시간 이내 |
| 429 | RATE_LIMIT_EXCEEDED | 초당 요청 수 10건 초과. 정산 조회 엔드포인트는 각각 별도 버킷으로 제한됩니다. |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
2.8 결제 링크 목록 조회 API
발급한 결제 링크를 상태별로 조회합니다. 2.2 결제 링크 발급 API 와 짝이 되는 조회 API 입니다.
URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| status | STRING | 선택 | 조회할 링크 상태 (ACTIVE / EXPIRED). 미지정 시 ACTIVE. |
| page | INTEGER | 선택 | 페이지 번호 (0부터 시작, 기본값: 0) |
| size | INTEGER | 선택 | 페이지 크기 (기본값: 20, 1 이상 100 이하) |
size 기본값은 20 이며, 다른 조회 API 의 기본값 50 과 다릅니다.요청 예시
GET /api/seller/v2/payment/link
?status=ACTIVE
&page=0
&size=20
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| content | List | 필수 | 결제 링크 목록. |
| ↳ linkId | STRING | 필수 | 링크 식별자. |
| ↳ linkUrl | STRING | 필수 | 결제 링크 URL. |
| ↳ storeId | STRING | 필수 | 파트너 내부 스토어 ID. |
| ↳ serviceName | STRING | 필수 | 서비스 명칭. |
| ↳ itemName | STRING | 필수 | 상품명. |
| ↳ itemPrice | DOUBLE | 필수 | 상품 가격. |
| ↳ orderCurrencyCode | STRING | 필수 | 주문 통화 코드. |
| ↳ status | STRING | 필수 | 링크 상태 (ACTIVE / EXPIRED). 조회 시점의 expiresAt 경과 여부로 산출됩니다. |
| ↳ returnUrl | STRING | 선택 | 발급 시 설정한 값. 미설정 시 null 입니다. |
| ↳ callbackUrl | STRING | 선택 | 발급 시 설정한 값. 미설정 시 null 입니다. |
| ↳ expiresAt | INSTANT | 필수 | 링크 만료 시각. |
| ↳ createdAt | INSTANT | 필수 | 링크 발급 시각. |
| totalElements | LONG | 필수 | 전체 건수 |
| totalPages | INTEGER | 필수 | 전체 페이지수 |
| pageNumber | INTEGER | 필수 | 현재 페이지 번호 |
| first | BOOLEAN | 필수 | 첫 페이지 여부 |
| last | BOOLEAN | 필수 | 마지막 페이지 여부 |
status 는 저장된 상태가 아니라 조회 시점에 expiresAt 가 지났는지로 산출됩니다. 강제 만료도 expiresAt 를 당기므로 자연 만료와 같이 EXPIRED 로 나옵니다. status=EXPIRED 조회는 만료 후 30일 이내 링크만 반환하며, 그보다 오래된 링크는 목록에서 제외됩니다.응답 예시 — 성공
{
"content": [
{
"linkId": "3kQ9xR2mN7pLw8vBc1dEfH",
"linkUrl": "https://unifipay.example.com/pay/links/3kQ9xR2mN7pLw8vBc1dEfH",
"storeId": "STORE-001",
"serviceName": "GameShop",
"itemName": "Premium Package",
"itemPrice": 100.0,
"orderCurrencyCode": "USD",
"status": "ACTIVE",
"returnUrl": "https://myshop.com/payment/returnUrl",
"callbackUrl": "https://myshop.com/payment/callbackUrl",
"expiresAt": "2026-09-26T00:00:00.000Z",
"createdAt": "2026-08-25T09:12:44.000Z"
}
],
"totalElements": 1,
"totalPages": 1,
"pageNumber": 0,
"first": true,
"last": true
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
2.9 결제 링크 강제 만료 API
발급한 결제 링크를 강제로 만료시킵니다. expiresAt 를 호출 시각으로 당겨 이후 checkout 진입을 막으며, 이미 생성된 결제에는 영향이 없습니다.
요청 바디 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| linkId | STRING | 필수 | 만료시킬 링크 식별자. 결제 링크 발급 응답의 linkId 를 그대로 사용합니다. |
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| linkId | STRING | 필수 | 링크 식별자. |
| linkUrl | STRING | 필수 | 결제 링크 URL. |
| storeId | STRING | 필수 | 파트너 내부 스토어 ID. |
| serviceName | STRING | 필수 | 서비스 명칭. |
| itemName | STRING | 필수 | 상품명. |
| itemPrice | DOUBLE | 필수 | 상품 가격. |
| orderCurrencyCode | STRING | 필수 | 주문 통화 코드. |
| status | STRING | 필수 | 강제 만료 처리 직후의 응답이므로 항상 EXPIRED 입니다. |
| returnUrl | STRING | 선택 | 발급 시 설정한 값. 미설정 시 null 입니다. |
| callbackUrl | STRING | 선택 | 발급 시 설정한 값. 미설정 시 null 입니다. |
| expiresAt | INSTANT | 필수 | 만료 처리 시각(호출 시각)으로 갱신됩니다. |
| createdAt | INSTANT | 필수 | 링크 발급 시각. 원래 값이 유지됩니다. |
응답 예시
{
"linkId": "3kQ9xR2mN7pLw8vBc1dEfH",
"linkUrl": "https://unifipay.example.com/pay/links/3kQ9xR2mN7pLw8vBc1dEfH",
"storeId": "STORE-001",
"serviceName": "GameShop",
"itemName": "Premium Package",
"itemPrice": 100.0,
"orderCurrencyCode": "USD",
"status": "EXPIRED",
"returnUrl": "https://myshop.com/payment/returnUrl",
"callbackUrl": "https://myshop.com/payment/callbackUrl",
"expiresAt": "2026-09-07T10:20:00.000Z",
"createdAt": "2026-08-25T09:12:44.000Z"
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 406 | PAYMENT_LINK_INVALID | linkId 가 없거나 소유자가 일치하지 않는 경우. 링크의 존재를 노출하지 않기 위해 두 경우 모두 같은 코드로 응답합니다. |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
2.10 결제 링크 거래 내역 조회 API
결제 링크 하나로 발생한 거래를 전 상태로 조회합니다. 만료된 링크의 거래도 그대로 조회됩니다.
URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| linkId | STRING | 필수 | 링크 식별자 (base62 22자). 결제 링크 발급 응답의 linkId 를 그대로 사용합니다. 형식이 다르면 400 으로 응답합니다. |
| to | STRING | 필수 | 조회 종료 시각 (createdAt 기준, ISO 8601 UTC). 이 시점은 구간에 포함되지 않습니다. |
| from | STRING | 선택 | 조회 시작 시각 (createdAt 기준, ISO 8601 UTC). 이 시점은 구간에 포함됩니다. 생략 시 링크 발급 시각으로 채웁니다. |
| status | STRING | 선택 | 결제 상태 필터. 콤마로 여러 값을 지정할 수 있습니다. 미지정 시 전 상태. |
| paymentType | STRING | 선택 | 결제 타입 필터 (PURCHASE / REFUND). 미지정 시 전체 |
| cursor | STRING | 선택 | 이전 응답의 nextCursor 를 그대로 전달합니다. 첫 페이지는 생략합니다. page 파라미터는 없습니다. |
| size | INTEGER | 선택 | 페이지 크기 (기본값: 50, 1 이상 100 이하) |
| order | STRING | 선택 | 정렬 방향 DESC(기본) / ASC. createdAt 기준. |
from 이상 to 미만이며 to 는 구간에 포함되지 않습니다. from 를 생략하면 링크 발급 시각으로 채워지고, 구간 폭은 최대 90일입니다.orderId 를 승계하므로, paymentType 를 지정하지 않으면 구매와 환불이 함께 조회됩니다.요청 예시
GET /api/seller/v2/payment/link/Qx4nW2GRAEFkZQsdq7Fj1F/transaction
?to=2026-08-31T00:00:00Z
&from=2026-08-01T00:00:00Z
&status=CONFIRMED,PENDING
&paymentType=PURCHASE
&size=50
&order=DESC
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| content | List | 필수 | 거래 목록. |
| transactionId | STRING | 필수 | Unifi Pay에서 생성한 거래 번호. |
| orderId | STRING | 필수 | 주문 id. 결제 링크로 발생한 거래는 LINK 접두, linkId, 랜덤 문자열을 하이픈으로 이은 형태로 서버가 채번합니다. |
| storeId | STRING | 필수 | 요청자가 제공하는 가맹점 ID 정보. |
| serviceName | STRING | 필수 | 결제창에 노출될 서비스 또는 가맹점 정보. |
| items | List | 필수 | 결제 상품 목록. |
| ↳ name | STRING | 필수 | 판매 상품의 식별 정보. |
| ↳ price | DOUBLE | 필수 | 판매 상품의 가격. |
| paymentType | STRING | 필수 | 결제: PURCHASE / 환불: REFUND |
| status | STRING | 필수 | 결제 상태 (공개 표기). CREATED, PENDING, PAID, CONFIRMED, FAILED, CANCELED 6종입니다. |
| failType | STRING | 선택 | status 가 FAILED 일 때 설정되며 그 외에는 null 입니다. 값은 WALLET_PURCHASE_BLOCKCHAIN_FAILED, WALLET_REFUND_BLOCKCHAIN_FAILED, WALLET_PURCHASE_INSUFFICIENT_BALANCE, WALLET_REFUND_INSUFFICIENT_BALANCE, PAYMENT_PURCHASE_BLACKLISTED, PAYMENT_STORE_INACTIVE, WALLET_SESSION_EXPIRED, WALLET_TRANSFER_IN_PROGRESS, UNKNOWN 9종입니다. |
| countryCode | STRING | 필수 | ISO Alpha-3를 따르는 국가 코드 (예: KOR). |
| orderCurrencyCode | STRING | 필수 | ISO 4217를 따르는 주문 통화 코드 |
| orderAmount | DOUBLE | 필수 | 주문 금액 |
| payCurrencyCode | STRING | 선택 | 결제 토큰 통화 (USDT, JPYC). 확정 전에는 null 입니다. |
| payAmount | DOUBLE | 선택 | 실제 결제된 토큰 금액. 확정 전에는 null 입니다. |
| netAmount | DOUBLE | 선택 | 파트너 실수령액 (결제 통화 기준). CONFIRMED 이후 제공 |
| buyerWalletAddress | STRING | 선택 | 구매자 지갑 주소. 확정 전에는 null 입니다. |
| blockchainTxId | STRING | 선택 | 블록체인 트랜잭션 해시. 블록체인 확정 이후(CONFIRMED)이거나, 블록체인 네트워크에 전파된 후 실패(FAILED)한 경우에 반환됩니다. |
| blockchainNetworkFee | DOUBLE | 선택 | 블록체인 네트워크 수수료. 블록체인 확정 이후(CONFIRMED) 및 네트워크 전파 후 실패(FAILED) 시점에 실제로 소모된 수수료 금액이 반환됩니다. (Unifi가 전액 대납하여 사용자 부담은 없습니다.) |
| createdAt | INSTANT | 필수 | 결제 생성 시각 (ISO 8601 UTC). 기간, 정렬, cursor 의 기준입니다. |
| capturedAt | INSTANT | 선택 | 체인 이벤트가 관측된 시각. 관측 전에는 null 입니다. 값이 있어도 결제 성공을 뜻하지 않으므로 성공 여부는 status 로 판단하십시오. |
| finalizedAt | INSTANT | 선택 | 결제가 종료(확정, 실패, 취소)된 시각. 종결 전에는 null 입니다. |
| nextCursor | STRING | 선택 | 다음 페이지 cursor. 다음 요청의 cursor로 그대로 전달. 마지막 페이지면 null. |
| hasNext | BOOLEAN | 필수 | 다음 페이지 존재 여부 |
hasNext 가 true 인 동안 nextCursor 를 이어서 호출합니다. 순회 도중 from, to, status, paymentType, order 는 바꾸지 마십시오.응답 예시 — 성공
{
"content": [
{
"transactionId": "20260801XQ7MH9KV2RDBN4T",
"orderId": "LINK-Qx4nW2GRAEFkZQsdq7Fj1F-7bK2mQ9xR4pL",
"storeId": "123",
"serviceName": "GameShop",
"items": [
{
"name": "ITEM-GAME-001",
"price": 50.0
}
],
"paymentType": "PURCHASE",
"status": "CONFIRMED",
"failType": null,
"countryCode": "KOR",
"orderCurrencyCode": "USD",
"orderAmount": 50.0,
"payCurrencyCode": "USDT",
"payAmount": 49.98,
"netAmount": 49.48,
"buyerWalletAddress": "0xabc...123",
"blockchainTxId": "0x4fce0d72ff7f4b9f4ba0cf58d3011992...",
"blockchainNetworkFee": 0.00253778,
"createdAt": "2026-08-01T04:00:00.000Z",
"capturedAt": "2026-08-01T04:01:28.000Z",
"finalizedAt": "2026-08-01T04:01:30.000Z"
}
],
"nextCursor": "eyJ0cyI6IjIwMjYtMDgtMDFUMDQ6MDA6MDBaIiwidHgiOiIyMDI2MDgwMVhRN01IOUtWMlJEQk40VCJ9",
"hasNext": true
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | linkId 형식 오류 (base62 22자가 아님), size 범위 초과 등 |
| 406 | PAYMENT_LINK_INVALID | linkId 가 없거나 소유자가 일치하지 않는 경우. 링크의 존재를 노출하지 않기 위해 두 경우 모두 같은 코드로 응답합니다. |
| 406 | PAYMENT_INVALID_REQUEST | 날짜 형식 오류, from 이 to 보다 늦음, 조회 기간 90일 초과. from 을 생략한 경우에는 메시지에 링크 발급 시각이 포함됩니다. |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
2.11 결제 내역 조회 API
기간 안의 결제 내역을 전 상태로 조회합니다. 정산 대상(CONFIRMED) 만 돌려주는 2.6 정산 내역 API 와 달리 CREATED, PENDING, FAILED, CANCELED 도 포함합니다.
URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| from | STRING | 필수 | 조회 시작 시각 (createdAt 기준, ISO 8601 UTC). 이 시점은 구간에 포함되며, 구간 폭은 최대 90일입니다. |
| to | STRING | 필수 | 조회 종료 시각 (createdAt 기준, ISO 8601 UTC). 이 시점은 구간에 포함되지 않습니다. |
| status | STRING | 선택 | 결제 상태 필터. 콤마로 여러 값을 지정할 수 있습니다. 미지정 시 전 상태. |
| paymentType | STRING | 선택 | 결제 타입 필터 (PURCHASE / REFUND). 미지정 시 전체 |
| cursor | STRING | 선택 | 이전 응답의 nextCursor 를 그대로 전달합니다. 첫 페이지는 생략합니다. page 파라미터는 없습니다. |
| size | INTEGER | 선택 | 페이지 크기 (기본값: 50, 1 이상 100 이하) |
| order | STRING | 선택 | 정렬 방향 DESC(기본) / ASC. createdAt 기준. |
요청 예시
GET /api/seller/v2/payment/transaction
?from=2026-08-01T00:00:00Z
&to=2026-08-31T00:00:00Z
&status=CONFIRMED,PENDING
&paymentType=PURCHASE
&size=50
&order=DESC
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| content | List | 필수 | 거래 목록. |
| transactionId | STRING | 필수 | Unifi Pay에서 생성한 거래 번호. |
| orderId | STRING | 필수 | 주문 id. 결제 링크로 발생한 거래는 LINK 접두, linkId, 랜덤 문자열을 하이픈으로 이은 형태로 서버가 채번합니다. |
| storeId | STRING | 필수 | 요청자가 제공하는 가맹점 ID 정보. |
| serviceName | STRING | 필수 | 결제창에 노출될 서비스 또는 가맹점 정보. |
| items | List | 필수 | 결제 상품 목록. |
| ↳ name | STRING | 필수 | 판매 상품의 식별 정보. |
| ↳ price | DOUBLE | 필수 | 판매 상품의 가격. |
| paymentType | STRING | 필수 | 결제: PURCHASE / 환불: REFUND |
| status | STRING | 필수 | 결제 상태 (공개 표기). CREATED, PENDING, PAID, CONFIRMED, FAILED, CANCELED 6종입니다. |
| failType | STRING | 선택 | status 가 FAILED 일 때 설정되며 그 외에는 null 입니다. 값은 WALLET_PURCHASE_BLOCKCHAIN_FAILED, WALLET_REFUND_BLOCKCHAIN_FAILED, WALLET_PURCHASE_INSUFFICIENT_BALANCE, WALLET_REFUND_INSUFFICIENT_BALANCE, PAYMENT_PURCHASE_BLACKLISTED, PAYMENT_STORE_INACTIVE, WALLET_SESSION_EXPIRED, WALLET_TRANSFER_IN_PROGRESS, UNKNOWN 9종입니다. |
| countryCode | STRING | 필수 | ISO Alpha-3를 따르는 국가 코드 (예: KOR). |
| orderCurrencyCode | STRING | 필수 | ISO 4217를 따르는 주문 통화 코드 |
| orderAmount | DOUBLE | 필수 | 주문 금액 |
| payCurrencyCode | STRING | 선택 | 결제 토큰 통화 (USDT, JPYC). 확정 전에는 null 입니다. |
| payAmount | DOUBLE | 선택 | 실제 결제된 토큰 금액. 확정 전에는 null 입니다. |
| netAmount | DOUBLE | 선택 | 파트너 실수령액 (결제 통화 기준). CONFIRMED 이후 제공 |
| buyerWalletAddress | STRING | 선택 | 구매자 지갑 주소. 확정 전에는 null 입니다. |
| blockchainTxId | STRING | 선택 | 블록체인 트랜잭션 해시. 블록체인 확정 이후(CONFIRMED)이거나, 블록체인 네트워크에 전파된 후 실패(FAILED)한 경우에 반환됩니다. |
| blockchainNetworkFee | DOUBLE | 선택 | 블록체인 네트워크 수수료. 블록체인 확정 이후(CONFIRMED) 및 네트워크 전파 후 실패(FAILED) 시점에 실제로 소모된 수수료 금액이 반환됩니다. (Unifi가 전액 대납하여 사용자 부담은 없습니다.) |
| createdAt | INSTANT | 필수 | 결제 생성 시각 (ISO 8601 UTC). 기간, 정렬, cursor 의 기준입니다. |
| capturedAt | INSTANT | 선택 | 체인 이벤트가 관측된 시각. 관측 전에는 null 입니다. 값이 있어도 결제 성공을 뜻하지 않으므로 성공 여부는 status 로 판단하십시오. |
| finalizedAt | INSTANT | 선택 | 결제가 종료(확정, 실패, 취소)된 시각. 종결 전에는 null 입니다. |
| nextCursor | STRING | 선택 | 다음 페이지 cursor. 다음 요청의 cursor로 그대로 전달. 마지막 페이지면 null. |
| hasNext | BOOLEAN | 필수 | 다음 페이지 존재 여부 |
hasNext 가 true 인 동안 nextCursor 를 이어서 호출합니다. 순회 도중 from, to, status, paymentType, order 는 바꾸지 마십시오.PAID 상태이면 status=PAID 필터에는 걸리지만 응답의 status 는 CONFIRMED 로 내려갑니다. 결제를 생성한 버전과 조회에 쓴 버전이 모두 v2 일 때만 PAID 가 노출됩니다.응답 예시 — 성공
{
"content": [
{
"transactionId": "20260801XQ7MH9KV2RDBN4T",
"orderId": "ORD-20260304-0001",
"storeId": "123",
"serviceName": "GameShop",
"items": [
{
"name": "ITEM-GAME-001",
"price": 50.0
}
],
"paymentType": "PURCHASE",
"status": "CONFIRMED",
"failType": null,
"countryCode": "KOR",
"orderCurrencyCode": "USD",
"orderAmount": 50.0,
"payCurrencyCode": "USDT",
"payAmount": 49.98,
"netAmount": 49.48,
"buyerWalletAddress": "0xabc...123",
"blockchainTxId": "0x4fce0d72ff7f4b9f4ba0cf58d3011992...",
"blockchainNetworkFee": 0.00253778,
"createdAt": "2026-08-01T04:00:00.000Z",
"capturedAt": "2026-08-01T04:01:28.000Z",
"finalizedAt": "2026-08-01T04:01:30.000Z"
}
],
"nextCursor": "eyJ0cyI6IjIwMjYtMDgtMDFUMDQ6MDA6MDBaIiwidHgiOiIyMDI2MDgwMVhRN01IOUtWMlJEQk40VCJ9",
"hasNext": true
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | from 또는 to 누락, size 범위 초과, 알 수 없는 status, paymentType, order 값 등 |
| 406 | PAYMENT_INVALID_REQUEST | 날짜 형식 오류 (ISO 8601 아님), from 이 to 보다 늦음, 조회 기간 90일 초과 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
2.12 스토어 목록 조회 API
자기 파트너에 속한 스토어 목록을 조회합니다. 결제 링크는 스토어에 속하고 주문 통화와 결제 통화가 스토어를 따라가므로, 2.2 결제 링크 발급 API 를 호출하기 전에 이 API 로 partnerStoreId 와 허용 통화를 확인합니다.
URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| partnerStoreId | STRING | 선택 | 파트너 내부 스토어 ID 로 필터링합니다. 미지정 시 전체. |
| status | STRING | 선택 | 조회할 스토어 상태 (ACTIVE / INACTIVE). 미지정 시 전체. |
| page | INTEGER | 선택 | 페이지 번호 (0부터 시작, 기본값: 0) |
| size | INTEGER | 선택 | 페이지 크기 (기본값: 20, 1 이상 50 이하) |
요청 예시
GET /api/seller/v2/store
?status=ACTIVE
&page=0
&size=20
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| content | List | 필수 | 스토어 목록. |
| ↳ partnerStoreId | STRING | 필수 | 파트너 내부 스토어 ID. 결제 링크 발급의 storeId 로 쓰는 값입니다. |
| ↳ name | STRING | 필수 | 스토어 명. |
| ↳ status | STRING | 필수 | 스토어 상태 (ACTIVE / INACTIVE). |
| ↳ orderCurrencyCodes | List | 선택 | 허용 주문 통화 목록. null 이면 파트너 정책을 상속합니다. |
| ↳ paymentCurrencyCodes | List | 선택 | 허용 결제 코인 목록. null 이면 파트너 정책을 상속합니다. |
| totalElements | LONG | 필수 | 전체 건수 |
| totalPages | INTEGER | 필수 | 전체 페이지수 |
| pageNumber | INTEGER | 필수 | 현재 페이지 번호 |
| first | BOOLEAN | 필수 | 첫 페이지 여부 |
| last | BOOLEAN | 필수 | 마지막 페이지 여부 |
null 이면 파트너 정책을 그대로 상속하며, 스토어 통화는 항상 파트너 통화의 부분집합입니다. 결제 링크 발급 시점에 요청한 주문 통화가 허용 목록 밖이면 발급이 거부됩니다.응답 예시 — 성공
{
"content": [
{
"partnerStoreId": "STORE-001",
"name": "GameShop Main",
"status": "ACTIVE",
"orderCurrencyCodes": [
"USD",
"JPY"
],
"paymentCurrencyCodes": [
"USDT"
]
}
],
"totalElements": 1,
"totalPages": 1,
"pageNumber": 0,
"first": true,
"last": true
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
2.13 Blacklist API
자기 파트너 범위의 차단 지갑을 등록, 조회, 범위 변경, 해제하는 API 6종입니다. 인증은 2.1 인증 (Authentication) 과 동일한 HMAC 방식이며, 항상 자기 파트너 범위로만 동작합니다.
지갑 주소 형식
| 항목 | 설명 |
|---|---|
| walletAddress | 0x 로 시작하는 16진수 40자 EVM 주소입니다. 대문자와 소문자를 모두 허용합니다 (^0x[0-9a-fA-F]{40}$). |
차단 사유 (reason)
| 값 | 설명 |
|---|---|
| FRAUD_PATTERN | 이상 거래 반복 |
| REFUND_ABUSE | 비정상적 환불 요청 |
| AML_SUSPECT | 자금세탁 의심 |
| BLACK_CONSUMER | 블랙컨슈머 |
| OTHER | 기타. memo 로 보충합니다. |
차단 유형 (blockTypes)
| 값 | 설명 |
|---|---|
| PURCHASE | 결제를 차단합니다. |
| REFUND | 환불을 차단합니다. |
scopeType 은 PARTNER (파트너 전체) 와 STORE (지정 스토어) 두 가지입니다. 차단 등록 요청 바디에는 scopeType 필드가 없으며, storeIds 를 비우면 PARTNER, 스토어를 지정하면 STORE 로 결정됩니다.PAYMENT_PURCHASE_BLACKLISTED 로 실패하며 2.3 결제 상태 확인 API 의 failType 표에 있습니다. 환불은 PAYMENT_REFUND_BLACKLISTED 로 거절되며 2.5 환불 API (DIRECT) 의 환불 접수 오류 표에 있습니다.차단 지갑 목록 조회 API
자기 파트너 범위에 등록된 차단 지갑을 조회합니다. 응답의 id 는 차단 범위 변경과 차단 해제의 경로 변수로 사용합니다.
요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| walletAddress | STRING | 선택 | 지갑 주소로 필터링합니다. |
| reason | STRING | 선택 | 차단 사유로 필터링합니다 (FRAUD_PATTERN / REFUND_ABUSE / AML_SUSPECT / BLACK_CONSUMER / OTHER). 미지정 시 전체. |
| scopeType | STRING | 선택 | 차단 범위로 필터링합니다 (PARTNER / STORE). 미지정 시 전체. |
| blockType | STRING | 선택 | 차단 유형으로 필터링합니다 (PURCHASE / REFUND). 미지정 시 전체. |
| page | INTEGER | 선택 | 페이지 번호 (0부터 시작, 기본값: 0) |
| size | INTEGER | 선택 | 페이지 크기 (기본값: 20, 1 이상 100 이하) |
요청 예시
GET /api/seller/v2/blacklist/search
?scopeType=PARTNER
&page=0
&size=20
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| content | List | 필수 | 차단 지갑 목록. |
| ↳ id | LONG | 필수 | 차단 행 ID. 차단 범위 변경과 차단 해제의 경로 변수 {id} 로 사용합니다. |
| ↳ walletAddress | STRING | 필수 | 차단된 지갑 주소. |
| ↳ reason | STRING | 필수 | 차단 사유. |
| ↳ blockTypes | List | 선택 | 차단 유형 (PURCHASE / REFUND). |
| ↳ scopeType | STRING | 필수 | 차단 범위 (PARTNER / STORE). |
| ↳ scopes | List | 필수 | 적용 범위 목록 (partnerId, storeIds). |
| ↳ active | BOOLEAN | 필수 | 활성 여부. |
| ↳ memo | STRING | 선택 | 메모. |
| ↳ registeredBy | STRING | 선택 | 등록 주체 (appId). |
| ↳ registeredAt | INSTANT | 필수 | 등록 일시. |
| totalElements | LONG | 필수 | 전체 건수 |
| totalPages | INTEGER | 필수 | 전체 페이지수 |
| pageNumber | INTEGER | 필수 | 현재 페이지 번호 |
| first | BOOLEAN | 필수 | 첫 페이지 여부 |
| last | BOOLEAN | 필수 | 마지막 페이지 여부 |
응답 예시 — 성공
{
"content": [
{
"id": 3012,
"walletAddress": "0x1234567890abcdef1234567890abcdef12345678",
"reason": "REFUND_ABUSE",
"blockTypes": [
"PURCHASE",
"REFUND"
],
"scopeType": "PARTNER",
"scopes": [
{
"partnerId": "55",
"storeIds": null
}
],
"active": true,
"memo": "반복 환불 요청",
"registeredBy": "seller-app-001",
"registeredAt": "2026-08-24T05:31:00.000Z"
}
],
"totalElements": 1,
"totalPages": 1,
"pageNumber": 0,
"first": true,
"last": true
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
차단 등록 API
지갑을 차단 목록에 등록합니다. 사유나 메모를 바꾸는 API 는 없으므로 차단을 해제한 뒤 다시 등록해야 하며, 범위만 차단 범위 변경 API 로 바꿀 수 있습니다.
요청 바디 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| walletAddress | STRING | 필수 | 차단할 지갑 주소입니다. 0x 로 시작하는 16진수 40자 EVM 주소를 입력합니다. |
| reason | STRING | 필수 | 차단 사유입니다 (FRAUD_PATTERN / REFUND_ABUSE / AML_SUSPECT / BLACK_CONSUMER / OTHER). |
| blockTypes | List | 선택 | 차단 유형입니다 (PURCHASE / REFUND). 생략하면 전 유형을 차단합니다. |
| storeIds | List | 선택 | 비우면 파트너 전체, 지정하면 그 스토어만 차단합니다. 최대 50개이며 각 항목은 최대 64자입니다. 0 은 예약값이라 입력할 수 없습니다. |
| memo | STRING | 선택 | 메모입니다. 최대 1000자. |
요청 예시
{
"walletAddress": "0x1234567890abcdef1234567890abcdef12345678",
"reason": "REFUND_ABUSE",
"blockTypes": [
"PURCHASE",
"REFUND"
],
"storeIds": [
"STORE-001"
],
"memo": "반복 환불 요청"
}
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| id | LONG | 필수 | 등록된 차단 행 ID. |
응답 예시 — 성공
{
"id": 3012
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 지갑 주소 형식 오류, 또는 storeIds 에 예약값 0 포함 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 406 | BLACKLIST_ALREADY_EXIST | 이미 차단된 지갑입니다. 같은 파트너로 활성 항목이 존재합니다. |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
차단 범위 변경 API
차단의 적용 범위를 파트너 전체와 지정 스토어 사이에서 전환합니다. 경로 변수 {id} 는 차단 지갑 목록 조회 응답의 id 입니다.
요청 바디 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| storeIds | List | 선택 | 비우면 파트너 전체, 지정하면 그 스토어만 차단합니다. 최대 50개이며 각 항목은 최대 64자입니다. 0 은 예약값이라 입력할 수 없습니다. |
storeIds 는 부분 수정이 아니라 기존 범위 전체를 교체합니다. 필드를 생략하거나 null 로 보내면 파트너 전체로 전환되고, 빈 배열을 보내면 400 으로 거부됩니다.요청 예시
{
"storeIds": [
"STORE-001"
]
}
응답 필드 (200 OK)
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | storeIds 가 빈 배열이거나 예약값 0 을 포함한 경우 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 406 | PAYMENT_TRANSACTION_NOT_FOUND | id 가 없거나 다른 파트너 소유인 경우. 항목의 존재를 노출하지 않기 위해 두 경우 모두 같은 코드로 응답합니다. |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
차단 해제 API
등록한 차단을 해제합니다. 경로 변수 {id} 는 차단 지갑 목록 조회 응답의 id 입니다.
요청 바디 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| reason | STRING | 선택 | 해제 사유입니다. 이력에 기록되며 최대 1000자입니다. |
요청 예시
{
"reason": "이의신청 승인으로 차단 해제"
}
응답 필드 (200 OK)
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 406 | PAYMENT_TRANSACTION_NOT_FOUND | id 가 없거나 이미 해제되었거나 다른 파트너 소유인 경우. 항목의 존재를 노출하지 않기 위해 모두 같은 코드로 응답합니다. |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
차단 요약 조회 API
활성 차단 지갑 수와 최근 24시간 차단 시도를 요약해 조회합니다. 요청 파라미터는 없습니다.
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| blacklistWalletCount | LONG | 필수 | 활성 차단 지갑 수. |
| blockedAttempt.count | LONG | 필수 | 거절 건수. |
| blockedAttempt.period | STRING | 선택 | 집계 기간 표기입니다. 현재 24H 로 고정입니다. |
응답 예시 — 성공
{
"blacklistWalletCount": 7,
"blockedAttempt": {
"count": 23,
"period": "24H"
}
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
차단 해제 이력 조회 API
자기 파트너가 영향받은 차단, 범위 변경, 해제 이력을 조회합니다. 필터 없이 페이징만 제공합니다.
요청 쿼리 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| page | INTEGER | 선택 | 페이지 번호 (0부터 시작, 기본값: 0) |
| size | INTEGER | 선택 | 페이지 크기 (기본값: 20, 1 이상 100 이하) |
요청 예시
GET /api/seller/v2/blacklist/history/search
?page=0
&size=20
응답 필드 (200 OK)
| 필드 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| content | List | 필수 | 차단 변경 이력 목록. |
| ↳ id | LONG | 필수 | 이력 행 ID. |
| ↳ blacklistId | LONG | 필수 | 대상 차단 행 ID. |
| ↳ walletAddress | STRING | 필수 | 지갑 주소. |
| ↳ changeType | STRING | 필수 | 변경 유형 (REGISTER / SCOPE_CHANGE / UNBLOCK). |
| ↳ beforeScopes | List | 선택 | 변경 전 범위 (partnerId, storeIds). |
| ↳ afterScopes | List | 선택 | 변경 후 범위. |
| ↳ blockTypes | List | 선택 | 차단 유형. |
| ↳ unblockReason | STRING | 선택 | 해제 사유 (UNBLOCK 인 경우). |
| ↳ createdAt | INSTANT | 필수 | 변경 일시. |
| totalElements | LONG | 필수 | 전체 건수 |
| totalPages | INTEGER | 필수 | 전체 페이지수 |
| pageNumber | INTEGER | 필수 | 현재 페이지 번호 |
| first | BOOLEAN | 필수 | 첫 페이지 여부 |
| last | BOOLEAN | 필수 | 마지막 페이지 여부 |
응답 예시 — 성공
{
"content": [
{
"id": 9001,
"blacklistId": 3012,
"walletAddress": "0x1234567890abcdef1234567890abcdef12345678",
"changeType": "REGISTER",
"beforeScopes": null,
"afterScopes": [
{
"partnerId": "55",
"storeIds": null
}
],
"blockTypes": [
"PURCHASE",
"REFUND"
],
"unblockReason": null,
"createdAt": "2026-08-24T05:31:00.000Z"
}
],
"totalElements": 1,
"totalPages": 1,
"pageNumber": 0,
"first": true,
"last": true
}
오류 타입 코드
| HTTP 상태 | 오류 코드 | 설명 |
|---|---|---|
| 400 | BAD_REQUEST | 유효하지 않은 입력 값 |
| 401 | UNAUTHORIZED | 유효하지 않은 HMAC |
| 403 | FORBIDDEN | 허용되지 않은 IP 혹은 Path |
| 500 | INTERNAL_SERVER_ERROR | 서버 내부 오류 |
| 503 | MAINTENANCE | 점검 중 |
3. 테스트 가이드
Preview 환경에서 Unifi Pay 결제 연동을 테스트하는 방법입니다.
- 1 Unifi Pay 테스트는 Preview 환경에서 진행할 수 있습니다.
- 2 Unifi Wallet은 Preview 환경에서 Production 기준의 Google 계정으로 생성 및 연동을 진행합니다. (Preview 환경에서 생성한 Unifi Wallet은 Production 환경과 별도로 관리됩니다.) Preview Unifi Wallet →
- 3 Preview 환경의 결제는 Kaia Blockchain의 테스트넷 환경인 Kairos 기준으로 진행됩니다.
- 4 아래 가이드를 참고하여 Kairos 테스트넷에서 테스트용 USDT를 확보한 후 결제 테스트를 진행해주시기 바랍니다.
Preview 환경
Kairos Testnet (테스트넷)
Preview 환경에서는 카이아 블록체인의 테스트넷인 Kairos 체인이 연동되며, 테스트 자금은 아래 Faucet 서비스를 통해 확보할 수 있습니다.
Kaia Faucet →https://app-api-pay.unifi.me