Docs Sandbox API

Unifi Pay Direct API 레퍼런스

문서 버전 안내: 이 페이지는 최신 API v2 기준 문서입니다. API v1으로 연동 중인 파트너를 위한 기존 문서도 계속 제공됩니다. V1 문서 보기

Unifi Pay API를 연동하는 개발자를 위한 API 레퍼런스 입니다.

빠른 연동

SDK 없이 REST API만으로 결제 연동 완료

HMAC 보안

API 요청 시 HMAC 서명 인증 적용

Webhook 지원

비동기 Webhook으로 실시간 결제 상태 수신

AI 연동 가이드

AI 코딩 어시스턴트에 제공하면 API 연동 작업에 참고 자료로 활용할 수 있습니다.

1 PDF 또는 평문(txt) 파일을 받습니다.
2 Claude Code, Codex CLI 등 AI 코딩 어시스턴트에 파일로 제공합니다.
3 "이 문서를 참고해서 결제 연동 코드를 작성해줘"처럼 요청합니다.

1. API 연동 다이어그램

결제 링크 발급 방식의 가맹점 서버·고객·Unifi Pay 간 데이터 흐름입니다.

1.1 결제 다이어그램

결제 링크 발급부터 Webhook 수신까지의 전체 흐름입니다.

동기 호출 (Sync)
응답 (Response)
비동기 Webhook (Async)
Customer (Browser) Your Server Backend Unifi Pay API Server 1 POST /api/seller/v2/payment/link X-API-Key · X-Timestamp · X-Authorization-Hmac 2 200 OK — linkUrl, linkId 3 고객에게 결제 링크 공유 linkUrl Unifi Pay 결제 링크 페이지 4 결제 링크 접속 5 ‘결제 진행하기’ 클릭 시 결제 요청 생성 transactionId · orderId = LINK-{linkId}-{randomstring} 6 지갑 연결 및 결제 승인 온체인 전송 7 POST {callbackUrl} callbackUrl 등록 시에만 전송 status: PAID [1st Webhook] 8 POST {callbackUrl} callbackUrl 등록 시에만 전송 status: CONFIRMED / FAILED [2nd Webhook]

Your Server: apiKey와 HMAC Signature를 이용해 Unifi Pay에 결제 링크 발급을 요청합니다.

결제 링크: 발급받은 linkUrl을 고객에게 공유합니다. 공유 채널에는 제한이 없습니다.

Customer: 링크에 접속해 결제를 진행하면 결제 요청이 생성되고, 지갑 연결 및 서명으로 결제가 완료됩니다.

Webhook: 결제 링크 발급 시 callbackUrl을 등록한 경우에만 전송됩니다. PAID 시점에 1차, CONFIRMED 시점에 2차로 결제 결과를 비동기 전송합니다. 결제 결과를 전달받는 유일한 경로이므로 반드시 등록하십시오.


2. API 상세 소개

Base URL
Preview https://app-api-pay.unifi.me
Production https://api-pay.unifi.me

2.1 인증 (Authentication)

서버 간 API 요청은 기본적으로 HMAC 인증이 필수입니다. X-Authorization-Hmac 헤더에 서명값을 포함해야 합니다. X-Authorization-Hmac

기본 인증 규칙: 별도 표기가 없는 한 서버 간 API 는 모두 HMAC 인증이 기본입니다. 인증 방식이 다른 API(예: 무인증 공개 API)는 해당 API 에 별도로 표기합니다.

HMAC 생성 공식

Formula
BASE64(HMACSHA256(apiSecret, {HTTP_METHOD}{URI}{X-API-Key}{X-Timestamp}{REQUEST_BODY}))
REQUEST_BODY가 있는 경우
POST /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 (공백 없이)
  )
)
REQUEST_BODY가 없는 경우
GET /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 없음 (생략)
  )
)
쿼리 파라미터가 있는 경우
GET /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-HmacSTRING필수생성된 HMAC 서명값. 모든 서버 간 API 요청에 필수입니다.
X-API-KeySTRING필수Unifi Pay에서 발급받은 apiKey.
X-TimestampSTRING필수밀리초 단위 Unix 타임스탬프. 현재 시각과 5분 이상 차이 시 요청이 거부됩니다.
⚠️ 타임스탬프 유효 범위: X-Timestamp는 현재 서버 시각에서 5분 이내여야 합니다. 이 범위를 벗어나면 재전송 공격(Replay Attack) 방지를 위해 요청이 자동으로 거부됩니다.
서버 timestamp 조회

Unifi Pay 서버의 timestamp를 조회하여 서버 상태를 확인하고, 응답의 timestamp 값을 HMAC 서명에 활용합니다.

GET /api/v2/server/time
인증 방식: 이 API 는 무인증 공개 API 입니다. X-API-Key · X-Timestamp · X-Authorization-Hmac 헤더 없이 호출합니다. HMAC 서명에 사용할 timestamp 를 얻기 위한 API 이므로 위 기본 인증 규칙에서 제외됩니다.

응답 필드

필드 이름 타입 설명
timestampINTEGER(INT64)서버의 timestamp 밀리초 단위 값

응답 예시

정상 응답 · 200 OK
{
  "timestamp": 1773017787000
}
오류 응답 · 500 Internal Server Error
{
  "code": "INTERNAL_SERVER_ERROR",
  "message": ""
}

2.3 결제 상태 확인 API

생성된 결제 건의 현재 상태를 확인합니다.

아래 응답 필드와 예시는 v2 응답 기준입니다. v2 응답에만 있는 필드에는 v2 전용 배지를 표시했습니다.

GET /api/seller/v2/payment/{transactionId}

응답 필드

