문서 보고 따라하기
- 웹에 연동하기
- 앱에 연동하기
웹 환경에 iframe으로 연동하기
이 페이지에서는 웹(Web) 환경에서 eKYC를 연동하는 방법을 안내합니다.
고객사 서비스 내에서 eKYC 인증 UI를 호출하려면 iframe 방식을 사용해 인증 페이지를 불러와야 합니다.
아래 가이드를 참고해 고객사 서비스에 인증 화면을 자연스럽게 연동해 주세요.
웹에 연동하기 전 필수 세팅: HTML에 iframe 삽입하기
eKYC 인증 화면은 iframe을 통해 고객사 서비스 내에 임베딩되어 보여지게 돼요.
따라서 인증 요청을 하기 전에, 먼저 HTML에 iframe 태그를 정의해 두어야 해요.
iframe은 인증 요청 후 화면을 띄우는 그릇 역할을 하며,
이 요소가 있어야 인증 페이지가 정상적으로 로드되고 이후 결과도 전달받을 수 있어요.
- HTML 예제
<iframe
id="kyc_iframe"
class="fullscreen bg-white"
allow="camera"
src="https://kyc.useb.co.kr/auth"
>
</iframe>
Q. 웹앱 환경에서 카메라가 실행되지 않아요. 어떻게 해야 하나요?
ㄴ A. 웹앱에서는 기본적으로 브라우저의 카메라 권한을 따라갑니다.
- 고객사 코드 설정 확인
iframe태그에allow="camera"속성이 추가되어있는지 확인해 주세요. 이 속성이 반드시 있어야 카메라가 실행됩니다. - 엔드 유저 기기/브라우저 설정 확인
1. 사용 중인 브라우저(Chrome, Safari)의 카메라 권한이 허용되어 있는지 확인해 주세요.
2. iOS Safari 환경에서는 반드시 https 환경에서만 카메라가 동작합니다.
Q. iframe의 id는 꼭 "kyc_iframe"이어야 하나요?
ㄴ A. 예제에서는 "kyc_iframe"으로
지정했지만, 실제 서비스에서는 다른 이름을 써도 돼요.
단, 이후 JavaScript 코드에서 동일한 id로 document.getElementById("...")를 통해
참조하므로, id 값은 반드시 HTML과 JS에서 일치해야 해요.
Q. iframe은 꼭 이렇게 생겨야 하나요? (id, class, allow, src 전부 필수인가요?)
ㄴ A. 꼭 전부 필수는 아니지만, 대부분의 경우 아래 항목들은 권장합니다:
id: JavaScript에서 해당 iframe을 조작하려면 반드시 필요해요 (document.getElementById()로 찾음)allow="camera": 카메라를 사용하는 인증 방식이라면 반드시 필요해요src: 인증 화면을 띄우려면 반드시 URL이 지정돼야 해요class: TailwindCSS를 쓰는 경우 스타일용. 없애도 동작에는 문제 없어요 (단, 기본 높이나 배경은 지정 필요)
Q. 우리 서비스가 PHP, JSP인데 React 예제처럼 사용해도 되나요?
ㄴ A. 네, iframe은 HTML 기반 요소이기 때문에, 프레임워크에 관계없이 JSP, PHP, HTML 어디서든 동일하게 사용 가능해요.
단, 결과 수신을 위한 postMessage 처리 코드는 별도 <script> 로 삽입해주세요.
PHP/JSP 파일에서도 <script> 블록은 클라이언트에서 실행돼요.
1단계. 인증 방식 정하기
고객사에서 유스비 eKYC 서버에 접근하기 위해서는 유스비의 고객사라는 것을 먼저 인증해야 해요.
이 때 인증하는 방식은 토큰 없이도 인증이 가능한 Credential과 토큰 발급이 필수적인 Access Token이 있어요. 고객사마다 각자의 보안 및 운영 목적에 맞는 방식을 선택해 인증을 진행하면 돼요.
- Credential → 테스트/PoC 용
- Access Token → 보편적인 운영용
1. Credential
메일로 전달받은 customer_id, id, key 값을 요청에 그대로 사용해요.
구조가 단순하지만 보안상 노출 위험이 있어 이 방식은 실제 운영 전 테스트, PoC 용도로 한정해 사용하는 것을 권장해요.
2. Access Token 방식
서버 또는 클라이언트에서 Access Token을 먼저 발급받고, 해당 토큰으로 인증 요청을 보내요.
이 방식은 보안이 더 강하고, 토큰은 24시간 동안 유효해요.
Access Token을 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.
Access Token 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/sign-in
{
"customer_id": <customer_id>, //number, 고객사id
"username": "<id>", //string, client_id
"password": "<key>" //string, client_secret
}
Response
{
"api_response": {
"result_code": "N100",
"result_message": "OK."
},
"company": {
"name": "id",
"industry": 2,
"phone_number": "1500-0002"
},
"expire": "2022-08-17T11:10:29Z", // 생성 후 24시간 뒤에 만료됨
"is_temp_password": true,
"name": "",
"role": 2,
"token": "**<access_token>**", // **Access Token** 획득
"username": "<client_id>"
}
2단계. 요청 보내기
HTML에 iframe을 세팅했고, 인증 방식을 정했다면 이제 요청을 보낼 차례예요.
이 단계에서는 리스너 등록부터 조건에 맞는 요청을 보낼 때 고려해야하는 항목들을 정해 eKYC 인증 화면을 요청하는 절차까지 진행할 거예요.
요청을 보낼 때는 다음 항목들을 정해 두어야 해요.
- 인증 방식 (Credential / Access Token)
- 필수 정보 입력 방식 (고객사 자체 구현 (파라미터 전달, Transaction_id (심사 사전 등록) 전달)/ 유스비 제공 화면 사용)
- 다국어(영문) 지원 및 폰트 적용 여부
1. 리스너 등록하기
eKYC 인증이 완료되면, 결과는 postMessage를 통해 iframe을 띄운 고객사 페이지로 전달돼요.
이때, 결과 메시지를 놓치지 않고 받으려면 브라우저의 window에 리스너가 등록되어 있어야 해요.
-
리스너 등록 예제 확인하기
⚠️ 예제는 요청 보내는 전체 소스의 일부만 예시로 제공하는 것이니 참고용으로 활용해 주세요.window.addEventListener("message", (e) => {
console.log("alcherakyc response", e.data); // base64 encoded된 JSON 메시지이므로 decoded해야 함(needs to be decoded becaused it`s encoded by base64)
console.log("origin :", e.origin);
try {
const decodedData = decodeURIComponent(atob(e.data));
console.log("decoded", decodedData);
const json = JSON.parse(decodedData);
console.log("json", json);
// 데이터처리 부분
// UI 처리
} catch (error) {
console.log("wrong data", error);
}
});
Q. 리스너는 언제 등록해야 하나요?
ㄴ A. 인증 요청을 보내기 전에 등록해야 해요. 리스너가 먼저 준비되어 있어야 결과 메시지를 받을 수 있어요.
Q. 리스너가 등록되어 있는데 결과를 못 받아요. 왜 그런가요?
ㄴ A. iframe이 제대로 로드되지 않았거나, postMessage를 보낸 쪽과 받은 쪽의 origin이 다를 수 있어요. 콘솔 로그로 origin 값을 꼭 확인해 주세요.
Q. 메시지를 디코딩할 때 오류가 나요. 어떤 문제일까요?
ㄴ A. e.data는
base64 + URI 인코딩 형식이라서, 반드시 decodeURIComponent(atob(...))
순서로 처리해야 해요.
2. 파라미터 조건 채우기
1) 인증 방식에 따른 인증 값 넣어주기 (필수)
1단계에서 미리 인증 방식을 결정한 상태이므로, 요청을 보내는 시점에서는 인증 방식에 따른 인증 값을 전달하면 돼요.
- Credential: 계정 정보 3가지
customer_id,id,key - Access Token:
Access Token
2) 필수 정보 입력 방식 정하기 (필수)
(1) 고객사 자체 구현
고객사에서 직접 구현한 화면을 통해 엔드 유저의 필수 정보를 입력받는 경우예요.
이
경우, 요청 시 엔드 유저에게서 받은 정보를 반드시 파라미터로 전달해 주셔야 해요.
이 때, 정보를 파라미터로 직접 전달하거나 심사 사전 등록 방식을 통해 transaction_id 로 전달할 수도 있어요.
-
파라미터 전달 방식
-
Transaction (심사 사전 등록) 방식
Transaction (심사 사전 등록) 방식으로 전달하기
eKYC 인증을 위해 엔드 유저의 필수 개인 정보를 고객사에서 직접 수집하는 경우, 해당 정보를 전달하는 과정에 보안을 강화할 수 있는 인증 방식이에요. Access Token으로 먼저 인증 정보를 서버에 등록하고, 받은
transaction_id로 인증을 진행해요.인증 요청 전에 정보를 서버에서 설정하기 때문에 클라이언트에 민감한 정보가 노출되지 않아 보안적으로 더 안전해요. 이 방식은 Access Token을 먼저 발급받은 후
/verificationsAPI를 통해 사용할 수 있어요.Transaction_id를 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.Transaction_id 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/verfications
{
"name": "홍길동",
"birthday": "1981-11-23",
"phone_number": "01012345678",
"email": "test@test.com"
}Response
{
"form": {
"transaction_id": "1754035720510123456-6126383872156123456",
"progress": {
"is_id_card_checked": false,
"is_account_checked": false,
"is_face_checked": null,
"is_custom_field_checked": null,
"is_edd_field_checked": null
},
"module": {
"id_card_ocr": true,
"id_card_verification": true,
"face_authentication": false,
"account_verification": true,
"liveness": false,
"custom_field": false,
"edd_field": false
}
},
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
} -
[POST]
(2) 유스비 화면 사용
유스비 eKYC 인증 화면에서 엔드 유저 정보를 입력받도록 위임하는 경우예요.
이 경우, 유스비 Admin에서 설정을 변경해 주어야 해요.
설정 위치: Admin > 기타 설정 > 개인정보 옵션에서 [사용자 필수 정보 수신]을 미사용으로 선택해 주세요.
3) 다국어 (영문) 지원 및 폰트 적용 여부 (선택)
다국어(영문) 지원과 폰트 (나눔 고딕) 적용 여부를 선택할 수 있어요.
별도로 파라미터를 전달하지 않으면, 기본 설정값은 한국어, Pretendard로 적용하여 제공돼요.
3. 요청 코드 예제
아래 코드는 Access Token + 자체 구현 + 다국어 On + 폰트 On 조건일 때의 파라미터 예제예요.
const KYC_TARGET_ORIGIN = "https://kyc.useb.co.kr";
const KYC_URL = "https://kyc.useb.co.kr/auth";
const params = {
access_token: "<access_token>",
name: "홍길동",
birthday: "1984-11-23",
phone_number: "01012345678",
email: "test@test.com",
font: "Nanum Gothic", // 폰트명 (Noto Serif KR | Nanum Gothic) (default: pretendard)
language: "en", // 영어 지원 (en) (default : 한국어)
};
고객사별 상황에 딱 맞는 예제는 다음 페이지인 ‘예제로 바로 적용하기’에서 만들어 볼 수 있어요.
4. 인코딩 규칙
파라미터 전달 시 “JSON → URI 인코딩 → Base64” 순서를 유지하고,
수신 시에는 “Base64 → URI 디코딩 → JSON 파싱” 순서를 지켜야 해요.
const KYC_TARGET_ORIGIN = "https://kyc.useb.co.kr";
const KYC_URL = "https://kyc.useb.co.kr/auth";
const params = {
access_token: "<access_token>",
name: "홍길동",
birthday: "1984-11-23",
phone_number: "01012345678",
email: "test@test.com",
};
const encodedParams = btoa(encodeURIComponent(JSON.stringify(params)));
3단계. 결과 받아 처리하기
1. 결과 데이터 파싱
웹 페이지에서 window.addEventListener("message")를 통해 결과를 수신해요.
이때 전달되는 데이터는 Base64 + URI 인코딩된 JSON 문자열이에요.
따라서 Base64 디코딩 → URI 디코딩 → JSON 파싱 순서로 처리해야 해요.
window.addEventListener("message", (e) => {
console.log("alcherakyc response", e.data); // base64 encoded된 JSON 메시지이므로 decoded해야 함(needs to be decoded becaused it`s encoded by base64)
console.log("origin :", e.origin);
try {
const decodedData = decodeURIComponent(atob(e.data));
console.log("decoded", decodedData);
const json = JSON.parse(decodedData);
console.log("json", json);
2. 결과 수신 방식
eKYC 인증 결과를 수신하는 방식은 두 가지 중 선택할 수 있어요.
1) postMessagepostMessage 방식은 결과 메시지를 프론트에서 그대로 받아서 처리하는 방식이에요.
2) postMessage + APIpostMessage + API 방식은 postMessage에서 전달받은 일부 값(id, result_type)을
바탕으로 서버에서 전체 결과를 조회해요.
API 방식은 보안을 강화할 수 있지만 아래와 같은 절차를 추가로 진행해야 해요.
- 유스비 담당자에게 문의하여 reviewer account 를 받아야 해요.
- reviewer account로 전달받은
customer_id,username,password로 API를 조회하여 결과 수신용 Access Token을 취득해요.
• 결과 수신용 Access Token 취득하기
-
[POST]
https://kyc-api-swagger.useb.co.kr/Request
{
"customer_id": 1,
"username": "samsungAdmin",
"password": "password123!"
}Response
{
"company": {
"name": "samsung",
"industry": 1,
"phone_number": "1500-0000"
},
"role": 1,
"name": "samsung_reviewer",
"username": "Reviewer0001",
"is_temp_password": true,
"token": "<token>",
"expire": "2022-01-06T11:41:42+09:00",
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
}
- 취득한 Access Token과 postMessage 값 중
id,result_type을 활용해 API를 호출해요.
• 서버에 API 호출해 전체 결과 받아오기
취득한 Access Token은 HTTP 요청의 Authorization 헤더에 적용해 주세요.
아래 내용을 확인해 result_type 에 해당하는 API를 호출하면 전체 결과를 확인할 수 있어요.
1: Automatic approval (자동승인대상)
2 : Automatic rejection (자동거부대상)
5 :Manual review target (수동심사대상)
- result_type = 1, "auto_approve" / result_type = 2, "auto_reject"
-
[GET]
https://kyc-api.useb.co.kr/review/results/{id}- "auto_approve" : 3회 안에 진위확인 성공시
- "auto_reject" : 3회 진위확인 실패시
- "auto_approve" : 3회 안에 진위확인 성공시
- result_type = 5, "wait_review"
-
[GET]
https://kyc-api.useb.co.kr/review/manuals/{id} - OCR 판독 후에 개인정보를 수정한 경우, 사본으로 판별된 경우 등등
- 수동심사 대상인 경우에도 마지막 화면의 문구 변경은 가능합니다.
-
[GET]
- get attachment file (EDD 강화된 고객확인 서비스 사용시)
-
[GET]
https://kyc-api.useb.co.kr/attachments/{id}
-
[GET]
3. 결과 처리 예제
파싱된 JSON의 result 값에 따라 분기 처리하시면 돼요. 예제는 콘솔 출력이지만, 실제 서비스에서는 화면 전환/알림/재시도/서버 검증 등 비즈니스 로직으로 연결하세요.
window.addEventListener("message", (e) => {
console.log("alcherakyc response", e.data); // base64 encoded된 JSON 메시지이므로 decoded해야 함(needs to be decoded becaused it`s encoded by base64)
console.log("origin :", e.origin);
try {
const decodedData = decodeURIComponent(atob(e.data));
console.log("decoded", decodedData);
const json = JSON.parse(decodedData);
console.log("json", json);
// 데이터처리 부분
if (json.result === "success") {
// TODO: KYC 인증을 성공한 경우 데이터 처리
// console.log(json.result + "결과 서버 저장");
} else if (json.result === "failed") {
// TODO: KYC 인증을 실패한 경우 데이터 처리
// console.log(json.result + "결과 서버 저장");
}
// UI 처리
else if (json.result === "complete") {
// TODO: KYC 인증을 성공(자동승인 or 심사필요 케이스 모두 포함) 후 UI 처리
// iframe이 포함된 UI를 종료
// 고객사 서비스 UI를 다시 띄우고 상황에 맞는 UI 표시
// 예시 : 자동승인 -> KYC인증이 완료되었습니다. 계좌개설이 완료되었습니다.
// 예시 : 심사필요 -> KYC인증이 완료되었습니다. 심사가 완료된 이후 이메일로 안내 드리겠습니다.
} else if (json.result === "close") {
// TODO: KYC 인증을 실패(자동거부 or 중도이탈) 후 UI 처리
// iframe이 포함된 UI를 종료
// 고객사 서비스 UI를 다시 띄우고 상황에 맞는 UI 표시
// 예시 : 자동거부 -> KYC인증이 실패하였습니다. 다시 인증을 시도후 서비스 이용이 가능합니다.
} else {
// invalid result
}
} catch (error) {
console.log("wrong data", error);
}
});
Q. postMessage로 받은 결과가 어떤 형식인지 모르겠어요.
ㄴ A. base64로 인코딩된 JSON 문자열이에요. 디코딩 후 JSON으로 파싱해야 실제 데이터를 볼 수 있어요.
Q. 결과 값 중 complete나 close는 어떤 의미인가요?
ㄴ A. complete는 인증은 완료되었지만 심사 중인 상태이고, close는 인증이 중단되었거나 자동 거부된 상태예요.
Q. 보안 강화를 위해 결과를 서버에서 받아올 수 있나요?
ㄴ A. 네. postMessage로 받은 id와 result_type을 이용해 API로 전체 결과를 조회할 수 있어요. 단, 서버에서 결과를 받으려면, 유스비 담당자에게 직접 문의해 reviewer 계정을 받아서 진행해야 해요.
Q. postMessage에 개인정보가 오는 게 보안상 이슈가 될 것 같아요.
ㄴ A. Admin에서 기타 설정 > 보안 설정 > [인증 결과 전송]을 ‘개인정보 미포함’으로 설정을 변경해야 postMessage에서 개인정보를 제외한 결과가 제공돼요. 이 경우, 엔드 유저의 개인정보를 API 호출을 통해 받아와야 하며, 자세한 방법은 이 문서의 3단계에 안내되어있는 postMessage + API 방식을 참고해 주세요.
연동 완료
정상적으로 인증 화면을 띄우고, 결과를 받아 처리했다면 연동이 잘 완료된 거예요.
운영 환경에 반영하기 전에 테스트 환경에서 브라우저별로 동작을 꼭 확인해 주세요.
-
QA 체크리스트
Q. 연동 테스트는 어떤 환경에서 해보는 게 좋나요?
ㄴ A. Chrome, Safari, 삼성 브라우저, 주요 인앱 브라우저 등 iframe이 지원되는 환경에서 테스트해 보세요.
Q. 인증 요청은 보냈는데 결과가 안 와요. 어디서 문제를 확인해야 하나요?
ㄴ A. 리스너가 등록되어 있는지, postMessage 수신이 정상적으로 동작하는지, 파라미터 값이 올바른지 순서대로 점검해 보세요.
앱 환경에 웹뷰로 연동하기
이 페이지에서는 네이티브 앱에서 WebView를 통해 eKYC 인증 화면을 연동하는 방법을 안내합니다.
앱 안에서 유스비 eKYC 인증 UI를 호출하려면 WebView 방식을 사용해 인증 페이지를 불러와야 합니다.
아래 가이드를 따라 앱에 인증 화면을 자연스럽게 연동해 주세요.
앱 언어별 가이드
샘플코드 다운로드 받기
React Native 앱에 연동하기 전 필수 세팅
앱에서 eKYC 인증을 사용하려면 카메라 권한과
네트워크 통신이 꼭 필요해요.
따라서 Android, iOS 환경 모두에서 권한 설정을 먼저 해주어야 WebView 안에서
카메라가 정상적으로 동작합니다.
1. JavaScript Packages 설치
React Native에서 WebView와 권한 처리를 위해 필요한 기본 Package를 먼저 설치해 주세요.
react-native-webview: WebView를 띄우기 위해 필수react-native-permissions: 카메라 권한 요청/체크 처리용
"dependencies": {
...
"react-native-permissions": "^5.4.2",
"react-native-webview": "^13.15.0"
...
}
2. Android 설정
Android는 Manifest 권한 선언과 런타임 권한 요청이 모두 필요해요.
이 권한이 있어야 카메라 화면을 열고, eKYC 서버와 통신할 수 있어요.
1) 권한 선언 — AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
2) 런타임 권한 요청
Android 6.0(Marshmallow) 이상에서는 실행 시점에 카메라 권한을 따로 요청해야 해요.
이 부분은 예제 코드에서 react-native-permissions 또는 PermissionsAndroid를 참고해 주세요.
3. iOS 설정
iOS는 Podfile 설정과 Info.plist 권한 문구를 설정해야 해요.
1) Podfile
Podfile에 react-native-permissions 스크립트를 추가하고, 필요한 권한만 활성화해 주세요.
아래의 코드를 적용하면 빌드 시 카메라 권한 핸들러가 포함됩니다.
def node_require(script)
# Resolve script with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
"require.resolve(
'#{script}',
{paths: [process.argv[1]]},
)", __dir__]).strip
end
node_require('react-native/scripts/react_native_pods.rb')
node_require('react-native-permissions/scripts/setup.rb')
setup_permissions([
'Camera',
])
2) Info.plist
권한 팝업에 표시될 안내 문구를 추가해 주세요.
문구는 서비스에 맞게 바꿀 수 있지만, 키 이름은 반드시 아래와 같아야 해요.
<key>NSCameraUsageDescription</key>
<string>카메라를 사용하여 사진을 촬영합니다.</string>
1단계. 인증 방식 정하기
고객사에서 유스비 eKYC 서버에 접근하기 위해서는 유스비의 고객사라는 것을 먼저 인증해야 해요.
이 때 인증하는 방식은 토큰 없이도 인증이 가능한 Credential과 토큰 발급이 필수적인 Access Token이 있어요. 고객사마다 각자의 보안 및 운영 목적에 맞는 방식을 선택해 인증을 진행하면 돼요.
- Credential → 테스트/PoC 용
- Access Token → 보편적인 운영용
1. Credential
메일로 전달받은 customer_id, id, key 값을 요청에 그대로 사용해요.
구조가 단순하지만 보안상 노출 위험이 있어 이 방식은 실제 운영 전 테스트, PoC 용도로 한정해 사용하는 것을 권장해요.
2. Access Token
서버 또는 클라이언트에서 Access Token을 먼저 발급받고, 해당 토큰으로 인증 요청을 보내요.
이 방식은 보안이 더 강하고, 토큰은 24시간 동안 유효해요.
Access Token을 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.
Access Token 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/sign-in
{
"customer_id": <customer_id>, //number, 고객사id
"username": "<id>", //string, client_id
"password": "<key>" //string, client_secret
}
Response
{
"api_response": {
"result_code": "N100",
"result_message": "OK."
},
"company": {
"name": "id",
"industry": 2,
"phone_number": "1500-0002"
},
"expire": "2022-08-17T11:10:29Z", // 생성 후 24시간 뒤에 만료됨
"is_temp_password": true,
"name": "",
"role": 2,
"token": "**<access_token>**", // **Access Token** 획득
"username": "<client_id>"
}
2단계. 요청 보내기
필수 설정을 완료했고, 유스비의 고객임을 인증할 인증 방식도 정했다면 이제 eKYC 인증 요청을 보낼 차례예요.
이 단계에서는 WebView를 초기화하고, 인증 페이지 URL을 로드한 뒤, 파라미터를 전달하는 과정을 진행해요.
요청을 보낼 때는 다음 항목들을 정해 두어야 해요.
- 인증 방식 (Credential / Access Token)
- 필수 정보 입력 방식 (고객사 자체 구현 (파라미터 전달, Transaction_id (심사 사전 등록) 전달)/ 유스비 제공 화면 사용)
- 다국어(영문) 지원 및 폰트 적용 여부
1. 리스너 등록하기
1) WebView에 리스너 등록
WebView에서 window.ReactNativeWebView.postMessage()로 보낸 메시지를 앱이 받을 수 있도록,
WebView의 onMessage 속성에 onReceivedWebViewMessage 메서드를 연결해요.
이렇게 등록해 두면 인증 화면에서 결과를 보낼 때, 앱 쪽 onReceivedWebViewMessage가 자동으로 호출되어 후속 처리(파싱/분기)를 진행할 수 있어요.
<WebView
...
onMessage={this.onReceivedWebViewMessage}
onLoadEnd={this.onWebViewLoadEnd}
/>
2) 결과를 수신하는 리스너 함수
WebView가 보낸 문자열을 받아 Base64 → URI 디코딩 → JSON 파싱 순서로 변환한 뒤,
doneProcessHandler로 넘기는 진입점이에요. (필요 시 messageName 등으로 메시지 타입을 먼저 확인하세요.)
/**
* 화면에서 post를 던지면 react-native에서 받음(Throw a post on the screen, you will receive it from react-native)
*/
onReceivedWebViewMessage = (event) => {
console.log("onReceivedWebViewMessage", event.nativeEvent.data);
const decodedMsg = decodeURIComponent(Base64.atob(event.nativeEvent.data));
let msgData;
try {
msgData = JSON.parse(decodedMsg) || {};
this.doneProcessHandler(msgData);
} catch (error) {
console.error(error);
return;
}
};
2. 카메라 권한 확인 및 WebView 로드하기
1) 카메라 권한 확인
eKYC 인증 과정에서는 카메라 촬영이 필요하므로, 앱 실행 중에 카메라 권한을 명시적으로 요청해야 해요.
카메라 권한을 확인하고 요청한 뒤, 권한이 허용되면 WebView 화면을 로드해요.
예제에서는 permissionsGranted가 true일 때만 WebView가 나타납니다.
handleCameraPermission = async () => {
if (Platform.OS === "android") {
// Calling the permission function
const result = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.CAMERA,
]);
if (result["android.permission.CAMERA"] === "granted") {
this.setPermissionsGranted(true);
} else {
this.setPermissionsGranted(false);
}
} else if (Platform.OS === "ios") {
const res = await checkMultiple([PERMISSIONS.IOS.CAMERA]);
if (res[PERMISSIONS.IOS.CAMERA] === RESULTS.GRANTED) {
this.setPermissionsGranted(true);
} else {
console.log("Need Permission");
const res2 = await requestMultiple([PERMISSIONS.IOS.CAMERA]);
console.log("Permission Status" + JSON.stringify(res2));
if (res2[PERMISSIONS.IOS.CAMERA] === RESULTS.GRANTED) {
this.setPermissionsGranted(true);
} else {
this.setPermissionsGranted(false);
}
}
}
};
setPermissionsGranted = (value) => {
console.log("setPermissionsGranted", value);
this.setState({ permissionsGranted: value });
};
2) WebView 로드
권한이 허용되면 WebView를 로드해요. 초기 URL은 this.domain + '?ver=1'로 설정된 indexPage를 WebView의 source에 사용해요.
render() {
return (
<SafeAreaView style={styles.container}>
{this.state.permissionsGranted && (
<WebView
style={styles.webview}
source={this.state.indexPage}
originWhitelist={['*']}
ref={webview => (this.appWebview = webview)}
javaScriptEnabled={true}
useWebKit={true}
mediaPlaybackRequiresUserAction={false}
domStorageEnabled={true}
allowsInlineMediaPlayback={true}
startInLoadingState={true}
allowUniversalAccessFromFileURLs={true}
onMessage={this.onReceivedWebViewMessage}
onLoadEnd={this.onWebViewLoadEnd}
/>
)}
{!this.state.permissionsGranted && (
<Text>
카메라/갤러리 접근 권한이 없습니다. 권한 허용 후 이용해주세요. // no
access authority for camera and gallery. check allowance of
authortiy.
</Text>
)}
</SafeAreaView>
);
}
3. 파라미터 조건 채우기
1) 인증 방식에 따른 인증 값 넣어주기 (필수)
1단계에서 미리 인증 방식을 결정한 상태이므로, 요청을 보내는 시점에서는 인증 방식에 따른 인증 값을 전달하면 돼요.
- Credential: 계정 정보 3가지
customer_id,id,key - Access Token:
Access Token
2) 필수 정보 입력 방식 정하기 (필수)
(1) 고객사 자체 구현
고객사에서 직접 구현한 화면을 통해 엔드 유저의 필수 정보를 입력받는 경우예요.
이 경우, 요청 시 엔드 유저에게서 받은 정보를 반드시 eKYC 서버로 전달해 주셔야 해요.
이 때, 정보를 파라미터로 직접 전달하거나 심사 사전 등록 방식을 통해 transaction_id 로 전달할 수도 있어요.
-
파라미터 전달 방식
-
Transaction (심사 사전 등록) 방식
Transaction (심사 사전 등록) 방식으로 전달하기
eKYC 인증을 위해 엔드 유저의 필수 개인 정보를 고객사에서 직접 수집하는 경우, 해당 정보를 전달하는 과정에 보안을 강화할 수 있는 인증 방식이에요. Access Token으로 먼저 인증 정보를 서버에 등록하고, 받은
transaction_id로 인증을 진행해요.인증 요청 전에 정보를 서버에서 설정하기 때문에 클라이언트에 민감한 정보가 노출되지 않아 보안적으로 더 안전해요. 이 방식은 Access Token을 먼저 발급받은 후
/verificationsAPI를 통해 사용할 수 있어요.Transaction_id를 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.Transaction_id 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/verfications
{
"name": "홍길동",
"birthday": "1981-11-23",
"phone_number": "01012345678",
"email": "test@test.com"
}Response
{
"form": {
"transaction_id": "1754035720510123456-6126383872156123456",
"progress": {
"is_id_card_checked": false,
"is_account_checked": false,
"is_face_checked": null,
"is_custom_field_checked": null,
"is_edd_field_checked": null
},
"module": {
"id_card_ocr": true,
"id_card_verification": true,
"face_authentication": false,
"account_verification": true,
"liveness": false,
"custom_field": false,
"edd_field": false
}
},
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
} -
[POST]
(2) 유스비 화면 사용
유스비 eKYC 인증 화면에서 엔드 유저 정보를 입력받도록 위임하는 경우예요.
이 경우, 유스비 Admin에서 설정을 변경해 주어야 해요.
설정 위치: Admin > 기타 설정 > 개인정보 옵션에서 [사용자 필수 정보 수신]을 미사용으로 선택해 주세요.
3) 다국어 (영문) 지원 및 폰트 적용 여부 (선택)
다국어(영문) 지원과 폰트 (나눔 고딕) 적용 여부를 선택할 수 있어요.
별도로 파라미터를 전달하지 않으면, 기본 설정값은 한국어, Pretendard로 적용하여 제공돼요.
4. 요청 시 파라미터 예제
아래 코드는 Access Token + 자체 구현 + 다국어 On + 폰트 On 조건일 때의 파라미터 예제예요.
onWebViewLoadEnd = () => {
console.log("onWebViewLoadEnd");
const customer_id = "2"; // all
let params = {
access_token: "<access_token>",
};
params.name = "홍길동";
params.birthday = "1988-01-01";
params.phone_number = "01012341234";
params.email = "test@test.com";
params.font = "Nanum Gothic";
params.language = "en";
};
고객사별 상황에 딱 맞는 예제는 다음 페이지인 ‘예제로 바로 적용하기’에서 만들어 볼 수 있어요.
5. 인코딩 규칙
파라미터 전달 시 “JSON → URI 인코딩 → Base64” 순서를 유지하고,
수신 시에는 “Base64 → URI 디코딩 → JSON 파싱” 순서를 지켜야 해요.
웹/앱 양쪽 인코딩 규칙이 다르면 파싱 오류가 발생해요.
1) 인증 파라미터를 구성하고 인코딩한 뒤 WebView로 전송 준비하기
onWebViewLoadEnd = () => {
console.log("onWebViewLoadEnd");
const customer_id = "2"; // all
let params = {
access_token: "<access_token>",
};
params.name = "홍길동";
params.birthday = "1988-01-01";
params.phone_number = "01012341234";
params.email = "test@test.com";
let encodedParams = Base64.btoa(encodeURIComponent(JSON.stringify(params)));
this.sendWebViewPostMessage(encodedParams);
};
2) 인코딩된 파라미터를 WebView로 실제 전송하기
/**
* 화면에서 post를 던지면 react-native에서 받음(Throw a post on the screen, you will receive it from react-native)
*/
sendWebViewPostMessage = (message) => {
console.log("sendWebViewPostMessage", message);
// console.log("sendWebViewPostMessage (decoded)", decodeURIComponent(Base64.atob(message)));
this.appWebview.postMessage(message);
};
3) Base64 인코딩/디코딩을 지원하는 유틸리티 함수 정의
const chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
const Base64 = {
btoa: (input = "") => {
let str = input;
let output = "";
for (
let block = 0, charCode, i = 0, map = chars;
str.charAt(i | 0) || ((map = "="), i % 1);
output += map.charAt(63 & (block >> (8 - (i % 1) * 8)))
) {
charCode = str.charCodeAt((i += 3 / 4));
if (charCode > 0xff) {
throw new Error(
"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
);
}
block = (block << 8) | charCode;
}
return output;
},
atob: (input = "") => {
let str = input.replace(/[=]+$/, "");
let output = "";
if (str.length % 4 == 1) {
throw new Error(
"'atob' failed: The string to be decoded is not correctly encoded."
);
}
for (
let bc = 0, bs = 0, buffer, i = 0;
(buffer = str.charAt(i++));
~buffer && ((bs = bc % 4 ? bs * 64 + buffer : buffer), bc++ % 4)
? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
: 0
) {
buffer = chars.indexOf(buffer);
}
return output;
},
};
3단계. 결과 받아 처리하기
1. 결과 데이터 파싱
인증 화면에서 전달하는 결과는 문자열 형태로 들어오며, Base64와 URI 인코딩이 적용돼 있어요.
onReceivedWebViewMessage에서 이 문자열을 Base64 디코딩 → URI 디코딩 → JSON 파싱 순서로 변환하면, 최종 결과 값(result 등)을 안전하게 확인하고 이후 로직에 사용할 수 있어요.
onReceivedWebViewMessage = (event) => {
console.log("onReceivedWebViewMessage", event.nativeEvent.data);
const decodedMsg = decodeURIComponent(Base64.atob(event.nativeEvent.data));
let msgData;
try {
msgData = JSON.parse(decodedMsg) || {};
this.doneProcessHandler(msgData);
} catch (error) {
console.error(error);
return;
}
};
2. 결과 수신 방식
eKYC 인증 결과를 수신하는 방식은 두 가지 중 선택할 수 있어요.
postMessage 방식은 결과 메시지를 프론트에서 그대로 받아서 처리하는 방식이에요.
2) postMessage + APIpostMessage + API 방식은 postMessage에서 전달받은 일부 값(id, result_type)을
바탕으로 서버에서 전체 결과를 조회해요.
API 방식은 보안을 강화할 수 있지만 아래와 같은 절차를 추가로 진행해야 해요.
- 유스비 담당자에게 문의하여 reviewer account 를 받아야 해요.
- reviewer account로 전달받은
customer_id,username,password로 API를 조회하여 결과 수신용 Access Token을 취득해요.
• 결과 수신용 Access Token 취득하기
-
[POST]
https://kyc-api-swagger.useb.co.kr/Request
{
"customer_id": 1,
"username": "samsungAdmin",
"password": "password123!"
}Response
{
"company": {
"name": "samsung",
"industry": 1,
"phone_number": "1500-0000"
},
"role": 1,
"name": "samsung_reviewer",
"username": "Reviewer0001",
"is_temp_password": true,
"token": "<token>",
"expire": "2022-01-06T11:41:42+09:00",
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
}
- 취득한 Access Token과 postMessage 값 중
id,result_type을 활용해 API를 호출해요.
• 서버에 API 호출해 전체 결과 받아오기
취득한 Access Token은 HTTP 요청의 Authorization 헤더에 적용해 주세요.
아래 내용을 확인해 result_type 에 해당하는 API를 호출하면 전체 결과를 확인할 수 있어요.
1: Automatic approval (자동승인대상)
2 : Automatic rejection (자동거부대상)
5 :Manual review target (수동심사대상)
- result_type = 1, "auto_approve" / result_type = 2, "auto_reject"
-
[GET]
https://kyc-api.useb.co.kr/review/results/{id}- "auto_approve" : 3회 안에 진위확인 성공시
- "auto_reject" : 3회 진위확인 실패시
- "auto_approve" : 3회 안에 진위확인 성공시
- result_type = 5, "wait_review"
-
[GET]
https://kyc-api.useb.co.kr/review/manuals/{id} - OCR 판독 후에 개인정보를 수정한 경우, 사본으로 판별된 경우 등등
- 수동심사 대상인 경우에도 마지막 화면의 문구 변경은 가능합니다.
-
[GET]
- get attachment file (EDD 강화된 고객확인 서비스 사용시)
-
[GET]
https://kyc-api.useb.co.kr/attachments/{id}
-
[GET]
3. 결과 처리 예제
파싱된 JSON의 result 값에 따라 분기 처리하시면 돼요. 예제는 콘솔 출력이지만, 실제 서비스에서는 화면 전환/알림/재시도/서버 검증 등 비즈니스 로직으로 연결하세요.
doneProcessHandler = (msgData) => {
if (msgData?.result) {
const resultData = msgData.result;
switch (resultData) {
case "success":
console.log("success - KYC 작업이 성공했습니다.");
break;
case "failed":
console.log("failed - KYC 작업이 실패했습니다.");
break;
case "complete":
console.log("complete - KYC가 완료되었습니다.");
break;
case "close":
console.log("close - KYC가 완료되지 않았습니다.");
break;
default:
console.log("알 수 없는 결과:", resultData);
break;
}
}
};
Q. postMessage와 receive 함수는 어떻게 연결되나요?
ㄴ A. 웹에서 지정한
인터페이스 이름(alcherakyc)과 @JavascriptInterface가 연결 고리 역할을 해요.
Q. result 값은 어디서 확인하나요?
ㄴ A. JSON 데이터 안의 result 필드에서 확인해요.
Q. postMessage로 받은 결과가 어떤 형식인지 모르겠어요.
ㄴ A. base64로 인코딩된 JSON 문자열이에요. 디코딩 후 JSON으로 파싱해야 실제 데이터를 볼 수 있어요.
연동 완료
인증 화면을 띄우고, 결과까지 정상적으로 받아 처리했다면 연동이 완료된 거예요.
운영 환경에 반영하기 전에는 다양한 기기와 브라우저 환경에서 QA 테스트를 꼭 진행해 주세요.
샘플코드 다운로드 받기
React Native 앱에 연동하기 전 필수 세팅
앱에서 eKYC 인증을 사용하려면 카메라 권한과
네트워크 통신이 꼭 필요해요.
따라서 Android, iOS 환경 모두에서 권한 설정을 먼저 해주어야 WebView 안에서
카메라가 정상적으로 동작합니다.
1. JavaScript Packages 설치
React Native에서 WebView와 권한 처리를 위해 필요한 기본 Package를 먼저 설치해 주세요.
react-native-webview: WebView를 띄우기 위해 필수react-native-permissions: 카메라 권한 요청/체크 처리용
"dependencies": {
...
"react-native-permissions": "^5.4.2",
"react-native-webview": "^13.15.0"
...
}
2. Android 설정
Android는 Manifest 권한 선언과 런타임 권한 요청이 모두 필요해요.
이 권한이 있어야 카메라 화면을 열고, eKYC 서버와 통신할 수 있어요.
1) 권한 선언 — AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
2) 런타임 권한 요청
Android 6.0(Marshmallow) 이상에서는 실행 시점에 카메라 권한을 따로 요청해야 해요.
이 부분은 예제 코드에서 react-native-permissions 또는 PermissionsAndroid를 참고해 주세요.
3. iOS 설정
iOS는 Podfile 설정과 Info.plist 권한 문구를 설정해야 해요.
1) Podfile
Podfile에 react-native-permissions 스크립트를 추가하고, 필요한 권한만 활성화해 주세요.
아래의 코드를 적용하면 빌드 시 카메라 권한 핸들러가 포함됩니다.
def node_require(script)
# Resolve script with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
"require.resolve(
'#{script}',
{paths: [process.argv[1]]},
)", __dir__]).strip
end
node_require('react-native/scripts/react_native_pods.rb')
node_require('react-native-permissions/scripts/setup.rb')
setup_permissions([
'Camera',
])
2) Info.plist
권한 팝업에 표시될 안내 문구를 추가해 주세요.
문구는 서비스에 맞게 바꿀 수 있지만, 키 이름은 반드시 아래와 같아야 해요.
<key>NSCameraUsageDescription</key>
<string>카메라를 사용하여 사진을 촬영합니다.</string>
1단계. 인증 방식 정하기
고객사에서 유스비 eKYC 서버에 접근하기 위해서는 유스비의 고객사라는 것을 먼저 인증해야 해요.
이 때 인증하는 방식은 토큰 없이도 인증이 가능한 Credential과 토큰 발급이 필수적인 Access Token이 있어요. 고객사마다 각자의 보안 및 운영 목적에 맞는 방식을 선택해 인증을 진행하면 돼요.
- Credential → 테스트/PoC 용
- Access Token → 보편적인 운영용
1. Credential
메일로 전달받은 customer_id, id, key 값을 요청에 그대로 사용해요.
구조가 단순하지만 보안상 노출 위험이 있어 이 방식은 실제 운영 전 테스트, PoC 용도로 한정해 사용하는 것을 권장해요.
2. Access Token
서버 또는 클라이언트에서 Access Token을 먼저 발급받고, 해당 토큰으로 인증 요청을 보내요.
이 방식은 보안이 더 강하고, 토큰은 24시간 동안 유효해요.
Access Token을 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.
Access Token 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/sign-in
{
"customer_id": <customer_id>, //number, 고객사id
"username": "<id>", //string, client_id
"password": "<key>" //string, client_secret
}
Response
{
"api_response": {
"result_code": "N100",
"result_message": "OK."
},
"company": {
"name": "id",
"industry": 2,
"phone_number": "1500-0002"
},
"expire": "2022-08-17T11:10:29Z", // 생성 후 24시간 뒤에 만료됨
"is_temp_password": true,
"name": "",
"role": 2,
"token": "**<access_token>**", // **Access Token** 획득
"username": "<client_id>"
}
2단계. 요청 보내기
필수 설정을 완료했고, 유스비의 고객임을 인증할 인증 방식도 정했다면 이제 eKYC 인증 요청을 보낼 차례예요.
이 단계에서는 WebView를 초기화하고, 인증 페이지 URL을 로드한 뒤, 파라미터를 전달하는 과정을 진행해요.
요청을 보낼 때는 다음 항목들을 정해 두어야 해요.
- 인증 방식 (Credential / Access Token)
- 필수 정보 입력 방식 (고객사 자체 구현 (파라미터 전달, Transaction_id (심사 사전 등록) 전달)/ 유스비 제공 화면 사용)
- 다국어(영문) 지원 및 폰트 적용 여부
1. 리스너 등록하기
1) WebView에 리스너 등록
WebView에서 window.ReactNativeWebView.postMessage()로 보낸 메시지를 앱이 받을 수 있도록,
WebView의 onMessage 속성에 onReceivedWebViewMessage 메서드를 연결해요.
이렇게 등록해 두면 인증 화면에서 결과를 보낼 때, 앱 쪽 onReceivedWebViewMessage가 자동으로 호출되어 후속 처리(파싱/분기)를 진행할 수 있어요.
<WebView
style={styles.webview}
source={this.state.indexPage}
originWhitelist={["*"]}
ref={(webview) => (this.appWebview = webview)}
javaScriptEnabled={true}
useWebKit={true}
mediaPlaybackRequiresUserAction={false}
domStorageEnabled={true}
allowsInlineMediaPlayback={true}
startInLoadingState={true}
allowUniversalAccessFromFileURLs={true}
onMessage={this.onReceivedWebViewMessage}
onLoadEnd={this.onWebViewLoadEnd}
/>
2) 결과를 수신하는 리스너 함수
WebView가 보낸 문자열을 받아 Base64 → URI 디코딩 → JSON 파싱 순서로 변환한 뒤,
doneProcessHandler로 넘기는 진입점이에요. (필요 시 messageName 등으로 메시지 타입을 먼저 확인하세요.)
/**
* 화면에서 post를 던지면 react-native에서 받음(Throw a post on the screen, you will receive it from react-native)
*/
onReceivedWebViewMessage = (event) => {
console.log("onReceivedWebViewMessage", event.nativeEvent.data);
const decodedMsg = decodeURIComponent(Base64.atob(event.nativeEvent.data));
let msgData;
try {
msgData = JSON.parse(decodedMsg) || {};
this.doneProcessHandler(msgData);
} catch (error) {
console.error(error);
return;
}
};
2. 카메라 권한 확인 및 WebView 로드하기
1) 카메라 권한 확인
eKYC 인증 과정에서는 카메라 촬영이 필요하므로, 앱 실행 중에 카메라 권한을 명시적으로 요청해야 해요.
카메라 권한을 확인하고 요청한 뒤, 권한이 허용되면 WebView 화면을 로드해요.
예제에서는 permissionsGranted가 true일 때만 WebView가 나타납니다.
handleCameraPermission = async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
console.log(status);
if (status === "granted") {
this.setPermissionsGranted(true);
}
};
setPermissionsGranted = (value) => {
console.log("setPermissionsGranted", value);
this.setState({ permissionsGranted: value });
};
2) WebView 로드
권한이 허용되면 WebView를 로드해요. 초기 URL은 this.domain + '?ver=1'로 설정된 indexPage를 WebView의 source에 사용해요.
{
this.state.permissionsGranted && (
<WebView
style={styles.webview}
source={this.state.indexPage}
originWhitelist={["*"]}
ref={(webview) => (this.appWebview = webview)}
javaScriptEnabled={true}
useWebKit={true}
mediaPlaybackRequiresUserAction={false}
domStorageEnabled={true}
allowsInlineMediaPlayback={true}
startInLoadingState={true}
allowUniversalAccessFromFileURLs={true}
onMessage={this.onReceivedWebViewMessage}
onLoadEnd={this.onWebViewLoadEnd}
/>
);
}
{
!this.state.permissionsGranted && (
<Text>
카메라/갤러리 접근 권한이 없습니다. 권한 허용 후 이용해주세요. // no
access authority for camera and gallery. check allowance of authortiy.
</Text>
);
}
3. 파라미터 조건 채우기
1) 인증 방식에 따른 인증 값 넣어주기 (필수)
1단계에서 미리 인증 방식을 결정한 상태이므로, 요청을 보내는 시점에서는 인증 방식에 따른 인증 값을 전달하면 돼요.
- Credential: 계정 정보 3가지
customer_id,id,key - Access Token:
Access Token
2) 필수 정보 입력 방식 정하기 (필수)
(1) 고객사 자체 구현
고객사에서 직접 구현한 화면을 통해 엔드 유저의 필수 정보를 입력받는 경우예요.
이 경우, 요청 시 엔드 유저에게서 받은 정보를 반드시 eKYC 서버로 전달해 주셔야 해요.
이 때, 정보를 파라미터로 직접 전달하거나 심사 사전 등록 방식을 통해 transaction_id 로 전달할 수도 있어요.
-
파라미터 전달 방식
-
Transaction (심사 사전 등록) 방식
Transaction (심사 사전 등록) 방식으로 전달하기
eKYC 인증을 위해 엔드 유저의 필수 개인 정보를 고객사에서 직접 수집하는 경우, 해당 정보를 전달하는 과정에 보안을 강화할 수 있는 인증 방식이에요. Access Token으로 먼저 인증 정보를 서버에 등록하고, 받은
transaction_id로 인증을 진행해요.인증 요청 전에 정보를 서버에서 설정하기 때문에 클라이언트에 민감한 정보가 노출되지 않아 보안적으로 더 안전해요. 이 방식은 Access Token을 먼저 발급받은 후
/verificationsAPI를 통해 사용할 수 있어요.Transaction_id를 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.Transaction_id 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/verfications
{
"name": "홍길동",
"birthday": "1981-11-23",
"phone_number": "01012345678",
"email": "test@test.com"
}Response
{
"form": {
"transaction_id": "1754035720510123456-6126383872156123456",
"progress": {
"is_id_card_checked": false,
"is_account_checked": false,
"is_face_checked": null,
"is_custom_field_checked": null,
"is_edd_field_checked": null
},
"module": {
"id_card_ocr": true,
"id_card_verification": true,
"face_authentication": false,
"account_verification": true,
"liveness": false,
"custom_field": false,
"edd_field": false
}
},
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
} -
[POST]
(2) 유스비 화면 사용
유스비 eKYC 인증 화면에서 엔드 유저 정보를 입력받도록 위임하는 경우예요.
이 경우, 유스비 Admin에서 설정을 변경해 주어야 해요.
설정 위치: Admin > 기타 설정 > 개인정보 옵션에서 [사용자 필수 정보 수신]을 미사용으로 선택해 주세요.
3) 다국어 (영문) 지원 및 폰트 적용 여부 (선택)
다국어(영문) 지원과 폰트 (나눔 고딕) 적용 여부를 선택할 수 있어요.
별도로 파라미터를 전달하지 않으면, 기본 설정값은 한국어, Pretendard로 적용하여 제공돼요.
4. 요청 시 파라미터 예제
아래 코드는 Access Token + 자체 구현 + 다국어 On + 폰트 On 조건일 때의 파라미터 예제예요.
onWebViewLoadEnd = () => {
console.log("onWebViewLoadEnd");
const customer_id = "2"; // all
let params = {
access_token: "<access_token>",
id: "demoUser",
key: "demoUser0000!",
};
params.name = "홍길동";
params.birthday = "1988-01-01";
params.phone_number = "01012341234";
params.email = "test@test.com";
params.font = "Nanum Gothic";
params.language = "en";
// (인코딩/전송은 다음 절에서 이어집니다)
};
고객사별 상황에 딱 맞는 예제는 다음 페이지인 ‘예제로 바로 적용하기’에서 만들어 볼 수 있어요.
5. 인코딩 규칙
파라미터 전달 시 “JSON → URI 인코딩 → Base64” 순서를 유지하고,
수신 시에는 “Base64 → URI 디코딩 → JSON 파싱” 순서를 지켜야 해요.
웹/앱 양쪽 인코딩 규칙이 다르면 파싱 오류가 발생해요.
1) 인증 파라미터를 구성하고 인코딩한 뒤 WebView로 전송 준비하기
onWebViewLoadEnd = () => {
console.log("onWebViewLoadEnd");
const customer_id = "2"; // all
let params = {
access_token: "<access_token>",
};
params.name = "홍길동";
params.birthday = "1988-01-01";
params.phone_number = "01012341234";
params.email = "test@test.com";
let encodedParams = Base64.btoa(encodeURIComponent(JSON.stringify(params)));
this.sendWebViewPostMessage(encodedParams);
};
2) 인코딩된 파라미터를 WebView로 실제 전송하기
/**
* 화면에서 post를 던지면 react-native에서 받음(Throw a post on the screen, you will receive it from react-native)
*/
sendWebViewPostMessage = (message) => {
console.log("sendWebViewPostMessage", message);
// console.log("sendWebViewPostMessage (decoded)", decodeURIComponent(Base64.atob(message)));
this.appWebview.postMessage(message);
};
3) Base64 인코딩/디코딩을 지원하는 유틸리티 함수 정의
const chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
const Base64 = {
btoa: (input = "") => {
let str = input;
let output = "";
for (
let block = 0, charCode, i = 0, map = chars;
str.charAt(i | 0) || ((map = "="), i % 1);
output += map.charAt(63 & (block >> (8 - (i % 1) * 8)))
) {
charCode = str.charCodeAt((i += 3 / 4));
if (charCode > 0xff) {
throw new Error(
"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
);
}
block = (block << 8) | charCode;
}
return output;
},
atob: (input = "") => {
let str = input.replace(/[=]+$/, "");
let output = "";
if (str.length % 4 == 1) {
throw new Error(
"'atob' failed: The string to be decoded is not correctly encoded."
);
}
for (
let bc = 0, bs = 0, buffer, i = 0;
(buffer = str.charAt(i++));
~buffer && ((bs = bc % 4 ? bs * 64 + buffer : buffer), bc++ % 4)
? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
: 0
) {
buffer = chars.indexOf(buffer);
}
return output;
},
};
3단계. 결과 받아 처리하기
1. 결과 데이터 파싱
인증 화면에서 전달하는 결과는 문자열 형태로 들어오며, Base64와 URI 인코딩이 적용돼 있어요.
onReceivedWebViewMessage에서 이 문자열을 Base64 디코딩 → URI 디코딩 → JSON 파싱 순서로 변환하면, 최종 결과 값(result 등)을 안전하게 확인하고 이후 로직에 사용할 수 있어요.
/**
* 화면에서 post를 던지면 react-native에서 받음(Throw a post on the screen, you will receive it from react-native)
*/
onReceivedWebViewMessage = (event) => {
const decodedMsg = decodeURIComponent(Base64.atob(event.nativeEvent.data));
let msgData;
try {
msgData = JSON.parse(decodedMsg) || {};
this.doneProcessHandler(msgData);
} catch (error) {
console.error(error);
return;
}
};
2. 결과 수신 방식
eKYC 인증 결과를 수신하는 방식은 두 가지 중 선택할 수 있어요.
postMessage 방식은 결과 메시지를 프론트에서 그대로 받아서 처리하는 방식이에요.
2) postMessage + APIpostMessage + API 방식은 postMessage에서 전달받은 일부 값(id, result_type)을
바탕으로 서버에서 전체 결과를 조회해요.
API 방식은 보안을 강화할 수 있지만 아래와 같은 절차를 추가로 진행해야 해요.
- 유스비 담당자에게 문의하여 reviewer account 를 받아야 해요.
- reviewer account로 전달받은
customer_id,username,password로 API를 조회하여 결과 수신용 Access Token을 취득해요.
• 결과 수신용 Access Token 취득하기
-
[POST]
https://kyc-api-swagger.useb.co.kr/Request
{
"customer_id": 1,
"username": "samsungAdmin",
"password": "password123!"
}Response
{
"company": {
"name": "samsung",
"industry": 1,
"phone_number": "1500-0000"
},
"role": 1,
"name": "samsung_reviewer",
"username": "Reviewer0001",
"is_temp_password": true,
"token": "<token>",
"expire": "2022-01-06T11:41:42+09:00",
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
}
- 취득한 Access Token과 postMessage 값 중
id,result_type을 활용해 API를 호출해요.
• 서버에 API 호출해 전체 결과 받아오기
취득한 Access Token은 HTTP 요청의 Authorization 헤더에 적용해 주세요.
아래 내용을 확인해 result_type 에 해당하는 API를 호출하면 전체 결과를 확인할 수 있어요.
1: Automatic approval (자동승인대상)
2 : Automatic rejection (자동거부대상)
5 :Manual review target (수동심사대상)
- result_type = 1, "auto_approve" / result_type = 2, "auto_reject"
-
[GET]
https://kyc-api.useb.co.kr/review/results/{id}- "auto_approve" : 3회 안에 진위확인 성공시
- "auto_reject" : 3회 진위확인 실패시
- "auto_approve" : 3회 안에 진위확인 성공시
- result_type = 5, "wait_review"
-
[GET]
https://kyc-api.useb.co.kr/review/manuals/{id} - OCR 판독 후에 개인정보를 수정한 경우, 사본으로 판별된 경우 등등
- 수동심사 대상인 경우에도 마지막 화면의 문구 변경은 가능합니다.
-
[GET]
- get attachment file (EDD 강화된 고객확인 서비스 사용시)
-
[GET]
https://kyc-api.useb.co.kr/attachments/{id}
-
[GET]
3. 결과 처리 예제
파싱된 JSON의 result 값에 따라 분기 처리하시면 돼요. 예제는 콘솔 출력이지만, 실제 서비스에서는 화면 전환/알림/재시도/서버 검증 등 비즈니스 로직으로 연결하세요.
doneProcessHandler = (msgData) => {
if (msgData?.result) {
const resultData = msgData.result;
switch (resultData) {
case "success":
console.log("success - KYC 작업이 성공했습니다.");
break;
case "failed":
console.log("failed - KYC 작업이 실패했습니다.");
break;
case "complete":
console.log("complete - KYC가 완료되었습니다.");
break;
case "close":
console.log("close - KYC가 완료되지 않았습니다.");
break;
default:
console.log("알 수 없는 결과:", resultData);
break;
}
}
};
Q. postMessage와 receive 함수는 어떻게 연결되나요?
ㄴ A. 웹에서 지정한
인터페이스 이름(alcherakyc)과 @JavascriptInterface가 연결 고리 역할을 해요.
Q. result 값은 어디서 확인하나요?
ㄴ A. JSON 데이터 안의 result 필드에서 확인해요.
Q. postMessage로 받은 결과가 어떤 형식인지 모르겠어요.
ㄴ A. base64로 인코딩된 JSON 문자열이에요. 디코딩 후 JSON으로 파싱해야 실제 데이터를 볼 수 있어요.
연동 완료
인증 화면을 띄우고, 결과까지 정상적으로 받아 처리했다면 연동이 완료된 거예요.
운영 환경에 반영하기 전에는 다양한 기기와 브라우저 환경에서 QA 테스트를 꼭 진행해 주세요.
샘플코드 다운로드 받기
iOS 앱에 연동하기 전 필수 세팅
카메라 권한
카메라를 사용하는 모든 iOS 앱은 Info.plist에 아래 키를 꼭 넣어야 해요.
key: Privacy - Camera Usage Description
value: 신분증 및 본인 확인을 위해 카메라를 사용합니다. (고객이 원하는대로 변경, UI나 alert에 어차피 표시 안됨)
1단계. 인증 방식 정하기
고객사에서 유스비 eKYC 서버에 접근하기 위해서는 유스비의 고객사라는 것을 먼저 인증해야 해요.
이 때 인증하는 방식은 토큰 없이도 인증이 가능한 Credential과 토큰 발급이 필수적인 Access Token이 있어요. 고객사마다 각자의 보안 및 운영 목적에 맞는 방식을 선택해 인증을 진행하면 돼요.
- Credential → 테스트/PoC 용
- Access Token → 보편적인 운영용
1. Credential
메일로 전달받은 customer_id, id, key 값을 요청에 그대로 사용해요.
구조가 단순하지만 보안상 노출 위험이 있어 이 방식은 실제 운영 전 테스트, PoC 용도로 한정해 사용하는 것을 권장해요.
2. Access Token
서버 또는 클라이언트에서 Access Token을 먼저 발급받고, 해당 토큰으로 인증 요청을 보내요.
이 방식은 보안이 더 강하고, 토큰은 24시간 동안 유효해요.
Access Token을 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.
Access Token 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/sign-in
{
"customer_id": <customer_id>, //number, 고객사id
"username": "<id>", //string, client_id
"password": "<key>" //string, client_secret
}
Response
{
"api_response": {
"result_code": "N100",
"result_message": "OK."
},
"company": {
"name": "id",
"industry": 2,
"phone_number": "1500-0002"
},
"expire": "2022-08-17T11:10:29Z", // 생성 후 24시간 뒤에 만료됨
"is_temp_password": true,
"name": "",
"role": 2,
"token": "**<access_token>**", // **Access Token** 획득
"username": "<client_id>"
}
2단계. 요청 보내기
카메라 필수 권한도 추가했고, 유스비의 고객임을 인증할 인증 방식도 정했다면 이제 eKYC 인증 요청을 보낼 차례예요.
이 단계에서는 WKWebView를 초기화하고, 인증 페이지 URL을 로드한 뒤, 파라미터를 전달하는 과정을 진행해요.
요청을 보낼 때는 다음 항목들을 정해 두어야 해요.
- 인증 방식 (Credential / Access Token)
- 필수 정보 입력 방식 (고객사 자체 구현 (파라미터 전달, Transaction_id (심사 사전 등록) 전달)/ 유스비 제공 화면 사용)
- 다국어(영문) 지원 및 폰트 적용 여부
1. 리스너 등록하기
WKUserScript로 요청 데이터를 담은 postMessage를 웹 문서 로딩 시점에 삽입해요.
동시에 userContentController.add(self, name: responseName)으로 리스너(핸들러)를 등록해, 웹에서 보내는 메시지를 앱이 바로 수신할 수 있게 준비해요.
/* View 불러오기 */
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.allowsInlineMediaPlayback = true
// 엔드 유저의 정보를 담은 postMessage 설정
if let requestData = encodedPostMessage() {
let userScript = WKUserScript(
source: "postMessage('\(requestData)')",
injectionTime: .atDocumentEnd,
forMainFrameOnly: true
)
webConfiguration.userContentController.addUserScript(userScript)
webConfiguration.preferences.javaScriptEnabled = true
}
// 메시지 수신할 핸들러 등록
webConfiguration.userContentController.add(self, name: responseName)
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
2. 카메라 권한 확인 및 WebView 로드하기
1) 카메라 권한 확인
viewWillAppear에서 권한을 확인해요. 허용이면 곧바로 loadWebView()로 인증 화면을 띄우고, 거부면 안내 Alert, 미정이면 권한 요청 후 허용 시에만 로드해요.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
checkCameraPermission()
navigationController?.isNavigationBarHidden = false
}
/* Camera 권한 체크 */
func checkCameraPermission() {
let permission = AVCaptureDevice.authorizationStatus(for: .video)
switch permission {
case .authorized:
DispatchQueue.main.async { self.loadWebView() }
case .denied:
let alert = UIAlertController(title: "카메라 권한 필요",
message: "설정 > 개인 정보 보호 > 카메라에서 권한을 변경하실 수 있습니다.",
preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(okAction)
present(alert, animated: false, completion: nil)
return
case .notDetermined:
// 권한 요청
AVCaptureDevice.requestAccess(for: .video) { granted in
if granted {
DispatchQueue.main.async { self.loadWebView() }
} else {
NSLog("권한이 거부되었습니다.")
self.navigationController?.popViewController(animated: true)
}
}
default:
NSLog("Permission = \(permission.rawValue)")
}
}
2) WebView 로드
권한이 허용되면 eKYC 인증 페이지 URL을 WebView에 로드해요. 이 호출이 성공하면 사용자에게 eKYC 화면이 표시돼요.
/* WebView 불러오기 */
func loadWebView() {
guard let url = URL(string: "https://kyc.useb.co.kr/auth") else { return }
let request = URLRequest(url: url)
webView.load(request)
}
3. 파라미터 조건 채우기
1) 인증 방식에 따른 인증 값 넣어주기 (필수)
1단계에서 미리 인증 방식을 결정한 상태이므로, 요청을 보내는 시점에서는 인증 방식에 따른 인증 값을 전달하면 돼요.
- Credential: 계정 정보 3가지
customer_id,id,key - Access Token:
Access Token
2) 필수 정보 입력 방식 정하기 (필수)
(1) 고객사 자체 구현
고객사에서 직접 구현한 화면을 통해 엔드 유저의 필수 정보를 입력받는 경우예요.
이 경우, 요청 시 엔드 유저에게서 받은 정보를 반드시 eKYC 서버로 전달해 주셔야 해요.
이 때, 정보를 파라미터로 직접 전달하거나 심사 사전 등록 방식을 통해 transaction_id 로 전달할 수도 있어요.
-
파라미터 전달 방식
-
Transaction (심사 사전 등록) 방식
Transaction (심사 사전 등록) 방식으로 전달하기
eKYC 인증을 위해 엔드 유저의 필수 개인 정보를 고객사에서 직접 수집하는 경우, 해당 정보를 전달하는 과정에 보안을 강화할 수 있는 인증 방식이에요. Access Token으로 먼저 인증 정보를 서버에 등록하고, 받은
transaction_id로 인증을 진행해요.인증 요청 전에 정보를 서버에서 설정하기 때문에 클라이언트에 민감한 정보가 노출되지 않아 보안적으로 더 안전해요. 이 방식은 Access Token을 먼저 발급받은 후
/verificationsAPI를 통해 사용할 수 있어요.Transaction_id를 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.Transaction_id 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/verfications
{
"name": "홍길동",
"birthday": "1981-11-23",
"phone_number": "01012345678",
"email": "test@test.com"
}Response
{
"form": {
"transaction_id": "1754035720510123456-6126383872156123456",
"progress": {
"is_id_card_checked": false,
"is_account_checked": false,
"is_face_checked": null,
"is_custom_field_checked": null,
"is_edd_field_checked": null
},
"module": {
"id_card_ocr": true,
"id_card_verification": true,
"face_authentication": false,
"account_verification": true,
"liveness": false,
"custom_field": false,
"edd_field": false
}
},
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
} -
[POST]
(2) 유스비 화면 사용
유스비 eKYC 인증 화면에서 엔드 유저 정보를 입력받도록 위임하는 경우예요.
이 경우, 유스비 Admin에서 설정을 변경해 주어야 해요.
설정 위치: Admin > 기타 설정 > 개인정보 옵션에서 [사용자 필수 정보 수신]을 미사용으로 선택해 주세요.
3) 다국어 (영문) 지원 및 폰트 적용 여부 (선택)
다국어(영문) 지원과 폰트 (나눔 고딕) 적용 여부를 선택할 수 있어요.
별도로 파라미터를 전달하지 않으면, 기본 설정값은 한국어, Pretendard로 적용하여 제공돼요.
4. 요청 시 파라미터 예제
아래 코드는 Access Token + 자체 구현 + 다국어 On + 폰트 On 조건일 때의 파라미터 예제예요.
/* PostMessage로 보낼 엔드 유저 정보를 생성합니다. */
func encodedPostMessage() -> String? {
let jsonData: [String: Any] = [
"access_token": "<access_token>",
"name": "홍길동",
"birthday": "1988-01-01",
"phone_number": "01012341234",
"email": "test@test.com",
"font": "Nanum Gothic",
"language": "en",
]
고객사별 상황에 딱 맞는 예제는 다음 페이지인 ‘예제로 바로 적용하기’에서 만들어 볼 수 있어요.
5. 인코딩 규칙
파라미터 전달 시 “JSON → URI 인코딩 → Base64” 순서를 유지하고,
수신 시에는 “Base64 → URI 디코딩 → JSON 파싱” 순서를 지켜야 해요.
웹/앱 양쪽 인코딩 규칙이 다르면 파싱 오류가 발생해요.
func encodedPostMessage() -> String? {
let jsonData: [String: Any] = [
"access_token": "<access_token>",
"name": "홍길동",
"birthday": "1988-01-01",
"phone_number": "01012341234",
"email": "test@test.com",
"font": "Nanum Gothic",
"language": "en",
]
do {
// JSON -> encodeURIComponent -> Base64Encoding
let jsonData = try JSONSerialization.data(withJSONObject: jsonData, options: .prettyPrinted)
if let jsonString = String(data: jsonData, encoding: .utf8),
let uriEncoded = jsonString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
return uriEncoded.data(using: .utf8)?.base64EncodedString(options: .endLineWithLineFeed)
}
} catch {
NSLog(error.localizedDescription)
}
return nil
}
3단계. 결과 받아 처리하기
웹에서 보낸 메시지를 WKScriptMessageHandler로 받고, Base64 → URI 디코딩 → JSON 파싱 순으로 처리해요. 이 과정을 거쳐 나온 데이터를 가지고 클라이언트에서 직접 처리하거나, 서버 API로 전체 결과를 받아 처리할 수 있어요.
1. 결과 수신 (eKYC → 고객사 앱으로 메시지 받기)
웹이 보낸 메시지를 WKScriptMessageHandler가 가장 먼저 수신해요.
웹에서 전달된 메시지는 앱에서 미리 등록해 둔 채널명(responseName)과 웹에서 보낸 message.name 값이 일치할 때만 처리돼요.
즉, 웹과 앱이 같은 채널명을 공유해야 메시지가 정상적으로 수신되고 이후 단계(디코딩 → 파싱)로 넘어갈 수 있어요.
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard message.name == responseName, let body = message.body as? String else { return }
guard let decodedMessage = decodedPostMessage(body) else {
NSLog("KYC 응답 메시지 분석에 실패했습니다.")
return
}
guard let kycResponse = parsingJson(decodedMessage) else {
NSLog("KYC 응답 메시지 변환에 실패했습니다.")
return
}
result = kycResponse.result
switch kycResponse.result {
case "success":
NSLog("KYC 작업이 성공했습니다.")
responseJson = decodedMessage
case "failed":
NSLog("KYC가 작업이 실패했습니다.")
responseJson = decodedMessage
case "complete":
NSLog("KYC가 완료되었습니다.")
responseJson = responseJson ?? decodedMessage
loadReportView()
case "close":
NSLog("KYC가 완료되지 않았습니다.")
responseJson = responseJson ?? decodedMessage
loadReportView()
default:
result = nil
responseJson = nil
break
}
}
Q. 채널명은 무엇을 사용해야 하나요?
ㄴ A. 웹에서 전달된
메시지는 앱에서 미리 등록한 채널명(responseName)과 웹에서 보낸 message.name 값이
같을 때만 처리돼요. 샘플앱에서는 채널명으로 "alcherakyc"를 사용하고 있으니, 웹과
앱 모두 동일한 이름을 공유해야 메시지가 정상적으로 수신돼요.
2. 결과 데이터 디코딩 (Base64 → URI 디코딩)
Base64 디코딩으로 바이너리를 문자열로 바꾸고, 이어서 URI 디코딩(removingPercentEncoding)으로 원래의 JSON 문자열을 복원해요.
복원에 실패하면 nil을 반환하고, 호출부(3-1. 결과 수신)에서 “분석 실패” 로그를 남기고 처리를 중단해요.
func decodedPostMessage(_ encodedMessage: String) -> String? {
// Base64Decoding -> decodeURIComponent -> JSON
if let base64DecodedData = Data(base64Encoded: encodedMessage, options: .ignoreUnknownCharacters),
let base64DecodedString = String(data: base64DecodedData, encoding: .utf8) {
let jsonString = base64DecodedString.removingPercentEncoding
return jsonString
}
return nil
}
Q. 로그에 출력된 Base64 문자열이 공백처럼 보이는데, 오류가 발생한 건가요?
ㄴ A. 오류가 발생한 건 아니에요. 콘솔 출력 특성상 긴 Base64 문자열이 공백이나 잘린 것처럼 보일 수 있어요. 실제 데이터는 정상적으로 전달되며, 확인이 필요하다면 디코딩 후 JSON 파싱 결과를 로그로 확인하면 돼요.
3. 파싱 모델과 함수 (JSON → 모델 (kycResponse)로 변환)
디코딩으로 복원한 JSON 문자열을 JSONDecoder로 타입 세이프한 모델(KycResponse)로 변환해요.
이후 결과 수신 단계의 switch kycResponse.result { ... }에서 success/failed/complete/close 값에 따라 분기 처리가 이어져요.
// ekyc Response Parsing Classes
struct KycResponse: Codable {
let result: String
let review_result: Review_result?
}
struct Review_result: Codable {
let name: String
let phone_number: String
let birthday: String
let module: Module
let id_card: Id_card?
let face_check: Face_check?
let account: Account?
}
struct Module: Codable {
let id_card_ocr: Bool
let id_card_verification: Bool
let face_authentication: Bool
let account_verification: Bool
let liveness: Bool
}
struct Id_card: Codable {
let modified: Bool
let verified: Bool
let id_card_image: Data?
let id_card_origin: Data?
let id_crop_image: Data?
}
struct Face_check: Codable {
let is_same_person: Int
let is_live: Int
let selfie_image: Data?
}
struct Account: Codable {
let verified: Bool
let account_holder: String?
let finance_company: String?
let finance_code: String?
let account_number: String?
}
/* Json을 KycResponse로 변환합니다. */
func parsingJson(_ jsonString: String) -> KycResponse? {
if let uriDecodedData = jsonString.data(using: .utf8) {
let decoder = JSONDecoder()
do {
let response = try decoder.decode(KycResponse.self, from: uriDecodedData)
return response
} catch let error {
print("error: \(error)")
return nil
}
}
return nil
}
4. 결과 수신 방식 (클라이언트 vs 서버)
eKYC 인증 결과를 수신하는 방식은 두 가지 중 선택할 수 있어요.
postMessage 방식은 결과 메시지를 프론트에서 그대로 받아서 처리하는 방식이에요.
2) postMessage + APIpostMessage + API 방식은 postMessage에서 전달받은 일부 값(id, result_type)을
바탕으로 서버에서 전체 결과를 조회해요.
API 방식은 보안을 강화할 수 있지만 아래와 같은 절차를 추가로 진행해야 해요.
- 유스비 담당자에게 문의하여 reviewer account 를 받아야 해요.
- reviewer account로 전달받은
customer_id,username,password로 API를 조회하여 결과 수신용 Access Token을 취득해요.
• 결과 수신용 Access Token 취득하기
-
[POST]
https://kyc-api-swagger.useb.co.kr/Request
{
"customer_id": 1,
"username": "samsungAdmin",
"password": "password123!"
}Response
{
"company": {
"name": "samsung",
"industry": 1,
"phone_number": "1500-0000"
},
"role": 1,
"name": "samsung_reviewer",
"username": "Reviewer0001",
"is_temp_password": true,
"token": "<token>",
"expire": "2022-01-06T11:41:42+09:00",
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
}
- 취득한 Access Token과 postMessage 값 중
id,result_type을 활용해 API를 호출해요.
• 서버에 API 호출해 전체 결과 받아오기
취득한 Access Token은 HTTP 요청의 Authorization 헤더에 적용해 주세요.
아래 내용을 확인해 result_type 에 해당하는 API를 호출하면 전체 결과를 확인할 수 있어요.
1: Automatic approval (자동승인대상)
2 : Automatic rejection (자동거부대상)
5 :Manual review target (수동심사대상)
- result_type = 1, "auto_approve" / result_type = 2, "auto_reject"
-
[GET]
https://kyc-api.useb.co.kr/review/results/{id}- "auto_approve" : 3회 안에 진위확인 성공시
- "auto_reject" : 3회 진위확인 실패시
- "auto_approve" : 3회 안에 진위확인 성공시
- result_type = 5, "wait_review"
-
[GET]
https://kyc-api.useb.co.kr/review/manuals/{id} - OCR 판독 후에 개인정보를 수정한 경우, 사본으로 판별된 경우 등등
- 수동심사 대상인 경우에도 마지막 화면의 문구 변경은 가능합니다.
-
[GET]
- get attachment file (EDD 강화된 고객확인 서비스 사용시)
-
[GET]
https://kyc-api.useb.co.kr/attachments/{id}
-
[GET]
Q. postMessage와 receive 함수는 어떻게 연결되나요?
ㄴ A. 웹에서 지정한
인터페이스 이름(alcherakyc)과 @JavascriptInterface가 연결 고리 역할을 해요.
Q. result 값은 어디서 확인하나요?
ㄴ A. JSON 데이터 안의 result 필드에서 확인해요.
Q. postMessage로 받은 결과가 어떤 형식인지 모르겠어요.
ㄴ A. base64로 인코딩된 JSON 문자열이에요. 디코딩 후 JSON으로 파싱해야 실제 데이터를 볼 수 있어요.
5. 결과 후처리
파싱된 결과 값은 loadReportView()에서 로그 출력이나 결과 화면 전환 등 후속 처리에 사용돼요.
즉, 인증 완료 후 엔드 유저가 확인할 수 있는 UI와 데이터 후처리를 구현하면 돼요.
func loadReportView() {
print("ekyc result: \(result ?? "")")
print("ekyc responseJson: \(responseJson ?? "")")
}
연동 완료
인증 화면을 띄우고, 결과까지 정상적으로 받아 처리했다면 연동이 완료된 거예요.
운영 환경에 반영하기 전에는 다양한 기기와 브라우저 환경에서 QA 테스트를 꼭 진행해 주세요.
샘플코드 다운로드 받기
iOS 앱에 연동하기 전 필수 세팅
1. 카메라 권한
카메라를 사용하는 모든 iOS 앱은 Info.plist에 아래 키를 꼭 넣어야 해요.
key: Privacy - Camera Usage Description
value: 신분증 및 본인 확인을 위해 카메라를 사용합니다. (고객이 원하는대로 변경, UI나 alert에 어차피 표시 안됨)
2. WebViewController 설치
eKYC 인증 WebView를 띄우기 위해, 아래 Objective-C 파일을 프로젝트에 포함해 주세요.
- 포함해야 할 파일
WebViewController.h
2.4 KBWebViewController.m
13 KB
1단계. 인증 방식 정하기
고객사에서 유스비 eKYC 서버에 접근하기 위해서는 유스비의 고객사라는 것을 먼저 인증해야 해요.
이 때 인증하는 방식은 토큰 없이도 인증이 가능한 Credential과 토큰 발급이 필수적인 Access Token이 있어요. 고객사마다 각자의 보안 및 운영 목적에 맞는 방식을 선택해 인증을 진행하면 돼요.
- Credential → 테스트/PoC 용
- Access Token → 보편적인 운영용
1. Credential
메일로 전달받은 customer_id, id, key 값을 요청에 그대로 사용해요.
구조가 단순하지만 보안상 노출 위험이 있어 이 방식은 실제 운영 전 테스트, PoC 용도로 한정해 사용하는 것을 권장해요.
2. Access Token
서버 또는 클라이언트에서 Access Token을 먼저 발급받고, 해당 토큰으로 인증 요청을 보내요.
이 방식은 보안이 더 강하고, 토큰은 24시간 동안 유효해요.
Access Token을 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.
Access Token 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/sign-in
{
"customer_id": <customer_id>, //number, 고객사id
"username": "<id>", //string, client_id
"password": "<key>" //string, client_secret
}
Response
{
"api_response": {
"result_code": "N100",
"result_message": "OK."
},
"company": {
"name": "id",
"industry": 2,
"phone_number": "1500-0002"
},
"expire": "2022-08-17T11:10:29Z", // 생성 후 24시간 뒤에 만료됨
"is_temp_password": true,
"name": "",
"role": 2,
"token": "**<access_token>**", // **Access Token** 획득
"username": "<client_id>"
}
2단계. 요청 보내기
카메라 필수 권한도 추가했고, 유스비의 고객임을 인증할 인증 방식도 정했다면 이제 eKYC 인증 요청을 보낼 차례예요.
이 단계에서는 WKWebView를 초기화하고, 인증 페이지 URL을 로드한 뒤, 파라미터를 전달하는 과정을 진행해요.
요청을 보낼 때는 다음 항목들을 정해 두어야 해요.
- 인증 방식 (Credential / Access Token)
- 필수 정보 입력 방식 (고객사 자체 구현 (파라미터 전달, Transaction_id (심사 사전 등록) 전달)/ 유스비 제공 화면 사용)
- 다국어(영문) 지원 및 폰트 적용 여부
1. 리스너 등록하기
웹에서 전송하는 결과를 받기 위해 채널명을 등록하고, 동일한 이름으로 들어오는 메시지만 처리해요.
self.responseName = @"alcherakyc";로 앱 측 채널명을 정해요. 웹이 같은 이름(alcherakyc)으로 보낸 메시지는 아래의 메시지 핸들러에서 자동으로 수신돼요.
/* View 불러오기 */
- (void)loadView {
WKWebViewConfiguration *webConfiguration = [WKWebViewConfiguration new];
[webConfiguration setAllowsInlineMediaPlayback:YES];
// 엔드 유저 정보를 담은 postMessage 설정
NSString *requestData = [self encodedPostMessage];
if (requestData != nil) {
WKUserScript *userScript = [[WKUserScript alloc] initWithSource:[NSString stringWithFormat:@"postMessage('%@')", requestData]
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:YES];
[webConfiguration.userContentController addUserScript:userScript];
webConfiguration.preferences.javaScriptEnabled = YES;
}
// 메시지 수신할 핸들러 등록
self.responseName = @"alcherakyc";
[webConfiguration.userContentController addScriptMessageHandler:self name:self.responseName];
self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webConfiguration];
[self.webView setUIDelegate:self];
self.view = self.webView;
}
2. 카메라 권한 확인 및 WebView 로드하기
1) 카메라 권한 확인
앱에서 eKYC 인증을 실행하기 위해서는 카메라 접근 권한이 반드시 허용돼야 해요.
앱 실행 시점에 카메라 권한을 확인해요. 허용이면 바로 인증 화면을 띄우고, 거부면 안내 알림을 보여줘요. 미정이면 권한을 요청한 뒤, 승인되었을 때만 WebView를 불러요.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self checkCameraPermission];
[self.navigationController setNavigationBarHidden:NO];
}
/* Camera 권한 체크 */
- (void)checkCameraPermission {
AVAuthorizationStatus permission = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
switch (permission) {
case AVAuthorizationStatusAuthorized: {
dispatch_async(dispatch_get_main_queue(), ^{
[self loadWebView];
});
break;
}
case AVAuthorizationStatusDenied: {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"카메라 권한 필요"
message:@"설정 > 개인 정보 보호 > 카메라에서 권한을 변경하실 수 있습니다."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:okAction];
[self presentViewController:alert animated:NO completion:nil];
break;
}
case AVAuthorizationStatusNotDetermined: {
// 권한 요청
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted) {
dispatch_async(dispatch_get_main_queue(), ^{
[self loadWebView];
});
} else {
NSLog(@"권한이 거부되었습니다.");
[self.navigationController popViewControllerAnimated:YES];
}
}];
break;
}
default:
NSLog(@"Permission = %ld", permission);
break;
}
}
2) WebView 로드
권한이 허용되면 eKYC 인증 페이지 URL을 WebView에 로드해요. 이 호출이 성공하면 사용자에게 eKYC 화면이 표시돼요.
/* WebView 불러오기 */
- (void)loadWebView {
NSURL *url = [NSURL URLWithString:@"https://kyc.useb.co.kr/auth"];
if (url == nil) return;
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
3. 파라미터 조건 채우기
1) 인증 방식에 따른 인증 값 넣어주기 (필수)
1단계에서 미리 인증 방식을 결정한 상태이므로, 요청을 보내는 시점에서는 인증 방식에 따른 인증 값을 전달하면 돼요.
- Credential: 계정 정보 3가지
customer_id,id,key - Access Token:
Access Token
2) 필수 정보 입력 방식 정하기 (필수)
(1) 고객사 자체 구현
고객사에서 직접 구현한 화면을 통해 엔드 유저의 필수 정보를 입력받는 경우예요.
이 경우, 요청 시 엔드 유저에게서 받은 정보를 반드시 eKYC 서버로 전달해 주셔야 해요.
이 때, 정보를 파라미터로 직접 전달하거나 심사 사전 등록 방식을 통해 transaction_id 로 전달할 수도 있어요.
-
파라미터 전달 방식
-
Transaction (심사 사전 등록) 방식
Transaction (심사 사전 등록) 방식으로 전달하기
eKYC 인증을 위해 엔드 유저의 필수 개인 정보를 고객사에서 직접 수집하는 경우, 해당 정보를 전달하는 과정에 보안을 강화할 수 있는 인증 방식이에요. Access Token으로 먼저 인증 정보를 서버에 등록하고, 받은
transaction_id로 인증을 진행해요.인증 요청 전에 정보를 서버에서 설정하기 때문에 클라이언트에 민감한 정보가 노출되지 않아 보안적으로 더 안전해요. 이 방식은 Access Token을 먼저 발급받은 후
/verificationsAPI를 통해 사용할 수 있어요.Transaction_id를 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.Transaction_id 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/verfications
{
"name": "홍길동",
"birthday": "1981-11-23",
"phone_number": "01012345678",
"email": "test@test.com"
}Response
{
"form": {
"transaction_id": "1754035720510123456-6126383872156123456",
"progress": {
"is_id_card_checked": false,
"is_account_checked": false,
"is_face_checked": null,
"is_custom_field_checked": null,
"is_edd_field_checked": null
},
"module": {
"id_card_ocr": true,
"id_card_verification": true,
"face_authentication": false,
"account_verification": true,
"liveness": false,
"custom_field": false,
"edd_field": false
}
},
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
} -
[POST]
(2) 유스비 화면 사용
유스비 eKYC 인증 화면에서 엔드 유저 정보를 입력받도록 위임하는 경우예요.
이 경우, 유스비 Admin에서 설정을 변경해 주어야 해요.
설정 위치: Admin > 기타 설정 > 개인정보 옵션에서 [사용자 필수 정보 수신]을 미사용으로 선택해 주세요.
3) 다국어 (영문) 지원 및 폰트 적용 여부 (선택)
다국어(영문) 지원과 폰트 (나눔 고딕) 적용 여부를 선택할 수 있어요.
별도로 파라미터를 전달하지 않으면, 기본 설정값은 한국어, Pretendard로 적용하여 제공돼요.
4. 요청 시 파라미터 예제
아래 코드는 Access Token + 자체 구현 + 다국어 On + 폰트 On 조건일 때의 파라미터 예제예요.
/* PostMessage로 보낼 엔드 유저 정보를 생성합니다. */
- (nullable NSString *)encodedPostMessage {
NSDictionary *jsonDictionary = @{
@"access_token": @"<access_token>",
@"name": @"홍길동",
@"birthday": @"1988-01-01",
@"phone_number": @"01012341234",
@"email": @"test@test.com",
@"font": @"Nanum Gothic",
@"language": @"en",
};
고객사별 상황에 딱 맞는 예제는 다음 페이지인 ‘예제로 바로 적용하기’에서 만들어 볼 수 있어요.
5. 인코딩 규칙
파라미터 전달 시 “JSON → URI 인코딩 → Base64” 순서를 유지하고,
수신 시에는 “Base64 → URI 디코딩 → JSON 파싱” 순서를 지켜야 해요.
웹/앱 양쪽 인코딩 규칙이 다르면 파싱 오류가 발생해요.
/* PostMessage로 보낼 엔드 유저 정보를 생성합니다. */
- (nullable NSString *)encodedPostMessage {
NSDictionary *jsonDictionary = @{
@"access_token": @"<access_token>",
@"name": @"홍길동",
@"birthday": @"1988-01-01",
@"phone_number": @"01012341234",
@"email": @"test@test.com",
@"font": @"Nanum Gothic",
@"language": @"en",
};
// JSON -> encodeURIComponent -> Base64Encoding
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:NSJSONWritingPrettyPrinted error:&error];
if (error != nil) {
NSLog(@"고객 정보 생성에 실패했습니다. Error: %@", error.localizedDescription);
return nil;
}
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (jsonString != nil) {
NSString *uriEncoded = [jsonString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
return [[uriEncoded dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
}
return nil;
}
3단계. 결과 받아 처리하기
웹에서 보낸 메시지를 WKScriptMessageHandler로 받고, Base64 → URI 디코딩 → JSON 파싱 순으로 처리해요. 이 과정을 거쳐 나온 데이터를 가지고 클라이언트에서 직접 처리하거나, 서버 API로 전체 결과를 받아 처리할 수 있어요.
1. 결과 수신 (eKYC → 고객사 앱으로 메시지 받기)
웹이 보낸 메시지를 WKScriptMessageHandler가 가장 먼저 수신해요.
웹에서 전달된 메시지는 앱에서 미리 등록해 둔 채널명(responseName)과 웹에서 보낸 message.name 값이 일치할 때만 처리돼요.
즉, 웹과 앱이 같은 채널명을 공유해야 메시지가 정상적으로 수신되고 이후 단계(디코딩 → 파싱)로 넘어갈 수 있어요.
/* WebView 메시지 핸들러 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if (message.name != self.responseName || message.body == nil) return;
NSString *decodedMessage = [self decodedPostMessage:message.body];
if (decodedMessage == nil) {
NSLog(@"KYC 응답 메시지 분석에 실패했습니다.");
return;
}
KycResponse *kycResponse = [KycResponse parsingJson:decodedMessage];
if (kycResponse == nil) {
NSLog(@"KYC 응답 메시지 변환에 실패했습니다.");
return;
}
self.result = kycResponse.result;
if ([kycResponse.result isEqualToString:@"success"]) {
NSLog(@"KYC 작업이 성공했습니다.");
self.responseJson = decodedMessage;
} else if ([kycResponse.result isEqualToString:@"failed"]) {
NSLog(@"KYC가 작업이 실패했습니다.");
self.responseJson = decodedMessage;
} else if ([kycResponse.result isEqualToString:@"complete"]) {
NSLog(@"KYC가 완료되었습니다.");
if (self.responseJson == nil) self.responseJson = decodedMessage;
[self loadReportView];
} else if ([kycResponse.result isEqualToString:@"close"]) {
NSLog(@"KYC가 완료되지 않았습니다.");
if (self.responseJson == nil) self.responseJson = decodedMessage;
[self loadReportView];
} else {
self.result = nil;
self.responseJson = nil;
}
}
Q. 채널명은 무엇을 사용해야 하나요?
ㄴ A. 웹에서 전달된
메시지는 앱에서 미리 등록한 채널명(responseName)과 웹에서 보낸 message.name 값이
같을 때만 처리돼요. 샘플앱에서는 채널명으로 "alcherakyc"를 사용하고 있으니, 웹과
앱 모두 동일한 이름을 공유해야 메시지가 정상적으로 수신돼요.
2. 결과 데이터 디코딩 (Base64 → URI 디코딩)
Base64 디코딩으로 바이너리를 문자열로 바꾸고, 이어서 URI 디코딩(removingPercentEncoding)으로 원래의 JSON 문자열을 복원해요.
복원에 실패하면 nil을 반환하고, 호출부(3-1. 결과 수신)에서 “분석 실패” 로그를 남기고 처리를 중단해요.
/* KYC 수행 결과를 분석합니다. */
- (nullable NSString *)decodedPostMessage:(nonnull NSString *)encodedMessage {
// Base64Decoding -> decodeURIComponent -> JSON
NSData *base64DecodedData = [[NSData alloc] initWithBase64EncodedString:encodedMessage options:NSDataBase64DecodingIgnoreUnknownCharacters];
if (base64DecodedData != nil) {
NSString *base64DecodedString = [[NSString alloc] initWithData:base64DecodedData encoding:NSUTF8StringEncoding];
if (base64DecodedData != nil) {
NSString *jsonString = [base64DecodedString stringByRemovingPercentEncoding];
return jsonString;
}
}
return nil;
}
Q. 로그에 출력된 Base64 문자열이 공백처럼 보이는데, 오류가 발생한 건가요?
ㄴ A. 오류가 발생한 건 아니에요. 콘솔 출력 특성상 긴 Base64 문자열이 공백이나 잘린 것처럼 보일 수 있어요. 실제 데이터는 정상적으로 전달되며, 확인이 필요하다면 디코딩 후 JSON 파싱 결과를 로그로 확인하면 돼요.
3. 파싱 모델과 함수 (JSON → 모델 (kycResponse)로 변환)
디코딩으로 복원한 JSON 문자열을 JSONDecoder로 타입 세이프한 모델(KycResponse)로 변환해요.
이후 결과 수신 단계에서 if ([kycResponse.result isEqualToString:@"success"]) { ... } else if (...) 형태의 분기문을 사용해 success / failed / complete / close 값에 따라 각각 처리 로직이 이어져요.
/* Json을 KycResponse로 변환합니다. */
+ (nullable KycResponse *)parsingJson:(NSString *)jsonString {
NSData *uriDecodedData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
if (uriDecodedData != nil) {
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:uriDecodedData options:NSJSONReadingMutableContainers error:&error];
if (error == nil) {
KycResponse *response = [[KycResponse alloc] initWithDictionary:jsonDictionary];
return response;
} else {
NSLog(@"KYC 결과 정보 분석중 오류가 발생했습니다. Error: %@", error.localizedDescription);
}
}
return nil;
}
4. 결과 수신 방식 (클라이언트 vs 서버)
eKYC 인증 결과를 수신하는 방식은 두 가지 중 선택할 수 있어요.
postMessage 방식은 결과 메시지를 프론트에서 그대로 받아서 처리하는 방식이에요.
2) postMessage + APIpostMessage + API 방식은 postMessage에서 전달받은 일부 값(id, result_type)을
바탕으로 서버에서 전체 결과를 조회해요.
API 방식은 보안을 강화할 수 있지만 아래와 같은 절차를 추가로 진행해야 해요.
- 유스비 담당자에게 문의하여 reviewer account 를 받아야 해요.
- reviewer account로 전달받은
customer_id,username,password로 API를 조회하여 결과 수신용 Access Token을 취득해요.
• 결과 수신용 Access Token 취득하기
-
[POST]
https://kyc-api-swagger.useb.co.kr/Request
{
"customer_id": 1,
"username": "samsungAdmin",
"password": "password123!"
}Response
{
"company": {
"name": "samsung",
"industry": 1,
"phone_number": "1500-0000"
},
"role": 1,
"name": "samsung_reviewer",
"username": "Reviewer0001",
"is_temp_password": true,
"token": "<token>",
"expire": "2022-01-06T11:41:42+09:00",
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
}
- 취득한 Access Token과 postMessage 값 중
id,result_type을 활용해 API를 호출해요.
• 서버에 API 호출해 전체 결과 받아오기
취득한 Access Token은 HTTP 요청의 Authorization 헤더에 적용해 주세요.
아래 내용을 확인해 result_type 에 해당하는 API를 호출하면 전체 결과를 확인할 수 있어요.
1: Automatic approval (자동승인대상)
2 : Automatic rejection (자동거부대상)
5 :Manual review target (수동심사대상)
- result_type = 1, "auto_approve" / result_type = 2, "auto_reject"
-
[GET]
https://kyc-api.useb.co.kr/review/results/{id}- "auto_approve" : 3회 안에 진위확인 성공시
- "auto_reject" : 3회 진위확인 실패시
- "auto_approve" : 3회 안에 진위확인 성공시
- result_type = 5, "wait_review"
-
[GET]
https://kyc-api.useb.co.kr/review/manuals/{id} - OCR 판독 후에 개인정보를 수정한 경우, 사본으로 판별된 경우 등등
- 수동심사 대상인 경우에도 마지막 화면의 문구 변경은 가능합니다.
-
[GET]
- get attachment file (EDD 강화된 고객확인 서비스 사용시)
-
[GET]
https://kyc-api.useb.co.kr/attachments/{id}
-
[GET]
Q. postMessage와 receive 함수는 어떻게 연결되나요?
ㄴ A. 웹에서 지정한
인터페이스 이름(alcherakyc)과 @JavascriptInterface가 연결 고리 역할을 해요.
Q. result 값은 어디서 확인하나요?
ㄴ A. JSON 데이터 안의 result 필드에서 확인해요.
Q. postMessage로 받은 결과가 어떤 형식인지 모르겠어요.
ㄴ A. base64로 인코딩된 JSON 문자열이에요. 디코딩 후 JSON으로 파싱해야 실제 데이터를 볼 수 있어요.
5. 결과 후처리
파싱된 결과 값은 loadReportView()에서 로그 출력이나 결과 화면 전환 등 후속 처리에 사용돼요.
즉, 인증 완료 후 엔드 유저가 확인할 수 있는 UI와 데이터 후처리를 구현하면 돼요.
/* KYC 결과 창으로 이동 */
- (void)loadReportView {
NSLog(@"ekyc result: %@", self.result);
NSLog(@"ekyc responseJson: %@", self.responseJson);
}
연동 완료
인증 화면을 띄우고, 결과까지 정상적으로 받아 처리했다면 연동이 완료된 거예요.
운영 환경에 반영하기 전에는 다양한 기기와 브라우저 환경에서 QA 테스트를 꼭 진행해 주세요.
샘플코드 다운로드 받기
AOS 앱에 연동하기 전 필수 세팅
eKYC 인증 과정은 카메라와 네트워크 통신이 꼭 필요해요.
따라서 앱의 AndroidManifest.xml에 다음과 같이 권한을 추가해 주세요.
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
이 권한들이 선언되어 있어야 WebView에서 카메라를 열고, 인증 서버와 통신할 수 있어요.
1단계. 인증 방식 정하기
고객사에서 유스비 eKYC 서버에 접근하기 위해서는 유스비의 고객사라는 것을 먼저 인증해야 해요.
이 때 인증하는 방식은 토큰 없이도 인증이 가능한 Credential과 토큰 발급이 필수적인 Access Token이 있어요. 고객사마다 각자의 보안 및 운영 목적에 맞는 방식을 선택해 인증을 진행하면 돼요.
- Credential → 테스트/PoC 용
- Access Token → 보편적인 운영용
1. Credential
메일로 전달받은 customer_id, id, key 값을 요청에 그대로 사용해요.
구조가 단순하지만 보안상 노출 위험이 있어 이 방식은 실제 운영 전 테스트, PoC 용도로 한정해 사용하는 것을 권장해요.
2. Access Token
서버 또는 클라이언트에서 Access Token을 먼저 발급받고, 해당 토큰으로 인증 요청을 보내요.
이 방식은 보안이 더 강하고, 토큰은 24시간 동안 유효해요.
Access Token을 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.
Access Token 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/sign-in
{
"customer_id": <customer_id>, //number, 고객사id
"username": "<id>", //string, client_id
"password": "<key>" //string, client_secret
}
Response
{
"api_response": {
"result_code": "N100",
"result_message": "OK."
},
"company": {
"name": "id",
"industry": 2,
"phone_number": "1500-0002"
},
"expire": "2022-08-17T11:10:29Z", // 생성 후 24시간 뒤에 만료됨
"is_temp_password": true,
"name": "",
"role": 2,
"token": "**<access_token>**", // **Access Token** 획득
"username": "<client_id>"
}
2단계. 요청 보내기
Manifest에 권한을 선언했고, 유스비의 고객임을 인증할 인증 방식도 정했다면 이제 eKYC 인증 요청을 보낼 차례예요.
이 단계에서는 WebView를 초기화하고, 인증 페이지 URL을 로드한 뒤, 파라미터를 전달하는 과정을 진행해요.
요청을 보낼 때는 다음 항목들을 정해 두어야 해요.
- 인증 방식 (Credential / Access Token)
- 필수 정보 입력 방식 (고객사 자체 구현 (파라미터 전달, Transaction_id (심사 사전 등록) 전달)/ 유스비 제공 화면 사용)
- 다국어(영문) 지원 및 폰트 적용 여부
1. 리스너 등록하기
eKYC 인증이 완료되면, 결과는 WebView와 연결된 JavascriptInterface로 앱에 전달돼요.
앱에서 결과 메시지를 놓치지 않고 받으려면, 먼저 인터페이스를 등록해 두어야 해요.
예제에서는 addJavascriptInterface(this, "alcherakyc")로 등록하고, receive(data: String) 메서드에서 결과를 수신해요.
webview = findViewById(R.id.webview)
webview?.apply {
settings.javaScriptEnabled = true
webViewClient = WebViewClient()
addJavascriptInterface(this@WebViewActivity, "alcherakyc")
}
2. 카메라 권한 확인 및 WebView 로드하기
1) 카메라 권한 확인
eKYC 인증 과정에서는 카메라 촬영이 필요하므로, 앱 실행 중에 카메라 권한을 명시적으로 요청해야 해요.
Android에서는 권한이 허용되지 않은 상태에서 WebView를 먼저 띄우면 카메라 접근이 거부되어 인증이 실패할 수 있어요. 따라서 WebView 로드보다 먼저 권한을 확인하는 흐름이 중요해요.
private fun checkCameraPermissionAndLoadWebView() {
val permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 1000)
} else {
setupWebViewAndLoadUrl()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 1000) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
setupWebViewAndLoadUrl()
} else {
Toast.makeText(
this,
"카메라/갤러리 접근 권한이 없습니다. 권한 허용 후 이용해주세요.",
Toast.LENGTH_SHORT
).show()
finish()
}
}
}
2) WebView 로드
카메라 권한이 허용되면, 이제 WebView를 초기화하고 인증 페이지를 띄울 수 있어요.
이 단계에서는 WebView에서 JavaScript 실행을 허용하고, 인증에 필요한 파라미터를 JS 브릿지를 통해 전달해요.
또한, 인증 화면에서 카메라를 사용할 수 있도록 WebRTC 권한(RESOURCE_VIDEO_CAPTURE)을 따로 허용해주는 설정도 필요해요.
private fun setupWebViewAndLoadUrl() {
val url = "https://kyc.useb.co.kr/auth"
val param = createParam()
webview = findViewById(R.id.webview)
webview?.apply {
settings.javaScriptEnabled = true
settings.mediaPlaybackRequiresUserGesture = false
clearCache(true)
clearHistory()
addJavascriptInterface(this@WebViewActivity, "alcherakyc")
}
webview?.webChromeClient = object : WebChromeClient() {
override fun onPermissionRequest(request: PermissionRequest?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
request?.resources?.let { resources ->
if (resources.contains(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(arrayOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE))
}
}
}
}
}
val handler = Handler(Looper.getMainLooper())
handler.post {
webview?.loadUrl(url)
webview?.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
webview?.loadUrl("javascript:alcherakycreceive('$param')")
}
}
}
}
3. 파라미터 조건 채우기
1) 인증 방식에 따른 인증 값 넣어주기 (필수)
1단계에서 미리 인증 방식을 결정한 상태이므로, 요청을 보내는 시점에서는 인증 방식에 따른 인증 값을 전달하면 돼요.
- Credential: 계정 정보 3가지
customer_id,id,key - Access Token:
Access Token
2) 필수 정보 입력 방식 정하기 (필수)
(1) 고객사 자체 구현
고객사에서 직접 구현한 화면을 통해 엔드 유저의 필수 정보를 입력받는 경우예요.
이 경우, 요청 시 엔드 유저에게서 받은 정보를 반드시 eKYC 서버로 전달해 주셔야 해요.
이 때, 정보를 파라미터로 직접 전달하거나 심사 사전 등록 방식을 통해 transaction_id 로 전달할 수도 있어요.
-
파라미터 전달 방식
-
Transaction (심사 사전 등록) 방식
Transaction (심사 사전 등록) 방식으로 전달하기
eKYC 인증을 위해 엔드 유저의 필수 개인 정보를 고객사에서 직접 수집하는 경우, 해당 정보를 전달하는 과정에 보안을 강화할 수 있는 인증 방식이에요. Access Token으로 먼저 인증 정보를 서버에 등록하고, 받은
transaction_id로 인증을 진행해요.인증 요청 전에 정보를 서버에서 설정하기 때문에 클라이언트에 민감한 정보가 노출되지 않아 보안적으로 더 안전해요. 이 방식은 Access Token을 먼저 발급받은 후
/verificationsAPI를 통해 사용할 수 있어요.Transaction_id를 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.Transaction_id 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/verfications
{
"name": "홍길동",
"birthday": "1981-11-23",
"phone_number": "01012345678",
"email": "test@test.com"
}Response
{
"form": {
"transaction_id": "1754035720510123456-6126383872156123456",
"progress": {
"is_id_card_checked": false,
"is_account_checked": false,
"is_face_checked": null,
"is_custom_field_checked": null,
"is_edd_field_checked": null
},
"module": {
"id_card_ocr": true,
"id_card_verification": true,
"face_authentication": false,
"account_verification": true,
"liveness": false,
"custom_field": false,
"edd_field": false
}
},
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
} -
[POST]
(2) 유스비 화면 사용
유스비 eKYC 인증 화면에서 엔드 유저 정보를 입력받도록 위임하는 경우예요.
이 경우, 유스비 Admin에서 설정을 변경해 주어야 해요.
설정 위치: Admin > 기타 설정 > 개인정보 옵션에서 [사용자 필수 정보 수신]을 미사용으로 선택해 주세요.
3) 다국어 (영문) 지원 및 폰트 적용 여부 (선택)
다국어(영문) 지원과 폰트 (나눔 고딕) 적용 여부를 선택할 수 있어요.
별도로 파라미터를 전달하지 않으면, 기본 설정값은 한국어, Pretendard로 적용하여 제공돼요.
4. 요청 시 파라미터 예제
아래 코드는 Access Token + 자체 구현 + 다국어 On + 폰트 On 조건일 때의 파라미터 예제예요.
private fun createParam(): String {
val paramObj = JSONObject().apply {
try {
put("access_token", "<access_token>");
put("name", "홍길동")
put("birthday", "1988-01-01")
put("phone_number", "01012341234")
put("email", "test@alcherainc.com")
put("font", "Nanum Gothic")
put("language", "en")
} catch (e: JSONException) {
e.printStackTrace()
}
}
고객사별 상황에 딱 맞는 예제는 다음 페이지인 ‘예제로 바로 적용하기’에서 만들어 볼 수 있어요.
5. 인코딩 규칙
파라미터 전달 시 “JSON → URI 인코딩 → Base64” 순서를 유지하고,
수신 시에는 “Base64 → URI 디코딩 → JSON 파싱” 순서를 지켜야 해요.
웹/앱 양쪽 인코딩 규칙이 다르면 파싱 오류가 발생해요.
private fun createParam(): String {
val paramObj = JSONObject().apply {
try {
put("access_token", "<access_token>");
put("name", "홍길동")
put("birthday", "1988-01-01")
put("phone_number", "01012341234")
put("email", "test@alcherainc.com")
put("font", "Nanum Gothic")
put("language", "en")
} catch (e: JSONException) {
e.printStackTrace()
}
}
return encodeJson(paramObj)
}
private fun encodeJson(data: JSONObject): String {
val uriEncodedData = encodeURIComponent(data.toString())
return Base64.encodeToString(uriEncodedData.toByteArray(), 0)
}
private fun encodeURIComponent(encoded: String): String {
return try {
URLEncoder.encode(encoded, "UTF-8")
.replace("\\+".toRegex(), "%20")
.replace("\\%21".toRegex(), "!")
.replace("\\%27".toRegex(), "'")
.replace("\\%28".toRegex(), "(")
.replace("\\%29".toRegex(), ")")
.replace("\\%7E".toRegex(), "~")
} catch (e: UnsupportedEncodingException) {
e.printStackTrace()
""
}
}
3단계. 결과 받아 처리하기
1. 결과 데이터 파싱
앱에서는 인증 화면이 전달하는 결과를 receive(data: String) 메서드에서 받아요.
이때 전달되는 데이터는 Base64 + URI 인코딩된 JSON 문자열이에요.
따라서 Base64 디코딩 → URI 디코딩 → JSON 파싱 순서로 처리해야 해요.
// Base64 → URI 디코딩 → JSON 파싱 (결과 받을 때)
private fun decodedReceiveData(data: String): String {
val decoded = String(Base64.decode(data, 0))
return decodeURIComponent(decoded)
}
private fun decodeURIComponent(decoded: String): String {
return try {
URLDecoder.decode(decoded, "UTF-8")
.replace("%20", "\\+")
.replace("!", "\\%21")
.replace("'", "\\%27")
.replace("\\(", "\\%28")
.replace("\\)", "\\%29")
.replace("~", "\\%7E")
} catch (e: UnsupportedEncodingException) {
e.printStackTrace()
""
}
}
2. 결과 수신 방식
eKYC 인증 결과를 수신하는 방식은 두 가지 중 선택할 수 있어요.
postMessage 방식은 결과 메시지를 프론트에서 그대로 받아서 처리하는 방식이에요.
2) postMessage + APIpostMessage + API 방식은 postMessage에서 전달받은 일부 값(id, result_type)을
바탕으로 서버에서 전체 결과를 조회해요.
API 방식은 보안을 강화할 수 있지만 아래와 같은 절차를 추가로 진행해야 해요.
- 유스비 담당자에게 문의하여 reviewer account 를 받아야 해요.
- reviewer account로 전달받은
customer_id,username,password로 API를 조회하여 결과 수신용 Access Token을 취득해요.
• 결과 수신용 Access Token 취득하기
-
[POST]
https://kyc-api-swagger.useb.co.kr/Request
{
"customer_id": 1,
"username": "samsungAdmin",
"password": "password123!"
}Response
{
"company": {
"name": "samsung",
"industry": 1,
"phone_number": "1500-0000"
},
"role": 1,
"name": "samsung_reviewer",
"username": "Reviewer0001",
"is_temp_password": true,
"token": "<token>",
"expire": "2022-01-06T11:41:42+09:00",
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
}
- 취득한 Access Token과 postMessage 값 중
id,result_type을 활용해 API를 호출해요.
• 서버에 API 호출해 전체 결과 받아오기
취득한 Access Token은 HTTP 요청의 Authorization 헤더에 적용해 주세요.
아래 내용을 확인해 result_type 에 해당하는 API를 호출하면 전체 결과를 확인할 수 있어요.
1: Automatic approval (자동승인대상)
2 : Automatic rejection (자동거부대상)
5 :Manual review target (수동심사대상)
- result_type = 1, "auto_approve" / result_type = 2, "auto_reject"
-
[GET]
https://kyc-api.useb.co.kr/review/results/{id}- "auto_approve" : 3회 안에 진위확인 성공시
- "auto_reject" : 3회 진위확인 실패시
- "auto_approve" : 3회 안에 진위확인 성공시
- result_type = 5, "wait_review"
-
[GET]
https://kyc-api.useb.co.kr/review/manuals/{id} - OCR 판독 후에 개인정보를 수정한 경우, 사본으로 판별된 경우 등등
- 수동심사 대상인 경우에도 마지막 화면의 문구 변경은 가능합니다.
-
[GET]
- get attachment file (EDD 강화된 고객확인 서비스 사용시)
-
[GET]
https://kyc-api.useb.co.kr/attachments/{id}
-
[GET]
3. 결과 처리 예제
파싱된 JSON의 result 값에 따라 분기 처리하시면 돼요. 예제는 콘솔 출력이지만, 실제 서비스에서는 화면 전환/알림/재시도/서버 검증 등 비즈니스 로직으로 연결하세요.
@JavascriptInterface
fun receive(data: String) {
try {
val decodedData = decodedReceiveData(data)
val jsonObject = JSONObject(decodedData)
val resultData = jsonObject.getString("result")
when (resultData) {
"success" -> {
Log.d("success", "KYC 작업이 성공했습니다.")
}
"failed" -> {
Log.d("failed", "KYC 작업이 실패했습니다.")
}
"complete" -> {
Log.d("complete", "KYC가 완료되었습니다.")
}
"close" -> {
Log.d("close", "KYC가 완료되지 않았습니다.")
}
}
finish()
} catch (e: JSONException) {
e.printStackTrace()
}
}
private fun decodedReceiveData(data: String): String {
val decoded = String(Base64.decode(data, 0))
return decodeURIComponent(decoded)
}
private fun decodeURIComponent(decoded: String): String {
return try {
URLDecoder.decode(decoded, "UTF-8")
.replace("%20", "\\+")
.replace("!", "\\%21")
.replace("'", "\\%27")
.replace("\\(", "\\%28")
.replace("\\)", "\\%29")
.replace("~", "\\%7E")
} catch (e: UnsupportedEncodingException) {
e.printStackTrace()
""
}
}
}
Q. postMessage와 receive 함수는 어떻게 연결되나요?
ㄴ A. 웹에서 지정한
인터페이스 이름(alcherakyc)과 @JavascriptInterface가 연결 고리 역할을 해요.
Q. result 값은 어디서 확인하나요?
ㄴ A. JSON 데이터 안의 result 필드에서 확인해요.
Q. postMessage로 받은 결과가 어떤 형식인지 모르겠어요.
ㄴ A. base64로 인코딩된 JSON 문자열이에요. 디코딩 후 JSON으로 파싱해야 실제 데이터를 볼 수 있어요.
연동 완료
인증 화면을 띄우고, 결과까지 정상적으로 받아 처리했다면 연동이 완료된 거예요.
운영 환경에 반영하기 전에는 다양한 기기와 브라우저 환경에서 QA 테스트를 꼭 진행해 주세요.
샘플코드 다운로드 받기
AOS 앱에 연동하기 전 필수 세팅
eKYC 인증 과정은 카메라와 네트워크 통신이 꼭 필요해요.
따라서 앱의 AndroidManifest.xml에 다음과 같이 권한을 추가해 주세요.
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
이 권한들이 선언되어 있어야 WebView에서 카메라를 열고, 인증 서버와 통신할 수 있어요.
1단계. 인증 방식 정하기
고객사에서 유스비 eKYC 서버에 접근하기 위해서는 유스비의 고객사라는 것을 먼저 인증해야 해요.
이 때 인증하는 방식은 토큰 없이도 인증이 가능한 Credential과 토큰 발급이 필수적인 Access Token이 있어요. 고객사마다 각자의 보안 및 운영 목적에 맞는 방식을 선택해 인증을 진행하면 돼요.
- Credential → 테스트/PoC 용
- Access Token → 보편적인 운영용
1. Credential
메일로 전달받은 customer_id, id, key 값을 요청에 그대로 사용해요.
구조가 단순하지만 보안상 노출 위험이 있어 이 방식은 실제 운영 전 테스트, PoC 용도로 한정해 사용하는 것을 권장해요.
2. Access Token
서버 또는 클라이언트에서 Access Token을 먼저 발급받고, 해당 토큰으로 인증 요청을 보내요.
이 방식은 보안이 더 강하고, 토큰은 24시간 동안 유효해요.
Access Token을 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.
Access Token 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/sign-in
{
"customer_id": <customer_id>, //number, 고객사id
"username": "<id>", //string, client_id
"password": "<key>" //string, client_secret
}
Response
{
"api_response": {
"result_code": "N100",
"result_message": "OK."
},
"company": {
"name": "id",
"industry": 2,
"phone_number": "1500-0002"
},
"expire": "2022-08-17T11:10:29Z", // 생성 후 24시간 뒤에 만료됨
"is_temp_password": true,
"name": "",
"role": 2,
"token": "**<access_token>**", // **Access Token** 획득
"username": "<client_id>"
}
2단계. 요청 보내기
Manifest에 권한을 선언했고, 유스비의 고객임을 인증할 인증 방식도 정했다면 이제 eKYC 인증 요청을 보낼 차례예요.
이 단계에서는 WebView를 초기화하고, 인증 페이지 URL을 로드한 뒤, 파라미터를 전달하는 과정을 진행해요.
요청을 보낼 때는 다음 항목들을 정해 두어야 해요.
- 인증 방식 (Credential / Access Token)
- 필수 정보 입력 방식 (고객사 자체 구현 (파라미터 전달, Transaction_id (심사 사전 등록) 전달)/ 유스비 제공 화면 사용)
- 다국어(영문) 지원 및 폰트 적용 여부
1. 리스너 등록하기
eKYC 인증이 완료되면, 결과는 WebView와 연결된 JavascriptInterface로 앱에 전달돼요.
앱에서 결과 메시지를 놓치지 않고 받으려면, 먼저 인터페이스를 등록해 두어야 해요.
예제에서는 addJavascriptInterface(this, "alcherakyc")로 등록하고, receive(data: String) 메서드에서 결과를 수신해요.
String url = "https://kyc.useb.co.kr/auth";
String param = createParam();
Handler handler = new Handler();
handler.post(() -> {
cameraAuthRequest();
webview.loadUrl(url);
webview.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
webview.loadUrl("javascript:alcherakyc.receive('" + param + "')");
}
});
});
2. 카메라 권한 확인 및 WebView 로드하기
1) 카메라 권한 확인
eKYC 인증 과정에서는 카메라 촬영이 필요하므로, 앱 실행 중에 카메라 권한을 명시적으로 요청해야 해요.
Android에서는 권한이 허용되지 않은 상태에서 WebView를 먼저 띄우면 카메라 접근이 거부되어 인증이 실패할 수 있어요. 따라서 WebView 로드보다 먼저 권한을 확인하는 흐름이 중요해요.
private void cameraAuthRequest() {
// WebView 초기화
webview = findViewById(R.id.webview);
// WebRTC로 카메라 접근 허용하기 위한 설정
WebSettings ws = webview.getSettings();
ws.setMediaPlaybackRequiresUserGesture(false);
webview.setWebChromeClient(new WebChromeClient() {
@Override
public void onPermissionRequest(final PermissionRequest request) {
// Android 7.0 이상에서만 동작
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
final String[] requestedResources = request.getResources();
for (String r : requestedResources) {
if (r.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE});
break;
}
}
}
}
});
// 카메라 권한이 없으면 요청
int cameraPermissionCheck = ContextCompat.checkSelfPermission(WebViewActivity.this, Manifest.permission.CAMERA);
if (cameraPermissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(WebViewActivity.this, new String[]{Manifest.permission.CAMERA}, 1000);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// 권한 요청 응답 처리
if (requestCode == 1000) {
// 사용자가 권한을 거부한 경우
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(WebViewActivity.this,
"카메라/갤러리 접근 권한이 없습니다. 권한 허용 후 이용해주세요.",
Toast.LENGTH_SHORT).show();
finish();
}
}
}
2) WebView 로드
카메라 권한이 허용되면, 이제 WebView를 초기화하고 인증 페이지를 띄울 수 있어요.
eKYC 인증 URL을 WebView에 loadUrl()로 호출하고,
필요한 인증 파라미터를 JS 브릿지(alcherakycreceive)를 통해 전달해요.
webview = findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebViewClient(new WebViewClient());
// webview.setWebChromeClient(new WebChromeClient());
webview.addJavascriptInterface(this, "alcherakyc");
// 카메라 프리뷰 성능
webview.clearCache(true);
webview.clearHistory();
String url = "https://kyc.useb.co.kr/auth";
String param = createParam();
Handler handler = new Handler();
handler.post(() -> {
cameraAuthRequest();
webview.loadUrl(url);
webview.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
webview.loadUrl("javascript:alcherakycreceive('" + param + "')");
}
});
});
3. 파라미터 조건 채우기
1) 인증 방식에 따른 인증 값 넣어주기 (필수)
1단계에서 미리 인증 방식을 결정한 상태이므로, 요청을 보내는 시점에서는 인증 방식에 따른 인증 값을 전달하면 돼요.
- Credential: 계정 정보 3가지
customer_id,id,key - Access Token:
Access Token
2) 필수 정보 입력 방식 정하기 (필수)
(1) 고객사 자체 구현
고객사에서 직접 구현한 화면을 통해 엔드 유저의 필수 정보를 입력받는 경우예요.
이 경우, 요청 시 엔드 유저에게서 받은 정보를 반드시 eKYC 서버로 전달해 주셔야 해요.
이 때, 정보를 파라미터로 직접 전달하거나 심사 사전 등록 방식을 통해 transaction_id 로 전달할 수도 있어요.
-
파라미터 전달 방식
-
Transaction (심사 사전 등록) 방식
Transaction (심사 사전 등록) 방식으로 전달하기
eKYC 인증을 위해 엔드 유저의 필수 개인 정보를 고객사에서 직접 수집하는 경우, 해당 정보를 전달하는 과정에 보안을 강화할 수 있는 인증 방식이에요. Access Token으로 먼저 인증 정보를 서버에 등록하고, 받은
transaction_id로 인증을 진행해요.인증 요청 전에 정보를 서버에서 설정하기 때문에 클라이언트에 민감한 정보가 노출되지 않아 보안적으로 더 안전해요. 이 방식은 Access Token을 먼저 발급받은 후
/verificationsAPI를 통해 사용할 수 있어요.Transaction_id를 발급 받으려면, 아래의 정보로 API를 조회하면 돼요.Transaction_id 발급을 위한 API 조회 방법 확인하기
Request Body:
-
[POST]
https://kyc-api.useb.co.kr/verfications
{
"name": "홍길동",
"birthday": "1981-11-23",
"phone_number": "01012345678",
"email": "test@test.com"
}Response
{
"form": {
"transaction_id": "1754035720510123456-6126383872156123456",
"progress": {
"is_id_card_checked": false,
"is_account_checked": false,
"is_face_checked": null,
"is_custom_field_checked": null,
"is_edd_field_checked": null
},
"module": {
"id_card_ocr": true,
"id_card_verification": true,
"face_authentication": false,
"account_verification": true,
"liveness": false,
"custom_field": false,
"edd_field": false
}
},
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
} -
[POST]
(2) 유스비 화면 사용
유스비 eKYC 인증 화면에서 엔드 유저 정보를 입력받도록 위임하는 경우예요.
이 경우, 유스비 Admin에서 설정을 변경해 주어야 해요.
설정 위치: Admin > 기타 설정 > 개인정보 옵션에서 [사용자 필수 정보 수신]을 미사용으로 선택해 주세요.
3) 다국어 (영문) 지원 및 폰트 적용 여부 (선택)
다국어(영문) 지원과 폰트 (나눔 고딕) 적용 여부를 선택할 수 있어요.
별도로 파라미터를 전달하지 않으면, 기본 설정값은 한국어, Pretendard로 적용하여 제공돼요.
4. 요청 시 파라미터 예제
아래 코드는 Access Token + 자체 구현 + 다국어 On + 폰트 On 조건일 때의 파라미터 예제예요.
private String createParam() {
JSONObject paramObj = new JSONObject();
try {
paramObj.put("access_token", "<access_token>");
paramObj.put("name", "홍길동");
paramObj.put("birthday", "1988-01-01");
paramObj.put("phone_number", "01012341234");
paramObj.put("email", "test@alcherainc.com");
paramObj.put("font", "Nanum Gothic");
paramObj.put("language", "en");
} catch (JSONException e) {
e.printStackTrace();
}
고객사별 상황에 딱 맞는 예제는 다음 페이지인 ‘예제로 바로 적용하기’에서 만들어 볼 수 있어요.
5. 인코딩 규칙
파라미터 전달 시 “JSON → URI 인코딩 → Base64” 순서를 유지하고,
수신 시에는 “Base64 → URI 디코딩 → JSON 파싱” 순서를 지켜야 해요.
웹/앱 양쪽 인코딩 규칙이 다르면 파싱 오류가 발생해요.
// JSON → URI 인코딩 → Base64 (요청 보낼 때)
private String encodeJson(JSONObject data) {
String uriEncodedData = encodeURIComponent(data.toString());
return Base64.encodeToString(uriEncodedData.getBytes(), 0);
}
private String encodeURIComponent(String encoded) {
String encodedURI = null;
try {
encodedURI = URLEncoder.encode(encoded, "UTF-8")
.replaceAll("\\+", "%20")
.replaceAll("\\%21", "!")
.replaceAll("\\%27", "'")
.replaceAll("\\%28", "(")
.replaceAll("\\%29", ")")
.replaceAll("\\%7E", "~");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return encodedURI;
}
3단계. 결과 받아 처리하기
1. 결과 데이터 파싱
앱에서는 인증 화면이 전달하는 결과를 receive(data: String) 메서드에서 받아요.
이때 전달되는 데이터는 Base64 + URI 인코딩된 JSON 문자열이에요.
따라서 Base64 디코딩 → URI 디코딩 → JSON 파싱 순서로 처리해야 해요.
// Base64 → URI 디코딩 → JSON 파싱 (결과 받을 때)
public String decodedReceiveData(String data) {
String decoded = new String(Base64.decode(data, 0));
return decodeURIComponent(decoded);
}
private String decodeURIComponent(String decoded) {
String decodedURI = null;
try {
decodedURI = URLDecoder.decode(decoded, "UTF-8")
.replaceAll("%20", "\\+")
.replaceAll("!", "\\%21")
.replaceAll("'", "\\%27")
.replaceAll("\\(", "\\%28")
.replaceAll("\\)", "\\%29")
.replaceAll("~", "\\%7E");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return decodedURI;
}
2. 결과 수신 방식
eKYC 인증 결과를 수신하는 방식은 두 가지 중 선택할 수 있어요.
postMessage 방식은 결과 메시지를 프론트에서 그대로 받아서 처리하는 방식이에요.
2) postMessage + APIpostMessage + API 방식은 postMessage에서 전달받은 일부 값(id, result_type)을
바탕으로 서버에서 전체 결과를 조회해요.
API 방식은 보안을 강화할 수 있지만 아래와 같은 절차를 추가로 진행해야 해요.
- 유스비 담당자에게 문의하여 reviewer account 를 받아야 해요.
- reviewer account로 전달받은
customer_id,username,password로 API를 조회하여 결과 수신용 Access Token을 취득해요.
• 결과 수신용 Access Token 취득하기
-
[POST]
https://kyc-api-swagger.useb.co.kr/Request
{
"customer_id": 1,
"username": "samsungAdmin",
"password": "password123!"
}Response
{
"company": {
"name": "samsung",
"industry": 1,
"phone_number": "1500-0000"
},
"role": 1,
"name": "samsung_reviewer",
"username": "Reviewer0001",
"is_temp_password": true,
"token": "<token>",
"expire": "2022-01-06T11:41:42+09:00",
"api_response": {
"result_code": "N100",
"result_message": "OK."
}
}
- 취득한 Access Token과 postMessage 값 중
id,result_type을 활용해 API를 호출해요.
• 서버에 API 호출해 전체 결과 받아오기
취득한 Access Token은 HTTP 요청의 Authorization 헤더에 적용해 주세요.
아래 내용을 확인해 result_type 에 해당하는 API를 호출하면 전체 결과를 확인할 수 있어요.
1: Automatic approval (자동승인대상)
2 : Automatic rejection (자동거부대상)
5 :Manual review target (수동심사대상)
- result_type = 1, "auto_approve" / result_type = 2, "auto_reject"
-
[GET]
https://kyc-api.useb.co.kr/review/results/{id}- "auto_approve" : 3회 안에 진위확인 성공시
- "auto_reject" : 3회 진위확인 실패시
- "auto_approve" : 3회 안에 진위확인 성공시
- result_type = 5, "wait_review"
-
[GET]
https://kyc-api.useb.co.kr/review/manuals/{id} - OCR 판독 후에 개인정보를 수정한 경우, 사본으로 판별된 경우 등등
- 수동심사 대상인 경우에도 마지막 화면의 문구 변경은 가능합니다.
-
[GET]
- get attachment file (EDD 강화된 고객확인 서비스 사용시)
-
[GET]
https://kyc-api.useb.co.kr/attachments/{id}
-
[GET]
3. 결과 처리 예제
파싱된 JSON의 result 값에 따라 분기 처리하시면 돼요. 예제는 콘솔 출력이지만, 실제 서비스에서는 화면 전환/알림/재시도/서버 검증 등 비즈니스 로직으로 연결하세요.
@JavascriptInterface
public void receive(String data) throws JSONException {
String decodedData = decodedReceiveData(data);
JSONObject jsonObject = new JSONObject(decodedData);
String resultData = jsonObject.getString("result");
if (resultData.equals("success")) {
Log.d("success", "KYC 작업이 성공했습니다.");
} else if (resultData.equals("failed")) {
Log.d("failed", "KYC 작업이 실패했습니다.");
}
if (resultData.equals("complete")) {
Log.d("complete", "KYC가 완료되었습니다.");
} else if (resultData.equals("close")) {
Log.d("close", "KYC가 완료되지 않았습니다.");
}
finish();
}
Q. postMessage와 receive 함수는 어떻게 연결되나요?
ㄴ A. 웹에서 지정한
인터페이스 이름(alcherakyc)과 @JavascriptInterface가 연결 고리 역할을 해요.
Q. result 값은 어디서 확인하나요?
ㄴ A. JSON 데이터 안의 result 필드에서 확인해요.
Q. postMessage로 받은 결과가 어떤 형식인지 모르겠어요.
ㄴ A. base64로 인코딩된 JSON 문자열이에요. 디코딩 후 JSON으로 파싱해야 실제 데이터를 볼 수 있어요.
연동 완료
인증 화면을 띄우고, 결과까지 정상적으로 받아 처리했다면 연동이 완료된 거예요.
운영 환경에 반영하기 전에는 다양한 기기와 브라우저 환경에서 QA 테스트를 꼭 진행해 주세요.