에스크로
에스크로 서비스 연동하기
NHN KCP 에스크로(Escrow)는 고객이 결제한 금액을 NHN KCP가 먼저 안전하게 보관하고, 고객이 상품을 정상적으로 받았다고 확인한 뒤 가맹점에 대금을 지급하는 서비스이며 현금성 결제수단인 계좌이체와 가상계좌 결제에서 제공됩니다.
상품 배송, 교환, 환불 과정에서 발생할 수 있는 분쟁을 줄이기 위해 결제 대금의 보관과 지급 과정을 NHN KCP가 중간에서 관리합니다.
이를 통해 고객과 가맹점 모두 더 안전하게 거래할 수 있습니다.
에스크로는 기존 표준결제 연동 방식에 에스크로 관련 파라미터만 추가해 사용할 수 있습니다.
이 가이드에서는 거래등록, 결제창 호출, 결제 응답, 상태 변경, Webhook 처리에 필요한 에스크로 추가 파라미터를 안내합니다.
에스크로 관련 법률
에스크로 특징
대금 보관 서비스
고객이 구매확인을 완료할 때까지 NHN KCP가 결제 대금을 안전하게 보관합니다. 이를 통해 거래 사고를 예방할 수 있습니다.
배송·구매확인 관리
결제 완료 후 배송 시작, 구매확인, 대금 지급까지 거래 상태를 단계별로 관리합니다.
현금성 결제수단
계좌이체와 가상계좌 결제에서 제공됩니다. 표준결제 연동 방식에 에스크로 파라미터를 추가해 사용할 수 있습니다.
장바구니 상품 정보
에스크로 배송 안내 메일에 표시할 상품 정보(상품명, 수량, 가격)를 장바구니 파라미터에 담아 전달합니다.
에스크로 서비스 과정
취소 거부
에스크로 결제는 일반 결제와 달리 결제 이후에도 주문과 배송 상태를 함께 관리해야 합니다.
에스크로에서 처리하는 주요 업무는 배송시작, 정산보류, 즉시취소, 취소, 발급계좌해지(가상계좌), 구매확인 후 취소입니다.
해당 업무는 NHN KCP 파트너관리자에서 처리할 수 있으며, 각 업무의 상세 내용은 아래와 같습니다.
결제가 승인되면 고객에게 상품을 배송한 뒤, 에스크로 거래 상태를 배송시작으로 변경합니다.
배송 시작 단계에서는 택배사명과 운송장 번호를 입력하며, 직접 배송하는 경우 자가배송으로 처리합니다.
배송시작 처리가 완료되어야 NHN KCP로부터 정산을 받을 수 있습니다.
배송정보를 입력하기 전에 고객이 구매취소를 요청한 경우, 가맹점에서 즉시취소를 요청하면 바로 취소 처리됩니다.
고객이 배송안내 메일에서 반품을 요청했거나, 배송된 상품을 고객 요청으로 취소해야 하는 경우에는 먼저 정산보류를 처리한 뒤 취소를 진행합니다.
배송 중이거나 배송이 완료된 후 고객이 구매취소를 요청한 경우, 정산보류 상태에서 상품을 돌려받은 뒤 취소를 요청하면 거래 취소가 완료됩니다.
가상계좌 결제에만 해당하는 업무로, 발급된 가상계좌를 해지합니다.
구매확인이 완료된 거래를 에스크로 상태 변경으로 취소합니다.
구매확인 후 환불 기능은 NHN KCP와 별도 계약이 필요하므로, 자세한 내용은 NHN KCP로 문의하세요.
정산 일정
배송 완료 후 구매확인까지 완료되면 정상 거래로 판단하며, 구매확인일로부터 2일 후 정산대금이 입금됩니다.
고객이 배송일로부터 5일 이내에 구매확인을 하지 않으면 상품을 정상 수령한 것으로 간주합니다.
이 경우 고객에게 자동구매확인 안내가 발송되며, 안내일로부터 2일 후 정산대금이 입금됩니다.
1. Mobile 거래등록 하기
Mobile 환경에서는 결제창 호출 전, 주문·결제 정보를 미리 NHN KCP 결제 서버에 등록하는 거래등록이 필요합니다.
거래등록 응답으로 받은 approval_key·PayUrl을 결제창 호출 시 사용합니다.
2. 장바구니 설정하기
에스크로를 사용하는 경우, 고객 결제가 완료된 뒤 가맹점이 배송 시작을 등록하면 결제창에 입력된 고객 이메일로 에스크로 배송 안내 메일이 발송됩니다.
배송 안내 메일에는 상품명, 수량, 가격 정보가 표시됩니다. 이 정보는 가맹점이 결제창 호출 시 전달한 장바구니 상품 정보 파라미터 값을 기준으로 표시됩니다.
장바구니 상품 정보 파라미터
good_info는 장바구니에 담긴 상품 정보를 하나의 문자열로 만들어 전달하는 파라미터입니다.
생성한 good_info는 order_info(주문데이터)에 저장한 뒤 결제창으로 전달합니다.
구분자 구조
good_info 문자열은 화면에는 보이지 않는 두 가지 제어문자를 구분자로 사용합니다.
| 구분자 | 역할 | 코드 |
|---|---|---|
| UNIT SEPARATOR | 한 상품 내에서 항목(seq, ordr_numb, good_name …)을 구분합니다. | chr(31) — String.fromCharCode(31) |
| RECORD SEPARATOR | 상품과 상품 사이를 구분합니다. | chr(30) — String.fromCharCode(30) |
구조를 정리하면 아래와 같습니다.
// 상품 1개의 구조 (항목 사이에 chr31) seq=1 [chr31] ordr_numb=주문번호 [chr31] good_name=상품명 [chr31] good_cntx=수량 [chr31] good_amtx=금액 // 상품 여러 개일 때 (상품 사이에 chr30) 상품1 [chr30] 상품2 [chr30] 상품3
올바른 예시 코드
function create_goodInfo() { var chr30 = String.fromCharCode(30); //상품 구분자 (RECORD SEPARATOR) var chr31 = String.fromCharCode(31); //항목 구분자 (UNIT SEPARATOR) var good_info = "seq=1" + chr31 + "ordr_numb=20060310_0001" + chr31 + "good_name=양말" + chr31 + "good_cntx=2" + chr31 + "good_amtx=1000" + chr30 + "seq=2" + chr31 + "ordr_numb=20060310_0002" + chr31 + "good_name=신발" + chr31 + "good_cntx=1" + chr31 + "good_amtx=1500" + chr30 + "seq=3" + chr31 + "ordr_numb=20060310_0003" + chr31 + "good_name=바지" + chr31 + "good_cntx=1" + chr31 + "good_amtx=1000"; document.order_info.good_info.value = good_info; v_frm.submit(); }
자주 하는 실수
| 실수 유형 | 설명 |
|---|---|
| chr30과 chr31을 반대로 사용 | chr31은 한 상품의 항목 구분, chr30은 상품 간 구분입니다. 뒤바뀌면 파싱 오류가 발생합니다. |
| 마지막 상품 뒤에 chr30 추가 | 마지막 상품 뒤에는 chr30을 붙이지 마세요. 빈 상품이 있는 것으로 인식될 수 있습니다. |
| 일반 문자(쉼표, 파이프 등)로 구분 | 반드시 ASCII 제어문자인 chr(30), chr(31)을 사용하세요. 일반 문자로 대체하면 정상 처리되지 않습니다. |
| seq 번호와 bask_cntx 불일치 | seq의 마지막 번호와 bask_cntx 값이 동일해야 합니다. 불일치 시 오류가 발생합니다. |
장바구니 개수
good_info에 담긴 상품 정보 개수를 bask_cntx 파라미터로 전달합니다.
예를 들어 seq가 3까지 있다면 bask_cntx 값도 3으로 입력하세요.
{
"bask_cntx":"3"
} good_info 항목 구조
| 항목 명 | 상품 정보 | 길이 |
|---|---|---|
| seq | 상품개수 일련번호 | 2 |
| ordr_numb | 상품 주문번호 | 40 |
| good_name | 상품 이름 | 30 |
| good_cntx | 상품 수량 | 2 |
| good_amtx | 상품 금액 | 12 |
3. 결제창 호출하기
거래등록이 끝나면 결제수단 인증과 결제 요청을 진행하기 위해 결제창을 호출합니다.
PC와 Mobile 환경에 따라 호출 방법이 다릅니다.
Mobile 결제창 호출
Mobile 환경에서는 거래등록 후 call_pay_form 함수를 호출합니다.
거래등록 응답으로 받은 PayUrl(결제창 호출 주소)에 order_info를 전달해 결제창을 호출합니다.
function call_pay_form() { var v_frm = document.order_info; var PayUrl = v_frm.PayUrl.value; v_frm.action = PayUrl.substring(0, PayUrl.lastIndexOf("/")) + "/jsp/encodingFilter/encodingFilter.jsp"; v_frm.submit(); }
<form name="order_info" method="post" action="PayUrl">
{
"site_cd":"T0007",
"pay_method":"BANK",
"currency":"410",
"shop_name":"NHN KCP SHOP",
"Ret_URL":"https://your-shop.example.com/return",
"approval_key":"J9z6rqeRrRIjGoxmPPQtpgcHyKIPdQiE35VBPEo1sQ=",
"PayUrl":"https://testsmpay.kcp.co.kr/pay/mobileGW.kcp",
"ordr_idxx":"TEST123456789",
"good_name":"운동화",
"good_mny":"1000",
"good_cd":"00",
"buyr_name":"홍길동",
"buyr_tel2":"010-1234-1234",
"escw_used":"Y",
"pay_mod":"Y",
"deli_term":"03",
"bask_cntx":"3",
"good_info":"seq=1...good_amtx=1000",
"rcvr_name":"홍길동",
"rcvr_tel1":"02-1234-1234",
"rcvr_tel2":"010-1234-1234",
"rcvr_mail":"rcvr@test.com",
"rcvr_zipx":"157864",
"rcvr_add1":"서울시 구로구 구로동",
"rcvr_add2":"A아파트 101동 101호"
} PC 결제창 호출
PC 환경에서는 결제창 스크립트를 불러온 뒤, jsf_pay 함수에서 KCP_Pay_Execute_Web 메서드로 order_info를 전달합니다.
테스트 환경 : https://testspay.kcp.co.kr/plugin/kcp_spay_hub.js
운영 환경 : https://spay.kcp.co.kr/plugin/kcp_spay_hub.js
function jsf_pay(form) { try { KCP_Pay_Execute_Web(form); // 결제창 호출 } catch (e) { /* 브라우저에서 결제창 정상 종료 시 throw되는 스크립트 종료 예외 */ } }
<form name="order_info" method="post" action="승인요청URL">
{
"site_cd":"T0007",
"site_name":"NHN KCP",
"currency":"410",
"pay_method":"010000000000",
"ordr_idxx":"TEST123456789",
"good_name":"운동화",
"good_mny":"1000",
"good_cd":"00",
"escw_used":"Y",
"pay_mod":"Y",
"deli_term":"03",
"bask_cntx":"3",
"good_info":"seq=1...good_amtx=1000",
"rcvr_name":"홍길동",
"rcvr_tel1":"02-1234-1234",
"rcvr_tel2":"010-1234-1234",
"rcvr_mail":"rcvr@test.com",
"rcvr_zipx":"157864",
"rcvr_add1":"서울시 구로구 구로동",
"rcvr_add2":"A아파트 101동 101호"
}결제창 호출 파라미터
신용카드 : CARD
계좌이체 : BANK
가상계좌 : VCNT
휴대폰 : MOBX
포인트 : TPNT
상품권 : GIFT ex) "pay_method" : "BANK" PC 결제수단 코드 값입니다. (12 Byte)
신용카드 : 100000000000
계좌이체 : 010000000000
가상계좌 : 001000000000
포인트 : 000100000000
휴대폰 : 000010000000
상품권 : 000000001000 ex) "pay_method" : "010000000000"
※ 거래등록 시 전송한 Ret_URL 값과 동일한 값을 결제창 호출 form에도 함께 전송해야 합니다.
※ 콜백 응답 Body는 EUC-KR로 인코딩되어 전달되므로, 가맹점 서버에서 디코딩 처리가 필요합니다.ex) "Ret_URL" : "https://your-shop.example.com/return"
※ 기관에 따라 리스크 관리 조치를 위한 쇼핑몰 관리 ID를 필수로 요청ex) "shop_user_id" : "hong123"
에스크로 필수 파라미터
에스크로 결제 처리 : Y, 일반 결제 처리 : Nex) "pay_mod" : "Y"
상품과 상품 사이는 RECORD SEPARATOR(chr(30))로 구분하고, 한 상품 안의 항목들은 UNIT SEPARATOR(chr(31))로 구분합니다.ex) "good_info" : "seq=1...good_amtx=1000"
신용카드 전용 옵션 파라미터
"" : 가맹점관리자 설정에 따릅니다.
"Y" : kcp_noint_quota 값에 따라 무이자로 표시됩니다. (가맹점관리자에 설정되어 있어야 합니다.)
"N" : 가맹점관리자 값을 무시하고 일반 할부로 처리됩니다.ex) "kcp_noint" : "Y"
이 값을 Y로 설정한 뒤 used_card에 노출할 신용카드 코드를 입력하면, 입력한 신용카드만 결제창에 노출됩니다.ex) "used_card_YN" : "Y"
가상계좌 추가 설정 파라미터
휴대폰 추가 설정 파라미터
휴대폰 결제는 Guide > 휴대폰 결제를 확인하세요.ex) "used_mobx" : "SKT:KTF:LGT"
포인트 추가 설정 파라미터
도서문화상품권: SCBL, 컬쳐랜드: SCCL, OK 캐쉬백: SCSK, 베네피아복지포인트: SCWB
상품권 추가 설정 파라미터
도서문화상품권: SCBL, 컬쳐랜드: SCCL, OK 캐쉬백: SCSK, 베네피아복지포인트: SCWB
추가옵션 파라미터
- 로고 파일은 GIF, JPG 파일만 지원합니다.
- 최대 크기는 150 X 50 미만입니다.
- 이미지 파일을 150 X 50 이상으로 설정하거나 이 파라미터를 생략하면 site_name 값이 표시됩니다.
※ site_logo 설정 시 결제창 호출이 느려질 수 있습니다.ex) "site_logo" : "https://test.kcp.co.kr/logo.jpg"
"", "0" : 일반결제
"1" : 제공기간
※ 기본값은 일반결제입니다.ex) "good_expr" : "0"
※ 복합과세 전용 사이트코드로 계약한 가맹점에만 해당합니다.ex) "comm_tax_mny" : "909"
※ 복합과세 전용 사이트코드로 계약한 가맹점에만 해당합니다.ex) "comm_free_mny" : "0"
※ 복합과세 전용 사이트코드로 계약한 가맹점에만 해당합니다.ex) "comm_vat_mny" : "91"
4. 결제창 인증 결과
결제창에서 인증이 완료되면 인증 결과 데이터가 가맹점으로 전달됩니다.
Mobile 환경에서는 거래등록 시 지정한 Ret_URL로 인증 결과 데이터가 리턴되고, PC 환경에서는 m_Completepayment 콜백 함수를 통해 인증 결과가 전달됩니다.
인증 결과의 res_cd 값이 0000이면 인증 성공이며, 이때 받은 enc_data·enc_info로 결제 승인을 요청합니다.
결제창 인증 주요 파라미터
{
"res_cd":"0000",
"res_msg":"정상처리",
"tran_cd":"00100000",
"enc_data":"SnvXdGftIEjAequorkpNhJXc4u3GRuotLHW9vyDDOhdeorM4DPXMJgJllEoRo6divo=",
"enc_info":"3dsgjljlsSEGHsdccndsgnfdSDDhhbdrhffRbdfRYHFgfgnb=_"
} 결제창 인증 결과 파라미터
※ 임의로 변경할 수 없으며 결제창에서 내려 주는 값을 그대로 사용합니다.ex) "enc_data" : "SnvXdGftIEjAequorkpNhJXc4u3GRuotLHW9vyDDOhdeorM4DPXMJgJllEoRo6divo="
※ 임의로 변경할 수 없으며 결제창에서 내려 주는 값을 그대로 사용합니다.ex) "enc_info" : "3dsgjljlsSEGHsdccndsgnfdSDDhhbdrhffRbdfRYHFgfgnb=_"
5. 결제 승인 요청하기
전달받은 인증 결과 데이터(enc_data·enc_info)를 API 통신으로 결제 승인 요청하는 단계입니다.
승인 요청 데이터는 NHN KCP가 제공하는 API URL로 JSON 문자열 형태로 전송합니다.
승인 요청 전에는 결제창에서 받은 인증 결과와 실제 승인 요청 값이 일치하는지 확인하기 위해 결제 금액(ordr_mony)·주문번호(ordr_no)·결제수단(pay_type)을 함께 전달하여 결제정보를 검증하세요.
6. 결제 승인 응답
결제 승인에 성공하면 res_cd에 0000이 리턴되고, 결제수단별 응답 파라미터에 값이 채워져 함께 리턴됩니다.
응답 데이터를 확인해 결제수단별 결과 값을 가맹점 서버에 저장·관리하세요.
7. 웹훅
웹훅은 에스크로 거래 상태가 바뀌었을 때, 가맹점 시스템으로 변경 내용을 자동으로 알려주는 기능입니다.
가맹점이 Webhook URL을 등록해두면 NHN KCP가 해당 주소로 상태 변경 알림(Notification)을 전송합니다.
에스크로 거래는 결제 완료 이후에도 배송 시작, 정산보류, 취소처럼 상태가 계속 변경될 수 있습니다.
웹훅을 사용하면 가맹점이 거래 상태를 매번 직접 조회하지 않아도, 변경된 내용을 가맹점 시스템에서 자동으로 확인하고 주문 상태를 업데이트할 수 있습니다.
통보 대상 업무
에스크로 웹훅 통보 서비스는 아래 업무에서 거래 상태가 변경되는 경우 제공됩니다.
| 업무 | 설명 |
|---|---|
| 배송시작 | 가맹점이 상품 배송을 시작해 에스크로 거래 상태가 배송 단계로 변경된 경우입니다. |
| 정산보류 | 반품 요청이나 거래 취소 처리를 위해 정산을 잠시 보류한 경우입니다. |
| 즉시취소 | 배송정보 입력 전에 고객 요청 등으로 거래가 바로 취소된 경우입니다. |
| 취소 | 배송 중이거나 배송 완료 후 상품 회수 등 필요한 절차를 거쳐 거래가 취소된 경우입니다. |
| 발급계좌해지 | 가상계좌 결제에서 발급된 계좌가 해지된 경우입니다. |
| 구매확인 후 취소 | 고객의 구매확인이 완료된 이후, 별도 절차에 따라 거래가 취소된 경우입니다. |