필드 이름 타입 설명
transactionIdSTRINGUnifi Pay에서 생성한 거래 번호.
orderIdSTRINGUnifi Pay에서 생성한 주문 id. 결제 링크를 통한 거래는 LINK-{linkId}-{12문자 랜덤 문자열} 형식으로 발급됩니다.
storeIdSTRING요청자가 제공하는 가맹점 ID 정보.
serviceNameSTRING결제창에 노출될 서비스 또는 가맹점 정보.
paymentTypeSTRINGv2 전용 결제: PURCHASE / 환불: REFUND
statusSTRING
CREATED결제 생성 완료
PENDING결제 진행 중
PAID결제 성공
CONFIRMED정산 완료 (종결)
FAILED결제 실패 (종결)
CANCELED결제 취소 (종결)
failTypeSTRING

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건
↳ nameSTRING판매 상품의 식별 정보.
↳ priceDOUBLE판매 상품의 가격.
countryCodeSTRINGISO Alpha-3를 따르는 국가 코드 (예: KOR).
orderCurrencyCodeSTRINGISO 4217를 따르는 주문 통화 코드 (USD, JPY).
orderAmountDOUBLE주문한 금액.
payCurrencyCodeSTRING결제한 스테이블 코인 종류.
payAmountDOUBLE결제된 금액.
buyerWalletAddressSTRING구매자 지갑 주소. 서명 전(CREATED)에는 null 입니다.
netAmountDOUBLEv2 전용 파트너 실수령액 (결제 통화 기준). CONFIRMED 이후 제공
blockchainTxIdSTRING블록체인 트랜잭션 해시. 블록체인 확정 이후(CONFIRMED)이거나, 블록체인 네트워크에 전파된 후 실패(FAILED)한 경우에 반환됩니다.
blockchainNetworkFeeDOUBLE블록체인 네트워크 수수료. 블록체인 확정 이후(CONFIRMED) 및 네트워크 전파 후 실패(FAILED) 시점에 실제로 소모된 수수료 금액이 반환됩니다. (Unifi가 전액 대납하여 사용자 부담은 없습니다.)
createdAtINSTANTv2 전용 주문 결제 요청 일시
capturedAtINSTANTv2 전용 체인 이벤트가 관측된 시각. 관측 전에는 null 입니다. 값이 있어도 결제 성공을 뜻하지 않으므로 성공 여부는 status 로 판단하십시오.
finalizedAtINSTANTv2 전용 결제가 종료(확정, 실패, 취소)된 시각. 종결 전에는 null 입니다.
📌 v1·v2 혼용 안내: PAID 상태는 결제 건이 v2로 생성되고 v2 API로 조회·수신하는 경우에만 노출됩니다. 생성 또는 조회 중 하나라도 v1이면 PAID 없이 기존과 동일하게 CONFIRMED로 안내됩니다.
⚠️ PAID 시점 응답 안내: PAID 시점에는 blockchainTxId·blockchainNetworkFee가 반환되지 않습니다. 결제 금액(payAmount)은 CONFIRMED 시점에 확정되므로, 금액·블록체인 정보는 CONFIRMED 이후 조회한 값을 사용하시기 바랍니다.

응답 예시

JSON
{
  "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"
}
CONFIRMED

결제가 확정되고 정산까지 완료되어 종결된 상태입니다.

FAILED

결제가 실패한 상태입니다.

오류 응답

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) 수신 시점부터 결제 완료 화면으로 전환할 수 있습니다.

POST <가맹점 callbackUrl>

Webhook 바디 필드

필드 이름 타입 필수 설명
transactionIdSTRING필수Unifi Pay에서 생성한 거래 번호.
orderIdSTRING필수Unifi Pay에서 생성한 주문 id. 결제 링크를 통한 거래는 LINK-{linkId}-{12문자 랜덤 문자열} 형식으로 발급되며, 고객이 결제 링크에서 결제를 진행한 시점에 결정됩니다.
statusSTRING필수결제 처리 결과. PAID: 결제 성공 (1차 Webhook), CONFIRMED: 정산 완료 (2차 Webhook), FAILED: 실패, CANCELED: CREATED 상태로 약 30분 이상 유지되거나 사용자가 결제창을 이탈한 경우 취소.
typeSTRING필수거래 유형. PURCHASE 또는 REFUND입니다. 환불도 같은 Webhook으로 통지되며, 이때 transactionId와 orderId는 환불 거래의 값입니다 (orderId는 원결제의 orderId를 승계하므로 구매 건과 같은 값입니다). 조회 응답의 paymentType 필드와 같은 값을 뜻합니다.

요청 예시 (JSON) — 1차 Webhook (PAID)

JSON
{
  "transactionId": "<transactionId>",
  "orderId": "LINK-3f1d0a549c1e4f6a8a5b2f-a1b2c3d4e5f6",
  "status": "PAID",
  "type": "PURCHASE"
}

요청 예시 (JSON) — 2차 Webhook (CONFIRMED)

JSON
{
  "transactionId": "<transactionId>",
  "orderId": "LINK-3f1d0a549c1e4f6a8a5b2f-a1b2c3d4e5f6",
  "status": "CONFIRMED",
  "type": "PURCHASE"
}
📡 응답 필수 안내: 가맹점 서버는 Webhook 수신 후 반드시 HTTP 200 OK 응답 코드를 반환해야 합니다.
💡 상세 조회: Webhook은 최소한의 정보만 전달합니다. 결제 상세 정보는 Webhook 수신 후 2.3 결제 상태 확인 API를 호출하여 조회하세요.
⚠️ PAID 시점 응답 안내: 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 경로를 기준으로 기재합니다.

