Toss Payments 정리

Toss Payments 정리

13분 소요

토스페이먼츠 API 연동하기

토스페이먼츠 API와 연동하기 위해서는 API 키가 필요하다.

API 키 종류

  1. 클라이언트 키: 결제위젯 SDK를 초기화할 때 사용. 일반 결제, 브랜드페이, 해외결제 서비스를 모두 지원한다.
  2. 시크릿 키: 결제위젯 클라이언트 키로 생성한 모든 결제를 승인, 취소, 조회하고 싶을 때 사용
  • 코어 API: 결제 승인, 결제 취소, paymentKey로 결제 조회, 거래 조회, 정산 조회, 수동 정산 조회
  • 브랜드페이 API: 결제 승인
  1. 보안 키: 지급대행과 같이 'ENCRYPTION' 보안을 요구하는 서비스에서 Request Body를 JWE로 암호화하는데 사용
  • 지급대행 API: 셀러 등록, 셀러 수정, 지급 대행 요청 API

API 키 에러

상태 코드에러 코드에러 메시지해결 방법
400INVALID_CLIENT_KEY잘못된 클라이언트 연동 정보입니다.클라이언트 키값을 다시 확인해주세요.
400INVALID_API_KEY잘못된 시크릿 키 연동 정보입니다.클라이언트 키와 매칭된 시크릿 키를 사용하고 있는지 확인하세요.
401UNAUTHORIZED_KEY인증되지 않은 시크릿 키 혹은 클라이언트 키입니다.클라이언트 키와 매칭된 시크릿 키를 사용하고 있는지 확인하세요. 시크릿 키 인코딩을 다시 확인하세요.
401INCORRECT_BASIC_AUTH_FORMAT잘못된 요청입니다. :를 포함해 인코딩해주세요.시크릿 키 인코딩을 다시 확인하세요.

인증 및 기타 헤더 설정

인증 헤더

일반적으로 Basic 인증에 시크릿 키를 사용한다.

시크릿 키로 인증하기

  1. 개발자 센터에서 내 시크릿 키 확인
  2. 시크릿 키에 :를 붙여 Base64로 인코딩
  3. 인코딩된 시크릿 키를 Authorization: Basic <인코딩된 시크릿 키> 형태로 전달

멱등키 헤더

API 요청에서 멱등성을 보장하면 같은 요청이 여러 번 전송되더라도 한 번만 처리되도록 할 수 있다.

멱등키를 사용하면 민감한 API 요청이 반복적으로 일어나는 문제를 막을 수 있고, 네트워크 이슈나 타임아웃 문제로 응답을 받지 못했을 때도 안전하게 같은 요청을 다시 보낼 수 있다.

멱등키 사용하기

Idempotency-Key 헤더에 유의미한 값을 전달하면 된다.

Idempotency-Key: {IDEMPOTENCY_KEY}
  • 멱등키는 UUID와 같이 충분히 무작위적인 고유 값으로 생성. (최대 길이 300자)
  • 멱등키는 처음 요청에 사용한 날부터 15일간 유효. 처음 요청에 사용한 멱등키는 15일 후 자동으로 삭제된다.

아래와 같이 API 요청에 멱등키 헤더를 사용하면 같은 요청이 두 번 일어나도 실제로 요청이 이루어지지 않고 첫 번째 요청 응답과 같은 응답을 보내준다.

curl --request POST \
  --url https://api.tosspayments.com/v1/payments/confirm \
  --header 'Authorization: Basic dGVzdF9nc2tfZG9jc19PYVB6OEw1S2RtUVhrelJ6M3k0N0JNdzY6' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: SAAABPQbcqjEXiDL' \
  --data '{"paymentKey":"5zJ4xY7m0kODnyRpQWGrN2xqGlNvLrKwv1M9ENjbeoPaZdL6","orderId":"a4CWyWY5m89PNh7xJwhk1","amount":15000}'
  • 토스페이먼츠 서버는 상점에서 API 요청 헤더로 보낸 멱등키와 API키, API 주소, HTTP 메서드 조합이 같은 요청이 있는지 확인해서 멱등성을 보장. 따라서 API키, API주소, HTTP 메서드가 다르다면 같은 멱등키를 사용해도 된다.

  • 멱등키 관리를 위한 별도의 DB나 테이블을 사용하면 서버 성능 및 보안 및 유지보수 측면에서 장점이 있다. 단순한 데이터 구조일 경우 Redis와 같은 KV 저장소를 사용하면 되며, 멱등키와 관련된 데이터의 복잡도, 유효 기간 관리, 확장성, 성능 등을 고려하여 적절한 DB 유형을 선택.

  • 멱등한 요청에서 에러가 반환되었을 때 멱등키를 변경하여 동일한 요청을 재시도하는 것은 위험하다. 정확한 오류 원인을 파악하고 해결한 후 다시 요청을 보낸다.

| 토스페이먼츠는 POST 메서드 API 요청에 대해서만 멱등키를 지원한다. |

에러 처리하기

HTTP Status Code에러 코드메시지
400INVALID_IDEMPOTENCY_KEY멱등키는 300자 이하여야 합니다.
409IDEMPOTENT_REQUEST_PROCESSING이전 멱등 요청이 처리중입니다.

테스트 환경에서 에러 재현

테스트 환경에서 에러를 재현할 때에는 토스페이먼츠 API 테스트 헤더를 사용.

TossPayments-Test-Code:

  • 자리에 재현하고 싶은 에러 코드를 넣고 API 실행
  • test_로 시작하는 테스트 API 키를 사용. 라이브 환경에서는 테스트 코드 헤더가 무시된다.

