페이지 이동경로
  • 문서>
  • 카카오톡 인증 서비스>
  • K3100: 출금동의

카카오톡 인증 서비스

K3100: 출금동의

이 문서는 카카오톡 인증 서비스의 K3100 출금동의 API 사용법을 안내합니다.

시작하기 전에

K3100 출금동의는 이름, 생년월일, 전화번호, CI로 자동이체 또는 자동납부 신청을 위한 출금동의를 제공하는 서비스입니다. 앱투앱(App to App) 또는 채널 메시지 방식으로 사용자에게 카카오톡을 통한 출금동의 전자서명을 요청할 수 있으며, 전자서명에 대한 검증을 통해 안전하게 출금동의를 완료할 수 있습니다.

카카오톡 인증 서비스 API는 서버간 연동(Server to Server)을 원칙으로 합니다.

전자서명 과정

아래는 카카오톡 출금동의의 전자서명 과정을 표현한 시퀀스 다이어그램(Sequence Diagram)입니다.

전자서명 과정

위 과정을 요약하면 다음과 같습니다.

  1. 이용기관이 인증할 사용자 정보를 전자서명 준비하기 API로 전달해 tx_id를 발급받습니다.
  2. 이용기관이 tx_id전자서명 요청하기 API를 호출해 사용자의 인증을 요청하면, 카카오톡 앱 실행 또는 카카오톡 메시지로 사용자에게 인증 요청이 전달됩니다.
    • identify_items 파라미터에 CI를 지정해 전자서명 요청 시 서명자 정보 가져오기 API로 연계정보(CI)가 포함된 개인정보를 전달받아야 합니다.
  3. 사용자는 카카오톡에서 전자서명으로 인증을 수행하고, 이용기관은 tx_id전자서명 상태 확인하기 API를 호출해 진행 상태를 확인합니다.
  4. 전자서명 완료 확인 후, 이용기관이 tx_id전자서명 검증하기 API를 호출해 전자서명 값을 전달받습니다.
  5. 이용기관이 tx_id서명자 정보 가져오기 API를 호출해 서명자 정보를 전달받습니다.
    • 제공받은 연계정보(CI)가 포함된 개인정보를 이용기관 서버에서 비교해 올바른 사용자인지 검증해야 합니다.
    • 카카오톡 인증 서비스에서 제공하는 서명자 정보는 사용자 비교 또는 검증 용도 외에는 사용할 수 없습니다.
자동납부 동의자료 금융결제원 제출

카카오톡 인증 서비스는 전자서명 완료 후 이용기관에 자동납부 동의자료만 제공합니다. 자동납부 동의자료 금융결제원 제출, 자동이체 또는 자동납부 등록은 이용기관에서 직접 처리해야 합니다.

사용자 인증 과정

사용자는 다음과 같은 과정을 거쳐 출금동의 전자서명을 수행합니다.

앱투앱 방식 출금동의 과정 채널 메시지 방식 출금동의 과정

카카오는 전자서명 준비하기 단계에서 개인정보, CI, 또는 CI와 전화번호를 함께 사용하여 인증을 요청할 사용자를 찾습니다. 대상 사용자가 확인되지 않거나 카카오 인증서를 발급받지 않은 경우, 카카오톡 출금동의가 불가능하여 전자서명 준비하기 API 호출 시 에러가 반환됩니다.

CI, 또는 CI와 전화번호를 함께 사용하는 확인 과정은 다음과 같습니다.

CI 사용 사용자 확인 과정 CI와 전화번호 사용 사용자 확인 과정

전자서명 준비하기

기본 정보
메서드 URL 인증 방식
POST https://cert-sign.kakao.com/sign/doc/v1/prepare/${PRODUCT_CODE} REST API 키
권한 사전 설정 카카오 로그인 동의항목
필요 - - -

전자서명 준비하기 API는 전자서명을 수행할 사용자의 정보를 카카오톡 인증 서비스에 전달하고 접수번호를 발급하는 API입니다. 이 API의 요청 결과로 받은 접수번호인 tx_id를 사용해 다음 단계의 전자서명 요청하기, 상태 확인하기, 검증하기를 요청할 수 있습니다.

전자서명 준비하기 API는 요청 URL에 경로 변수(Path variable)로 상품 코드를 포함합니다. 예를 들어 K3110 상품 이용 시, 요청 URL의 마지막 부분에 /K3110을 반드시 포함해야 합니다.

헤더(Header)에 이용기관 앱 REST API 키와 딜러사 앱 REST API 키를 담아 POST로 요청합니다. 본문에 사용자의 사용자 인증 방식과 개인정보를 JSON 형식으로 포함해야 합니다. 개인정보는 반드시 지정된 키로 암호화하여 전달해야 하며, 자세한 사항은 암호화 예제를 참고합니다.

