현금영수증

현금영수증 발행

결제 건에 붙이거나 단독으로 현금영수증을 발행해요.

현금영수증은 두 가지로 발행해요. 이미 완료된 결제 건에 붙이는 결제 건 발행​, 결제와 무관하게 단독으로 발행하는 별건 발행​​이에요. 모두 서버에서 Basic Auth로 호출해요.

발행 유형(소득공제/지출증빙)과 identity_no 규칙은 현금영수증 개요를 참고해요.


1결제 건에 발행

완료된 결제의 receipt_id에 현금영수증을 발행해요. 계좌이체·가상계좌처럼 현금성 결제를 한 뒤 영수증만 따로 발행할 때 사용해요.

POSThttps://api.bootpay.co.kr/v2/request/receipt/cash/publishBasic Auth
파라미터 타입 필수 설명
receipt_id String 필수 현금영수증을 발행할 결제의 영수증 ID
cash_receipt_type String 선택 지출증빙이면 지출증빙, 그 외 모든 값은 소득공제로 처리. 생략하거나 빈 값이면 소득공제로 발행돼요
identity_no String 필수 발행 식별번호 (휴대폰번호 / 주민번호 / 사업자번호)
username String 필수 구매자명. PG와 무관하게 비어 있으면 RC_CASH_RECEIPT_NEED_USERNAME 오류. 다만 기본 채널로 발행할 때 PG로 전달되는 구매자명은 이 값이 아니라 원 결제의 extra.username(없으면 구매자)이에요
phone String 선택 구매자 전화번호. 이니시스·나이스페이먼츠는 그대로 PG로 전달돼요. 페이앱은 전화번호 자리에 identity_no를 넣어 보내므로 이 값을 쓰지 않고, 토스·기본 채널은 사용하지 않아요
email String 선택 구매자 이메일. 이니시스·나이스페이먼츠·페이앱은 PG로 전달돼요. 토스·기본 채널은 사용하지 않아요
pg String 선택 현금영수증을 발행할 PG를 직접 지정. 생략하면 부트페이 기본 발행 채널을 사용해요
test_production Boolean 선택 샌드박스 프로젝트에서도 실제 발행을 강제할 때 true (기본 false)
currency String 선택 통화. 생략 시 WON
pg를 생략하면 관리자 콘솔의 사업자 정보가 필요해요

pg 없이 부트페이 기본 발행 채널을 쓰면 발행 직전에 가맹점 정보를 검사해요. 관리자 콘솔사업자등록번호(하이픈 제외 10자리 숫자)·대표자명·상호​​가 채워져 있어야 하고, 비어 있거나 형식이 맞지 않으면 아래 오류로 거부돼요.

  • PROVIDER_RN_ONLY_NUMBER (389) — 사업자등록번호에 숫자가 아닌 문자가 섞임
  • PROVIDER_RN_INVALID (390) — 하이픈을 뺀 사업자등록번호가 10자리가 아님
  • PROVIDER_OWNER_BLANK (391) — 대표자명 미등록
  • PROVIDER_NAME_INVALID (322) — 상호(가맹점명) 미등록
curl -X POST "https://api.bootpay.co.kr/v2/request/receipt/cash/publish" \
  -H "Authorization: Basic $(printf '%s' 'CLIENT_KEY:SECRET_KEY' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "receipt_id": "RECEIPT_ID",
    "cash_receipt_type": "소득공제",
    "identity_no": "01012345678",
    "username": "홍길동",
    "phone": "01012345678"
  }'bash

응답 예시

응답은 결제 건 전체 정보​​를 그대로 돌려주고, 현금영수증 정보는 그 안의 결제수단 블록에 담겨요. 원 결제가 계좌이체면 bank_data, 가상계좌면 vbank_data 안에 cash_receipt_* 필드가 들어가요.

{
  "receipt_id": "62f356871fc192036f9f4ae2",
  "order_id": "order_1700000000",
  "price": 10000,
  "tax_free": 0,
  "cancelled_price": 0,
  "cancelled_tax_free": 0,
  "order_name": "테스트 결제",
  "company_name": "테스트상점",
  "gateway_url": "https://api.bootpay.co.kr",
  "metadata": {},
  "sandbox": false,
  "pg": "나이스페이먼츠",
  "method": "계좌이체",
  "method_symbol": "bank",
  "method_origin": "계좌이체",
  "method_origin_symbol": "bank",
  "purchased_at": "2026-04-10T15:56:08+09:00",
  "requested_at": "2026-04-10T15:55:41+09:00",
  "status_locale": "결제완료",
  "currency": "KRW",
  "receipt_url": "https://.../receipts/...",
  "status": 1,
  "bank_data": {
    "tid": "5zJ4xY7m0kODnyRpQWGrNWja7bkR78Kwv1M9ENjbeoPaZdL6",
    "bank_code": "088",
    "bank_name": "신한",
    "cash_receipt_tid": "AxMBvpmjnoD4yKeq5bgrp5QbZ7MqQ8GX0lzW6YOQJ1w9NLRZ",
    "cash_receipt_type": 1,
    "cash_receipt_no": "158190158",
    "cash_receipt_url": "https://.../receipts/cash-receipt/..."
  }
}json
필드 설명
cash_receipt_tid 현금영수증 발행 PG 거래 ID (취소 시 사용)
cash_receipt_no 발행된 현금영수증 번호 (국세청 조회용)
cash_receipt_type 1 소득공제 / 2 지출증빙
cash_receipt_url PG가 제공하는 현금영수증 확인 URL (일부 PG만 제공)