처리 방법: 아래 환불 접수 API 로 접수한 뒤, 응답으로 받은 startPageUrl 페이지에서 판매자가 본인 명의의 Unifi Wallet으로 직접 서명해야 환불이 실행됩니다 (billing 미경유). Unifi Pay 콘솔의 환불 관리 메뉴에서 접수하는 방법도 그대로 사용할 수 있습니다.
💡 참고: 환불은 원결제가 CONFIRMED 상태인 경우에만 진행할 수 있습니다.
💡 접수 조건: 위 상태 조건과 함께 원결제가 DIRECT 수취(파트너 지갑 즉시 분배)인 건만 환불할 수 있습니다. 같은 원결제에 진행 중인 환불은 1건만 허용되며, 서명하지 않은 접수 건은 자동으로 취소되어 집계에서 제외됩니다.
환불 상태값: DIRECT 환불은 PAID(판매자 서명 직후), CONFIRMED(체인 수집 완료), FAILED 세 가지 상태를 가집니다. PENDING 구간은 없습니다.

환불 접수 API

원결제에 대한 환불을 접수합니다. 응답으로 받은 서명 페이지에서 판매자가 서명해야 환불이 진행됩니다.

POST /api/seller/v2/payment/refund/direct

요청 바디 파라미터

파라미터 타입 길이 필수 설명
requestIdSTRING128필수환불 요청 식별자. 파트너 안에서 전역 유니크해야 합니다.
orderIdSTRING128필수원결제 주문 ID. 아래 환불 사전 조회 API 응답의 orderId 를 그대로 사용합니다.
orderCurrencyCodeSTRING8필수주문 통화 코드. 원결제와 일치해야 합니다.
orderAmountDOUBLE—필수환불 금액. 0보다 커야 합니다.
isPartialBOOLEAN—필수부분 환불 여부. true: 부분 환불, false: 전액 환불.

응답 필드

필드 이름 타입 필수 설명
transactionIdSTRING필수생성된 환불 거래 ID. 아래 환불 단건 조회 API 로 상태를 추적합니다.
startPageUrlSTRING필수판매자 서명 페이지 URL. 이 페이지에서 서명해야 환불이 진행됩니다.

요청 예시 (JSON)

JSON
{
  "requestId": "RFD-20260907-0001",
  "orderId": "LINK-3kQ9xR2mN7pLw8vBc1dEfH-a1B2c3D4e5F6",
  "orderCurrencyCode": "USD",
  "orderAmount": 30.0,
  "isPartial": true
}

응답 예시

JSON
{
  "transactionId": "20260907QH4MX9KV7RDB2NT",
  "startPageUrl": "https://unifipay.example.com/refund/start?token=<token>"
}

오류 응답

HTTP 상태 오류 코드 설명
400BAD_REQUEST유효하지 않은 입력 값
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
406PAYMENT_TRANSACTION_NOT_FOUND원결제를 찾을 수 없음
406PAYMENT_INVALID_REQUEST원결제가 DIRECT 수취가 아니거나 CONFIRMED 상태가 아님, 같은 원결제에 진행 중 환불 존재, 잔여 환불 가능액 초과, requestId 중복, 통화 또는 금액 정책 위반
406PAYMENT_REFUND_BLACKLISTED구매자 지갑이 환불 차단 대상
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

환불 사전 조회 API

환불 접수 전에 환불 가능 여부와 잔여 환불 가능액을 확인합니다. 접수 전 안내용이며 접수를 보장하지 않으므로, 접수 실패를 정상 흐름으로 처리해 주십시오.

GET /api/seller/v2/payment/refund/lookup
💡 서명 대상: HMAC 서명의 URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.

요청 쿼리 파라미터

파라미터 타입 필수 설명
transactionIdSTRING필수원결제 거래 ID.

응답 필드 (200 OK)

필드 이름 타입 필수 설명
transactionIdSTRING필수원결제 거래 ID.
orderIdSTRING필수원결제 주문 ID. 환불 접수 API 의 orderId 로 그대로 사용합니다.
statusSTRING필수원결제 상태 (공개 표기).
orderAmountDOUBLE필수원결제 주문 금액.
refundedAmountDOUBLE필수확정된 환불과 진행 중인 환불의 합계. 서명하지 않은 초안은 제외됩니다.
refundableAmountDOUBLE필수남은 환불 가능액. orderAmount 에서 refundedAmount 를 뺀 값입니다.
refundableBOOLEAN필수지금 접수할 수 있는지에 대한 사전 판정 결과.
reasonSTRING선택접수 불가 사유 코드. 접수할 수 있으면 null 입니다.
reason 값: ORIGINAL_NOT_CONFIRMED 원결제가 아직 확정 전, ORIGINAL_NOT_REFUNDABLE 실패 또는 취소로 종료, FULLY_REFUNDED 전액 환불 완료, NOT_DIRECT_PAYOUT DIRECT 수취가 아님.

응답 예시

JSON
{
  "transactionId": "20260820HV7QX2MK9RDBN4T",
  "orderId": "LINK-3kQ9xR2mN7pLw8vBc1dEfH-a1B2c3D4e5F6",
  "status": "CONFIRMED",
  "orderAmount": 100.0,
  "refundedAmount": 30.0,
  "refundableAmount": 70.0,
  "refundable": true,
  "reason": null
}

오류 응답

HTTP 상태 오류 코드 설명
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

환불 단건 조회 API

접수한 환불 1건의 상태를 조회합니다. 경로 변수 transactionId 는 원결제 ID 가 아니라 환불 접수 응답으로 받은 환불 거래 ID 입니다.

GET /api/seller/v2/payment/refund/{transactionId}
💡 서명 대상: HMAC 서명의 URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.

응답 필드 (200 OK)