요청 성공 시 응답은 tx_id와 처리 결과인 result 값을 포함합니다. 요청 실패 시 문제 해결에서 에러 코드 정보를 확인합니다.

암호화 예제

전자서명 준비하기 요청 시 사용자 개인정보인 이름, 전화번호, 생년월일과 서명할 데이터는 반드시 암호화 및 인코딩하여 전달해야 합니다. 다음 순서로 암호화와 인코딩을 처리합니다.

  1. 이용기관마다 발급된 암호화 키를 사용해 평문 데이터를 AES256(CTR) 방식으로 암호화
  2. 암호화한 데이터를 Base64 방식으로 인코딩(Encoding)

다음은 개인정보 암호화 및 인코딩 결과를 보여주는 예제입니다.

평문 AES256 암호화 값 Base64 인코딩 텍스트
이름:
홍길동

전화번호 :
01012345678


생년월일:
19950723
이름:
[6a 33 59 45 34 35 6a 2b 74 67 2b 43]

전화번호:
[55 74 36 35 4f 42 4a 31 61 62 55 74 75 45 59 3d]

생년월일:
[4e 38 4d 6a 32 54 6f 3d]
이름:
ajNZRTQ1ait0ZytD

전화번호:
VXQ2NU9CSjFhYlV0dUVZPQ==


생년월일:
TjhNajJUbz0=

요청

헤더
이름 설명 필수
Authorization Authorization: KakaoAK ${DEALER_REST_API_KEY}
인증 방식, 딜러사 앱의 REST API 키로 인증 요청
O
Target-Authorization Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}
인증 방식, 이용기관 앱 REST API 키로 인증 요청
O
경로 변수
이름 타입 설명 필수
PRODUCT_CODE String 상품 코드, 상품 상세 종류는 카카오톡 출금동의 상품 종류 참고
다음 중 이용하는 상품의 코드로 지정하여 요청:
- K3110
- K3120
(예: K3110 상품 이용 시 요청 URL은 /sign/v2/prepare/K3110)
O
쿼리 파라미터
이름 타입 설명 필수
settle_id String 정산 ID O
본문
  • 개인정보는 반드시 암호화하여 전송해야 합니다. 암호화 예제를 참고합니다.
이름 타입 설명 필수
type String 사용자 인증 방식

다음 중 하나의 값 선택:
PERSONAL_INFO: 전화번호, 성명, 생년월일 사용
CI_WITH_PHONE_NO: CI, 전화번호 사용
CI: CI 사용
(기본값: PERSONAL_INFO)

주의: 기본값이 아닌 CI_WITH_PHONE_NO 또는 CI 사용자 인증 방식은 매 요청 시 값을 설정해야 함
주의: CI로 인증하는 경우, 지갑 채널을 통해서 채널 메시지가 발송되며 파트너 채널을 이용할 수 없음
X
phone_no String 암호화된 01000000000 형식의 사용자 전화번호
하이픈(-)을 제외한 숫자로만 구성

주의: typePERSONAL_INFO 또는 CI_WITH_PHONE_NO인 경우 필수
X
name String 암호화된 사용자 성명

주의: typePERSONAL_INFO인 경우 필수
X
birthday String 암호화된 YYYYMMDD 형식의 사용자 생년월일

주의: typePERSONAL_INFO인 경우 필수
X
ci String 연계정보(Connecting Information, CI)

주의: typeCI_WITH_PHONE_NO 또는 CI인 경우 필수
X
enc_version Integer 암호화 및 복호화 키 버전
1로 고정
O

응답

본문
이름 타입 설명
tx_id String 전자서명 원문 접수번호

예제

요청
curl -i -X POST "https://cert-sign.kakao.com/sign/doc/v1/prepare/${PRODUCT_CODE}?settle_id=${SETTLE_ID}" \
    -H "Authorization: KakaoAK ${DEALER_REST_API_KEY}" \
    -H "Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}" \
    -H "Content-Type: application/json;charset=UTF-8" \
    -d '{
          "type": "PERSONAL_INFO",
          "phone_no": "3BKX7CnJ4GhDFnw=",
          "birthday": "3Rqf7CnL6m4=",
          "name": "AJY7MrlsNc/t",
          "enc_version": 1
    }'
응답
{
    "tx_id": "02a05c5bfe-d89a-448b-a538-d80dc5b038fa"
}

전자서명 요청하기

기본 정보
메서드 URL 인증 방식
POST https://cert-sign.kakao.com/sign/doc/v1/request REST API 키
권한 사전 설정 카카오 로그인 동의항목
필요 - - -