2별건 발행

결제와 무관하게 현금영수증만 단독으로 발행해요. 오프라인에서 현금을 직접 수령한 경우 등에 사용해요.

POSThttps://api.bootpay.co.kr/v2/request/cash/receiptBasic Auth
연동키에 현금영수증 스코프가 필요해요

별건 발행은 해당 연동키에 cash_receipt_request 스코프가 부여돼 있어야 호출할 수 있어요. 없으면 API_SCOPE_INVALID (HTTP 401)로 거부돼요. 관리자 콘솔의 연동키 권한 설정에서 확인해요.

파라미터 타입 필수 설명
pg String 필수 현금영수증 발행 PG (이니시스 / 토스 / 페이앱 / 나이스페이먼츠)
order_name String 필수 현금영수증 주문명
order_id String 필수 가맹점 고유 주문번호
price Integer 필수 발행 금액
tax_free Integer 선택 면세 금액
identity_no String 필수 발행 식별번호 (휴대폰번호 / 주민번호 / 사업자번호)
cash_receipt_type String 선택 소득공제 또는 지출증빙. 생략하거나 빈 값이면 소득공제로 발행돼요
user.username String 선택 구매자명. 이니시스·페이앱·나이스페이먼츠는 PG로 전달, 토스는 미사용
user.phone String 선택 구매자 전화번호. 이니시스·페이앱·나이스페이먼츠는 PG로 전달, 토스는 미사용
user.email String 선택 구매자 이메일. 이니시스·페이앱·나이스페이먼츠는 PG로 전달, 토스는 미사용
purchased_at String 선택 현금을 수령한 시각(ISO8601 등). 생략하면 요청 시각으로 발행돼요. 파싱에 실패해도 오류 없이 요청 시각으로 대체되니 형식을 직접 검증해서 보내요. 페이앱은 이 값을 발행 거래일시로 사용해요
metadata Object 선택 가맹점 커스텀 데이터. 응답의 metadata로 그대로 돌아와요
extra Object 선택 부가 옵션. extra.service_price(봉사료), extra.minimum_price_limit(최소금액 검사 해제) 등
currency String 선택 통화. 생략 시 WON
curl -X POST "https://api.bootpay.co.kr/v2/request/cash/receipt" \
  -H "Authorization: Basic $(printf '%s' 'CLIENT_KEY:SECRET_KEY' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "pg": "나이스페이먼츠",
    "order_name": "현장 수령 현금결제",
    "order_id": "cash_1700000000",
    "price": 10000,
    "tax_free": 0,
    "identity_no": "01012345678",
    "cash_receipt_type": "소득공제",
    "user": { "username": "홍길동", "phone": "01012345678" }
  }'bash

응답 예시

{
  "receipt_id": "62f356871fc192036f9f4ae2",
  "order_id": "cash_1700000000",
  "price": 10000,
  "tax_free": 0,
  "cancelled_price": 0,
  "cancelled_tax_free": 0,
  "order_name": "현장 수령 현금결제",
  "company_name": "테스트상점",
  "gateway_url": "https://api.bootpay.co.kr",
  "metadata": {},
  "sandbox": false,
  "pg": "나이스페이먼츠",
  "method": "현금영수증",
  "method_symbol": "cash_receipt",
  "method_origin": "현금영수증",
  "method_origin_symbol": "cash_receipt",
  "purchased_at": "2026-04-10T15:56:08+09:00",
  "requested_at": "2026-04-10T15:56:02+09:00",
  "status_locale": "현금영수증발행완료",
  "currency": "KRW",
  "status": 60,
  "cash_receipt_data": {
    "tid": "Ae75jWNka9lpP2YxJ4K87RXb62PYLrRGZwXLObgyB0vMDm1d",
    "cash_receipt_type": 1,
    "cash_receipt_no": "158190158",
    "receipt_url": "https://.../receipts/cash-receipt/..."
  }
}json

cash_receipt_data의 필드는 다음과 같아요.

필드 설명
tid 발행 PG 거래 ID
cash_receipt_type 1 소득공제 / 2 지출증빙
cash_receipt_no 국세청 조회용 승인번호
receipt_url PG가 제공하는 현금영수증 확인 URL (일부 PG만 제공)
cancel_tid 취소 거래 ID 자리. 취소한 뒤에만 나타나고 값이 없으면 키 자체가 빠지는데, 현재 현금영수증 취소 흐름에서는 채워지지 않아요
토스 별건 발행의 `cash_receipt_type`은 값이 달라요 (알려진 이슈)