필드 이름 타입 필수 설명
transactionIdSTRING필수환불 거래 ID.
orderIdSTRING필수원결제 주문 ID.
statusSTRING필수환불 상태 (공개 표기). PAID, CONFIRMED, FAILED 3종입니다.
failTypeSTRING선택환불 실패 사유.
orderAmountDOUBLE필수환불 주문 금액.
orderCurrencyCodeSTRING필수주문 통화 코드.
refundAmountDOUBLE필수실제 환불된 금액.
refundCurrencyCodeSTRING필수실제 환불 통화.
blockchainTxIdSTRING선택블록체인 트랜잭션 해시. 블록체인 확정 이후(CONFIRMED)이거나, 블록체인 네트워크에 전파된 후 실패(FAILED)한 경우에 반환됩니다.
blockchainNetworkFeeDOUBLE선택블록체인 네트워크 수수료. 블록체인 확정 이후(CONFIRMED) 및 네트워크 전파 후 실패(FAILED) 시점에 실제로 소모된 수수료 금액이 반환됩니다. (Unifi가 전액 대납하여 사용자 부담은 없습니다.)

응답 예시

JSON
{
  "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 상태 오류 코드 설명
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

연동 시 참고 사항

항목 설명
환불 Webhook결제 결과 Webhook과 같은 callbackUrl로 type가 REFUND인 통지가 발송됩니다. 이때 transactionId와 orderId는 환불 거래의 값이며, orderId는 원결제의 값을 승계합니다.
환불 내역 조회아래 2.6 정산 내역 API에서 paymentType=REFUND 로 조회하거나, 2.11 결제 내역 조회 API를 사용합니다.
원결제 연결환불 건의 originTransactionId 가 원결제의 transactionId 를 가리킵니다.
💡 참고: 환불 지갑·환불 금액 기준·주소 및 네트워크 조건 등 환불 정책은 이용 가이드 5. 환불(송금 보조 기능)을 참고하시기 바랍니다.

2.6 정산 내역 API

결제, 환불 내역을 확인합니다.

GET /api/seller/v2/payment/settlement/transaction

요청 쿼리 파라미터

파라미터 타입 필수 설명
fromSTRING조건부조회 시작일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-01T00:00:00Z). transactionId/settlementId 미지정 시 필수이며, to보다 이전 시점 설정 필수.
toSTRING조건부조회 종료일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-31T23:59:59Z). transactionId/settlementId 미지정 시 필수이며, 조회 기간은 최대 90일까지 허용.
paymentTypeSTRING선택결제 타입 필터 (PURCHASE / REFUND). 미지정 시 전체
transactionIdSTRING선택Unifi Pay에서 생성한 거래 번호. from/to/settlementId 미지정 시 필수.
settlementIdSTRING선택Unifi Pay 지급 명세서 ID 정보. from/to/transactionId 미지정 시 필수.
pageINTEGER선택페이지 번호 (0부터 시작, 기본값: 0)
sizeINTEGER선택페이지 크기 (기본 50, 1 이상 100 이하)

응답 필드 (200 OK)

필드 이름 타입 필수 설명
contentList필수결제 데이터 목록
↳ partnerCorpNameSTRING필수법인명 (EN)
↳ storeIdSTRING선택가맹점 ID 정보
↳ orderIdSTRING필수거래에 대한 ID 정보
↳ itemNameSTRING필수상품의 식별 정보
↳ serviceNameSTRING선택서비스 또는 가맹점명 (EN)
↳ orderCountryCodeSTRING필수구매자 국가 코드
↳ orderCurrencyCodeSTRING필수ISO 4217를 따르는 주문 통화 코드
↳ orderAmountDOUBLE필수주문 금액
↳ createdAtINSTANT필수주문 결제 요청 일시
↳ transactionIdSTRING필수Unifi Pay에서 생성한 거래 번호.
↳ blockchainTxIdSTRING필수KaiaScan TxID
↳ paymentTypeSTRING필수결제: PURCHASE / 환불: REFUND
↳ originTransactionIdSTRING선택환불 시 원 거래 번호 (REFUND인 경우 필수, PURCHASE인 경우 Null)
↳ statusSTRING필수CONFIRMED 고정 (CONFIRMED건만 조회)
↳ finalizedAtINSTANT필수주문 결제 최종 상태 일시
↳ capturedAtINSTANT필수주문 결제 완료 일시 (블록체인 확정 시각)
↳ failTypeSTRING선택주문 결제 실패 사유
↳ payCurrencyCodeSTRING필수실 결제 통화 USDT
↳ payAmountDOUBLE필수실 결제 금액
↳ netAmountDOUBLE선택v2 전용 파트너 실수령액 (결제 통화 기준). 환불 거래는 수령액이 없어 null 입니다.
↳ paymentExchangeRateDOUBLE필수결제 시점 환율. 결제 통화와 주문 통화가 다를 때 적용되며, 같으면 1입니다. (기준 통화: payCurrencyCode)
↳ buyerWalletAddressSTRING필수구매자 결제 지갑 주소
↳ variableFeeRateDOUBLE선택결제 수수료율 (%). Unifi Pay 지급 명세서 번호 생성 전인 경우 Null
↳ protocolFeeRateDOUBLE필수v2 전용 프로토콜 수수료율 (퍼센트, 1 은 1%). netAmount 공제에 쓰인 요율이며 판매자 (MERCHANT_LITE) 는 현재 항상 1 입니다.
↳ settlementIdSTRING선택Unifi Pay 지급 명세서 ID 정보. 생성 전인 경우 Null
↳ settlementCurrencyCodeSTRING선택정산 통화 코드 (USDT, JPYC). 정산 전인 경우 Null
↳ settlementExchangeRateDOUBLE선택정산 시점 환율. 정산 전인 경우 Null
totalElementsLONG필수전체 건수
totalPagesINTEGER필수전체 페이지수
pageNumberINTEGER필수현재 페이지 번호
firstBOOLEAN필수첫 페이지 여부
lastBOOLEAN필수마지막 페이지 여부