전자서명 요청하기 API는 전자서명 준비하기 API를 통해 접수된 tx_id에 해당하는 전자서명 요청을 실행합니다. 이 API의 요청 성공 결과로 사용자의 카카오톡에 전자서명 요청 또는 채널 메시지가 발송됩니다. 앱투앱 방식인 K3120 상품 이용 시, 이 API의 요청 성공 결과로 받은 scheme 값으로 카카오톡의 전자서명 요청 화면을 호출해야 합니다.

헤더(Header)에 이용기관 앱 REST API 키와 딜러사 앱 REST API 키를 담아 POST로 요청합니다. 본문에 서명 원문을 포함한 전자서명 요청 정보를 JSON 형식으로 전달해야 합니다. 서명 원문은 암호화된 자동출금 동의 자료입니다.

요청 성공 시 사용자에게 전자서명 요청이 보내지며, 응답은 tx_id와 처리 결과인 result 값을 포함합니다.

사용자는 전자서명 요청의 남은 유효시간 이내에 채널 메시지의 [인증하기] 버튼을 눌러 전자서명을 진행할 수 있습니다. 이미 전자서명을 완료했거나 유효시간이 경과한 후에는 사용자가 [인증하기] 버튼을 눌렀을 때 에러 안내가 나타납니다.

다음과 같은 경우에는 전자서명 요청이 실패할 수 있습니다.

  • 사용자 전화번호에 해당하는 카카오계정 없음
    • 카카오톡 인증 서비스 이용 불가능
  • 사용자 카카오계정에 본인인증 정보 없음
    • 본인인증 안내 페이지 출력
    • 사용자의 본인인증 완료 후 카카오톡 인증 서비스 이용 가능
    • 전자서명 요청하기 API 재호출 필요
  • 사용자 정보가 카카오계정의 본인인증 정보와 일치하지 않음
    • 카카오톡 인증 서비스 이용 불가능
  • 사용자 이름이 출금계좌 예금주명과 일치하지 않음
    • 사용자 이름과 출금계좌 예금주명이 동일한지 확인 후 요청해야 함
  • 사용자 정보에 계약 시 협의되지 않은 값이 있음
    • 카카오톡 인증 서비스 이용 불가능

요청 실패 시 문제 해결에서 에러 코드 정보를 확인합니다.

사용자 인증 요청 안내문

전자서명 요청하기의 파라미터 값은 사용자 인증 요청 안내문에 사용됩니다. 아래 예시와 설명을 참고합니다.

사용자 인증 요청 안내문 구성 예시
영역 파라미터 설명
🅐 요청구분 delegate_info.request_type 요청구분, 공백 포함 최대 40자

: 자동이체 출금동의
🅑 요청기관 - 등록된 이용기관 이름

: 서비스 이용기관
🅒 받는이 delegate_info.receiver_name 전자서명을 요청할 사용자 이름, 공백 포함 최대 80자

문구: 받는이 뒤에 receiver_name의 값을 대입해 출력
: 김라연
🅓 유효일시 - 전자서명 요청 시각으로부터 5분(300초) 후의 시각
🅔 서비스 이용기관 고객센터 - 등록된 이용기관 고객센터 이름과 연락처
🅕 자동출금 동의 자료 document 자동출금 동의 자료, 인증 정보 화면에만 노출

: 청구기관명: 요금청구기관, 출금은행: 테스트 은행, 계좌번호: 000-1111-222-3333, 예금주: 테스트 예금자명, 생년월일: 20000101, 서비스종류: CMS, 동의항목: 자동이체 출금에 동의함
🅖 커스텀 메시지 extra_message 이용기관에서 지정 가능한 상세 설명, 공백 포함 최대 500자
🅗 개인정보 제3자 제공 동의 identify_items 인증을 통해 이용기관에서 제공받을 서명자의 개인정보 동의항목

요청

헤더
이름 설명 필수
Authorization Authorization: KakaoAK ${DEALER_REST_API_KEY}
인증 방식, 딜러사 앱의 REST API 키로 인증 요청
O
Target-Authorization Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}
인증 방식, 이용기관 앱 REST API 키로 인증 요청
O
쿼리 파라미터
이름 타입 설명 필수
settle_id String 정산 ID O
본문
이름 타입 설명 필수
return_url String 전자서명 후 사용자가 복귀할 파트너 서비스 URL
전자서명 요청이 완료됐거나 실패했을 때, 사용자가 파트너 서비스로 이동할 수 있도록 하기 위해 사용
(최대: 255자)

