--- title: "환불" description: "Tokenz Refunds API로 완료된 결제를 환불하는 방법을 알아봅니다." source: "https://docs.tokenz.one/ko-KR/v1/refunds" api_version: "v1" locale: "ko-KR" version_status: "legacy" docs_stage: "prod" --- # 환불 Tokenz Refunds API로 완료된 결제를 환불하는 방법을 알아봅니다. Refunds API로 완료된 주문의 금액을 고객에게 반환할 수 있습니다. 환불을 시작하고 상태를 추적하며 수명 주기를 관리할 수 있습니다. **금액 형식:** 모든 금액 값(`amount` 필드 등)은 각 통화의 최소 단위로 표시합니다. 통화별 정확한 형식은 [지원 통화](https://docs.tokenz.one/ko-KR/v1/checkout/currency)를 참고하세요. ## 개요 환불 시스템은 다음 관리 기능을 제공합니다. - **환불 생성**: 사유를 지정하여 완료된 주문의 환불을 시작합니다. - **상태 추적**: 대기 또는 실패 상태를 통해 환불 진행 상황을 확인합니다. - **감사 추적**: 누가 언제 환불을 시작했는지 추적합니다. - **테스트 모드**: 개발과 테스트를 위한 테스트 환경을 지원합니다. ## 환불 수명 주기 환불은 다음 절차를 거칩니다. 1. **환불 시작**: 판매자 또는 API가 완료된 주문의 환불을 시작합니다. 2. **처리**: 비동기로 처리되며 상태는 `pending`으로 유지됩니다. 3. **실패**: 문제가 있으면 환불이 실패할 수 있으며 상태가 `failed`로 변경됩니다. ### 환불 상태 값 환불은 다음 상태를 가집니다. - `pending`: 환불이 시작되어 처리 중입니다. - `failed`: 환불 시도가 실패했습니다. ```mermaid sequenceDiagram; autonumber; participant M as 판매자 앱; participant T as Tokenz API; %% Refund Creation Flow; M->>T: POST /v1/refunds (환불 시작); T->>T: 주문 및 금액 검증; T-->>M: 환불 반환 (status: pending); T->>T: 비동기 환불 처리; T->>M: 웹훅 알림 (created/failed); ``` ## 환불 생성 주문 ID와 환불 사유를 포함하여 환불 엔드포인트로 POST 요청을 전송하세요. ```bash curl --request POST \ --url https://api.tokenz.one/v1/refunds \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \ --data '{ "orderId": "order_1p4LPTRKB5Z", "reason": "customer_cancellation", "detail": "Customer requested cancellation" }' ``` ### 필수 매개변수 - `orderId`: 환불할 주문 ID(완료된 주문이어야 함) - `reason`: 환불 사유. 유효한 값: - `customer_cancellation`: 고객이 주문을 취소함 - `duplicate_payment`: 중복 결제 - `other`: 기타 사유(`detail` 필요) - `detail`: 상세 설명(선택 사항이지만 `reason`이 `other`이면 필수) ### 응답 환불 생성이 성공하면 환불 객체를 반환합니다. ```json { "refund": { "id": "refund_1p4LS47fB1h", "object": "refund", "orderId": "order_1p4LPTRKB5Z", "amount": { "amount": 10000, "currency": "JPY" }, "status": "pending", "reason": "customer_cancellation", "initiatedBy": "apikey", "test": false, "createdAt": "2024-10-07T10:30:00Z", "updatedAt": "2024-10-07T10:30:00Z" } } ``` ## 환불 조회 특정 환불의 현재 상태와 상세 정보를 조회합니다. ```bash curl --request GET \ --url https://api.tokenz.one/v1/refunds/refund_1p4LS47fB1h \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### 응답 필드 - `id`: 환불의 고유 식별자 - `orderId`: 환불된 주문의 ID - `amount`: 통화의 최소 단위로 표시한 환불 금액 - `status`: 현재 환불 상태(`pending`, `failed`) - `reason`: 환불 요청 사유 - `initiatedBy`: 환불 시작 주체(merchantUser, apikey, admin) - `test`: 테스트 환불인지 여부 - `createdAt`: 환불 생성 시각 - `updatedAt`: 마지막 상태 업데이트 시각 ## 환불 목록 조회 필터를 선택하여 전체 환불을 조회합니다. ```bash curl --request GET \ --url 'https://api.tokenz.one/v1/refunds?orderId=order_1p4LPTRKB5Z&limit=10' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### 쿼리 매개변수 - `orderId`: 주문 ID로 필터 - `status`: 환불 상태로 필터(`pending`, `failed`) - `limit`: 최대 반환 수(1~100, 기본: 10) - `createdAfter`: 지정 시각 이후 생성된 환불(ISO 8601) - `createdBefore`: 지정 시각 이전 생성된 환불(ISO 8601) ### 응답 ```json { "refunds": { "items": [ { "id": "refund_1p4LS47fB1h", "object": "refund", "orderId": "order_1p4LPTRKB5Z", "amount": { "amount": 10000, "currency": "JPY" }, "status": "pending", "reason": "customer_cancellation", "initiatedBy": "apikey", "test": false, "createdAt": "2024-10-07T10:30:00Z", "updatedAt": "2024-10-07T10:30:00Z" } ], "hasMore": false } } ``` ## 환불 웹훅 환불 이벤트 알림을 받도록 웹훅을 설정하세요. ### `refund.created` 환불이 생성되면 발생합니다. ```json { "id": "d4e5f6a7-b8c9-0123-defa-234567890123", "object": "refund.created", "createdAt": "2024-10-07T10:30:00Z", "test": false, "eventData": { "type": "refund", "version": "v1", "data": { "refund": { "id": "refund_1p4LS47fB1h", "object": "refund", "orderId": "order_1p4LPTRKB5Z", "amount": { "amount": 10000, "currency": "JPY" }, "status": "pending", "reason": "customer_cancellation", "initiatedBy": "apikey", "test": false, "createdAt": "2024-10-07T10:30:00Z", "updatedAt": "2024-10-07T10:30:00Z" } } } } ``` ### `refund.failed` 환불이 실패하면 발생합니다. ```json { "id": "e5f6a7b8-c9d0-1234-efab-345678901234", "object": "refund.failed", "createdAt": "2024-10-07T10:40:00Z", "test": false, "eventData": { "type": "refund", "version": "v1", "data": { "refund": { "id": "refund_1p4LS47fB1h", "object": "refund", "orderId": "order_1p4LPTRKB5Z", "amount": { "amount": 10000, "currency": "JPY" }, "status": "failed", "reason": "customer_cancellation", "initiatedBy": "apikey", "test": false, "createdAt": "2024-10-07T10:30:00Z", "updatedAt": "2024-10-07T10:40:00Z" } } } } ``` ## 오류 처리 Refunds API는 표준 HTTP 상태 코드와 상세 오류 메시지를 반환합니다. ### 일반적인 오류 - `400 Bad Request`: 요청 매개변수 또는 형식이 잘못되었습니다. - `401 Unauthorized`: API 키가 없거나 유효하지 않습니다. - `403 Forbidden`: 환불에 필요한 권한이 없습니다. - `404 Not Found`: 주문 또는 환불을 찾을 수 없습니다. - `422 Unprocessable Entity`: 비즈니스 로직 오류가 발생했습니다. ### 오류 응답 형식 ```json { "status": 422, "code": "refund.amount-exceeds-available", "message": "Refund amount exceeds available refund amount for this order" } ``` ## 환불 테스트 테스트 모드로 환불 연동을 개발하고 테스트하세요. 1. 테스트 API 키(`secret_test_` 접두사)를 사용하세요. 2. 테스트 Checkout Session으로 테스트 주문을 생성하세요. 3. 테스트 환불 ID에는 `_t` 접미사가 있습니다(예: `refund_1p4LS47fB1h_t`). 4. 테스트 웹훅은 설정된 테스트 엔드포인트로 전송됩니다. ## API 레퍼런스 ### 엔드포인트 - `POST /v1/refunds` - 새 환불 생성 - `GET /v1/refunds/{refundId}` - 특정 환불 조회 - `GET /v1/refunds` - 선택적 필터로 환불 목록 조회 ### 인증 모든 엔드포인트는 Bearer 토큰 인증이 필요합니다. ``` Authorization: Bearer secret_test_YOUR_KEY_HERE ```