응답 예시 — 성공

JSON
{
  "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
}

응답 예시 — 실패

JSON
{
  "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 단건 필터는 지원하지 않습니다.

이 API 는 v2 경로에서만 제공됩니다
GET /api/seller/v2/payment/settlement/transaction/cursor
💡 서명 대상: HMAC 서명의 URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.

요청 쿼리 파라미터

파라미터 타입 필수 설명
fromSTRING필수조회 시작일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-01T00:00:00Z). 필수이며, to보다 이전 시점 설정 필수.
toSTRING필수조회 종료일 (capturedAt 기준, ISO 8601 UTC. 예시 2026-03-31T23:59:59Z). 필수이며, 조회 기간은 최대 90일. 현재보다 최소 1시간 이전이어야 함.
paymentTypeSTRING선택결제 타입 필터 (PURCHASE / REFUND). 미지정 시 전체
cursorSTRING선택이전 응답의 nextCursor를 그대로 전달. 미지정 시 첫 페이지 (불투명 base64 토큰).
sizeINTEGER선택페이지 크기 (기본값: 50, 최대: 100)
orderSTRING선택정렬 방향 DESC(기본) / ASC. capturedAt 기준.

요청 예시

HTTP
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)

필드 이름 타입 필수 설명
contentList필수결제 데이터 목록. 항목 필드는 2.6 정산 내역 API 의 content 와 동일하며, 이 엔드포인트는 v2 전용이라 netAmount 와 protocolFeeRate 가 항상 포함됩니다.
nextCursorSTRING선택다음 페이지 cursor. 다음 요청의 cursor로 그대로 전달. 마지막 페이지면 null.
hasNextBOOLEAN필수다음 페이지 존재 여부
totalElements / totalPages / pageNumber / first / last 는 제공하지 않습니다 (count 쿼리 비용 제거가 목적).

응답 예시 — 성공

JSON
{
  "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 토큰

Cursor는 정렬키(capturedAt, transactionId)를 기반으로 URL-safe base64로 인코딩한 불투명 토큰입니다(암호화 아님). 파트너는 응답의 nextCursor를 다음 요청에 그대로 전달만 하면 되며, 직접 생성하거나 조작하지 않습니다.

offset 방식과의 차이

항목 2.6 offset 2.7 cursor
페이지 이동page / sizecursor / size
전체 건수totalElements 제공미제공
단건 필터transactionId / settlementId 지원미지원
대용량 성능deep offset 에서 저하일정 (O(size))
용도화면 페이지네이션파일 다운로드, 대량 순회

오류 타입 코드

HTTP 상태 오류 코드 설명
400BAD_REQUEST유효하지 않은 입력 값
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
406PAYMENT_INVALID_REQUEST날짜 형식 오류, from 또는 to 누락, 조회 기간 90일 초과, to 가 현재로부터 1시간 이내
429RATE_LIMIT_EXCEEDED초당 요청 수 10건 초과. 정산 조회 엔드포인트는 각각 별도 버킷으로 제한됩니다.
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

2.11 결제 내역 조회 API

기간 안의 결제 내역을 전 상태로 조회합니다. 정산 대상(CONFIRMED) 만 돌려주는 2.6 정산 내역 API 와 달리 CREATED, PENDING, FAILED, CANCELED 도 포함합니다.

이 API 는 v2 경로에서만 제공됩니다
GET /api/seller/v2/payment/transaction
💡 서명 대상: HMAC 서명의 URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.

요청 쿼리 파라미터

파라미터 타입 필수 설명
fromSTRING필수조회 시작 시각 (createdAt 기준, ISO 8601 UTC). 이 시점은 구간에 포함되며, 구간 폭은 최대 90일입니다.
toSTRING필수조회 종료 시각 (createdAt 기준, ISO 8601 UTC). 이 시점은 구간에 포함되지 않습니다.
statusSTRING선택결제 상태 필터. 콤마로 여러 값을 지정할 수 있습니다. 미지정 시 전 상태.
paymentTypeSTRING선택결제 타입 필터 (PURCHASE / REFUND). 미지정 시 전체
cursorSTRING선택이전 응답의 nextCursor 를 그대로 전달합니다. 첫 페이지는 생략합니다. page 파라미터는 없습니다.
sizeINTEGER선택페이지 크기 (기본값: 50, 1 이상 100 이하)
orderSTRING선택정렬 방향 DESC(기본) / ASC. createdAt 기준.

요청 예시

HTTP
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)