주의: 채널 메시지 방식에서 사용 불가
주의: URL에 스킴(Scheme) 지정 시 카카오톡 종료 스킴 사용 불가, 스킴 이름은 알파벳과 숫자만 사용 가능(예: kakaocert://xxxxx 사용 가능, kakao.cert://xxxxx 사용 불가)
X
expires_in Integer 처리 마감시간(단위: 초, 기본값: 600, 최대값: 1200) X
tx_id String 전자서명 원문 접수번호 O
document Document 서명할 데이터
암호화된 값으로 전달, 예제 참고
자동출금 동의 자료 항목의 키와 값 쌍으로 구성
(예: "{\"txId\":\"094f8bf9e2-5c41-4641-867a-4a89eb604330\",\"data\":\"{\\\"청구기관명\\\":\\\"청구 기관명\\\",\\\"출금은행\\\":\\\"이름\\\",\\\"계좌번호\\\":\\\"000-1111-222-3333\\\",\\\"예금주\\\":\\\"예금주 이름\\\",\\\"생년월일\\\":\\\"20000101\\\",\\\"서비스종류\\\":\\\"CMS\\\",\\\"동의항목\\\":\\\"자동이체 출금에 동의함\\\"}\"}")
O
document_type String 상세 서명 정보 화면에서 노출되는 서명 원문의 타입
TEXT로 고정
O
delegate_info JSON 사용자에게 보여질 인증 요청 안내문, delegate_info: 사용자 인증 요청 안내문예제 참고 O
extra_message String 커스텀 메시지, 사용자에게 보여질 상세 설명, 사용자 인증 요청 안내문 참고
모든 문자 입력 가능, 공백 포함 최대 500자

주의: 카카오톡을 이용하여 메시지를 발송함에 있어 메시지 집행 가이드발송 유의사항 가이드를 준수해야 하며, 위반 시 운영정책에 따라 서비스 이용이 제한될 수 있음
X
identify_items String[] 서명자 정보 가져오기 응답으로 확인할 서명자 정보 목록
다음 중 하나 이상의 값 사용 가능
CI: 연계정보
NAME: 이름
BIRTHDAY: 생일
PHONE_NUMBER: 전화번호
GENDER: 성별
X
Document
이름 타입 설명 필수
청구기관명 String 청구 기관 이름 O
출금은행 String 출금은행 이름 O
계좌번호 String 출금계좌번호 O
예금주 String 출금계좌 예금주명 O
생년월일 String 출금계좌 예금주 생년월일, YYYYMMDD 형식 O
서비스종류 String CMS, 펌뱅킹, 지로 중 하나 X
동의항목 String 자동이체 출금 동의 확인 문구 X
delegate_info: 사용자 인증 요청 안내문
이름 타입 설명 필수
receiver_name String 전자서명을 요청할 사용자 이름, 공백 포함 최대 80자

주의:
암호화 필수, 예제 참고
카카오계정의 이름과 다른 경우 E2002 에러 발생
O
request_type String 요청 구분, 공백 포함 최대 40자
(기본값: 자동이체 출금동의)
X

* call_center_number, call_center_name, request_organization: Deprecated, 등록된 이용기관 정보를 사용하도록 변경

응답

본문
이름 타입 설명
tx_id String 전자서명 원문 접수번호
result String 처리 결과
Y: 정상 접수
N: 접수 실패
scheme String K3120 상품 이용 시에만 응답에 포함
사용자가 카카오톡 앱을 실행해 전자서명을 수행할 수 있도록 하기 위한 커스텀 URL 스킴(Custom URL Scheme)
전자서명 요청하기 API 성공 응답을 통해 전달 받은 scheme 값을 사용해 사용자가 전자서명을 요청할 수 있도록 해야 함

예제

요청
curl -i -X POST "https://cert-sign.kakao.com/sign/doc/v1/request?settle_id=${SETTLE_ID}" \
    -H "Authorization: KakaoAK ${DEALER_REST_API_KEY}" \
    -H "Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}" \
    -H "Content-Type: application/json;charset=UTF-8" \
    -d '{
        "tx_id": "09c0fe5dd9-d201-41dc-ab59-50a3ac3cace6",
        "expires_in": 1200,
        "document_type": "TEXT",
        "document": "lwHTplCd+mBTF3UxUxG4d7gke...",
        "identify_items": ["CI", "NAME", "BIRTHDAY", "PHONE_NUMBER", "GENDER"],
        "delegate_info": {
            "receiver_name": "AJY7MrlsNc/t",
        }
    }'
응답: K3110 상품 이용 시
{
   "tx_id": "02a05c5bfe-d89a-448b-a538-d80dc5b038fa",
   "result": "Y"
}
응답: K3120 상품 이용 시
{
   "tx_id": "02a05c5bfe-d89a-448b-a538-d80dc5b038fa",
   "result": "Y",
   "scheme": "kakaotalk://..."
}