토스로 별건 발행​​한 경우 응답의 cash_receipt_data.cash_receipt_type이 다른 PG와 달리 0(소득공제) / 1(지출증빙)로 내려와요. 게다가 이 값은 요청의 최상위 cash_receipt_type이 아니라 extra 안의 값​​을 기준으로 계산돼서, 최상위 파라메터로만 지출증빙을 보내면 실제 발행은 지출증빙인데 응답값은 0으로 표시돼요. 발행 유형은 응답값 대신 요청에 보낸 cash_receipt_type을 기준으로 관리해요.

별건 발행은 receipt_id를 새로 발급받아요. 이 receipt_id현금영수증 취소를 호출할 수 있으므로 저장해 두세요.


에러 코드

공통 에러

인증·권한 관련 에러는 에러 코드표를 참고해요.

코드 의미 대처 방법
RC_NOT_FOUND 영수증 정보를 찾지 못했습니다 receipt_id가 올바른지 확인해요
RC_NOT_CONFIRMED 결제 완료 상태가 아닙니다 결제가 승인(status: 1)된 뒤에 발행해요
RC_CASH_RECEIPT_PUBLISHED (2809) 이미 현금영수증이 발행된 건입니다 결제 건 상태를 먼저 조회해요
RC_CASH_RECEIPT_PUBLISH_UNABLE (2810) 해당 결제의 PG로는 현금영수증을 발행할 수 없습니다 원 결제 PG가 이니시스·페이앱·토스·나이스페이먼츠인지 확인해요
RC_CASH_RECEIPT_NO_NEED_PAY_METHOD (2814) 현금영수증 발행이 불가능한 결제수단입니다 계좌이체·가상계좌 결제 건에만 발행할 수 있어요. 원 결제 PG가 페이앱이면 카카오머니·네이버포인트 결제 건도 발행할 수 있어요
RC_CASH_RECEIPT_NEED_USERNAME (2812) 구매자명(username)이 비어 있습니다 username을 함께 보내요
RC_CASH_RECEIPT_NEED_IDENTITY_NO (2813) 식별번호(identity_no)가 비어 있습니다 identity_no를 함께 보내요
RC_CASH_RECEIPT_PUBLISH_FAILED (2815) 현금영수증 발행에 실패했습니다 identity_no 형식과 PG의 현금영수증 지원 여부를 확인해요
RC_CASH_RECEIPT_FAILED (2802) 현금영수증 발행에 실패했습니다 별건 발행뿐 아니라 결제 건을 기본 채널(pg 생략)로 발행하다 실패한 경우​​에도 내려와요. message는 PG가 내려준 응답 메시지 그대로예요
RC_CASH_PURCHASED_AT_INVALID (2800) purchased_at 형식이 올바르지 않습니다 현재 미사용 — 파싱에 실패해도 이 오류 대신 요청 시각으로 대체 발행돼요. 원하는 발행 시각이 있다면 형식을 직접 검증해서 보내요

별건 발행에서 추가로 발생하는 에러

별건 발행은 영수증을 새로 만들기 때문에 결제 요청과 같은 기본 검증을 함께 거쳐요.

코드 의미 대처 방법
RC_NAME_BLANK (2003) 상품명을 입력해주세요 order_name을 채워 보내요
RC_O_ID_BLANK (2005) 가맹점에서 식별할 수 있는 order_id 값을 입력해주세요 order_id를 채워 보내요
RC_PRICE_LEAST_LT (2004) 100원보다 큰 금액을 결제할 수 있습니다 price를 100원 이상으로 보내요. 소액을 허용하려면 extra.minimum_price_limit: false를 함께 보내요
RC_PG_NOT_FOUND (2001) PG 정보를 찾지 못했습니다 pg 값이 올바른 PG 이름인지 확인해요 (HTTP 404)
RC_PM_NOT_FOUND (2002) 결제수단 정보를 찾지 못했습니다 지정한 PG에 현금영수증 결제수단이 열려 있는지 확인해요 (HTTP 404)
RC_CASH_RECEIPT_METHOD_NOT_FOUND (2803) 요청한 PG에서는 현금영수증 발행 기능을 지원하지 않습니다 이니시스·토스·페이앱·나이스페이먼츠 중에서 골라요 (HTTP 404)
RC_CASH_REQUEST_FAILED (2801) 현금영수증 신청이 실패하였습니다 영수증 생성 단계에서 예기치 못한 오류가 난 경우예요. message의 실패 사유를 확인해요
에러 응답 형식

에러 본문은 { "error_code": "...", "pg_error_code": "...", "message": "...", "payload": { ... } } 이고, 값이 없는 키는 응답에서 빠져요. error_code는 숫자가 아니라 위 표의 상수 이름 문자열​​이에요.

다음 단계