필드 이름 타입 필수 설명
contentList필수거래 목록.
transactionIdSTRING필수Unifi Pay에서 생성한 거래 번호.
orderIdSTRING필수주문 id. 결제 링크로 발생한 거래는 LINK 접두, linkId, 랜덤 문자열을 하이픈으로 이은 형태로 서버가 채번합니다.
storeIdSTRING필수요청자가 제공하는 가맹점 ID 정보.
serviceNameSTRING필수결제창에 노출될 서비스 또는 가맹점 정보.
itemsList필수결제 상품 목록.
↳ nameSTRING필수판매 상품의 식별 정보.
↳ priceDOUBLE필수판매 상품의 가격.
paymentTypeSTRING필수결제: PURCHASE / 환불: REFUND
statusSTRING필수결제 상태 (공개 표기). CREATED, PENDING, PAID, CONFIRMED, FAILED, CANCELED 6종입니다.
failTypeSTRING선택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종입니다.
countryCodeSTRING필수ISO Alpha-3를 따르는 국가 코드 (예: KOR).
orderCurrencyCodeSTRING필수ISO 4217를 따르는 주문 통화 코드
orderAmountDOUBLE필수주문 금액
payCurrencyCodeSTRING선택결제 토큰 통화 (USDT, JPYC). 확정 전에는 null 입니다.
payAmountDOUBLE선택실제 결제된 토큰 금액. 확정 전에는 null 입니다.
netAmountDOUBLE선택파트너 실수령액 (결제 통화 기준). CONFIRMED 이후 제공
buyerWalletAddressSTRING선택구매자 지갑 주소. 확정 전에는 null 입니다.
blockchainTxIdSTRING선택블록체인 트랜잭션 해시. 블록체인 확정 이후(CONFIRMED)이거나, 블록체인 네트워크에 전파된 후 실패(FAILED)한 경우에 반환됩니다.
blockchainNetworkFeeDOUBLE선택블록체인 네트워크 수수료. 블록체인 확정 이후(CONFIRMED) 및 네트워크 전파 후 실패(FAILED) 시점에 실제로 소모된 수수료 금액이 반환됩니다. (Unifi가 전액 대납하여 사용자 부담은 없습니다.)
createdAtINSTANT필수결제 생성 시각 (ISO 8601 UTC). 기간, 정렬, cursor 의 기준입니다.
capturedAtINSTANT선택체인 이벤트가 관측된 시각. 관측 전에는 null 입니다. 값이 있어도 결제 성공을 뜻하지 않으므로 성공 여부는 status 로 판단하십시오.
finalizedAtINSTANT선택결제가 종료(확정, 실패, 취소)된 시각. 종결 전에는 null 입니다.
nextCursorSTRING선택다음 페이지 cursor. 다음 요청의 cursor로 그대로 전달. 마지막 페이지면 null.
hasNextBOOLEAN필수다음 페이지 존재 여부
순회 주의: 총 건수는 제공되지 않으므로 hasNext 가 true 인 동안 nextCursor 를 이어서 호출합니다. 순회 도중 from, to, status, paymentType, order 는 바꾸지 마십시오.
📌 버전 혼용 주의: v1 으로 생성된 결제가 PAID 상태이면 status=PAID 필터에는 걸리지만 응답의 status 는 CONFIRMED 로 내려갑니다. 결제를 생성한 버전과 조회에 쓴 버전이 모두 v2 일 때만 PAID 가 노출됩니다.

응답 예시 — 성공