전자서명 상태 확인하기

기본 정보
메서드 URL 인증 방식
GET https://cert-sign.kakao.com/sign/doc/v1/status REST API 키
권한 사전 설정 카카오 로그인 동의항목
필요 - - -

전자서명 상태 확인하기 API는 카카오톡 출금동의(K3100) 상품을 통해 요청된 전자서명의 진행 상태를 확인합니다. 사용자는 카카오톡을 통해 인증을 수행하므로, 이용기관은 전자서명 상태 확인하기 API를 통해서만 인증 진행 상태를 확인할 수 있습니다.

헤더(Header)에 이용기관 앱 REST API 키와 딜러사 앱 REST API 키를 담아 GET으로 요청합니다. 본문에 상태를 확인할 전자서명 요청의 tx_id와 정산 ID를 포함해야 합니다.

요청 성공 시 응답은 전자서명의 상태를 포함합니다. 전자서명의 상태는 요청(REQUESTED), 완료(COMPLETED), 만료(EXPIRED) 세 가지로 각각 다음과 같이 조치합니다.

  • 요청
    • 사용자에게 전자서명 요청이 전달된 상태
    • 사용자가 전자서명 요청을 정상적으로 확인했다면 viewed_at 필드 값으로 확인 가능
    • 전자서명 상태가 완료 또는 만료로 확인될 때까지 주기적으로 전자서명 확인하기 API 재요청
  • 완료
  • 만료
    • 전자서명 요청이 만료된 상태
    • 인증 실패 처리, 또는 전자서명 요청하기 API를 사용해 다시 사용자에게 전자서명 요청

전자서명이 완료된 경우에는 사용자가 서명한 일시, 전자서명이 만료되는 일시를 비롯한 시간 정보들을 제공합니다. 이미 이용기관이 전자서명 검증하기 API를 통해 전자서명 값을 전달받았다면, 전자서명 값이 전달된 일시 정보를 제공합니다.

사용자의 인증서 상태에 따라 인증서를 발급 또는 재발급하거나 2차 본인인증(은행 계좌 확인)을 해야 할 수 있습니다. 이 경우, 추가 인증까지 모두 완료된 후 전자서명 상태가 완료로 변경됩니다.

요청 실패 시 문제 해결에서 에러 코드 정보를 확인합니다.

요청

헤더
이름 설명 필수
Authorization Authorization: KakaoAK ${DEALER_REST_API_KEY}
인증 방식, 딜러사 앱의 REST API 키로 인증 요청
O
Target-Authorization Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}
인증 방식, 이용기관 앱 REST API 키로 인증 요청
O
쿼리 파라미터
이름 타입 설명 필수
settle_id String 정산 ID O
tx_id String 전자서명 원문 접수번호 O

응답

본문
이름 타입 설명
tx_id String 전자서명 원문 접수번호
status String 전자서명 상태, 다음 중 하나
REQUESTED: 사용자에게 전자서명을 요청함, 사용자는 채널 메시지를 통해 전자서명 요청을 받음
COMPLETED: 사용자가 전자서명을 완료함
EXPIRED: 유효시간 이내에 사용자가 전자서명을 완료하지 않아 요청이 만료됨
created_at String 전자서명 요청 일시*
viewed_at String 사용자가 전자서명 요청을 확인한 일시*
completed_at String 사용자가 전자서명을 완료한 일시*
expired_at String 전자서명 만료 일시*
partner_notified_at String 이용기관이 전자서명 검증하기 API를 통해 전자서명 값을 전달받은 일시*

* 시간은 yyyy-MM-dd'T'HH:mm:ss 형식, RFC3339 참고

예제

요청
curl -i -X GET "https://cert-sign.kakao.com/sign/doc/v1/status?settle_id=${SETTLE_ID}&tx_id=${TX_ID}" \
    -H "Authorization: KakaoAK ${DEALER_REST_API_KEY}" \
    -H "Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}" \
    -H "Content-Type: application/json;charset=UTF-8"
응답
{
    "status": "REQUESTED",
    "tx_id": "d3a83f53-239d-4d7a-968d-25ec0969047e",
    "created_at": "2021-06-18 13:53:36",
    "viewed_at": null,
    "completed_at": null,
    "expired_at": "2021-06-18 14:03:36",
    "partner_notified_at": null
}

전자서명 검증하기

기본 정보
메서드 URL 인증 방식
GET https://cert-sign.kakao.com/sign/doc/v1/verify REST API 키
권한 사전 설정 카카오 로그인 동의항목
필요 - - -