예시

curl --request POST \
  --url https://api.tosspayments.com/v1/payments/key-in \
  --header 'Authorization: Basic dGVzdF9za19EbnlScFFXR3JORGFuZTY3NXlXTDNLd3YxTTlFOg==' \
  --header 'Content-Type: application/json' \
  --header 'TossPayments-Test-Code: INVALID_CARD_EXPIRATION' \

요청 응답 본문

요청 본문은 JSON을 사용한다.

요청 본문

URL 인코딩

전체 요청 본문을 인코딩할 필요는 없다. 특수 문자가 요청 본문이나 쿼리 파라미터에 포함된 경우에만 URL 인코딩을 하면 된다.

URL 인코딩은 웹에서 안전하게 데이터를 전송하기 위해 특정 문자 % 기호와 두 개의 16진수 숫자로 변환하는 과정이다. 인코딩은 데이터가 전달되는 과정에서 오류나 변조 없이 완전하고 믿을 수 있는 상태로 유지해서 웹 서버가 요청을 정확하게 해석하도록 한다.

// 원본 데이터 
name=John Doe&age=30&city=New%20York

// URL 인코딩된 데이터
name=John%20Doe&age=30&city=New%20York

API 요청을 할 때 데이터 전송의 정확성과 안전성을 보장하려면 URL 인코딩을 해야한다.

응답 본문

토스페이먼츠 API의 성공 여부는 HTTP 상태 코드로 전달한다. 돌아온 HTTP 상태 코드에 따라 요청이나 에러를 처리하는 로직을 구축한다.

모든 API 응답, 요청 본문은 JSON 형식이다. 따라서 응답 헤더에는 Content-Type 이 포함된다.

Content-Type: application/json

응답 HTTP 상태 코드

HTTP 상태 코드설명
200 - OK요청이 성공적으로 처리되었습니다.
400 - Bad Request요청을 처리할 수 없습니다. 필수 파라미터를 보내지 않았거나, 파라미터 포맷이 잘못되었을 때 돌아오는 응답입니다. 요청 파라미터를 확인해주세요.
403 - Forbidden시크릿 키 없이 요청했거나 사용한 시크릿 키가 잘못되었습니다. 개발자센터에서 내 상점의 키값을 다시 한번 확인하고, 시크릿 키 문서를 참고하세요.
404 - Not Found요청한 리소스가 존재하지 않습니다. 요청한 API 주소를 다시 한번 확인해보세요.
429 - Too Many Requests비정상적으로 많은 요청을 보냈습니다. 잠시 후 다시 시도해주세요.
500 - Server Error 토스페이먼츠 서버에서 에러가 발생했습니다.

리소스 객체

토스페이먼츠 API v2는 리소스 중심으로 설계되었다. 어떤 API를 호출해도 일정하게 리소스 객체가 응답된다.

{
  "version": "2024-06-01",
  "traceId": "{traceId}",
  "entityType": "{entityType}",
  "entityBody": {
    // ...
  }
}

version string API 버전입니다. 토스페이먼츠의 API 버전 정책 및 API 변경사항을 확인해보세요.

traceId string 토스페이먼츠에서 발급하는 API 요청의 고유 식별자입니다. 기술문의 시 traceId를 첨부하면 더 빠르게 답변을 받을 수 있습니다.

entityType string 응답 객체 유형입니다.

  • 단건 객체가 응답되는 요청이라면 payout와 같이 객체 영문 이름이 소문자로 응답됩니다.

  • 객체 목록이 응답되는 요청이라면 payout-list와 같이 객체 이름 뒤에 -list가 붙습니다.

  • 객체가 삭제되는 요청이라면 deleted-entity가 응답됩니다.

entityBody string 응답 객체입니다. 단건 응답이라면 객체가 돌아옵니다. 목록 응답에는 pagination 정보와 응답 목록이 돌아옵니다.

리스트 객체

리소스 목록을 조회하면 entityType에는 객체 이름 뒤에 -list가 붙고 아래 예시와 같은 객체가 돌아온다. entityBody에는 hasNext, lastCursor와 같은 pagination 정보와 items 필드에 객체 목록이 돌아온다.

{
  "version": "2024-06-01",
  "traceId": "{traceId}",
  "entityType": "{entityType}-list",
  "entityBody": {
    "hasNext": false,
    "lastCursor": 213805090,
    "items": [ {...}, {...} ]
  }
}

삭제된 객체

리소스가 삭제되면 아래와 같이 deleted-entity 리소스 삭제 객체가 돌아온다. entityBody에는 삭제된 객체의 idref*Id가 돌아온다. id는 토스페이먼츠에서 발급한 리소스 식별자이다. ref*Id는 내 상점에서 직접 발급한 리소스 식별자이다.

{
  "version": "2024-06-01",
  "traceId": "{traceId}",
  "entityType": "deleted-entity",
  "entityBody": {
    "id": "{id}",
    "ref*Id": "{ref*id}" // nullable
  }
}

에러 객체

요청이 정상적으로 처리되지 않으면 응답으로 HTTP 상태 코드와 함게 아래와 같은 에러 객체가 돌아온다. API별 에러 코드와 메시지는 에러 코드 페이지에서 살펴본다. 에러 코드

API v1 에러 객체

{
  "code": "NOT_FOUND_PAYMENT",
  "message": "존재하지 않는 결제 입니다."
}

API v2 에러 객체

{
  "version": "2024-06-01",
  "traceId": "{traceId}",
  "error": {
    "code": "{CODE}",
    "message": "{MESSAGE}",
  }
}