JSON
{
  "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 상태 오류 코드 설명
400BAD_REQUESTfrom 또는 to 누락, size 범위 초과, 알 수 없는 status, paymentType, order 값 등
406PAYMENT_INVALID_REQUEST날짜 형식 오류 (ISO 8601 아님), from 이 to 보다 늦음, 조회 기간 90일 초과
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

2.12 스토어 목록 조회 API

자기 파트너에 속한 스토어 목록을 조회합니다. 결제 링크는 스토어에 속하고 주문 통화와 결제 통화가 스토어를 따라가므로, 2.2 결제 링크 발급 API 를 호출하기 전에 이 API 로 partnerStoreId 와 허용 통화를 확인합니다.

이 API 는 v2 경로에서만 제공됩니다
GET /api/seller/v2/store
💡 서명 대상: HMAC 서명의 URI 에는 경로만 포함하며 쿼리스트링은 포함하지 않습니다. 상세는 2.1 인증 (Authentication)을 참고하시기 바랍니다.

요청 쿼리 파라미터

파라미터 타입 필수 설명
partnerStoreIdSTRING선택파트너 내부 스토어 ID 로 필터링합니다. 미지정 시 전체.
statusSTRING선택조회할 스토어 상태 (ACTIVE / INACTIVE). 미지정 시 전체.
pageINTEGER선택페이지 번호 (0부터 시작, 기본값: 0)
sizeINTEGER선택페이지 크기 (기본값: 20, 1 이상 50 이하)

요청 예시

HTTP
GET /api/seller/v2/store
    ?status=ACTIVE
    &page=0
    &size=20

응답 필드 (200 OK)

필드 이름 타입 필수 설명
contentList필수스토어 목록.
↳ partnerStoreIdSTRING필수파트너 내부 스토어 ID. 결제 링크 발급의 storeId 로 쓰는 값입니다.
↳ nameSTRING필수스토어 명.
↳ statusSTRING필수스토어 상태 (ACTIVE / INACTIVE).
↳ orderCurrencyCodesList선택허용 주문 통화 목록. null 이면 파트너 정책을 상속합니다.
↳ paymentCurrencyCodesList선택허용 결제 코인 목록. null 이면 파트너 정책을 상속합니다.
totalElementsLONG필수전체 건수
totalPagesINTEGER필수전체 페이지수
pageNumberINTEGER필수현재 페이지 번호
firstBOOLEAN필수첫 페이지 여부
lastBOOLEAN필수마지막 페이지 여부
통화 정책: 스토어 통화는 파트너 통화 중에서 고릅니다. 스토어 통화 목록이 비어 있거나 null 이면 파트너 정책을 그대로 상속하며, 스토어 통화는 항상 파트너 통화의 부분집합입니다. 결제 링크 발급 시점에 요청한 주문 통화가 허용 목록 밖이면 발급이 거부됩니다.

응답 예시 — 성공

JSON
{
  "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 상태 오류 코드 설명
400BAD_REQUEST유효하지 않은 입력 값
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

2.13 Blacklist API

자기 파트너 범위의 차단 지갑을 등록, 조회, 범위 변경, 해제하는 API 6종입니다. 인증은 2.1 인증 (Authentication) 과 동일한 HMAC 방식이며, 항상 자기 파트너 범위로만 동작합니다.

이 API 는 v2 경로에서만 제공됩니다
⚠️ 주의: 차단하면 그 지갑의 결제 또는 환불이 즉시 거절됩니다. 호출 전에 지갑 주소, 사유, 범위를 반드시 확인해 주십시오.
Unifi Pay 운영자가 전체 범위로 등록한 차단은 이 API 의 목록과 이력에 나타나지 않습니다. 판매자가 자기 차단을 해제해도 운영자 차단이 남아 있으면 그 지갑은 계속 거절될 수 있습니다.

지갑 주소 형식

항목 설명
walletAddress0x 로 시작하는 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 는 차단 범위 변경과 차단 해제의 경로 변수로 사용합니다.

GET /api/seller/v2/blacklist/search

요청 쿼리 파라미터

파라미터 타입 필수 설명
walletAddressSTRING선택지갑 주소로 필터링합니다.
reasonSTRING선택차단 사유로 필터링합니다 (FRAUD_PATTERN / REFUND_ABUSE / AML_SUSPECT / BLACK_CONSUMER / OTHER). 미지정 시 전체.
scopeTypeSTRING선택차단 범위로 필터링합니다 (PARTNER / STORE). 미지정 시 전체.
blockTypeSTRING선택차단 유형으로 필터링합니다 (PURCHASE / REFUND). 미지정 시 전체.
pageINTEGER선택페이지 번호 (0부터 시작, 기본값: 0)
sizeINTEGER선택페이지 크기 (기본값: 20, 1 이상 100 이하)

요청 예시

HTTP
GET /api/seller/v2/blacklist/search
    ?scopeType=PARTNER
    &page=0
    &size=20

응답 필드 (200 OK)

필드 이름 타입 필수 설명
contentList필수차단 지갑 목록.
↳ idLONG필수차단 행 ID. 차단 범위 변경과 차단 해제의 경로 변수 {id} 로 사용합니다.
↳ walletAddressSTRING필수차단된 지갑 주소.
↳ reasonSTRING필수차단 사유.
↳ blockTypesList선택차단 유형 (PURCHASE / REFUND).
↳ scopeTypeSTRING필수차단 범위 (PARTNER / STORE).
↳ scopesList필수적용 범위 목록 (partnerId, storeIds).
↳ activeBOOLEAN필수활성 여부.
↳ memoSTRING선택메모.
↳ registeredBySTRING선택등록 주체 (appId).
↳ registeredAtINSTANT필수등록 일시.
totalElementsLONG필수전체 건수
totalPagesINTEGER필수전체 페이지수
pageNumberINTEGER필수현재 페이지 번호
firstBOOLEAN필수첫 페이지 여부
lastBOOLEAN필수마지막 페이지 여부

응답 예시 — 성공

JSON
{
  "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 상태 오류 코드 설명
400BAD_REQUEST유효하지 않은 입력 값
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

차단 등록 API

지갑을 차단 목록에 등록합니다. 사유나 메모를 바꾸는 API 는 없으므로 차단을 해제한 뒤 다시 등록해야 하며, 범위만 차단 범위 변경 API 로 바꿀 수 있습니다.

⚠️ 주의: 차단하면 그 지갑의 결제 또는 환불이 즉시 거절됩니다. 호출 전에 지갑 주소, 사유, 범위를 반드시 확인해 주십시오.
POST /api/seller/v2/blacklist

요청 바디 파라미터

파라미터 타입 필수 설명
walletAddressSTRING필수차단할 지갑 주소입니다. 0x 로 시작하는 16진수 40자 EVM 주소를 입력합니다.
reasonSTRING필수차단 사유입니다 (FRAUD_PATTERN / REFUND_ABUSE / AML_SUSPECT / BLACK_CONSUMER / OTHER).
blockTypesList선택차단 유형입니다 (PURCHASE / REFUND). 생략하면 전 유형을 차단합니다.
storeIdsList선택비우면 파트너 전체, 지정하면 그 스토어만 차단합니다. 최대 50개이며 각 항목은 최대 64자입니다. 0 은 예약값이라 입력할 수 없습니다.
memoSTRING선택메모입니다. 최대 1000자.

요청 예시

JSON
{
  "walletAddress": "0x1234567890abcdef1234567890abcdef12345678",
  "reason": "REFUND_ABUSE",
  "blockTypes": [
    "PURCHASE",
    "REFUND"
  ],
  "storeIds": [
    "STORE-001"
  ],
  "memo": "반복 환불 요청"
}

응답 필드 (200 OK)

필드 이름 타입 필수 설명
idLONG필수등록된 차단 행 ID.

응답 예시 — 성공

JSON
{
  "id": 3012
}

오류 타입 코드

HTTP 상태 오류 코드 설명
400BAD_REQUEST지갑 주소 형식 오류, 또는 storeIds 에 예약값 0 포함
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
406BLACKLIST_ALREADY_EXIST이미 차단된 지갑입니다. 같은 파트너로 활성 항목이 존재합니다.
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

차단 범위 변경 API

차단의 적용 범위를 파트너 전체와 지정 스토어 사이에서 전환합니다. 경로 변수 {id} 는 차단 지갑 목록 조회 응답의 id 입니다.

PUT /api/seller/v2/blacklist/{id}/scope

요청 바디 파라미터

파라미터 타입 필수 설명
storeIdsList선택비우면 파트너 전체, 지정하면 그 스토어만 차단합니다. 최대 50개이며 각 항목은 최대 64자입니다. 0 은 예약값이라 입력할 수 없습니다.
전체 교체: storeIds 는 부분 수정이 아니라 기존 범위 전체를 교체합니다. 필드를 생략하거나 null 로 보내면 파트너 전체로 전환되고, 빈 배열을 보내면 400 으로 거부됩니다.

요청 예시

JSON
{
  "storeIds": [
    "STORE-001"
  ]
}

응답 필드 (200 OK)

200 OK 응답에 본문이 없습니다.

오류 타입 코드

HTTP 상태 오류 코드 설명
400BAD_REQUESTstoreIds 가 빈 배열이거나 예약값 0 을 포함한 경우
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
406PAYMENT_TRANSACTION_NOT_FOUNDid 가 없거나 다른 파트너 소유인 경우. 항목의 존재를 노출하지 않기 위해 두 경우 모두 같은 코드로 응답합니다.
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

차단 해제 API

등록한 차단을 해제합니다. 경로 변수 {id} 는 차단 지갑 목록 조회 응답의 id 입니다.

⚠️ 주의: 막아둔 지갑이 다시 결제할 수 있게 됩니다. 차단 등록과 같은 수준의 확인이 필요합니다.
POST /api/seller/v2/blacklist/{id}/unblock

요청 바디 파라미터

파라미터 타입 필수 설명
reasonSTRING선택해제 사유입니다. 이력에 기록되며 최대 1000자입니다.

요청 예시

JSON
{
  "reason": "이의신청 승인으로 차단 해제"
}

응답 필드 (200 OK)

200 OK 응답에 본문이 없습니다.

오류 타입 코드

HTTP 상태 오류 코드 설명
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
406PAYMENT_TRANSACTION_NOT_FOUNDid 가 없거나 이미 해제되었거나 다른 파트너 소유인 경우. 항목의 존재를 노출하지 않기 위해 모두 같은 코드로 응답합니다.
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

차단 요약 조회 API

활성 차단 지갑 수와 최근 24시간 차단 시도를 요약해 조회합니다. 요청 파라미터는 없습니다.

GET /api/seller/v2/blacklist/summary

응답 필드 (200 OK)

필드 이름 타입 필수 설명
blacklistWalletCountLONG필수활성 차단 지갑 수.
blockedAttempt.countLONG필수거절 건수.
blockedAttempt.periodSTRING선택집계 기간 표기입니다. 현재 24H 로 고정입니다.

응답 예시 — 성공

JSON
{
  "blacklistWalletCount": 7,
  "blockedAttempt": {
    "count": 23,
    "period": "24H"
  }
}

오류 타입 코드

HTTP 상태 오류 코드 설명
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

차단 해제 이력 조회 API

자기 파트너가 영향받은 차단, 범위 변경, 해제 이력을 조회합니다. 필터 없이 페이징만 제공합니다.

GET /api/seller/v2/blacklist/history/search

요청 쿼리 파라미터

파라미터 타입 필수 설명
pageINTEGER선택페이지 번호 (0부터 시작, 기본값: 0)
sizeINTEGER선택페이지 크기 (기본값: 20, 1 이상 100 이하)

요청 예시

HTTP
GET /api/seller/v2/blacklist/history/search
    ?page=0
    &size=20

응답 필드 (200 OK)

필드 이름 타입 필수 설명
contentList필수차단 변경 이력 목록.
↳ idLONG필수이력 행 ID.
↳ blacklistIdLONG필수대상 차단 행 ID.
↳ walletAddressSTRING필수지갑 주소.
↳ changeTypeSTRING필수변경 유형 (REGISTER / SCOPE_CHANGE / UNBLOCK).
↳ beforeScopesList선택변경 전 범위 (partnerId, storeIds).
↳ afterScopesList선택변경 후 범위.
↳ blockTypesList선택차단 유형.
↳ unblockReasonSTRING선택해제 사유 (UNBLOCK 인 경우).
↳ createdAtINSTANT필수변경 일시.
totalElementsLONG필수전체 건수
totalPagesINTEGER필수전체 페이지수
pageNumberINTEGER필수현재 페이지 번호
firstBOOLEAN필수첫 페이지 여부
lastBOOLEAN필수마지막 페이지 여부

응답 예시 — 성공

JSON
{
  "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 상태 오류 코드 설명
400BAD_REQUEST유효하지 않은 입력 값
401UNAUTHORIZED유효하지 않은 HMAC
403FORBIDDEN허용되지 않은 IP 혹은 Path
500INTERNAL_SERVER_ERROR서버 내부 오류
503MAINTENANCE점검 중

3. 테스트 가이드

Preview 환경에서 Unifi Pay 결제 연동을 테스트하는 방법입니다.

  1. 1 Unifi Pay 테스트는 Preview 환경에서 진행할 수 있습니다.
  2. 2 Unifi Wallet은 Preview 환경에서 Production 기준의 Google 계정으로 생성 및 연동을 진행합니다. (Preview 환경에서 생성한 Unifi Wallet은 Production 환경과 별도로 관리됩니다.) Preview Unifi Wallet →
  3. 3 Preview 환경의 결제는 Kaia Blockchain의 테스트넷 환경인 Kairos 기준으로 진행됩니다.
  4. 4 아래 가이드를 참고하여 Kairos 테스트넷에서 테스트용 USDT를 확보한 후 결제 테스트를 진행해주시기 바랍니다.
PREVIEW (Kairos Testnet) Unifi Wallet 생성 Preview 환경의 Unifi Wallet 생성 및 연동 STEP 1 테스트 USDT 확보 Kaia Faucet에서 Kairos USDT 수령 STEP 2 결제 테스트 진행 Preview 환경에서 API 연동 테스트 STEP 3

Preview 환경

Kairos Testnet (테스트넷)

Testnet

Preview 환경에서는 카이아 블록체인의 테스트넷인 Kairos 체인이 연동되며, 테스트 자금은 아래 Faucet 서비스를 통해 확보할 수 있습니다.

Kaia Faucet →
Base URL https://app-api-pay.unifi.me