전자서명 검증하기 API는 완료된 전자서명을 검증하고 이용기관에 전자서명 데이터 전문을 제공합니다. 전자서명 데이터 전문은 자동이체 또는 자동납부 등록 시 필요한 자동출금 동의 자료를 포함합니다.

헤더(Header)에 이용기관 앱 REST API 키와 딜러사 앱 REST API 키를 담아 GET으로 요청합니다. 본문에 완료된 전자서명 요청의 tx_id와 정산 ID를 포함해야 합니다. 전자서명 검증하기는 완료된 전자서명 요청당 1회만 요청 가능합니다.

요청 성공 시 응답은 전자서명의 상태와 전자서명 검증 결과를 포함합니다. 요청 실패 시 문제 해결에서 에러 코드 정보를 확인합니다.

요청

헤더
이름 설명 필수
Authorization Authorization: KakaoAK ${DEALER_REST_API_KEY}
인증 방식, 딜러사 앱의 REST API 키로 인증 요청
O
Target-Authorization Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}
인증 방식, 이용기관 앱 REST API 키로 인증 요청
O
쿼리 파라미터
이름 타입 설명 필수
settle_id String 정산 ID O
tx_id String 전자서명 원문 접수번호 O

응답

본문
이름 타입 설명
status String 전자서명 상태, 전자서명 검증 시에는 전자서명이 완료된 상태인 COMPLETE 값만 제공되며, 이 외 상태인 경우 에러 응답
result String 전자서명 검증 결과
Y: 성공
N: 실패
ci String 연계정보(Connecting Information, CI)
카카오톡 출금동의 K3100 상품 이용 시 이용기관이 가진 권한 및 사용자 동의 여부에 따라, AES256(CTR) 방식으로 암호화된 CI 포함

비고: 전자서명 요청하기 요청의 identify_itemsCI 포함 시 응답에 미포함
vid String 계약 시 ci 제공에 협의한 경우에만 제공
사용자의 원본 CI(Base64 decoded CI)와 인증서 일련번호(Serial number byte array)로 구성된 SHA256 해시 값(sha256_hash)
signed_document String Base64 인코딩된 DER 형식의 서명된 문서
(참고: CMSSignedData)

예제

요청
curl -i -X GET "https://cert-sign.kakao.com/sign/doc/v1/verify?settle_id=${SETTLE_ID}&tx_id=${TX_ID}" \
    -H "Authorization: KakaoAK ${DEALER_REST_API_KEY}" \
    -H "Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}" \
    -H "Content-Type: application/json;charset=UTF-8"
응답
{
  "status": "COMPLETED",
  "result": "Y",
  "signed_document": "${CMSSignedData}"    // 상단 설명 및 표 참고
}
응답: CI 제공에 협의한경우
{
    "status": "COMPLETED",
    "result": "Y",
    "ci": "${CI}",    // 상단 설명 및 표 참고
    "vid": "${VID}",    // 상단 설명 및 표 참고
    "signed_document": "${CMSSignedData}"    // 상단 설명 및 표 참고
}
언어별 예제

아래는 실제 서비스에서 고려해야 할 여러 요소(성능, 예외 처리, 동시성 등)가 반영되지 않은 참고용 예제입니다.

Kotlin
Java
C++
class VerifySample {
 
    val kakaoClient = HttpClient.newBuilder().build()
    val mapper = ObjectMapper()
    val settleId = "PARTNER_SETTLE_ID"
    private val transformation = "AES/CTR/NoPadding"
    private val secretKeySpec = SecretKeySpec("PARTNER_SECRET_KEY".decodeBase64(), "AES")
    private val ivSpec = IvParameterSpec("PARTNER_IV".decodeBase64())
 
    private fun decrypt(content: ByteArray): String =
        Cipher.getInstance(transformation).run {
            init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec)
            String(doFinal(content))
        }
 
    private fun createHttpRequest(uri: URI): HttpRequest {
        return HttpRequest.newBuilder()
            .uri(uri)
            .setHeader(AUTHORIZATION, DEALER_REST_API_KEY)
            .setHeader(TARGET_AUTHORIZATION, PARTNER_REST_API_KEY)
            .GET()
            .build()
    }
 
    // 전자서명 검증하기 API
    private fun callVerify(txId: String): VerifyResponse {
        val uri = URI.create(createURI(txId))
        val response: HttpResponse<String> = kakaoClient.send(createHttpRequest(uri), HttpResponse.BodyHandlers.ofString())
        return mapper.readValue<VerifyResponse>(response.body())
    }
 
    private fun createURI(txId: String): String {
        val sb = StringBuilder()
        sb.append("https://cert-sign.kakao.com/sign/doc/v1/verify?settle_id=")
            .append(settleId)
            .append("&tx_id=")
            .append(txId)
        return sb.toString()
    }
 
    /**
     * 이용기관에서 CI를 보유한 경우
     * 전자서명 검증하기 API를 호출하여 보유한 CI와 비교
     * !!중요!! 전자서명 검증하기 API 호출 및 CI 비교는 반드시 서버에서 수행
     */
    // 전자서명 검증하기 API 호출
    fun compareCI(txId: String): Boolean {
        // 응답에 포함된 CI를 복호화
        val encryptedCi = callVerify(txId).ci
        // 이용기관에서 보유한 CI와 비교
        val decryptedCI = decrypt(encryptedCi.decodeBase64())
        return exist(decryptedCI)
    }
 
    /**
     * 실명인증된 CI가 있는 경우
     * 전자서명 검증하기 API의 결과와 실명인증된 CI를 비교
     * !!중요!! 전자서명 검증하기 API 호출 및 CI 비교는 반드시 서버에서 수행
     */
    // 전자서명 검증하기 API 호출
    fun compareCI(txId: String, ci: String): Boolean {
        // 응답에 포함된 CI를 복호화
        val encryptedCi = callVerify(txId).ci
        // 실명인증된 CI와 비교
        val decryptedCI = decrypt(encryptedCi.decodeBase64())
        return ci == decryptedCI
    }
}
class VerifySample {
 
    private final HttpClient kakaoClient = HttpClient.newBuilder().build();
    private final SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode("PARTNER_SECRET_KEY"), "AES");
    private final IvParameterSpec ivSpec = new IvParameterSpec(Base64.getDecoder().decode("PARTNER_IV"));
    private final String settleId = "PARTNER_SETTLE_ID";
 
    private String decrypt(byte[] content) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeyException {
        String transformation = "AES/CTR/NoPadding";
        Cipher cipher = Cipher.getInstance(transformation);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
        return new String(cipher.doFinal(content));
    }
 
    private HttpRequest createHttpRequest(URI uri)  {
        return HttpRequest.newBuilder()
                .uri(uri)
                .setHeader(AUTHORIZATION, DEALER_REST_API_KEY)
                .setHeader(TARGET_AUTHORIZATION, PARTNER_REST_API_KEY)
                .GET()
                .build();
    }
 
    private VerifyResponse callVerify(String txId) throws IOException, InterruptedException {
        URI uri = URI.create(createURI(txId));
        // 전자서명 검증하기 API
        HttpResponse<String> response = kakaoClient.send(createHttpRequest(uri), HttpResponse.BodyHandlers.ofString());
        return Mapper.getInstance().readValue(response.body(), VerifyResponse.class);
    }
 
    private String createURI(String txId) {
        StringBuilder sb = new StringBuilder();
        sb.append("https://cert-sign.kakao.com/sign/doc/v1/verify?settle_id=")
                .append(settleId)
                .append("&tx_id=")
                .append(txId);
        return sb.toString();
    }
 
    /**
     * 이용기관에서 CI를 보유한 경우
     * 전자서명 검증하기 API를 호출하여 보유한 CI와 비교
     * !!중요!! 전자서명 검증하기 API 호출 및 CI 비교는 반드시 서버에서 수행
     */
    // 전자서명 검증하기 API 호출
    boolean compareCI(String txId) throws IOException, InterruptedException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
        // 응답에 포함된 CI를 복호화
        String encryptedCi = callVerify(txId).getCi();
        // 이용기관에서 보유한 CI와 비교
        String decryptedCI = decrypt(Base64.getDecoder().decode(encryptedCi));
        return exist(decryptedCI);
    }
 
    /**
     * 실명인증된 CI가 있는 경우
     * 전자서명 검증하기 API의 결과와 실명인증된 CI를 비교
     * !!중요!! 전자서명 검증하기 API 호출 및 CI 비교는 반드시 서버에서 수행
     */
    // 전자서명 검증하기 API 호출
    boolean compareCI(String txId, String ci) throws IOException, InterruptedException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
        // 응답에 포함된 CI를 복호화
        String encryptedCi = callVerify(txId).getCi();
        // 실명인증된 CI와 비교
        String decryptedCI = decrypt(Base64.getDecoder().decode(encryptedCi));
        return ci.equals(decryptedCI);
    }
}
class VerifySample {
private:
    //카카오의 전자서명 검증하기 API를 호출.
    json callVerify(const string& txId) {
        string uri = createURI(txId);
        auto response = kakaoClient.Get(uri.c_str());
        return json::parse(response->body);
    }
 
    string createURI(const string& txId) {
        return "https://cert-sign.kakao.com/sign/doc/v1/verify?settle_id=" + settleId + "&tx_id=" + txId;
    }
 
public:
    /**
     * 이용기관에서 CI를 보유한 경우
     * 전자서명 검증하기 API를 호출하여 보유한 CI와 비교
     * !!중요!! 전자서명 검증하기 API 호출 및 CI 비교는 반드시 서버에서 수행
     */
    // 전자서명 검증하기 API 호출
    bool compareCI(const string& txId) {
        // 응답에 포함된 CI를 복호화
        string encryptedCi = callVerify(txId)["ci"];
        // 이용기관에서 보유한 CI와 비교
        string decryptedCI = decrypt(base64_decode(encryptedCi));
        return exist(decryptedCI);
    }
 
    /**
     * 실명인증된 CI가 있는 경우
     * 전자서명 검증하기 API의 결과와 실명인증된 CI를 비교
     * !!중요!! 전자서명 검증하기 API 호출 및 CI 비교는 반드시 서버에서 수행
     */
    // 전자서명 검증하기 API 호출
    bool compareCI(const string& txId, const string& ci) {
        // 응답에 포함된 CI를 복호화
        string encryptedCi = callVerify(txId)["ci"];
        // 실명인증된 CI와 비교
        string decryptedCI = decrypt(base64_decode(encryptedCi));
        return ci == decryptedCI;
    }
};

서명자 정보 가져오기

기본 정보
메서드 URL 인증 방식
GET https://cert-sign.kakao.com/sign/v2/identify REST API 키
권한 사전 설정 카카오 로그인 동의항목
필요 - - -

서명자 정보받기 API는 서명을 완료한 서명자 정보를 제공합니다.

이 API는 전자서명 검증하기 호출 후 요청 가능하며, 사용자 서명 완료 후 일정시간(10분)동안 1회만 요청 가능합니다. 이후 요청에 대해서는 E2017 에러가 발생합니다. 서명자의 개인정보 제공 동의 및 서명 완료 후, 개발 설계 오류, 네트워크 오류 등으로 인한 이용기관의 정보 수신 실패에 대해 카카오는 책임을 지지 않습니다.

헤더(Header)에 이용기관 앱 REST API 키와 딜러사 앱 REST API 키를 담아 GET으로 요청합니다. 본문에 완료된 전자서명 요청의 tx_id와 정산 ID를 포함해야 합니다.

요청 성공 시 응답은 전자서명 요청하기identify_items 파라미터로 지정한 서명자 정보를 포함합니다. 요청 실패 시 문제 해결에서 에러 코드 정보를 확인합니다.

주의

카카오톡 인증 서비스에서 제공하는 연계정보(CI)와 이름, 생년월일, 전화번호는 사용자 비교 및 검증 용도로만 사용할 수 있습니다. 서명자 정보 가져오기 API를 통해 제공받은 CI, 이름, 생년월일, 전화번호를 이용기관의 정보와 비교해 올바른 사용자인지 검증해야 합니다. 비교 및 검증은 반드시 이용기관 서버에서 수행해야 합니다.

요청

헤더
이름 설명 필수
Authorization Authorization: KakaoAK ${DEALER_REST_API_KEY}
인증 방식, 딜러사 앱의 REST API 키로 인증 요청
O
Target-Authorization Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}
인증 방식, 이용기관 앱 REST API 키로 인증 요청
O
쿼리 파라미터
이름 타입 설명 필수
settle_id String 정산 ID O
tx_id String 전자서명 원문 접수번호 O

응답

본문
이름 타입 설명
name String 암호화된 서명자의 이름
phone_no String 암호화된 서명자의 카카오톡 전화번호
birthday String 암호화된 서명자의 생년월일
gender String 암호화된 서명자의 성별
ci String 암호화된 서명자의 CI(연계정보)

비고: 전자서명 검증하기CI 수신 시 응답에 미포함
vid String 암호화된 서명자의 CI 검증값

비고: 전자서명 검증하기CI 수신 시 응답에 미포함

예제

요청
curl -i -X GET "https://cert-sign.kakao.com/sign/v2/identify?settle_id=${SETTLE_ID}&tx_id=${TX_ID}" \
    -H "Authorization: KakaoAK ${DEALER_REST_API_KEY}" \
    -H "Target-Authorization: KakaoAK ${PARTNER_REST_API_KEY}" \
    -H "Content-Type: application/json;charset=UTF-8"
응답
{
    "name": "${NAME}",
    "phone_no": "${PHONE_NO}",
    "birthday": "${BIRTHDAY}",
    "gender": "${GENDER}",
    "ci": "${CI}",
    "vid": "${VID}"
}

더 보기