KOVAN PG › 시작하기
TLS 1.2 REST/JSON HMAC-SHA256

KOVAN PG 통합 연동 가이드

결제연동(SimplePay)과 정산/지급대행 API를 하나의 문서에서 확인하세요. 모든 통신은 TLS 1.2를 사용하며, HMAC-SHA256 해시를 통해 무결성을 검증합니다.

15+
API 엔드포인트
TLS
1.2
필수 보안 프로토콜
7종
결제수단 지원
SHA256
해시 알고리즘

문서 구성

💳
결제연동 가이드
SimplePay v2.34 · 결제/취소/조회/Notification
📊
정산/지급대행 API
v1.0.2 · 정산조회/가맹점등록/지급요청

결제창 호출 방식 권장사항

🚨
IFRAME 방식 연동 지양 권고 금융보안원·카드사 등 주요 기관에서 보안 취약점을 이유로 IFRAME 방식의 결제창 연동을 지양하도록 권고하고 있습니다. IFRAME 내부에서 ISP/페이북 등 공인인증 팝업이 호출될 경우 부모창(parent window)을 정상적으로 참조하지 못해 인증 결과 전달이 실패하는 오류가 발생할 수 있습니다.
✅
팝업(Popup) 방식 사용 권장 KOVAN PG는 window.open() 팝업 방식을 공식 권장 연동 방식으로 채택하고 있습니다.
팝업 방식은 결제창이 독립된 최상위 window로 열리므로 ISP/페이북 등 카드사 인증 팝업과의 parent-child 통신이 안정적으로 동작합니다.
// 권장 호출 방식
window.name = 'myOpener'; // 부모창 이름 설정 (필수)
window.open('', 'pgPopup', opts).focus();
form.target = 'pgPopup';
form.submit();

도메인 정보

결제 연동 (SimplePay)

🔧 개발기
https://dev-epay.kovanpay.com
🚀 상용기
https://epay.kovanpay.com

정산/지급대행 API

🔧 개발기 (승인/정산)
http://220.117.220.108:30200
🚀 상용기 (승인/정산)
https://ema.kovanpay.com
🔧 개발기 (지급대행 등록)
http://220.117.220.108:30100
🚀 상용기 (지급대행 등록)
https://ebiz.kovanpay.com

현금영수증/리모트결제/매출전표

🔧 개발기
http://220.117.220.108:30200
🚀 상용기
https://ema.kovanpay.com

🔐공통사항 & 보안

모든 API 연동에서 공통으로 적용되는 인증 방식과 보안 규칙입니다.

API_KEY (암호화 Key)

상점 계약 체결 시 PG사에서 부여하는 32자리 고유키입니다. 반드시 서버 사이드에서만 사용하고, 절대 클라이언트에 노출되어서는 안 됩니다.

⚠️
API_KEY는 모든 통신의 무결성 검증에 사용되는 핵심 보안 키입니다. 노출 시 즉시 PG사에 재발급을 요청하세요.

유효성 검증 Hash 값 (HMAC-SHA256)

각 API 전문의 요청/응답 시 무결성 검증을 위해 HMAC-SHA256 알고리즘으로 Base64-Encoded Hash값을 생성해야 합니다.

java
// [생성규칙] message: orderno + orderdt + ordertm + reqamt
// secretKey: API_KEY (상점 별 고유키 값)

String message = "ORDER12345201706051322385000";
String secretKey = "ef5df61805ea166bb16867a9bf566082";

Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(
    secretKey.getBytes("UTF-8"), "HmacSHA256"
);
sha256_HMAC.init(secret_key);

String hashValue = Base64.encodeBase64String(
    sha256_HMAC.doFinal(message.getBytes("UTF-8"))
);
// 결과: YFiOzc2rY46gJb6OMM7nfz7W0l4mhhJzsbmWMYxYbc4=
php
// [생성규칙] message: orderno + orderdt + ordertm + reqamt
$message = "ORDER12345201706051322385000";
$secretKey = "ef5df61805ea166bb16867a9bf566082";

$hmac = hash_hmac('sha256', $message, $secretKey, true);
$hashValue = base64_encode($hmac);
// 결과: YFiOzc2rY46gJb6OMM7nfz7W0l4mhhJzsbmWMYxYbc4=
c# / asp.net
string message = "ORDER12345201706051322385000";
string secretKey = "ef5df61805ea166bb16867a9bf566082";

UTF8Encoding encoding = new UTF8Encoding();
byte[] keyBytes = encoding.GetBytes(secretKey);
HMACSHA256 hmacsha256 = new HMACSHA256(keyBytes);
byte[] messageBytes = encoding.GetBytes(message);
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
string hashValue = Convert.ToBase64String(hashmessage);

TLS 통신 프로토콜

🔒
서버와 클라이언트 간 모든 HTTPS 통신은 TLS 1.2를 적용해야 합니다. AES 256-GCM 암호화와 SHA-2 해시를 사용합니다. TLS 1.0/1.1 및 SSL은 사용 불가합니다.

User-Agent 규칙

⚠️
기본 User-Agent 사용 금지: PHP/x.x.x, curl/x.x.x, Java/x.x.x, Python-urllib/x.x.x 등은 WAF/API Gateway에 의해 차단될 수 있습니다.
권장 형식: 서비스명, 버전, 플랫폼, 연락처를 포함한 식별 가능한 UA를 사용하세요.
금지 사항: CR/LF 제어문자, 비ASCII 문자(이모지/한글), 과도한 길이

Chrome 141, 142 버전 로컬 네트워크 접근 권한 활성화 대응 가이드

계좌이체 결제 시 보안 프로그램이 계속 다운로드되는 현상에 대한 대응입니다. Chrome 141·142 버전에 도입된 로컬 네트워크 접근 권한 확인(Local Network Access Check) 기능이 결제 모듈과 로컬 보안 프로그램 간 통신을 차단하여 발생하며, 아래 브라우저 플래그를 Disabled로 설정하면 해결됩니다.

⚠️
결제하는 PC의 브라우저 주소창에 아래 주소를 입력해 이동한 뒤, 해당 항목을 Disabled로 변경하고 브라우저를 재시작하세요.
  • 크롬: chrome://flags/#local-network-access-check
  • 엣지: edge://flags/#local-network-access-check
ℹ️
이 플래그는 결제를 진행하는 사용자 PC의 브라우저 설정으로, 서버·가맹점 코드 수정과는 무관합니다. 브라우저 정식 버전에서 해당 플래그가 제거될 수 있으므로, 근본 대응은 로컬 보안 프로그램을 최신 버전으로 갱신하는 것입니다.

📊결제처리 Flow

결제요청부터 승인완료까지의 전체 프로세스를 확인하세요.

⚠️
결제창 호출 시 IFRAME 방식 사용 금지 IFRAME 내에서 결제창을 호출하면 카드사 인증(ISP/페이북 등) 팝업이 parent window를 찾지 못해 "부모창이 없습니다" 오류와 함께 결제가 중단됩니다. 반드시 window.open() 팝업 방식으로 연동하시기 바랍니다.

결제요청 처리 Flow

1
상품구매 요청

가맹점 사이트에서 고객이 상품구매를 요청합니다.

2
결제요청 전송

결제요청 정보를 PG결제서버로 전송합니다. 요청금액 변조 방지를 위한 checkHash 값을 함께 전송합니다.

3
통합결제페이지 응답

PG결제서버에서 제공하는 통합결제 페이지를 표시합니다.

4
결제정보 입력

고객이 통합결제 페이지를 통해 신용카드 결제 정보를 입력합니다.

5
인증페이지 응답

PG결제서버에서 입력된 결제 정보에 따른 인증페이지를 표시합니다.

6
인증정보 입력

인증페이지에서 고객이 인증정보를 입력하여 인증 요청을 합니다.

7
인증결과 전달

인증 요청을 하면 PG결제서버가 인증 결과를 받아 통합결제 페이지에 표시합니다.

8
결제승인 요청

통합결제 페이지에서 인증 결과를 확인하여 결제 승인을 요청합니다.

9
결제승인 결과 전달

PG결제서버가 승인 결과를 Return URL로 전달합니다.

취소요청 처리 Flow

1
승인취소 요청

가맹점 서버에서 PG결제서버로 승인취소를 요청합니다.

2
승인취소 결과 전달

PG결제서버에서 승인취소 결과를 전달합니다.

💳결제요청

온라인 결제 페이지로 고객을 이동시켜 결제를 진행하는 API입니다.

URL 정보

🔧 개발기
https://dev-epay.kovanpay.com
🚀 상용기
https://epay.kovanpay.com
구분URL
웹 브라우저PG도메인/paypage/common/mainFrame.pay
모바일PG도메인/mobilepage/common/mainFrame.pay
POST /paypage/common/mainFrame.pay 결제요청 ▼
Content-Type: application/x-www-form-urlencoded
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDANFIX 15YPG에서 부여한 상점 ID예시: M20161206113241
rUrlReturn URLANSMAX 1024Y결제 결과를 Return받을 URL예시 : http://localhost/result.pay
rMethodReturn Http메소드AMAX 10Y결제 결과를 Return 받을 Http 메소드 예시 : POST
payGroup결제 그룹AFIX 3Y결제 그룹. GEP(일반), KKP(카카오페이), NVP(네이버페이), APP(애플페이), TSP(토스페이), SSP(삼성페이), PCP(페이코), LTP(엘페이), SGP(SGP페이)
payType결제수단ASMAX 2Y결제 수단. GEP: CC,BA,VA / KKP: CC,VO / NVP: CC,VO / APP: CC / TSP: CC,VO / SSP: CC / PCP: CC,VO / LTP: CC / SGP: CC
buyItemnm상품명ANMAX 80Y상점 구매 상품명예시: 오이비누
buyReqamt상품가격NMAX 8Y상점 구매금액. 반드시 숫자만 포함 예시: 5000
buyItemcd상품 코드ANMAX 10Y상점 판매상품코드예시: oiSoap
buyerid구매자 IDANMAX 20O상점 구매자 ID 카카오페이의 경우 필수예시: gildonghong
buyernm구매자명AMAX 50Y상점 구매자명예시: 홍길동
buyerEmail구매자e-mailANSMAX 50O상점 구매자 Email 주소예시: gildong2@naver.com
orderno주문번호ANMAX 20Y상점 주문번호 예시: T2017010100001
orderdt주문 일자NFIX 8Y상점 주문 일자 (YYYYMMDD)
ordertm주문 시간NFIX 6Y상점 주문 시간 (HHMMSS)
taxExemptYn비과세 구분A1O복합과세 Y / 비과세거래 D / 면세거래 F /그외 일반(기본)
taxExemptAmt면세/비과세금액NMAX 8O비과세금액/면세금액. 부가세 = (buyReqamt - taxExemptAmt) / 11
checkHash무결성 검증 HashANSMAX 128YHMAC-SHA256 Base64-Encoded. message: orderno+orderdt+ordertm+buyReqamt / secretKey: API KEY
reserved01가맹점예약필드1ANMAX 1024O응답 시 반환됨
reserved02가맹점예약필드2ANMAX 1024O응답 시 반환됨
returnAppUrlReturn App Scheme UriANSMAX 1024O모바일APP 결제의 경우 필수
notiUseYnL2 즉시통보 옵트인AFIX 1OY 설정 시 승인 즉시 rUrl로 결과를 1회 추가 전송(「L2 승인결과 즉시통보」 참조). 미설정/공백 시 기존과 동일 NEW
간편결제 현금성 거래 전용
bizMode발급구분NFIX 2O현금영수증 발급구분. 00: 개인 / 10: 법인 NEW
idInfo발급정보ANMAX 30O현금영수증 발급정보 (휴대폰번호 또는 발급 사업자번호) 예시: 01012345678 NEW
SGP 간편결제 전용
phoneNo휴대폰번호NMAX 11OSGP페이(payGroup=SGP) 결제 시 구매자 휴대폰번호. 숫자만 입력 예시: 01012345678 NEW
신용카드 전용
billYnBillKey 등록 여부A1OBillKey 발급 요청 시 Y 설정. 결제 후 BILL_KEY가 응답에 포함됨
billKeyBillKey 결제ANMAX 32O카드번호 대체로 사용할, 발급받은 BillKey 값
💡
아래 항목은 모든 결제수단 공통으로 포함됩니다:
RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02
⚠️
notiUseYn=Y로 옵트인한 상점은 카카오페이·네이버페이·계좌이체(BA) 응답에도 CHECK_HASH가 새로 포함됩니다(신용카드는 옵트인 여부와 무관하게 항상 포함). 미옵트인 상점의 응답은 기존과 동일합니다. 자세한 내용은 「L2 승인결과 즉시통보(옵트인)」 섹션을 참고하세요. NEW
🧾
2차PG 가맹점의 경우 카카오머니, 토스머니, 네이버포인트, 페이코머니 등 현금성 결제수단은 현금영수증 발급처리를 위해 결제 요청 시 현금영수증 발행 정보(휴대폰번호, 사업자번호 등)를 전달해 주셔야 합니다.
고객정보 미전달 시 자진발급으로 현금영수증이 발행될 수 있습니다.
응답 파라미터 — 일반 신용카드 (GEP · CC)
항목ID항목명타입길이(byte)설명
공통부
RESULT_CODE결제결과코드ANMAX 20결과코드표 참조
RESULT_MSG결제결과메시지ANSMAX 1024
DRESULT_CODE가맹점결과코드ANMAX 20
DRESULT_MSG가맹점결과메시지ANSMAX 1024
PAY_METHOD결제수단AFIX 2CC/BA/VA/VO
TIDPG거래고유번호ANMAX 15PG사 거래고유번호
ORDERNO주문번호ANMAX 20상점 주문번호
RESERVED01가맹점예약필드1ANSMAX 1024
RESERVED02가맹점예약필드2ANSMAX 1024
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO / secretKey : API KEY
신용카드 추가 항목
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_METHOD": "CC", "TID": "210728130414390", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "CHECK_HASH": "3zhVYYVtEflnMMkn8P3J7u3eKjeLyt64doJw81O2fzA=",
  "APPROVNO": "63586137", "APPRODT": "20210728", "APPROTM": "113855",
  "APPROAMT": "5000", "ISSUE_CODE": "1102", "ISSUE_NAME": "현대카드",
  "PURCHASE_CODE": "1102", "PURCHASE_NAME": "현대카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "489016**********"
}
응답 파라미터 — 카카오페이 신용카드 (KKP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
MID상점IDANFIX 15카카오페이 전용
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "KKP", "PAY_METHOD": "CC",
  "TID": "210728130414386", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "C",
  "CARD_NO": "510737**********", "MID": "M20200203113418"
}
응답 파라미터 — 카카오페이 머니 (KKP · VO)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
PAY_GROUP결제그룹AFIX 3KKP
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
MID상점IDANFIX 15
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "KKP", "PAY_METHOD": "VO",
  "TID": "210728130414388", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPRODT": "20210728", "APPROTM": "113730",
  "APPROAMT": "5000", "MID": "M20200203113418"
}
응답 파라미터 — 네이버페이 신용카드 (NVP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
MID상점IDANFIX 15상점ID (카카오페이만)
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키ANMAX 20
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "NVP", "PAY_METHOD": "CC",
  "TID": "210728130414386", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "C",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "3zhVYYVtEflnMMkn8P3J7u3eKjeLyt64doJw81O2fzA=",
  "VAN_RECV_KEY": ""
}
응답 파라미터 — 네이버페이 포인트 (NVP · VO)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
PAY_GROUP결제그룹AFIX 3NVP
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
MID상점IDANFIX 15
BUY_REQAMT상품가격NMAX 15
RESULT_DET_CODE결제결과 상세코드ANMAX 20
RESULT_DET_MSG결제결과 상세메시지ANSMAX 1024
PAY_KEY인증추적키ANSMAX 255
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "NVP", "PAY_METHOD": "VO",
  "TID": "210728130414388", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPRODT": "20210728", "APPROTM": "113730",
  "APPROAMT": "5000", "MID": "M20200203113418",
  "BUY_REQAMT": "5000",
  "RESULT_DET_CODE": "EC0000", "RESULT_DET_MSG": "성공"
}
응답 파라미터 — 계좌이체 (GEP · BA)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
MID상점IDANFIX 15상점
BANK_CD은행코드NFIX 3결제 은행코드
BANK_NM은행명AMAX 20결제 은행명
ACCT_NO계좌번호ANMAX 20결제 계좌번호
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "TID": "210728130414394", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "MID": "M20200203113418",
  "BANK_CD": "002", "BANK_NM": "산업은행", "ACCT_NO": "08724"
}
응답 파라미터 — 가상계좌 (GEP · VA)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO
TRBEGIN입금시작일NFIX 14YYYYMMDDHHMMSS
TREND입금종료일NFIX 14YYYYMMDDHHMMSS
BUY_REQAMT결제금액NMAX 15
BANK_CD은행코드NFIX 3
BANK_NM은행명AMAX 20
ACCT_NO계좌번호ANMAX 20발급된 가상계좌번호
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_METHOD": "VA", "TID": "210728130414389", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "CHECK_HASH": "M/N65K6T1Zc5XEBl5tERsENX/tGLzM+13w/ECb2kWXY=",
  "TRBEGIN": "20210728113820", "TREND": "20210807113806",
  "BUY_REQAMT": "5000",
  "BANK_CD": "020", "BANK_NM": "우리은행", "ACCT_NO": "27995319418878"
}
🔑
결제 요청 시 billYn=Y를 함께 전송하면, 승인 후 응답에 BILL_KEY가 포함됩니다.
발급된 BILL_KEY는 이후 카드번호 없이 반복 결제에 사용할 수 있습니다.
요청 파라미터 — BILLKEY 발급 (GEP · CC · billYn=Y)
항목ID항목명타입길이(byte)필수설명
공통 요청 파라미터 (결제요청 참고)
mid상점 IDANFIX 15Y예시: M20260114117276
rUrlReturn URLANSMAX 1024Y결제 결과를 Return받을 URL예시 : http://localhost/result.pay
rMethodReturn Http메소드AMAX 10Y결제 결과를 Return 받을 Http 메소드 예시 : POST
payGroup결제 그룹AFIX 3YGEP
payType결제수단ASMAX 2YCC
buyItemnm상품명ANMAX 80Y상점 구매 상품명예시: 오이비누
buyReqamt상품가격NMAX 8Y상점 구매금액. 반드시 숫자만 포함 예시: 5000
buyItemcd상품 코드ANMAX 10Y상점 판매상품코드예시: oiSoap
buyerid구매자 IDANMAX 20O상점 구매자 ID 카카오페이의 경우 필수예시: gildonghong
buyernm구매자명AMAX 50Y상점 구매자명예시: 홍길동
buyerEmail구매자e-mailANSMAX 50O상점 구매자 Email 주소예시: gildong2@naver.com
orderno주문번호ANMAX 20Y예시: ORDER20260429093952
orderdt주문 일자NFIX 8YYYYYMMDD
ordertm주문 시간NFIX 6YHHMMSS
checkHash무결성 검증 HashANSMAX 128YHMAC-SHA256 Base64. message: orderno+orderdt+ordertm+buyReqamt
reserved01가맹점예약필드1ANMAX 1024O응답 시 반환됨
reserved02가맹점예약필드2ANMAX 1024O응답 시 반환됨
BILLKEY 발급 전용
billYnBillKey 등록 여부A1YBillKey 발급 시 반드시 Y 설정
요청 예시
form-data
mid=M20260114117276
payGroup=GEP
payType=CC
orderno=ORDER20260429093952
orderdt=20260429
ordertm=093952
buyItemnm=테스트_상품
buyReqamt=1004
buyItemcd=item
buyerid=kovan_Dev
buyernm=코밴_Dev
buyerEmail=test@kovan.com
reserved01=reserved01
reserved02=reserved02
checkHash=G/Z/kOICS67b6eomKmU2kA2ODfOw7AHnGivjXHHRUS4=
billYn=Y
rUrl=http://220.117.220.108:50500/auth/response.action
rMethod=POST
응답 파라미터 — BILLKEY 발급
항목ID항목명타입길이(byte)설명
공통부
RESULT_CODE결과코드ANMAX 200000 성공
RESULT_MSG결과메시지ANSMAX 1024
DRESULT_CODE가맹점결과코드ANMAX 20EC0000 성공
DRESULT_MSG가맹점결과메시지ANSMAX 1024
MID상점 IDANFIX 15
PAY_METHOD결제수단AFIX 2CC
CHECK_HASH무결성 검증 HashANSMAX 128
RESERVED01가맹점예약필드1ANSMAX 1024
RESERVED02가맹점예약필드2ANSMAX 1024
BILLKEY 발급 추가 항목
ISSUE_CODE발급사코드NFIX 4예시: 1108
ISSUE_NAME발급사명AMAX 20예시: NH농협카드
BILL_KEYBillKeyANMAX 32발급된 BillKey. 이후 반복 결제에 사용 예시: bk8718565260429
응답 예시
json
{
  "RESULT_CODE": "0000",
  "RESULT_MSG": "정상완료",
  "DRESULT_CODE": "EC0000",
  "DRESULT_MSG": "SUCCESS",
  "MID": "M20260114117276",
  "PAY_METHOD": "CC",
  "CHECK_HASH": "G/Z/kOICS67b6eomKmU2kA2ODfOw7AHnGivjXHHRUS4=",
  "ISSUE_CODE": "1108",
  "ISSUE_NAME": "NH농협카드",
  "BILL_KEY": "bk8718565260429",
  "RESERVED01": "reserved01",
  "RESERVED02": "reserved02"
}
🔑
발급된 BILL_KEY를 billKey 파라미터로 전달하여 카드번호 없이 결제를 진행합니다.
최초 BILLKEY 발급 시 저장한 BILL_KEY 값을 그대로 사용합니다.

POST /payment/directApproval.pay

요청 파라미터 — BILLKEY 결제 (GEP · CC · billKey)
항목ID항목명타입길이(byte)필수설명
공통 요청 파라미터 (결제요청 참고)
mid상점 IDANFIX 15Y예시: M20260114117276
rUrlReturn URLANSMAX 1024Y결제 결과를 Return받을 URL예시 : http://localhost/result.pay
rMethodReturn Http메소드AMAX 10Y결제 결과를 Return 받을 Http 메소드 예시 : POST
payGroup결제 그룹AFIX 3YGEP
payType결제수단ASMAX 2YCC
buyItemnm상품명ANMAX 80Y상점 구매 상품명예시: 오이비누
buyReqamt상품가격NMAX 8Y상점 구매금액. 반드시 숫자만 포함 예시: 5000
buyItemcd상품 코드ANMAX 10Y상점 판매상품코드예시: oiSoap
buyerid구매자 IDANMAX 20O상점 구매자 ID 카카오페이의 경우 필수예시: gildonghong
buyernm구매자명AMAX 50Y상점 구매자명예시: 홍길동
buyerEmail구매자e-mailANSMAX 50O상점 구매자 Email 주소예시: gildong2@naver.com
orderno주문번호ANMAX 20Y예시: ORDER20260429093952
orderdt주문 일자NFIX 8YYYYYMMDD
ordertm주문 시간NFIX 6YHHMMSS
checkHash무결성 검증 HashANSMAX 128YHMAC-SHA256 Base64. message: orderno+orderdt+ordertm+buyReqamt
reserved01가맹점예약필드1ANMAX 1024O응답 시 반환됨
reserved02가맹점예약필드2ANMAX 1024O응답 시 반환됨
BILLKEY 결제 전용
billKeyBillKeyANMAX 32Y카드번호 대체로 사용할, 발급받은 BILL_KEY 값 예시: bk8718565260429
요청 예시
form-data
mid=M20260114117276
payGroup=GEP
payType=CC
orderno=ORDER20260429093952
orderdt=20260429
ordertm=093952
buyItemnm=테스트_상품
buyReqamt=1004
buyItemcd=item
buyerid=kovan_Dev
buyernm=코밴_Dev
buyerEmail=test@kovan.com
reserved01=reserved01
reserved02=reserved02
checkHash=G/Z/kOICS67b6eomKmU2kA2ODfOw7AHnGivjXHHRUS4=
billKey=bk8718565260429
rUrl=http://220.117.220.108:50500/auth/response.action
rMethod=POST
응답 파라미터 — BILLKEY 결제
항목ID항목명타입길이(byte)설명
공통부
RESULT_CODE결과코드ANMAX 200000 성공
RESULT_MSG결과메시지ANSMAX 1024
DRESULT_CODE가맹점결과코드ANMAX 20EC0000 성공
DRESULT_MSG가맹점결과메시지ANSMAX 1024
MID상점 IDANFIX 15
PAY_METHOD결제수단AFIX 2CC
CHECK_HASH무결성 검증 HashANSMAX 128
RESERVED01가맹점예약필드1ANSMAX 1024
RESERVED02가맹점예약필드2ANSMAX 1024
BILLKEY 결제 추가 항목
ISSUE_CODE발급사코드NFIX 4예시: 1108
ISSUE_NAME발급사명AMAX 20예시: NH농협카드
BILL_KEYBillKeyANMAX 32결제에 사용된 BillKey 예시: bk8718565260429
응답 예시
json
{
  "RESULT_CODE": "0000",
  "RESULT_MSG": "정상완료",
  "DRESULT_CODE": "EC0000",
  "DRESULT_MSG": "SUCCESS",
  "MID": "M20260114117276",
  "PAY_METHOD": "CC",
  "CHECK_HASH": "G/Z/kOICS67b6eomKmU2kA2ODfOw7AHnGivjXHHRUS4=",
  "ISSUE_CODE": "1108",
  "ISSUE_NAME": "NH농협카드",
  "BILL_KEY": "bk8718565260429",
  "RESERVED01": "reserved01",
  "RESERVED02": "reserved02"
}

⚡간편결제

애플페이, 토스페이, 삼성페이, 페이코, 엘페이, SGP페이 연동 가이드입니다. 연동 전문 포맷은 네이버페이 기준을 따릅니다.

URL 정보

🔧 개발기
https://dev-epay.kovanpay.com
🚀 상용기
https://epay.kovanpay.com
구분URL
웹 브라우저PG도메인/paypage/common/mainFrame.pay
모바일PG도메인/mobilepage/common/mainFrame.pay
💡
지원 결제수단 요약
APP(애플페이): CC  |  TSP(토스페이): CC, VO  |  SSP(삼성페이): CC  |  PCP(페이코): CC, VO  |  LTP(엘페이): CC  |  SGP(SGP페이): CC
POST /paypage/common/mainFrame.pay 간편결제 요청 ▼
Content-Type: application/x-www-form-urlencoded
요청 파라미터 (결제요청 공통 파라미터와 동일)
항목ID항목명타입길이(byte)필수설명
mid상점 IDANFIX 15YPG에서 부여한 상점 ID
payGroup결제 그룹AFIX 3YAPP / TSP / SSP / PCP / LTP / SGP
payType결제수단ASMAX 2YCC 또는 VO (수단별 지원 여부 상단 참고)
orderno주문번호ANMAX 20Y상점 주문번호
orderdt주문 일자NFIX 8YYYYYMMDD
ordertm주문 시간NFIX 6YHHMMSS
buyItemnm상품명ANMAX 80Y상점 구매 상품명
buyReqamt상품가격NMAX 8Y결제금액 (숫자만)
buyItemcd상품 코드ANMAX 10Y상점 판매상품코드
buyerid구매자 IDANMAX 20O상점 구매자 ID
buyernm구매자명AMAX 50Y상점 구매자명
buyerEmail구매자 e-mailANSMAX 50O상점 구매자 Email
checkHash무결성 검증 HashANSMAX 128YHMAC-SHA256 Base64. message: orderno+orderdt+ordertm+buyReqamt
reserved01가맹점예약필드1ANMAX 1024O응답 시 반환됨
reserved02가맹점예약필드2ANMAX 1024O응답 시 반환됨
rUrlReturn URLANSMAX 1024Y결제 결과를 Return 받을 URL
rMethodReturn Http 메소드AMAX 10YPOST
간편결제 현금성 거래 전용
bizMode발급구분NFIX 2O현금영수증 발급구분. 00: 개인 / 10: 법인 NEW
idInfo발급정보ANMAX 30O현금영수증 발급정보 (휴대폰번호 또는 발급 사업자번호) 예시: 01012345678 NEW
SGP 간편결제 전용
phoneNo휴대폰번호NMAX 11OSGP페이(payGroup=SGP) 결제 시 구매자 휴대폰번호. 숫자만 입력 예시: 01012345678 NEW
💡
아래 항목은 모든 결제수단 공통으로 포함됩니다:
RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02
🧾
2차PG 가맹점의 경우 카카오머니, 토스머니, 네이버포인트, 페이코머니 등 현금성 결제수단은 현금영수증 발급처리를 위해 결제 요청 시 현금영수증 발행 정보(휴대폰번호, 사업자번호 등)를 전달해 주셔야 합니다.
고객정보 미전달 시 자진발급으로 현금영수증이 발행될 수 있습니다.
응답 파라미터 — 애플페이 (APP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
MID상점IDANFIX 15
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키ANMAX 20
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "APP", "PAY_METHOD": "CC",
  "TID": "210728130414391", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "3zhVYYVtEflnMMkn8P3J7u3eKjeLyt64doJw81O2fzA=",
  "VAN_RECV_KEY": ""
}
응답 파라미터 — 토스페이 신용 (TSP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
MID상점IDANFIX 15
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키ANMAX 20
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "TSP", "PAY_METHOD": "CC",
  "TID": "210728130414392", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "3zhVYYVtEflnMMkn8P3J7u3eKjeLyt64doJw81O2fzA=",
  "VAN_RECV_KEY": ""
}
응답 파라미터 — 토스페이 머니 (TSP · VO)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
PAY_GROUP결제그룹AFIX 3TSP
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
MID상점IDANFIX 15
BUY_REQAMT상품가격NMAX 15
RESULT_DET_CODE결제결과 상세코드ANMAX 20
RESULT_DET_MSG결제결과 상세메시지ANSMAX 1024
PAY_KEY인증추적키ANSMAX 255
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "TSP", "PAY_METHOD": "VO",
  "TID": "210728130414393", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPRODT": "20210728", "APPROTM": "113730",
  "APPROAMT": "5000", "MID": "M20200203113418",
  "BUY_REQAMT": "5000",
  "RESULT_DET_CODE": "EC0000", "RESULT_DET_MSG": "성공"
}
응답 파라미터 — 삼성페이 (SSP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
MID상점IDANFIX 15
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키ANMAX 20
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "SSP", "PAY_METHOD": "CC",
  "TID": "210728130414394", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "3zhVYYVtEflnMMkn8P3J7u3eKjeLyt64doJw81O2fzA=",
  "VAN_RECV_KEY": ""
}
응답 파라미터 — 페이코 신용 (PCP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
MID상점IDANFIX 15
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키ANMAX 20
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "PCP", "PAY_METHOD": "CC",
  "TID": "210728130414395", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "3zhVYYVtEflnMMkn8P3J7u3eKjeLyt64doJw81O2fzA=",
  "VAN_RECV_KEY": ""
}
응답 파라미터 — 페이코 머니 (PCP · VO)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
PAY_GROUP결제그룹AFIX 3PCP
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
MID상점IDANFIX 15
BUY_REQAMT상품가격NMAX 15
RESULT_DET_CODE결제결과 상세코드ANMAX 20
RESULT_DET_MSG결제결과 상세메시지ANSMAX 1024
PAY_KEY인증추적키ANSMAX 255
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "PCP", "PAY_METHOD": "VO",
  "TID": "210728130414396", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPRODT": "20210728", "APPROTM": "113730",
  "APPROAMT": "5000", "MID": "M20200203113418",
  "BUY_REQAMT": "5000",
  "RESULT_DET_CODE": "EC0000", "RESULT_DET_MSG": "성공"
}
응답 파라미터 — 엘페이 (LTP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
MID상점IDANFIX 15
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키ANMAX 20
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "LTP", "PAY_METHOD": "CC",
  "TID": "210728130414397", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "3zhVYYVtEflnMMkn8P3J7u3eKjeLyt64doJw81O2fzA=",
  "VAN_RECV_KEY": ""
}
응답 파라미터 — SGP페이 (SGP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호ANMAX 20
APPRODT결제승인일자NFIX 8YYYYMMDD
APPROTM결제승인시간NFIX 6HHMMSS
APPROAMT결제승인금액NMAX 15
ISSUE_CODE발급사코드NFIX 4
ISSUE_NAME발급사명AMAX 20
PURCHASE_CODE매입사코드NFIX 4
PURCHASE_NAME매입사명AMAX 20
QUOTA_MONTHS할부개월수NFIX 2
NOINT무이자구분AFIX 1
CHECKCD카드구분AFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호ANSMAX 16마스킹 처리된 카드번호
MID상점IDANFIX 15
CHECK_HASH무결성 검증 HashANSMAX 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키ANMAX 20
응답 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "SGP", "PAY_METHOD": "CC",
  "TID": "210728130414398", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "3zhVYYVtEflnMMkn8P3J7u3eKjeLyt64doJw81O2fzA=",
  "VAN_RECV_KEY": ""
}

🧾현금영수증 API 승인/취소

🔧 개발기
http://220.117.220.108:30200
🚀 상용기
https://ema.kovanpay.com/
POST /cashbill/v1/approval.out 현금영수증 승인 ▼
Content-Type: application/json
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDANFIX 15YPG에서 부여한 상점 ID
orderno주문번호ANMAX 20Y상점 주문번호
orderdt주문 일자NFIX 8YYYYYMMDD
ordertm주문 시간NFIX 6YHHMMSS
approveAmt승인 요청 금액NMAX 9Y
checkHash무결성검증ANSMAX 128Ymessage: orderno+orderdt+ordertm+approveAmt
customerType발급유형ANFIX 2Y소득공제: 00 / 지출증빙: 10
idInfo발급정보ANMAX 30Y핸드폰번호, 사업자번호 등 현금영수증 발급 정보
subMbsNo하위몰사업자번호NFIX 10O2차PG 하위 가맹점(최종 판매자) 사업자등록번호
응답 파라미터
항목ID항목명타입길이(byte)설명
RESULT_CODE처리 결과 코드ANMAX 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지ANSMAX 1024
DRESULT_CODE가맹점결과코드ANMAX 20
DRESULT_MSG가맹점결과메시지ANSMAX 1024
TIDPG거래고유번호ANMAX 15
TAX세금NMAX 8승인금액에 대한 세금
CLRAMT공급가액NMAX 8승인금액 – 세금
ORDERNO상점주문번호ANMAX 20
MID상점IDANFIX 15
APPROV_NO승인번호ANFIX 9
APPROV_AMT승인금액NMAX 8
POST /cashbill/v1/cancel.out 현금영수증 취소 ▼
Accept: application/json, Content-Type: application/json
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDANFIX 15Y상점 별로 부여되는 상점 ID
tidPG원거래고유번호ANMAX 15Y결제승인 시 PG사 원거래고유번호
cancelAmt취소금액NumericMAX 8Y-5000 형식. 반드시 숫자만 포함
checkHash유효성 검증 HashANSMAX 128Ymessage: tid+mid+cancelAmt
subMbsNo하위몰사업자번호NFIX 10O2차PG 하위 가맹점(최종 판매자) 사업자등록번호
응답 파라미터
항목ID항목명타입길이(byte)설명
RESULT_CODE처리 결과 코드ANMAX 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지ANSMAX 1024
DRESULT_CODE가맹점결과코드ANMAX 20
DRESULT_MSG가맹점결과메시지ANSMAX 1024
TIDPG거래고유번호ANMAX 15
TAX세금NMAX 8승인금액에 대한 세금
CLRAMT공급가액NMAX 8승인금액 – 세금
ORDERNO상점주문번호ANMAX 20
MID상점IDANFIX 15
APPROV_NO승인번호ANFIX 9
APPROV_AMT승인금액NMAX 8

🔄결제취소 요청

🔧 개발기
https://dev-epay.kovanpay.com
🚀 상용기
https://epay.kovanpay.com/
구분URL
온라인 / 오프라인(PG방식)PG도메인/webpay/cancel.pay
오프라인(VAN방식)PG도메인/offline/cancel.pay
POST /webpay/cancel.pay 온라인/오프라인(PG방식) 결제취소 ▼
Accept: application/json, Content-Type: application/json
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDANFIX 15Y상점 별로 부여되는 상점 ID
payGroup결제그룹AFIX 3YDefault: GEP
payType결제수단AFIX 2Y결제수단 코드
tidPG원거래고유번호ANMAX 15Y결제승인 시 PG사 원거래고유번호
cancelAmt취소금액NumericMAX 8Y반드시 숫자만 포함
checkHash유효성 검증 HashANSMAX 128Ymessage: tid+mid+cancelAmt
cancelReason취소 사유ANSMAX 200Y취소사유
cancelRequester취소 요청자NFIX 1Y1: 구매자, 2: 가맹점 관리자
orgApprovalCancel원거래 정보 수신AFIX 1OY: 응답에 원거래 승인정보 추가 수신 / N(기본): 미수신. 옵트인(미전달 시 N과 동일)
reserved01가맹점예약필드1ANSMAX 1024O
reserved02가맹점예약필드2ANSMAX 1024O
taxExemptYn비과세 구분AFIX 1O복합과세 Y / 비과세 D / 면세 F
taxExemptAmt면세/비과세금액NMAX 8O반드시 숫자만 포함
가상계좌 취소 추가 항목
refundBank환불계좌 은행코드NFIX 3Y은행코드표 참조
refundAcctno환불계좌 번호ANMAX 20Y
refundAcctholder환불계좌 예금주명AMAX 20Y
⚠️
CANCEL_AMT, ORDERNO, CHECKCD, PART_CANCEL, CANCEL_DT/CANCEL_TM, QUOTA_MONTHS, NOINT, APPROVNO/APPRONO, APPRODT/APPROVDT, APPROTM/APPROVTM, APPROAMT/APPROVAMT, CARDNO, VAN_RECV_KEY, PCH_TID 필드는 옵션 항목입니다. 요청 파라미터 orgApprovalCancel을 Y로 전달한 경우에만 동기 응답에 추가로 포함되며, 전달하지 않거나 N인 경우 수신되지 않습니다(기본 응답에는 결과코드/거래정보만 포함). 즉, 동기 응답 포함 여부는 요청 시점의 orgApprovalCancel 옵트인 값에 따라 결정됩니다.
※ 가맹점 관리자 페이지 Notification 설정의 「원거래 정보 수신」 체크 여부는 NOTI(웹훅) 수신 시에만 적용되며, 본 동기 응답과는 무관합니다.
응답 파라미터
항목ID항목명타입길이(byte)필수설명
RESULT_CODE처리 결과 코드ANMAX 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지ANSMAX 1024
DRESULT_CODE가맹점결과코드ANMAX 20
DRESULT_MSG가맹점결과메시지ANSMAX 1024
PAY_GROUP결제그룹AFIX 3GEP / KKP / NVP
PAY_METHOD결제수단AFIX 2결제수단 코드
TIDPG거래고유번호ANMAX 15
RESERVED01가맹점예약필드1ANSMAX 1024
RESERVED02가맹점예약필드2ANSMAX 1024
요청 시 orgApprovalCancel=Y인 경우에만 추가 수신 (옵션)
CANCEL_AMT취소금액NMAX 8취소금액 (옵션)
ORDERNO상점주문번호ANMAX 20(옵션)
CHECKCD카드구분AFIX 1신용: N / 체크: C (옵션)
PART_CANCEL부분취소여부AFIX 1부분취소: Y / 전체취소: N (옵션)
CANCEL_DT취소일자NFIX 8YYYYMMDD (옵션)
CANCEL_TM취소시각NFIX 6HHMMSS (옵션)
QUOTA_MONTHS할부개월수NFIX 2일시불: 00 (옵션)
NOINT무이자구분AFIX 1무이자: Y / 일반: N (옵션)
APPROVNO카드사 승인번호ANMAX 15(옵션)
APPRONO카드사 승인번호ANMAX 15APPROVNO 중복 필드 (옵션)
APPROVDT결제승인일자NFIX 8YYYYMMDD (옵션)
APPRODT결제승인일자NFIX 8APPROVDT 중복 필드 (옵션)
APPROVTM결제승인시간NFIX 6HHMMSS (옵션)
APPROTM결제승인시간NFIX 6APPROVTM 중복 필드 (옵션)
APPROVAMT원거래 승인금액NumberMAX 15(옵션)
APPROAMT원거래 승인금액NumberMAX 15APPROVAMT 중복 필드 (옵션)
CARDNO카드번호ANSMAX 20마스킹 처리 ※필드명에 언더스코어 없음 (옵션)
VAN_RECV_KEYVAN 거래고유키ANMAX 20(옵션)
PCH_TID매입요청고유번호ANMAX 15(옵션)
응답 예시
json
// 요청 시 orgApprovalCancel 미전달 또는 "N" (기본)
{
  "RESULT_CODE": "EC0000",
  "RESULT_MSG": "SUCCESS",
  "PAY_GROUP": "GEP",
  "PAY_METHOD": "CC",
  "TID": "260915130569707",
  "DRESULT_CODE": "EC0000",
  "DRESULT_MSG": "SUCCESS",
  "RESERVED01": "reserved01",
  "RESERVED02": "reserved02"
}

// 요청 시 orgApprovalCancel: "Y" (옵션 필드 추가 수신)
{
  "CHECKCD": "N",
  "RESULT_CODE": "EC0000",
  "APPRODT": "20260915",
  "VAN_RECV_KEY": "",
  "PCH_TID": "260916127520245",
  "APPROVAMT": "1004",
  "APPROVNO": "49108459",
  "RESULT_MSG": "SUCCESS",
  "APPROVTM": "142155",
  "PAY_METHOD": "CC",
  "CANCEL_TM": "142155",
  "NOINT": "N",
  "CARDNO": "536148**********",
  "APPROAMT": "1004",
  "APPROVDT": "20260915",
  "DRESULT_MSG": "SUCCESS",
  "CANCEL_AMT": "100",
  "PAY_GROUP": "GEP",
  "TID": "260915130569707",
  "PART_CANCEL": "Y",
  "DRESULT_CODE": "EC0000",
  "APPROTM": "142155",
  "CANCEL_DT": "20260915",
  "ORDERNO": "ORDER20260915142152",
  "RESERVED01": "reserved01",
  "QUOTA_MONTHS": "00",
  "APPRONO": "49108459",
  "RESERVED02": "reserved02"
}
POST /offline/cancel.pay 오프라인(VAN방식) 결제취소 ▼
Accept: application/json, Content-Type: application/json
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDANFIX 15Y상점별로 부여되는 상점 ID
payType결제수단AFIX 2Y결제수단
vanTidPG원거래고유번호ANMAX 18Y결제승인시 VAN사 거래일련번호
cancelAmt취소금액NumericMAX 8Y반드시 숫자만 포함 (양수)
checkHash유효성 검증 HashANSMAX 128Ymessage: vanTid+mid+cancelAmt
reserved01가맹점예약필드1ANSMAX 1024O
reserved02가맹점예약필드2ANSMAX 1024O
taxExemptYn비과세 구분AFIX 1O비과세거래: Y / 일반: N
taxExemptAmt비과세금액NMAX 8O반드시 숫자만 포함
응답 파라미터
항목ID항목명타입길이(byte)필수설명
RESULT_CODE처리 결과 코드ANMAX 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지ANSMAX 1024
DRESULT_CODE가맹점결과코드ANMAX 20
DRESULT_MSG가맹점결과메시지ANSMAX 1024
VAN_TIDVAN원거래고유번호ANMAX 15
CANCEL_AMT취소금액NMAX 8승인금액에 대한 세금
RESERVED01가맹점예약필드1ANSMAX 1024
RESERVED02가맹점예약필드2ANSMAX 1024
응답 예시
json
{
  "RESULT_CODE": "EC0000",
  "RESULT_MSG": "정상결제취소",
  "DRESULT_CODE": "EC0000",
  "DRESULT_MSG": "성공",
  "VAN_TID": "201605280001",
  "CANCEL_AMT": "5000"
}

🔍결제내역 조회

🔧 개발기
https://dev-epay.kovanpay.com
🚀 상용기
https://epay.kovanpay.com/
POST /webpay/getTransInfo.pay 결제내역 조회 ▼
Content-Type: application/json
💡
조회 방법
· tid 또는 orderno를 알고 있을 경우: 두 항목 중 1개 필수
· tid, orderno를 모를 경우: approv_amt, approvdt, approv_no 3개 항목 필수
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDANFIX 15Y상점 별로 부여되는 상점 ID
payGroup결제그룹AFIX 3YDefault: GEP
paymethod결제수단AFIX 2Y결제수단 코드
tidPG원거래고유번호ANMAX 15O결제승인 시 PG사 원거래고유번호
orderno가맹점고유번호ANMAX 20O상점 주문번호
approv_amt결제승인금액NumericMAX 8Otid/orderno 없을 때 필수
approvdt승인일자NFIX 8O결제승인일자 (YYYYMMDD)
approv_no승인번호ANMAX 15O결제승인번호
checkHash유효성 검증 HashANSMAX 128Ymessage: tid+mid+cancelAmt
reserved01가맹점예약필드1ANSMAX 1024O
reserved02가맹점예약필드2ANSMAX 1024O
응답 파라미터
항목ID항목명타입설명
RESULT_CODE처리 결과 코드ANMAX 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지ANSMAX 1024
DRESULT_CODE가맹점결과코드ANMAX 20
DRESULT_MSG가맹점결과메시지ANSMAX 1024
PAY_METHOD결제수단A결제 수단 코드
TIDPG원거래고유번호AN결제승인시 PG사 원거래고유번호
ORDERNO상점주문번호AN상점 주문번호
MID상점IDANPG에서 부여한 상점 ID
BUY_ITEMNM상품명AN상점 구매 상품명
TRANS_STATUS_NM거래상태명A거래 상태 명칭
TRANS_STATUS거래상태AN거래 상태 코드표 참조
APPROAMT승인금액N숫자만 포함
CANCEL_AMT취소금액N취소 금액의 합계
APPRODT승인일자ANSyyyy-MM-dd hh:mm:ss
CANCEL_DT취소일자ANSyyyy-MM-dd hh:mm:ss
RESERVED01가맹점예약필드1ANSMAX 1024
RESERVED02가맹점예약필드2ANSMAX 1024
응답 예시
json
{
  "RESULT_CODE":"EC0000",
  "RESULT_MSG":"성공",
  "RESULT_DET_CODE":"EC0000",
  "RESULT_DET_MSG":"성공",
  "data":
      [
        {"PAY_METHOD":"CC","TID":"220310130423508",
          "ORDERNO":"ORDER220310000005",
          "RESERVED01":"2475","RESERVED02":"",
          "MID":"M20201104113435","BUY_ITEMNM":"테스트상품",
          "TRANS_STATUS_NM":"승인","TRANS_STATUS":"20",
          "APPROAMT":"1004","CANCEL_AMT":"-500",
          "APPRODT":"2022-03-10 19:55:59",
          "CANCEL_DT":"2022-03-10 20:00:34"}
      ]
}

🧾매출전표 조회

🔧 개발기
http://220.117.220.108:30200
🚀 상용기
https://ema.kovanpay.com
GET /Trade/Receipt/PgReceipt.out PG 매출전표 조회 ▼
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDANFIX 15Y상점 별로 부여되는 상점 ID
payGroup결제그룹AFIX 3YDefault: GEP
payMethod결제수단AFIX 2Y결제수단 코드
tidPG원거래고유번호ANMAX 15Y결제승인 시 PG사 원거래고유번호
amt결제승인금액NumericMAX 8Y승인: 1004 / 취소: -1004
text_tr승인,취소구분NFIX 2O승인: 00 / 취소: 99
checkHash유효성 검증 HashANSMAX 128Ymessage: tid+mid+amt
orderno주문번호ANMAX 20O상점 주문번호

📲리모트 결제

문자 메시지 또는 URL을 통해 고객에게 결제 링크를 전송하는 서비스입니다.

🔧 개발기
http://220.117.220.108:30200
🚀 상용기
https://ema.kovanpay.com
POST /Morder/v1/merchant/messagePay.out 메시지 결제 ▼
Content-Type: application/json, Encoding: UTF-8
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid대표IDANFIX 15YPG에서 부여한 상점 ID
orderno주문번호ANMAX 20Y상점 주문번호
orderdt주문 일자NumberFIX 8YYYYYMMDD
ordertm주문 시간NumberFIX 6YHHMMSS
buyReqamt상품가격NMAX 8Y상점 구매금액. 반드시 숫자만
checkHash무결성 검증 HashANSMAX 128Ymessage: orderno+orderdt+ordertm+buyReqamt
phoneNum휴대폰번호NumberMAX 15Y'-' 제외 숫자만
buyItemnm상품명ANMAX 60Y상점 판매 상품명
buyernm구매자 명AMAX 50O상점 구매자명
goodsInfo상품추가정보ANMAX 50O상점 판매 상품 추가 정보
payAbleTime결제 유효기간NumberMAX 5O분 단위 (기본 1시간)
응답 파라미터
항목ID항목명타입설명
RESULT_CODE결제결과코드AN결과코드표 참조
RESULT_MSG결제결과메시지ANS
POST /Morder/v1/merchant/urlPay.out URL 결제 ▼
Content-Type: application/json, Encoding: UTF-8
추가 파라미터 (메시지결제 파라미터 + 아래)
항목ID항목명타입길이(byte)필수설명
mid대표IDANFIX 15YPG에서 부여한 상점 ID
orderno주문번호ANMAX 20Y상점 주문번호
orderdt주문 일자NumberFIX 8YYYYYMMDD
ordertm주문 시간NumberFIX 6YHHMMSS
buyReqamt상품가격NMAX 8Y상점 구매금액. 반드시 숫자만
checkHash무결성 검증 HashANSMAX 128Ymessage: orderno+orderdt+ordertm+buyReqamt
phoneNum휴대폰번호NumberMAX 15Y'-' 제외 숫자만
buyItemnm상품명ANMAX 60Y상점 판매 상품명
buyernm구매자 명AMAX 50O상점 구매자명
goodsInfo상품추가정보ANMAX 50O상점 판매 상품 추가 정보
payAbleTime결제 유효기간NumberMAX 5O분 단위 (기본 1시간)
langType언어AFIX 3OKOR 한국어, ENG 영어 (기본 KOR)
응답 파라미터
항목ID항목명타입설명
REQ_URL결제 URLANS결제 URL (실패 시 공백)
RESULT_CODE결제결과코드AN결과코드표 참조
RESULT_MSG결제결과메시지ANS

🖊️수기(키인) 결제 API NEW · 2026-09-01 배포

카드소지자 인증(ISP/앱카드/안심클릭) 없이 카드번호 + 유효기간(YYMM)만으로 승인하는 비인증 카드결제 API입니다. 브라우저 결제창을 거치지 않는 순수 Server-to-Server 방식입니다.

🔒
별도 계약 상점 전용 — 상세 연동 규격 비공개
카드번호를 직접 수신하는 API 특성상, 수기결제 부속계약을 체결하고 사전 심사를 통과한 상점에 한해 사용할 수 있습니다. 파라미터·암호화 방식·요청/응답 샘플 등 상세 연동 규격은 본 통합가이드에는 포함하지 않으며, 계약 체결 후 담당자를 통해 개별 문서로 전달됩니다. 이용을 원하시는 경우 PG 연동 담당자에게 문의해 주세요.
🔒
네트워크 접근 제한
본 API는 반드시 전용선(Leased Line) 및 SSL VPN으로 구성된 폐쇄망 환경에서만 호출할 수 있습니다. 일반 인터넷 구간을 통한 호출은 허용되지 않습니다.

개요

  • CVC, 카드 비밀번호, 생년월일/사업자번호는 수집하지 않습니다.
  • 카드사(발급사) 코드는 요청하지 않으며, 서버가 카드번호로 자동 판별합니다.
  • 카드번호·유효기간은 평문으로 전송하지 않고 암호화하여 전송합니다.
  • 승인: 신규 API POST /webpay/keyinPayment.pay
  • 취소: 별도 API 없이 기존 「결제취소 요청」(POST /webpay/cancel.pay)을 그대로 사용합니다.
  • 모든 요청은 상점 API Key 기반 HMAC-SHA256(checkHash) 검증을 통과해야 합니다.
💡
본 API는 이미 동기(S2S) 방식으로 승인 결과를 즉시 반환하므로, 「L2 승인결과 즉시통보(옵트인)」 대상이 아닙니다.

🔔결제 Notification

결제승인 완료 시 계약정보에 등록된 Notify URL로 승인정보를 통지하는 기능입니다. 실시간 Return 응답과는 별개로 Background 프로세스에 의해 가맹점 서버로 통지됩니다.

💡
본 기능(계약 등록 Notify URL, 비동기)과 별개로, 결제요청 시 notiUseYn=Y로 옵트인하면 결제요청의 rUrl로 승인 즉시 결과를 동기 전송받는 「L2 승인결과 즉시통보(옵트인)」 기능이 추가되었습니다. 두 기능은 대상 URL·전송 시점이 다른 별개 채널이니 혼동하지 마세요. NEW

준비사항

📋
가맹점 준비 사항
· KOVAN PG WAS와 가맹점 WEB 서버 간 방화벽 오픈 (운영/테스트 별도 작업 필요)
· HTTP/POST 방식의 Notification 전용 웹 서버 프로세스 필요
· Notify URL은 계약정보에 등록 필요 (PG 담당자 문의)
⚠️
실제 응답 시 주의사항
· CHECK_HASH는 일부 결제수단(계좌이체 등)에서 null로 수신될 수 있습니다. null 여부를 반드시 확인 후 검증하세요.
· 오프라인 VAN방식의 경우 mid(소문자), payGroup, payMethod, ORDER_NO 등 소문자 필드가 혼재하여 수신됩니다. 대소문자 구분 없이 파싱하세요.
· APPROVDT / APPROVAMT / APPROVTM과 APPRODT / APPROAMT / APPROTM 두 가지 형태가 동시에 포함될 수 있습니다.
Content-Type: application/json;charset=UTF-8
전체 파라미터
항목ID타입설명예시값
RESULT_CODEAN결과코드. 성공: EC0000EC0000
RESULT_MSGANS결과메시지SUCCESS
DRESULT_CODEAN사용자 결과코드EC0000
DRESULT_MSGANS사용자 결과메시지SUCCESS
PAY_GROUPA결제그룹GEP
PAY_METHODA결제수단CC
TIDANPG 거래고유번호260105130562200
ORDERNOAN상점 주문번호ORDER20260105105237
RESERVED01ANS가맹점예약필드1reserved01
RESERVED02ANS가맹점예약필드2reserved02
CHECK_HASHANS무결성 검증 Hash. message: RESULT_CODE+TID+ORDERNOrmKd+h8AM8Tu...
VAN_RECV_KEYANVAN 거래고유키 (없을 경우 빈 문자열)
APPROVNOAN카드사 승인번호21676259
APPRODTN결제승인일자 (YYYYMMDD)20260105
APPROTMN결제승인시간 (HHMMSS)105240
APPROAMTN결제승인금액1004
ISSUE_CODEN발급사코드1104
ISSUE_NAMEA발급사명삼성카드
PURCHASE_CODEN매입사코드1104
PURCHASE_NAMEA매입사명삼성카드
QUOTA_MONTHSN할부개월수. 일시불: 0000
NOINTA무이자구분. 무이자: Y / 일반: NN
CHECKCDA카드구분. 신용: N / 체크: CN
CARD_NOANS마스킹 처리된 카드번호536148**********
실제 수신 JSON 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "SUCCESS",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "SUCCESS",
  "PAY_GROUP": "GEP", "PAY_METHOD": "CC",
  "TID": "260105130562200", "ORDERNO": "ORDER20260105105237",
  "RESERVED01": "reserved01", "RESERVED02": "reserved02",
  "CHECK_HASH": "rmKd+h8AM8Tuhz8KGWGUT6aLK4vi/1gzWgUZCiuQB/I=",
  "VAN_RECV_KEY": "",
  "APPROVNO": "21676259", "APPRODT": "20260105", "APPROTM": "105240",
  "APPROAMT": "1004", "ISSUE_CODE": "1104", "ISSUE_NAME": "삼성카드",
  "PURCHASE_CODE": "1104", "PURCHASE_NAME": "삼성카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "536148**********"
}
Content-Type: application/json;charset=UTF-8
⚠️
CHECK_HASH가 null로 수신됩니다. 계좌이체 Notification에서는 Hash 검증을 생략하고 RESULT_CODE와 TID로 처리하세요.
전체 파라미터
항목ID타입설명예시값
RESULT_CODEAN결과코드. 성공: EC0000EC0000
RESULT_MSGANS결과메시지성공
DRESULT_CODEAN사용자 결과코드EC0000
DRESULT_MSGANS사용자 결과메시지SUCCESS
PAY_GROUPA결제그룹GEP
PAY_METHODA결제수단BA
TIDANPG 거래고유번호260107130562229
ORDERNOAN상점 주문번호ORDER20260107110442
MIDAN상점IDM20200203113418
RESERVED01ANS가맹점예약필드1reserved01
RESERVED02ANS가맹점예약필드2reserved02
CHECK_HASHANS무결성 검증 Hash. 계좌이체는 null로 수신null
BANK_CDN은행코드 (은행 코드표 참조)050
BANK_NMA은행명상호저축은행
ACCT_NOAN계좌번호 (마스킹)45678
ESCR_FLAGA에스크로 여부
실제 수신 JSON 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "SUCCESS",
  "PAY_GROUP": "GEP", "PAY_METHOD": "BA",
  "TID": "260107130562229", "ORDERNO": "ORDER20260107110442",
  "MID": "M20200203113418",
  "RESERVED01": "reserved01", "RESERVED02": "reserved02",
  "CHECK_HASH": null,
  "BANK_CD": "050", "BANK_NM": "상호저축은행",
  "ACCT_NO": "45678", "ESCR_FLAG": ""
}
Content-Type: application/json;charset=UTF-8
💡
카카오페이 신용카드는 일반 신용카드(GEP·CC)와 동일한 파라미터 구조입니다. PAY_GROUP: KKP로 구분하세요. 실패 시에는 MID와 공통 결과 필드만 수신됩니다.
성공 시 파라미터 — GEP·CC와 동일 (PAY_GROUP: KKP)
항목ID타입설명예시값
RESULT_CODEAN결과코드EC0000
RESULT_MSGANS결과메시지SUCCESS
DRESULT_CODEAN사용자 결과코드EC0000
DRESULT_MSGANS사용자 결과메시지SUCCESS
PAY_GROUPA결제그룹KKP
PAY_METHODA결제수단CC
TIDANPG 거래고유번호260201130562925
ORDERNOAN상점 주문번호ORDER20260201202653
MIDAN상점IDM20200203113418
RESERVED01ANS가맹점예약필드1reserved01
RESERVED02ANS가맹점예약필드2reserved02
실패 시 수신 JSON 예시 (공통 필드만 포함)
json
{
  "MID": "M20200203113418",
  "TID": "260201130562925",
  "PAY_GROUP": "KKP", "PAY_METHOD": "CC",
  "ORDERNO": "ORDER20260201202653",
  "RESULT_CODE": "EC1029",
  "RESULT_MSG": "원천사 결제(취소) 결과실패([-780]approval failure![PG하위몰 사업자번호 오류])",
  "DRESULT_CODE": "EC1029",
  "DRESULT_MSG": "원천사 결제(취소) 결과실패([-780]approval failure![PG하위몰 사업자번호 오류])",
  "RESERVED01": "reserved01", "RESERVED02": "reserved02"
}
Content-Type: application/json;charset=UTF-8
⚠️
카카오머니는 APPROAMT/APPRODT/APPROTM과 APPROVAMT/APPROVDT/APPROVTM 두 가지 형태의 필드가 동시에 수신됩니다. 두 필드 모두 파싱하여 처리하세요.
전체 파라미터
항목ID타입설명예시값
RESULT_CODEAN결과코드. 성공: EC0000EC0000
RESULT_MSGANS결과메시지SUCCESS
DRESULT_CODEAN사용자 결과코드EC0000
DRESULT_MSGANS사용자 결과메시지SUCCESS
PAY_GROUPA결제그룹KKP
PAY_METHODA결제수단VO
TIDANPG 거래고유번호260409130565072
ORDERNOAN상점 주문번호ORDER20260409113324
MIDAN상점IDM20200203113418
RESERVED01ANS가맹점예약필드1reserved01
RESERVED02ANS가맹점예약필드2reserved02
APPROAMTN결제승인금액1004
APPRODTN결제승인일자 (YYYYMMDD)20260409
APPROTMN결제승인시간 (HHMMSS)113736
APPROVAMTN결제승인금액 (중복 필드, 동시 수신)1004
APPROVDTN결제승인일자 (중복 필드, 동시 수신)20260409
APPROVTMN결제승인시간 (중복 필드, 동시 수신)113736
실제 수신 JSON 예시
json
{
  "MID": "M20200203113418",
  "TID": "260409130565072",
  "PAY_GROUP": "KKP", "PAY_METHOD": "VO",
  "ORDERNO": "ORDER20260409113324",
  "RESULT_CODE": "EC0000", "RESULT_MSG": "SUCCESS",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "SUCCESS",
  "RESERVED01": "reserved01", "RESERVED02": "reserved02",
  "APPROAMT": "1004", "APPRODT": "20260409", "APPROTM": "113736",
  "APPROVAMT": "1004", "APPROVDT": "20260409", "APPROVTM": "113736"
}
Content-Type: application/json;charset=UTF-8
💡
네이버페이 신용카드는 일반 신용카드(GEP·CC)와 동일한 파라미터 구조입니다. PAY_GROUP: NVP로 구분하세요.
전체 파라미터 — GEP·CC와 동일 구조 (PAY_GROUP: NVP)
항목ID타입설명예시값
RESULT_CODEAN결과코드EC0000
RESULT_MSGANS결과메시지SUCCESS
DRESULT_CODEAN사용자 결과코드EC0000
DRESULT_MSGANS사용자 결과메시지SUCCESS
PAY_GROUPA결제그룹NVP
PAY_METHODA결제수단CC
TIDANPG 거래고유번호260116130562552
ORDERNOAN상점 주문번호ORDER20260116085029
RESERVED01ANS가맹점예약필드1reserved01
RESERVED02ANS가맹점예약필드2reserved02
CHECK_HASHANS무결성 검증 Hash70+UtK3FU/WQ...
VAN_RECV_KEYANVAN 거래고유키 (빈 문자열 가능)
APPROVNOAN카드사 승인번호87101195
APPRODTN결제승인일자 (YYYYMMDD)20260116
APPROTMN결제승인시간 (HHMMSS)085102
APPROAMTN결제승인금액1004
ISSUE_CODEN발급사코드1110
ISSUE_NAMEA발급사명우리카드
PURCHASE_CODEN매입사코드1110
PURCHASE_NAMEA매입사명우리카드
QUOTA_MONTHSN할부개월수. 일시불: 0000
NOINTA무이자구분N
CHECKCDA카드구분. 신용: N / 체크: CC
CARD_NOANS마스킹 처리된 카드번호537699**********
실제 수신 JSON 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "SUCCESS",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "SUCCESS",
  "PAY_GROUP": "NVP", "PAY_METHOD": "CC",
  "TID": "260116130562552", "ORDERNO": "ORDER20260116085029",
  "RESERVED01": "reserved01", "RESERVED02": "reserved02",
  "CHECK_HASH": "70+UtK3FU/WQopAcae+/EiQui3yw8a9u4r9nyVMfvws=",
  "VAN_RECV_KEY": "",
  "APPROVNO": "87101195", "APPRODT": "20260116", "APPROTM": "085102",
  "APPROAMT": "1004", "ISSUE_CODE": "1110", "ISSUE_NAME": "우리카드",
  "PURCHASE_CODE": "1110", "PURCHASE_NAME": "우리카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "C",
  "CARD_NO": "537699**********"
}
Content-Type: application/json;charset=UTF-8
💡
네이버포인트 실패 시 MID와 공통 결과 필드 + RESERVED01/02만 수신됩니다. 승인 필드(APPROAMT 등)는 포함되지 않습니다.
전체 파라미터 (실패 시 기준 — 성공 시 APPROAMT 등 추가)
항목ID타입설명예시값
RESULT_CODEAN결과코드EC1029
RESULT_MSGANS결과메시지 (실패 시 원천사 오류 메시지 포함)원천사 결제(취소) 결과실패(...)
DRESULT_CODEAN사용자 결과코드EC1029
DRESULT_MSGANS사용자 결과메시지원천사 결제(취소) 결과실패(...)
PAY_GROUPA결제그룹NVP
PAY_METHODA결제수단VO
TIDANPG 거래고유번호251121130561398
ORDERNOAN상점 주문번호ORDER20251121160018
MIDAN상점IDM20200203113418
RESERVED01ANS가맹점예약필드1reserved01
RESERVED02ANS가맹점예약필드2reserved02
실제 수신 JSON 예시 (잔고 부족 실패)
json
{
  "MID": "M20200203113418",
  "TID": "251121130561398",
  "PAY_GROUP": "NVP", "PAY_METHOD": "VO",
  "ORDERNO": "ORDER20251121160018",
  "RESULT_CODE": "EC1029",
  "RESULT_MSG": "원천사 결제(취소) 결과실패([NotEnoughAccountBalance]계좌 잔고가 충전 후 결제할 금액보다 부족합니다.)",
  "DRESULT_CODE": "EC1029",
  "DRESULT_MSG": "원천사 결제(취소) 결과실패([NotEnoughAccountBalance]계좌 잔고가 충전 후 결제할 금액보다 부족합니다.)",
  "RESERVED01": "reserved01", "RESERVED02": "reserved02"
}
Content-Type: application/json;charset=UTF-8
전체 파라미터
항목ID타입설명예시값
RESULT_CODEAN결과코드. 성공: EC0000EC0000
RESULT_MSGANS결과메시지SUCCESS
PAY_GROUPA결제그룹. 하드코딩 고정 GEPGEP
PAY_METHODA결제수단CC
TIDANPG 거래고유번호 (본 승인 거래 TID)260922130569960
ORG_TIDAN원거래 TID. 승인 시점에는 TID와 동일값260922130569960
MIDAN상점IDM20200203113418
EIDAN가맹점IDE20200203113529
VAN_CATIDANVAN 단말기ID (구 필드명: OPG_ID)2626260004
APPROVNOAN카드사 승인번호593871
APPRONOAN카드사 승인번호 — APPROVNO 동일 값 중복 전송593871
APPROVDTN결제승인일자 (YYYYMMDD)20260922
APPRODTN결제승인일자 — APPROVDT 동일 값 중복 전송20260922
APPROVTMN결제승인시간 (HHMMSS)110123
APPROTMN결제승인시간 — APPROVTM 동일 값 중복 전송110123
APPROVAMTNumber결제승인금액 ※숫자형(Integer)으로 수신51004
APPROAMTNumber결제승인금액 — APPROVAMT 동일 값 중복 전송 ※숫자형(Integer)51004
QUOTA_MONTHSN할부개월수. 일시불: 0000
ISSUE_CODEN발급사코드 (OPTR_VAN_OID_MAP 매핑값, 6자리 수신 가능)112622
PURCHASE_CODEN매입사코드1103
CHECKCDA카드구분. 신용: N / 체크: CN
CARD_NOANS마스킹 처리된 카드번호 (앞 6자리 + * 마스킹)354090**********
실제 수신 JSON 예시 (JCB 승인, 2026-09-22 dev 검증)
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "SUCCESS",
  "PAY_GROUP": "GEP", "PAY_METHOD": "CC",
  "TID": "260922130569960", "ORG_TID": "260922130569960",
  "MID": "M20200203113418", "EID": "E20200203113529",
  "VAN_CATID": "2626260004",
  "APPROVNO": "593871", "APPRONO": "593871",
  "APPROVDT": "20260922", "APPRODT": "20260922",
  "APPROVTM": "110123", "APPROTM": "110123",
  "APPROVAMT": 51004, "APPROAMT": 51004,
  "QUOTA_MONTHS": "00",
  "ISSUE_CODE": "112622", "PURCHASE_CODE": "1103",
  "CHECKCD": "N", "CARD_NO": "354090**********"
}
Content-Type: application/json;charset=UTF-8
⚠️
VAN방식은 소문자 필드가 혼재합니다. mid, payGroup, payMethod, ORDER_NO 등을 별도로 파싱해야 합니다.
또한 APPROAMT + APPROVAMT, APPROTM + APPROVTM, APPROVNO + APPRONO 등 중복 필드가 동시 수신됩니다.
ISSUE_CODE에 6자리 코드(예: 112672)가 수신되는 경우가 있습니다.
전체 파라미터
항목ID타입설명예시값
RESULT_CODEAN결과코드. 성공: EC0000EC0000
RESULT_MSGANS결과메시지SUCCESS
MIDAN상점ID (대문자)M20200203113418
midAN상점ID (소문자, 중복 수신)M20200203113418
TIDANPG 거래고유번호260106130562218
ORG_TIDAN원거래 TID260106130562218
ORDER_NOAN주문번호 (VAN방식 전용 필드명)260106130562218
payGroupA결제그룹 (소문자)GEP
payMethodA결제수단 (소문자)CC
APPROVNOAN카드사 승인번호21137313
APPRONOAN카드사 승인번호 (중복 필드)21137313
APPRODTN결제승인일자 (YYYYMMDD)20251224
APPROVDTN결제승인일자 (중복 필드)20251224
APPROTMN결제승인시간 (HHMMSS)111300
APPROVTMN결제승인시간 (중복 필드)111300
APPROAMTN결제승인금액72000
APPROVAMTN결제승인금액 (중복 필드)72000
BUY_REQAMTN구매요청금액72000
ISSUE_CODEN발급사코드 (6자리 코드 수신 가능)112672
PURCHASE_CODEN매입사코드1106
CHECKCDA카드구분. 신용: N / 체크: CC
CARD_NOANS마스킹 처리된 카드번호518185**********
실제 수신 JSON 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "SUCCESS",
  "MID": "M20200203113418", "mid": "M20200203113418",
  "TID": "260106130562218", "ORG_TID": "260106130562218",
  "ORDER_NO": "260106130562218",
  "payGroup": "GEP", "payMethod": "CC",
  "APPROVNO": "21137313", "APPRONO": "21137313",
  "APPRODT": "20251224", "APPROVDT": "20251224",
  "APPROTM": "111300", "APPROVTM": "111300",
  "APPROAMT": "72000", "APPROVAMT": "72000",
  "BUY_REQAMT": "72000",
  "ISSUE_CODE": "112672", "PURCHASE_CODE": "1106",
  "CHECKCD": "C", "CARD_NO": "518185**********"
}
Content-Type: application/json;charset=UTF-8
⚠️
ORDERNO, CHECKCD, PART_CANCEL, CANCEL_DT/CANCEL_TM, QUOTA_MONTHS, NOINT, APPROVNO/APPRONO, APPRODT/APPROVDT, APPROTM/APPROVTM, CARDNO 필드는 옵션 항목입니다. 가맹점 관리자 페이지의 Notification 설정에서 「원거래 정보 수신」이 체크된 가맹점에 한해 전송되며, 체크되어 있지 않으면 수신되지 않습니다.
전체 파라미터
항목ID타입길이(byte)설명
RESULT_CODEANMAX 20결과코드. 성공: EC0000
RESULT_MSGANSMAX 1024결과메시지
DRESULT_CODEANMAX 20사용자 결과코드
DRESULT_MSGANSMAX 1024사용자 결과메시지
PAY_METHODAFIX 2결제수단 (CC / VO)
PAY_GROUPAFIX 3결제그룹 (GEP / KKP / NVP)
TIDANFIX 15PG 취소 거래고유번호
ORG_TIDANFIX 15PG 원거래고유번호 (원 결제승인 TID)
CANCEL_AMTNMAX 20취소금액
APPROAMTNMAX 15원거래 승인금액
APPROVAMTNMAX 15원거래 승인금액 — APPROAMT 중복 필드
VAN_RECV_KEYANMAX 20VAN 거래고유키
PCH_TIDANMAX 15매입요청고유번호
EIDANFIX 15가맹점ID
MIDANFIX 15상점ID
RESERVED01ANSMAX 1024가맹점예약필드1 (원 결제요청 시 전달한 값)
RESERVED02ANSMAX 1024가맹점예약필드2 (원 결제요청 시 전달한 값)
「원거래 정보 수신」 체크 시에만 추가 수신 (옵션)
ORDERNOANMAX 20상점주문번호 (옵션)
CHECKCDAFIX 1카드구분. 신용: N / 체크: C (옵션)
PART_CANCELAFIX 1부분취소여부. 부분취소: Y / 전체취소: N (옵션)
CANCEL_DTNFIX 8취소일자 (YYYYMMDD) (옵션)
CANCEL_TMNFIX 6취소시각 (HHMMSS) (옵션)
QUOTA_MONTHSNFIX 2할부개월수. 일시불: 00 (옵션)
NOINTAFIX 1무이자구분. 무이자: Y / 일반: N (옵션)
APPROVNOANMAX 15카드사 승인번호 (옵션)
APPRONOANMAX 15카드사 승인번호 — APPROVNO 중복 필드 (옵션)
APPROVDTNFIX 8결제승인일자 (YYYYMMDD) (옵션)
APPRODTNFIX 8결제승인일자 — APPROVDT 중복 필드 (옵션)
APPROVTMNFIX 6결제승인시간 (HHMMSS) (옵션)
APPROTMNFIX 6결제승인시간 — APPROVTM 중복 필드 (옵션)
CARDNOANSMAX 20마스킹 처리된 카드번호 ※필드명에 언더스코어 없음 (옵션)
실제 수신 JSON 예시
json
// 「원거래 정보 수신」 미체크 (기본)
{
  "APPROAMT": "1004",
  "RESULT_CODE": "EC0000",
  "DRESULT_MSG": "SUCCESS",
  "CANCEL_AMT": "100",
  "VAN_RECV_KEY": "",
  "PAY_GROUP": "GEP",
  "TID": "260915130569723",
  "APPROVAMT": "1004",
  "PCH_TID": "260916127520254",
  "DRESULT_CODE": "EC0000",
  "RESULT_MSG": "SUCCESS",
  "RESERVED01": "reserved01",
  "ORG_TID": "260915130569707",
  "RESERVED02": "reserved02",
  "PAY_METHOD": "CC"
}

// 「원거래 정보 수신」 체크 (옵션 필드 추가 수신)
{
  "CHECKCD": "N",
  "RESULT_CODE": "EC0000",
  "APPRODT": "20260915",
  "VAN_RECV_KEY": "",
  "APPROVAMT": "1004",
  "PCH_TID": "260916127520252",
  "APPROVNO": "49108459",
  "RESULT_MSG": "SUCCESS",
  "APPROVTM": "142155",
  "PAY_METHOD": "CC",
  "CANCEL_TM": "142155",
  "NOINT": "N",
  "CARDNO": "536148**********",
  "APPROAMT": "1004",
  "APPROVDT": "20260915",
  "DRESULT_MSG": "SUCCESS",
  "CANCEL_AMT": "100",
  "PAY_GROUP": "GEP",
  "TID": "260915130569719",
  "PART_CANCEL": "Y",
  "DRESULT_CODE": "EC0000",
  "APPROTM": "142155",
  "CANCEL_DT": "20260915",
  "ORDERNO": "ORDER20260915142152",
  "RESERVED01": "reserved01",
  "QUOTA_MONTHS": "00",
  "APPRONO": "49108459",
  "ORG_TID": "260915130569707",
  "RESERVED02": "reserved02"
}
Content-Type: application/json;charset=UTF-8
⚠️
APPROVNO/APPRONO, APPRODT/APPROVDT, APPROTM/APPROVTM, APPROAMT/APPROVAMT, CARDNO 필드는 옵션 항목입니다. 가맹점 관리자 페이지의 Notification 설정에서 「원거래 정보 수신」(OPG_APPROVAL_CANCEL_YN='Y')이 체크된 가맹점에 한해 전송되며, 체크되어 있지 않으면 수신되지 않습니다.
VAN 특성상 APPRO* / APPROV* 중복 필드가 동시에 수신됩니다(예: APPROVNO와 APPRONO는 동일한 값). CARDNO는 다른 알림과 달리 언더스코어 없이 수신되므로(CARD_NO 아님) 파싱 시 주의하세요.
⚠️ APPROVAMT/APPROAMT는 필드명과 달리 원승인금액이 아니라 실제로는 CANCEL_AMT와 동일한 취소금액이 전송됩니다. 필드명만 보고 원거래 승인금액으로 오인하지 않도록 주의하세요.
PAY_METHOD/PAY_GROUP/PART_CANCEL은 승인과 동일한 사유로 각각 CC/GEP/N으로 하드코딩 고정 전송됩니다(부분취소 미지원, 항상 전체취소).
VAN_CATID는 승인 노티(getVanCatid())와 소스 필드가 달라(취소는 getOpgId()) 값이 같아 보이는 것이 우연일 수 있습니다.
전체 파라미터
항목ID타입길이(byte)설명
RESULT_CODEANMAX 20결과코드. 성공: EC0000
RESULT_MSGANSMAX 1024결과메시지
PAY_METHODAFIX 2결제수단. 하드코딩 고정 CC
PAY_GROUPAFIX 3결제그룹. 하드코딩 고정 GEP
TIDANFIX 15PG 취소 거래고유번호 (취소 거래 자체의 TID, 승인 TID와 다름)
ORG_TIDANFIX 15원 승인거래 TID
CANCEL_AMTNMAX 20취소금액
PART_CANCELAFIX 1부분취소여부. 부분취소 미지원으로 하드코딩 고정 N (항상 전체취소)
CANCEL_DTNFIX 8취소일자 (YYYYMMDD). 취소 처리시각(transdt) 기준
CANCEL_TMNFIX 6취소시각 (HHMMSS). 취소 처리시각(transdt) 기준
CHECKCDAFIX 1카드구분. 신용: N / 체크: C
QUOTA_MONTHSNFIX 2할부개월수. 일시불: 00
ISSUE_CODENMAX 10발급사코드
PURCHASE_CODENMAX 10매입사코드
VAN_CATIDANFIX 15VAN 단말기ID (구 필드명: OPG_ID). 승인 노티와 소스 필드 다름(getOpgId())
EIDANFIX 15가맹점ID
MIDANFIX 15상점ID
「원거래 정보 수신」 체크 시에만 추가 수신 (옵션)
APPROVNOANMAX 15원승인 승인번호 (옵션)
APPRONOANMAX 15원승인 승인번호 — APPROVNO 동일 값 중복 전송 (옵션)
APPROVDTNFIX 8원승인 결제승인일자 (YYYYMMDD) (옵션)
APPRODTNFIX 8원승인 결제승인일자 — APPROVDT 동일 값 중복 전송 (옵션)
APPROVTMNFIX 6원승인 결제승인시간 (HHMMSS) (옵션)
APPROTMNFIX 6원승인 결제승인시간 — APPROVTM 동일 값 중복 전송 (옵션)
APPROVAMTNumberMAX 15⚠️ 필드명은 승인금액이지만 실제로는 CANCEL_AMT와 동일한 취소금액이 담김. 원승인금액 아님 (옵션)
APPROAMTNumberMAX 15APPROVAMT 동일 값 중복 전송. 마찬가지로 취소금액 (옵션)
CARDNOANSMAX 20마스킹 처리된 카드번호 ※필드명에 언더스코어 없음, CARD_NO 아님 (옵션)
실제 수신 JSON 예시 (JCB 취소, 2026-09-22 dev 검증)
json
// 「원거래 정보 수신」 미체크 (기본)
{
  "CHECKCD": "N", "RESULT_CODE": "EC0000", "RESULT_MSG": "SUCCESS",
  "PAY_METHOD": "CC", "CANCEL_TM": "110912", "ISSUE_CODE": "112622",
  "EID": "E20200203113529", "MID": "M20200203113418",
  "CANCEL_AMT": 51004, "PAY_GROUP": "GEP",
  "TID": "260922130569963", "PART_CANCEL": "N", "VAN_CATID": "2626260004",
  "CANCEL_DT": "20260922", "QUOTA_MONTHS": "00",
  "ORG_TID": "260922130569960", "PURCHASE_CODE": "1103"
}

// 「원거래 정보 수신」 체크 (옵션 필드 추가 수신)
{
  "CHECKCD": "N", "RESULT_CODE": "EC0000",
  "APPRODT": "20260922", "APPROVAMT": 51004, "APPROVNO": "593871",
  "RESULT_MSG": "SUCCESS", "APPROVTM": "110913", "PAY_METHOD": "CC",
  "CANCEL_TM": "110912", "ISSUE_CODE": "112622", "CARDNO": "354090**********",
  "EID": "E20200203113529", "APPROAMT": 51004, "APPROVDT": "20260922",
  "MID": "M20200203113418", "CANCEL_AMT": 51004, "PAY_GROUP": "GEP",
  "TID": "260922130569963", "PART_CANCEL": "N", "VAN_CATID": "2626260004",
  "APPROTM": "110913", "CANCEL_DT": "20260922", "QUOTA_MONTHS": "00",
  "APPRONO": "593871", "ORG_TID": "260922130569960", "PURCHASE_CODE": "1103"
}
Content-Type: application/json;charset=UTF-8
⚠️
가상계좌는 결제 승인 시점이 아닌 실제 입금 확인 시점에 Notification이 발생합니다. 반드시 입금 Notification 수신 후 주문을 처리하세요.
전체 파라미터
항목ID타입길이(byte)설명
TIDANFIX 15PG사 거래고유번호
PAY_METHODAFIX 2VA
TEXT_TRNFIX 2입금: 00 / 입금취소: 99
ORDERNOANMAX 20상점 주문번호
TRANSDTNFIX 14거래일자 (YYYYMMDDHHMMSS)
RESULTNFIX 2처리결과코드. 성공: 00
RESULT_MSGANSMAX 1024처리결과메시지. 성공: Success

🛰️L2 승인결과 즉시통보 (옵트인) NEW · 2026-09-01 배포

결제요청 시 notiUseYn=Y로 옵트인한 상점에 한해, 승인 완료 즉시 PG 서버가 결제요청 때 전달받은 rUrl로 승인결과를 1회 직접 전송하는 Server-to-Server 통보입니다. 브라우저를 통한 기존 결과 수신("L3")의 보완 채널이며, 「결제 Notification」(계약 등록 Notify URL 기반 비동기 통보, "L1")과는 대상 URL·전송 시점이 다른 별개 기능입니다.

L1 · L2 · L3 비교
L1 (결제 Notification)L2 (본 기능)L3 (브라우저 리다이렉트)
수신 URL계약정보 등록 Notify URL결제요청 시 전달한 rUrl (L3과 동일)결제요청 시 전달한 rUrl
전송 방식Background 비동기승인 처리 중 동기 호출 (Timeout 3초)고객 브라우저 리다이렉트
대상 상점계약 시 등록한 전체 상점옵트인(notiUseYn=Y) 상점만전체 상점(기본 채널)
대상 결제수단계약 범위 전체(오프라인 포함)신용카드(GEP·심플페이) · 카카오페이 · 네이버페이 · 계좌이체(BA)온라인결제 전체
실패 시최대 5회 재전송내부에서 흡수, 승인/L3에 영향 없음, 재전송 없음-

옵트인 방법

💡
결제요청(/paypage 또는 /mobilepage/common/mainFrame.pay) 호출 시 파라미터 notiUseYn=Y를 추가 전송하면 해당 거래부터 L2가 적용됩니다. 값을 보내지 않거나 Y가 아니면 기존과 동일하게 L2 없이 L3로만 결과를 받습니다. (파라미터 상세는 「결제요청」 섹션 참조)

지원 대상 결제수단

결제수단지원 여부비고
신용카드 (GEP · 심플페이/PAYPAGE)지원CHECK_HASH 기존과 동일하게 항상 포함
카카오페이 (신용카드/머니)지원승인 실패 건은 정책 확정 전까지 L2 미발송(성공 건만)
네이버페이 (신용카드/포인트)지원승인 실패 건은 L2 미발송(성공 건만)
계좌이체 (BA)지원
가상계좌 (VA)미지원결제창 결과는 "계좌 발급"이며 "결제 완료"가 아닙니다. 입금 완료 통보는 기존 「결제 Notification」(입금통보) 채널을 이용하세요.

CHECK_HASH 포함 규칙

⚠️
· 신용카드(CC): 옵트인 여부와 무관하게 기존과 동일하게 항상 CHECK_HASH가 포함됩니다.
· 카카오페이·네이버페이·계좌이체(BA): 옵트인(notiUseYn=Y) 상점에 한해서만 CHECK_HASH가 새로 포함됩니다. 계산식은 신용카드와 동일한 표준 공식(HmacSHA256(apiKey, RESULT_CODE+TID+ORDERNO))입니다.
· 미옵트인 상점의 응답 전문은 기존과 100% 동일합니다(바이트 단위 불변). 카카오·네이버·BA에서 CHECK_HASH가 없거나 null로 오는 기존 동작은 그대로 유지됩니다.

통보 예시 (결제수단별)

아래 CHECK_HASH는 예시 API Key ef5df61805ea166bb16867a9bf566082 기준으로 HmacSHA256(apiKey, RESULT_CODE+TID+ORDERNO)를 직접 계산한 값입니다(「공통사항 & 보안」 섹션 해시 샘플과 동일 키). 실제 연동 시에는 상점에 부여된 API Key로 계산하세요. TID/ORDERNO는 본 가이드의 기존 예시값을 그대로 사용해, 일부 탭은 입력값이 같아 CHECK_HASH도 동일하게 계산됩니다(HMAC은 동일 입력에 항상 동일 결과를 내는 결정적 함수이므로 정상입니다).

rUrl로 수신되는 JSON (L3 응답과 동일 필드 구성)
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_METHOD": "CC", "TID": "260901130562200", "ORDERNO": "ORDER20260901105237",
  "RESERVED01": "reserved01", "RESERVED02": "reserved02",
  "CHECK_HASH": "cg+anYZOAGlzbxUCkp7Ai+T5h8c7QJ2I0Lf8pDRj+To=",
  "APPROVNO": "21676259", "APPRODT": "20260901", "APPROTM": "105240",
  "APPROAMT": "10000", "ISSUE_CODE": "1104", "ISSUE_NAME": "삼성카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "N",
  "CARD_NO": "536148**********"
}

신용카드는 옵트인 여부와 무관하게 기존과 동일하게 항상 CHECK_HASH가 포함됩니다.

rUrl로 수신되는 JSON — 카카오페이 신용카드(KKP·CC), 옵트인 상점
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "KKP", "PAY_METHOD": "CC",
  "TID": "210728130414386", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "C",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "jFzY7rkUQBGg2ceMh5xZVbdN/jG/goHQJbrTToy+myE="
}

카카오페이는 신용카드·머니 모두 현재 CHECK_HASH가 전혀 내려가지 않으며, 옵트인 상점에 한해서만 위와 같이 새로 포함됩니다.

rUrl로 수신되는 JSON — 카카오페이 머니(KKP·VO), 옵트인 상점
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "KKP", "PAY_METHOD": "VO",
  "TID": "210728130414388", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPRODT": "20210728", "APPROTM": "113730",
  "APPROAMT": "5000", "MID": "M20200203113418",
  "CHECK_HASH": "EDhw/rLEzF4fTqKxmFEGHcdYRoNTbOm9fOjdGfegdgU="
}

카카오페이 머니도 신용카드와 동일하게, 옵트인 상점에 한해 CHECK_HASH가 새로 포함됩니다.

rUrl로 수신되는 JSON — 네이버페이 신용카드(NVP·CC), 옵트인 상점
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "NVP", "PAY_METHOD": "CC",
  "TID": "210728130414386", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPROVNO": "33709377", "APPRODT": "20210728", "APPROTM": "113541",
  "APPROAMT": "5000", "ISSUE_CODE": "1107", "ISSUE_NAME": "신한카드",
  "PURCHASE_CODE": "1107", "PURCHASE_NAME": "신한카드",
  "QUOTA_MONTHS": "00", "NOINT": "N", "CHECKCD": "C",
  "CARD_NO": "510737**********", "MID": "M20200203113418",
  "CHECK_HASH": "jFzY7rkUQBGg2ceMh5xZVbdN/jG/goHQJbrTToy+myE=",
  "VAN_RECV_KEY": ""
}

네이버페이 신용카드(CC) 조합은 PGAS-CC(1200) 경로를 통해 옵트인 여부와 무관하게 이미 기존부터 CHECK_HASH가 내려가고 있었습니다(「결제요청」 섹션 응답 예시와 동일). 이번 배포로 새로 달라지는 것은 없으며, 참고용으로 함께 표시합니다.

rUrl로 수신되는 JSON — 네이버페이 포인트(NVP·VO), 옵트인 상점
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "PAY_GROUP": "NVP", "PAY_METHOD": "VO",
  "TID": "210728130414388", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "APPRODT": "20210728", "APPROTM": "113730",
  "APPROAMT": "5000", "MID": "M20200203113418",
  "CHECK_HASH": "EDhw/rLEzF4fTqKxmFEGHcdYRoNTbOm9fOjdGfegdgU="
}

네이버페이 포인트(VO)는 현재 CHECK_HASH가 없으며, 옵트인 상점에 한해서만 위와 같이 새로 포함됩니다 — 이번 배포로 실제 달라지는 케이스입니다.

rUrl로 수신되는 JSON — 계좌이체(GEP·BA), 옵트인 상점
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "성공",
  "DRESULT_CODE": "EC0000", "DRESULT_MSG": "성공",
  "TID": "210728130414394", "ORDERNO": "ORDER12345",
  "RESERVED01": "가맹점예약필드 1", "RESERVED02": "가맹점예약필드 2",
  "MID": "M20200203113418",
  "BANK_CD": "002", "BANK_NM": "산업은행", "ACCT_NO": "08724",
  "CHECK_HASH": "tFBMAJldIAvvlALOIRWagivaqy4Ilx4K8peh7tKtAok="
}

계좌이체는 기존에 CHECK_HASH가 null로 내려갔으나, 옵트인 상점에 한해 위와 같이 실값이 새로 포함됩니다.

가맹점 구현 시 필수 사항

🚨
이중 수신 대비 멱등(idempotent) 처리 필수
옵트인 상점은 동일 TID에 대한 결과를 L2(즉시) + L3(브라우저 완료 시)로 최대 2회 수신할 수 있습니다. TID(또는 ORDERNO) 기준으로 중복 처리를 반드시 방지하세요.

위·변조 검증
L2로 수신한 결과도 L3와 동일하게 CHECK_HASH로 검증한 뒤 신뢰하세요. 별도의 L2 전용 인증 헤더는 없습니다.

무응답/오류에 대한 재시도 없음
L2는 best-effort 1회 전송이며, 가맹점 서버가 3초 내 응답하지 않거나 오류를 반환해도 재전송하지 않습니다. 결제 승인 자체와 L3 처리에는 영향이 없으므로, L2만으로 결과 수신을 전적으로 의존하지 말고 L3/결제내역 조회와 함께 사용하세요.
📌
L2는 재시도 없는 1회성 통보입니다. L2 수신에 실패하거나 놓친 경우에도, 계약정보에 Notify URL을 등록해두면 「결제 Notification」(L1)을 통해 승인결과를 추가로 수신할 수 있습니다 — L1은 가맹점 서버가 실패를 반환하거나 무응답이어도 최대 5회까지 재전송하므로, L2보다 도달 가능성이 높습니다. L2 하나만으로 결과 수신을 보장하지 말고 L1과 함께 사용하는 것을 권장합니다.

📊정산 내역 조회

승인 대사 및 정산 대사 데이터를 조회하는 API입니다.

🔧 개발기
http://220.117.220.108:30200
🚀 상용기
https://ema.kovanpay.com
POST /Calculate/CalHist/getPgDataListOut.out 정산 내역 조회 ▼
Content-Type: application/json, Encoding: UTF-8 / TLS 1.2
요청 파라미터
항목ID항목명타입길이(byte)필수설명
id상점IDANFIX 15Y상점 별로 부여되는 상점 ID (가맹점ID는 apiKey가 없어 encData 생성이 불가하므로 사용 불가)
stmtReqDt대사요청일NFIX 8Y요청 일시 (YYYYMMDD)
stmtType대사타입NFIX 1Y0: 승인대사, 1: 정산대사
ediDate전문요청일시NFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값ANSFIX 256Yid + ediDate + api key를 이용한 키
승인 응답 데이터 (stmtType=0)
항목ID항목명타입설명
resultCd결과코드AN성공: 0000
resultMsg결과메시지ANS실패시에만 표시
id해당IDAN요청한 ID
stmtDt대사일N요청한 일자
stmtType대사타입N0: 승인대사, 1: 정산대사
mbsNo사업자번호N가맹점의 사업자번호
stmtCnt대사건수N대사 합계 건수
stmtSumAmt대사 합계 금액N대사 합계 금액
stmtData (JSONArray)
Mid상점IDAN(15)
appDtm승인일시N(14)YYYYMMDDHHMMSS 형식
canDtm취소일시N(14)YYYYMMDDHHMMSS 형식
payMethod결제수단A(10)CARD | BANK | VACNT | PAY
trxStCd거래상태코드N(1)0:승인, 1:전취소, 2:후취소, 3:부분취소
goodsNm상품명AN(100)상품이름
goodsAmt상품금액N(15)결제금액
remainAmt잔액N(15)부분취소 후 남은 금액
quotaMon할부개월N(2)할부 개월 수
appNo승인번호AN(10)카드사, 은행 승인번호
acqCardCd매입사코드N(4)신용카드: 카드사코드 / 계좌이체·가상계좌: 은행코드
appCardCd발급사코드N(4)카드사 코드
ezpAuthCd간편결제코드AN(4)간편 결제사 코드 (미사용 시 공백)
cardType카드타입N(1)0: 체크 / 1: 신용
cartMid카트MIDAN(10)장바구니 거래 시 MID (미사용 시 공백)
cartTid카트TIDAN(30)장바구니 거래 시 TID (미사용 시 공백)
TidPG거래번호AN(30)거래번호
Otid원거래 PG거래번호AN(30)부분취소 시 원거래 번호
ordNo주문번호AN(40)가맹점 주문번호
ordNm주문자명A(30)주문자 이름
ordTel주문자연락처ANS(20)주문자 연락처
mbsUsrId고객IDAN(20)가맹점 고객 ID
trxCd에스크로여부N(1)0: 일반 / 1: 에스크로
mbsReserved가맹점예약필드ANS(500)가맹점 예약 필드
⚠️
stmtType=1(정산대사)은 정산 처리가 완료된 거래만 조회됩니다. 아직 정산 전인 거래건은 조회되지 않을 수 있습니다.
정산 응답 데이터 (stmtType=1) - 추가 필드
항목ID항목명타입설명
Mid상점IDAN(15)
stmtDt입금일N(8)YYYYMMDD 형식
txtDt결제일N(8)승인/취소 일 (YYYYMMDD)
payMethod결제수단A(10)CARD | BANK | VACNT | PAY
fnCd금융사코드N(4)신용카드: 매입사 / 계좌이체·가상계좌: 금융사
appNo승인번호AN(10)카드사, 은행 승인번호
amt금액N(15)결제금액 (취소 시 마이너스)
fee수수료N(15)취소 시 마이너스
vatVATN(15)취소 시 마이너스
refundFee환불 수수료N(15)
refundFeeVat환불 수수료 VATN(15)
smsFeeSMS 수수료N(15)
stmtAmt입금액N(15)최종입금 금액 (취소 시 마이너스)
cartMid카트MIDAN(10)장바구니 거래 시 MID (미사용 시 공백)
cartTid카트TIDAN(30)장바구니 거래 시 TID (미사용 시 공백)
tidPG거래번호AN(30)거래번호
otid원거래 PG거래번호AN(30)부분취소 시 원거래 번호
ordNo주문번호AN(40)가맹점 주문번호
trxStCd거래상태코드N(1)0:승인, 1:취소
remainAmt잔액N(15)부분취소 후 남은 금액
goodsNm상품명AN(100)상품명
ordNm주문자명A(30)주문자 이름
mbsUsrId고객IDAN(20)가맹점 고객 ID
mbsReserved가맹점예약필드ANS(500)가맹점 예약 필드

🏪지급대행 가맹점 관리

지급대행 가맹점 등록, 수정, 조회 API입니다.

🔧 개발기
http://220.117.220.108:30100
🚀 상용기
https://ebiz.kovanpay.com
⚠️
API_KEY가 노출되지 않게 반드시 서버 사이드에서만 사용해야 합니다.
POST /api/v1/entp/payagent/merchant 지급대행 가맹점 등록 ▼
Content-Type: application/json, Encoding: UTF-8 / TLS 1.2
요청 파라미터
항목ID항목명타입길이(byte)필수설명
id대표IDANFIX 15Y지급대행을 관리하는 대표ID (KOVANPG 발급 EID)
editDate전문요청일시NFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값ANSFIX 256Yid + editDate + api key를 이용한 키
oid가맹점IDAN30Y가맹점에서 관리하는 가맹점 ID
shopNm상점명AN100Y
phone전화번호ANS20Y상점 전화번호
csPhoneCS 전화번호ANS20OCS 전화번호
email이메일주소ANS30Y메일주소
응답 파라미터
항목ID항목명타입설명
resultCd결과코드AN성공: 0000
resultMsg결과메시지ANS실패시에만 표시
data (JSONArray)
id대표IDAN요청한 ID (PG가 발급한 EID)
oid상점ID-가맹점AN가맹점에서 요청한 상점ID
rid상점ID-PGANPG에서 발급한 상점ID
PUT /api/v1/entp/payagent/merchant 지급대행 가맹점 수정 ▼
요청 파라미터 (id는 EID가 아닌 RID 사용)
항목ID항목명타입길이(byte)필수설명
idRIDANFIX 15Y지급대행용 RID
editDate전문요청일시NFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값ANSFIX 256Yid + editDate + api key를 이용한 키
oid가맹점IDAN30Y가맹점에서 관리하는 가맹점 ID
shopNm상점명AN100Y
phone전화번호ANS20Y상점 전화번호
csPhoneCS 전화번호ANS20OCS 전화번호
email이메일주소ANS30Y메일주소
응답 파라미터
항목ID항목명타입설명
resultCd결과코드AN성공: 0000
resultMsg결과메시지ANS실패시에만 표시
data (JSONArray)
id대표ID (RID)AN(15)수정된 가맹점의 RID
oid상점ID-가맹점AN(30)가맹점에서 요청한 상점ID
shopNm상점명AN(100)
phone전화번호ANS(20)상점 전화번호
csPhoneCS 전화번호ANS(20)CS 전화번호
email이메일주소ANS(30)메일주소
GET /api/v1/entp/payagent/merchant 지급대행 가맹점 조회 ▼
요청 파라미터
항목ID항목명타입길이(byte)필수설명
idRIDANFIX 15Y지급대행용 RID
editDate전문요청일시NFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값ANSFIX 256Yid + editDate + api key를 이용한 키
oid가맹점IDAN30Y가맹점에서 관리하는 가맹점 ID
응답 파라미터
항목ID항목명타입길이(byte)설명
resultCd결과코드ANMAX 4성공: 0000, 실패: 그외
resultMsg결과메시지ANSMAX 100실패시에만 표시
data (JSONArray)
id대표ID (RID)AN15조회된 가맹점의 RID
oid상점ID-가맹점AN30가맹점에서 요청한 상점ID
shopNm상점명AN100
phone전화번호ANS20상점 전화번호
csPhoneCS 전화번호ANS20CS 전화번호
email이메일주소ANS30메일주소

🏦지급대행 계좌 관리

지급대행 가맹점의 정산 계좌를 등록, 수정, 조회하는 API입니다.

POST /api/v1/entp/payagent/merchant/acct 계좌 등록 ▼
요청 파라미터
항목ID항목명타입길이(byte)필수설명
idRIDANFIX 15Y지급대행용 RID
editDate전문요청일시NFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값ANSFIX 256Yid + editDate + api key를 이용한 키
oid가맹점IDAN30Y가맹점에서 관리하는 가맹점 ID
bankCd은행코드N3Y은행코드 참조
acctNm예금주A30Y
acctNo계좌번호AN50Y
응답 파라미터
항목ID항목명타입길이(byte)설명
resultCd결과코드ANMAX 4성공: 0000, 실패: 그외
resultMsg결과메시지ANSMAX 100실패시에만 표시
PUT /api/v1/entp/payagent/merchant/acct 계좌 수정 ▼
요청 파라미터
항목ID항목명타입길이(byte)필수설명
idRIDANFIX 15Y지급대행용 RID
editDate전문요청일시NFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값ANSFIX 256Yid + editDate + api key를 이용한 키
oid가맹점IDAN30Y가맹점에서 관리하는 가맹점 ID
bankCd은행코드N3Y은행코드 참조
acctNm예금주A30Y
acctNo계좌번호AN50Y
응답 파라미터
항목ID항목명타입길이(byte)설명
resultCd결과코드ANMAX 4성공: 0000, 실패: 그외
resultMsg결과메시지ANSMAX 100실패시에만 표시
GET /api/v1/entp/payagent/merchant/acct 계좌 조회 ▼
요청 파라미터
항목ID항목명타입길이(byte)필수설명
idRIDANFIX 15Y지급대행용 RID
editDate전문요청일시NFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값ANSFIX 256Yid + editDate + api key를 이용한 키
oid가맹점IDAN30Y가맹점에서 관리하는 가맹점 ID
응답 파라미터
항목ID항목명타입길이(byte)설명
resultCd결과코드ANMAX 4성공: 0000, 실패: 그외
resultMsg결과메시지ANSMAX 100실패시에만 표시
acctStatus계좌 등록 상태ANS10계좌상태코드 참조 (REG_REQ, REG_CONF 등)
bankCd은행코드N3은행코드 참조
acctNm예금주A30
acctNo계좌번호AN50

💸지급 요청/취소/조회

🔧 개발기
http://220.117.220.108:30200
🚀 상용기
https://ema.kovanpay.com
POST /PayAgent/v1/merchant/settlements.out 지급대행 데이터 요청 ▼
요청 파라미터
항목ID항목명타입길이(byte)필수설명
id대표IDANFIX 15Y지급대행을 관리하는 대표ID (EID)
ediDate전문요청일시NFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값ANSFIX 256Yid + ediDate + api key를 이용한 키
payReqCnt지급요청건수N5Y지급요청건수
payReqList (배열)
ridPG 상점IDAN30OPG에서 부여한 지급대행 가맹점 ID
oid상점ID(가맹점)AN30Y지급대행 대상 상점 ID
shopNm상점명AN100Y
payReqDt지급일N8YYYYYMMDD
payReqAmt지급액N15Y
shopSeqNo요청일련번호AN50O가맹점 요청 일련번호
bankCd은행코드N3Y빈 값일 경우 가맹점 등록 시 계좌 정보 참조
acctNm예금주A30Y
acctNo계좌번호AN50Y
memo메모ANS35O다중 지급 요청 시 가장 최근 메모 적용
응답 파라미터
항목ID항목명타입길이(byte)설명
id대표IDANFIX 15요청한 EID
respDate전문응답일시NFIX 14응답 일시 (yyyymmddhhmmss)
payResultCnt응답건수N5
resCode응답코드AN40000: 성공 / 0010: 해시 불일치 / 0020: 지급 요청금액 오류
resMsg응답메시지ANSMAX 100실패시에만 표시
payResultList (JSONArray)
oid상점IDAN30지급대행 대상 상점 ID
rid상점ID-PGANFIX 15PG에서 발급한 상점ID
shopNm상점명AN100
bankCd은행코드N3은행 코드표 참조
shopSeqNo요청일련번호AN-가맹점 요청 일련번호
acctNm예금주A30
acctNo계좌번호AN50
payReqDt지급일N8YYYYMMDD
payReqAmt지급액N15
resultCdDetail결과코드ANMAX 4성공: 0000, 실패: 그외
resultMsgDetail결과메시지ANSMAX 100실패시에만 표시
POST /PayAgent/v1/merchant/settlements-cancel.out 지급대행 데이터 요청취소 ▼
요청 파라미터
항목ID항목명타입길이(byte)필수설명
id대표IDANFIX 15YEID
ediDate전문요청일시NFIX 14Yyyyymmddhhmmss
encData해쉬암호화값ANSFIX 256Y
orgEdiDate(원)지급요청일N8Y원 지급요청전문의 ediDate
canType취소구분A10Y전체: ALL / 단일: TARGET
oid상점IDAN30OcanType TARGET 시 필요
응답 파라미터
항목ID항목명타입길이(byte)설명
id대표IDANFIX 15요청한 EID
respDate전문응답일시NFIX 14응답 일시 (yyyymmddhhmmss)
canResultCnt응답건수N5
resCode응답코드AN40000: 성공 / 0010: 해시 불일치 / 0020: 조회조건 오류
resMsg응답메시지ANSMAX 100실패시에만 표시
canResultList (JSONArray)
oid상점IDAN30지급대행 대상 상점 ID
rid상점ID-PGANFIX 15PG에서 발급한 상점ID
shopNm상점명AN100
bankCd은행코드N3은행 코드표 참조
shopSeqNo요청일련번호AN-가맹점 요청 일련번호
acctNm예금주A30
acctNo계좌번호AN50
payReqDt지급일N8YYYYMMDD
payReqAmt지급액N15
resultCdDetail결과코드ANMAX 4성공: 0000, 실패: 그외
resultMsgDetail결과메시지ANSMAX 100실패시에만 표시
POST /PayAgent/v1/merchant/settlements-history.out 지급대행 처리결과 조회 ▼
요청 파라미터
항목ID항목명타입길이(byte)필수설명
id대표IDANFIX 15YEID
ediDate전문요청일시NFIX 14Y
encData해쉬암호화값ANSFIX 256Y
payDateFrom시작일N8Yyyyymmdd
payDateTo종료일N8Yyyyymmdd
schType조회구분A10Y전체: ALL / 단일: TARGET
oid상점IDAN30OschType TARGET 시 필요
응답 파라미터
항목ID항목명타입길이(byte)설명
id대표IDANFIX 15요청한 EID
respDate전문응답일시NFIX 14응답 일시 (yyyymmddhhmmss)
payResultCnt응답건수N5
resCode응답코드AN40000: 성공 / 0010: 해시 불일치 / 0020: 조회조건 오류
resMsg응답메시지ANSMAX 100실패시에만 표시
payResultList (JSONArray)
oid상점IDAN30지급대행 대상 상점 ID
rid상점ID-PGANFIX 15PG에서 발급한 상점ID
shopNm상점명AN100
bankCd은행코드N3은행 코드표 참조
shopSeqNo요청일련번호AN-가맹점 요청 일련번호
acctNm예금주A30
acctNo계좌번호AN50
payReqDt지급일N8YYYYMMDD
payReqAmt지급액N15
resultCdDetail결과코드ANMAX 4성공: 0000, 실패: 그외
resultMsgDetail결과메시지ANSMAX 100실패시에만 표시

📋코드표

결제수단 코드

결제 그룹결제 수단설명
일반결제
GEPCC신용카드
GEPVA가상계좌
GEPBA계좌이체
KKPCC카카오페이 신용
KKPVO카카오페이 머니
NVPCC네이버페이 신용
NVPVO네이버페이 포인트
TOT-통합결제창
간편결제
APPCC애플페이 신용
TSPCC토스페이 신용
TSPVO토스페이 머니
SSPCC삼성페이 신용
PCPCC페이코 신용
PCPVO페이코 머니
LTPCC엘페이 신용
SGPCCSGP페이 신용

카드사 코드

cardCode (결제요청), acqCardCd / appCardCd (정산 API), 차액정산 카드사 코드 모두 동일한 코드 체계를 사용합니다.

코드카드사/기관명코드카드사/기관명
주요 카드사
1101국민카드1107신한카드
1102현대카드1108NH카드
1103롯데카드1109씨티카드
1104삼성카드1110우리카드
1105하나카드1111우체국비씨
1106비씨카드1112기업비씨
1113광주은행1501SSG카드(JB)
1502코나아이1901카카오페이
2283NH농협비씨--
기타 기관 (112xxx)
112547광주카드112548수협BC카드
112549전북112550KDB산업은행
112551카카오뱅크112552K뱅크
112584전북(KB)112599토스뱅크
112600신한비씨112601국민비씨
112602하나비씨112606차이코퍼레이션
112607산림조합중앙회112608KG모빌리언스
112610한국투자증권112611한화투자증권
112612비바리퍼블리카112613지머니트랜스
112614디셈버앤컴퍼니112615한패스
112616토스112619VISA
112621MASTER112622JCB
112636iM뱅크BC112651해외아멕스
112652현대다이너스112653현대디스커버

거래상태 코드

TRANS_STATUS — 결제내역 조회 응답에서 사용합니다. (TRANS_STATUS_NM에 상태명도 함께 반환됩니다.)

코드코드명코드코드명
주문/인증
00주문요청10인증(주문)성공
11인증(주문)실패12인증요청
13인증시도--
승인/결제
20승인(결제)완료21승인(결제)실패
22승인요청--
매입
30매입완료31매입중
32매입거절34매입신청
36매입보류38매입불가
39매입거절/재매입--
승인취소
40승인(결제)취소41망취소전송중
42망취소실패43승인취소요청
44승인취소실패--
매입취소
50매입취소완료51매입취소중
52매입취소거절53매입취소신청
56매입취소보류58매입취소불가
59매입취소거절/재매입--
기타
70SMS확인성공71SMS확인실패
72망취소성공--

은행 코드

코드은행코드은행
002산업은행020우리은행
003기업은행023SC제일은행
004국민은행027한국씨티은행
007수협031IM뱅크
011농협032부산은행
012단위농협034광주은행
035제주은행037전북은행
039경남은행045새마을금고
048신협071우체국
081하나은행088신한은행
089케이뱅크090카카오뱅크
092토스뱅크064산림조합
005외환은행008한국수출입은행
021구)조흥은행026구)신한은행
050상호저축은행053구)씨티은행
054HSBC055도이치
056ABN암로057UFJ은행
058미즈호코퍼레이트은행059미쓰비시도쿄UFJ
060B.O.A--

계좌 상태 코드

코드설명
REG_REQ등록신청
REG_CONF등록승인
CHG_REQ변경신청
CHG_CONF변경승인
REJECT반려

⚠️결제처리결과 코드

결과코드(가맹점): RESULT_CODE / 결과메시지(가맹점): RESULT_MSG
결과코드(사용자): DRESULT_CODE / 결과메시지(사용자): DRESULT_MSG

✅
EC0000 - 성공 (가맹점/사용자 공통)
결과코드(가맹점)결과메시지(가맹점)결과코드(사용자)결과메시지(사용자)
EC1xxx — 거래 처리 오류
EC1001거래번호 생성 실패EC1001거래번호 생성 실패
EC1002거래데이타 생성 실패EC1002시스템오류(문의요망)
EC1003거래데이타 조회 실패EC1003시스템오류(문의요망)
EC1004거래데이타 이관 실패EC1004시스템오류(문의요망)
EC1005결제인증추적 조회 실패EC1005결제인증추적 조회 실패
EC1006RM(인증) 실패EC1006거래제한으로 인한 결제실패(문의요망)
EC1007RM(승인) 실패EC1007거래제한으로 인한 결제실패(문의요망)
EC1008RM 통계반영 실패EC1008RM 통계반영 실패
EC1009결제수단 조회 실패EC1009결제수단 조회 실패
EC1010잘못된 할부개월수EC1010잘못된 할부개월수
EC1011가맹점(계약) 정보 조회 실패EC1011가맹점(계약) 정보 조회 실패
EC1012원천사 정보 조회 실패EC1012원천사 정보 조회 실패
EC1013VAN사 조회 실패EC1013VAN사 조회 실패
EC1014ISP 인증 실패EC1014ISP 인증 실패
EC1015XMPI 인증 실패EC1015XMPI 인증 실패
EC1016KMPI 인증 실패EC1016KMPI 인증 실패
EC1017SMPI 인증 실패EC1017SMPI 인증 실패
EC1018예약정보 반영실패EC1018예약정보 반영실패
EC1019인증시도 반영실패EC1019인증시도 반영실패
EC1020인증결과 반영실패EC1020인증결과 반영실패
EC1021주문요청 반영실패EC1021주문요청 반영실패
EC1022승인(결제)요청 반영실패EC1022승인(결제)요청 반영실패
EC1023승인(결제)결과 반영실패EC1023승인(결제)결과 반영실패
EC1024취소요청 반영실패EC1024취소요청 반영실패
EC1025취소결과 반영실패EC1025취소결과 반영실패
EC1026망취소요청 반영실패EC1026망취소요청 반영실패
EC1027망취소결과 반영실패EC1027망취소결과 반영실패
EC1028원천사 등록심사 정보 없음EC1028원천사 등록심사 정보 없음
EC1029원천사 결제(취소) 결과실패EC1029원천사 결제(취소) 결과실패
EC1030원천사 응답코드 매핑 실패EC1030원천사 응답코드 매핑 실패
EC1031결제금액오류EC1031결제금액오류
EC1032취소금액오류EC1032취소금액오류
EC1033결제요청통신실패(VAN)EC1033결제요청실패(VAN)
EC1034취소요청통신실패(VAN)EC1034취소요청실패(VAN)
EC1035망취소요청 통신실패(VAN)EC1035망취소요청실패(VAN)
EC1036결제요청실패EC1036결제요청실패
EC1037취소요청실패EC1037취소요청실패
EC1038망취소요청실패EC1038망취소요청실패
EC1039가맹점 결과결과 전송 실패EC1039가맹점 결과결과 전송 실패
EC1040결제결과 메일전송실패EC1040결제결과 메일전송실패
EC1041가상계좌할당실패EC1041가상계좌할당실패
EC1042현금영수증 정보 생성 실패EC1042현금영수증 정보 생성 실패
EC1043망취소 이미완료 혹은 진행중EC1043망취소 이미완료 혹은 진행중
EC1044인증모듈 매핑오류EC1044인증모듈 매핑오류
EC1045원천사 취소실패EC1045원천사 취소실패
EC1046원천사 망취소실패EC1046원천사 망취소실패
EC1047결제구분 취득실패EC1047시스템오류(문의요망)
EC1048결제 카드리스트 취득실패EC1048시스템오류(문의요망)
EC1049무이자 할부정보 취득실패EC1049시스템오류(문의요망)
EC1050RM(인증) 실패(DB 오류)EC1050시스템오류(문의요망)
EC1051RM(승인)실패(DB오류)EC1051시스템오류(문의요망)
EC1052KBAPP 인증 실패EC1052KBAPP 인증 실패
EC1053거래취소데이타생성실패EC1053거래취소데이타생성실패
EC1054거래취소시간초과EC1054거래취소시간초과
EC1055응답 파라미터 설정 실패EC1055시스템오류(문의요망)
EC1056정의되지 않은 전문 값 오류 (PAYMENT_TYPE)EC1056정의되지 않은 전문 값 오류 (PAYMENT_TYPE)
EC1057승인취소 매입 반영 실패EC1057승인취소 매입 반영 실패
EC1058TAX_YN 검증오류EC1058TAX_YN 검증오류
EC1059할당된 가상계좌 정보 반영 실패EC1059할당된 가상계좌 정보 반영 실패
EC1060은행리스트 취득 실패EC1060시스템오류(문의요망)
EC1061할당가능한 은행리스트 미존재EC1061시스템오류(문의요망)
EC1062결제가능한 카드리스트 미존재EC1062시스템오류(문의요망)
EC1063가상계좌 거래종료일시 오류EC1063시스템오류(문의요망)
EC1064가상계좌 거래종료일시 최대설정 초과EC1064시스템오류(문의요망)
EC1065현금영수증 ISSUE_METHOD 오류EC1065시스템오류(문의요망)
EC1066현금영수증 ISSUE_CONTENTS 유효성검증 실패EC1066시스템오류(문의요망)
EC1067기취소된 거래로 취소 불가EC1067기취소된 거래로 취소 불가
EC1068남은 금액보다 취소 금액이 큼EC1068남은 금액보다 취소 금액이 큼
EC1069에스크로 정보 취득실패EC1069시스템오류(문의요망)
EC1070에스크로 시 고객 이메일 필요EC1070에스크로 시 고객 이메일 필요
EC1071에스크로 계약정보 미존재EC1071시스템오류(문의요망)
EC1072에스크로 거래 데이터 생성실패EC1072시스템오류(문의요망)
EC1073에스크로 구매확정 메일 발송 실패EC1073시스템오류(문의요망)
EC1074가능 할부개월수 초과EC1074시스템오류(문의요망)
EC1075해당 TID의 에스크로 데이터 미존재EC1075시스템오류(문의요망)
EC1076NOTI 데이터 삽입 실패EC1076시스템오류(문의요망)
EC1077계좌이체 취소실패 - 에스크로 구매확정/구매취소확정 시 취소불가EC1077시스템오류(문의요망)
EC1078계좌이체 취소실패 - 에스크로 배송등록 상태시 가맹점 API로 취소불가EC1078시스템오류(문의요망)
EC1079에스크로 데이터 생성 실패EC1079에스크로 처리 중 에러 발생
EC1080현금영수증 임시데이터 이전 실패EC1080현금영수증 처리 중 에러발생
EC1081에스크로 상태 변경 실패EC1081에스크로 처리 중 에러 발생
EC1082현금영수증 승인 데이터 조회 실패EC1082시스템오류(문의요망)
EC1083BankPay 인증 실패EC1083BankPay 인증 실패
EC1084취소요청 금액은 양수값이어야 함EC1084취소요청 금액은 양수값이어야 함
EC1085신용카드 CARD_TYPE/PAYMENT_TYPE 오류EC1085시스템오류(문의요망)
EC1086다날 인증 실패EC1086다날 인증 실패
EC1087매입 취소 불가 상태EC1087매입 취소 불가 상태
EC1088부분 취소 불가EC1088부분 취소 불가
EC1089해당상점 취소불가상태EC1089해당상점 취소불가상태
EC2xxx — 결제요청 데이터 검증 오류
EC2001결제요청 데이터 검증 오류(mid)EC2001시스템오류(문의요망)
EC2002결제요청 데이터 검증 오류(rUrl)EC2002시스템오류(문의요망)
EC2003결제요청 데이터 검증 오류(rMethod)EC2003시스템오류(문의요망)
EC2004결제요청 데이터 검증 오류(payType)EC2004시스템오류(문의요망)
EC2005결제요청 데이터 검증 오류(buyItemnm)EC2005시스템오류(문의요망)
EC2006결제요청 데이터 검증 오류(buyReqamt)EC2006시스템오류(문의요망)
EC2007결제요청 데이터 검증 오류(buyItemcd)EC2007시스템오류(문의요망)
EC2008결제요청 데이터 검증 오류(buyerid)EC2008시스템오류(문의요망)
EC2009결제요청 데이터 검증 오류(buyernm)EC2009시스템오류(문의요망)
EC2010결제요청 데이터 검증 오류(buyerEmail)EC2010시스템오류(문의요망)
EC2011결제요청 데이터 검증 오류(orderno)EC2011시스템오류(문의요망)
EC2012결제요청 데이터 검증 오류(orderdt)EC2012시스템오류(문의요망)
EC2013결제요청 데이터 검증 오류(ordertm)EC2013시스템오류(문의요망)
EC2014결제요청 데이터 검증 오류(apiKey)EC2014시스템오류(문의요망)
EC2015결제요청 데이터 검증 오류(checkHash)EC2015시스템오류(문의요망)
EC2016결제요청 데이터 검증 오류(cardCode)EC2016시스템오류(문의요망)
EC2017결제요청 데이터 검증 오류(quota)EC2017시스템오류(문의요망)
EC2018결제요청 데이터 검증 오류(noint_inf)EC2018시스템오류(문의요망)
EC2019결제요청 데이터 검증 오류(taxYn)EC2019시스템오류(문의요망)
EC2020결제요청 데이터 검증 오류(taxAmt)EC2020시스템오류(문의요망)
EC2021결제요청 데이터 검증 오류(returnAppUrl)EC2021시스템오류(문의요망)
EC2022결제요청 데이터 검증 오류(bankCode)EC2022시스템오류(문의요망)
EC2023결제요청 데이터 검증 오류(trend)EC2023시스템오류(문의요망)
EC2024결제요청 데이터 검증 오류(cashYn)EC2024시스템오류(문의요망)
EC2025결제요청 데이터 검증 오류(issueType)EC2025시스템오류(문의요망)
EC2026결제요청 데이터 검증 오류(issueMethod)EC2026시스템오류(문의요망)
EC2027결제요청 데이터 검증 오류(issueContents)EC2027시스템오류(문의요망)
EC2028결제요청 데이터 검증 오류(escrFlag)EC2028시스템오류(문의요망)
EC2029결제요청 데이터 검증 오류(phoneNum)--
EC2099에러내용 반영 실패EC2099시스템오류(문의요망)
EC5xxx — 전문 처리 오류
EC5001전문 인코딩 실패EC5001시스템오류(문의요망)
EC5002전문 디코딩 실패EC5002시스템오류(문의요망)
EC5003전문 암호화 실패EC5003시스템오류(문의요망)
EC5004전문 복호화 실패EC5004시스템오류(문의요망)
EC5005전문 개인정보 암호화 실패EC5005시스템오류(문의요망)
EC5006전문 개인정보 복호화 실패EC5006시스템오류(문의요망)
EC5007미등록 전문 및 URIEC5007시스템오류(문의요망)
EC5008인증 및 무결성 검증 실패(해시)EC5008시스템오류(문의요망)
EC5009필수항목 유효성 검증 실패EC5009시스템오류(문의요망)
EC5010전문 암복호화 키 취득 실패EC5010시스템오류(문의요망)
EC5011Failover 처리 실패EC5011시스템오류(문의요망)
EC5012데이터 암복호화 키 취득 실패EC5012시스템오류(문의요망)
EC5013데이터 암호화 실패EC5013시스템오류(문의요망)
EC5014데이터 복호화 실패EC5014시스템오류(문의요망)
EC5015데이터 해시값 생성 실패EC5015시스템오류(문의요망)
EC5016키 생성 실패EC5016시스템오류(문의요망)
EC5017PEER 연결실패EC5017결제실패
EC9xxx — 사용자/시스템
EC9000사용자 취소EC9000사용자 취소
EC9999시스템처리실패EC9999시스템처리실패(관리자 문의요망)

📱모바일 연동

모바일 웹뷰 및 앱 결제 연동 시 필요한 카드사/은행 앱 스키마와 패키지 목록입니다.

💡
모바일 결제는 앱투앱(App to App) 이동이 필요합니다. 각 카드사·은행 앱의 스키마를 미리 등록해야 인증 후 카드사 앱으로 정상 이동됩니다.
등록하지 않으면 앱이 설치되어 있어도 스토어로 이동하거나 오류가 발생합니다.

iOS — URL 스키마 목록 (Info.plist)

Info.plist의 LSApplicationQueriesSchemes에 아래 스키마를 추가하세요. 누락 시 콘솔에 canOpenURL: failed for URL 오류가 발생합니다.

카드사 / 기관URL 스키마
토스페이supertoss://
국민카드 (KB Pay)kb-acp://  |  liivbank://  |  newliiv://  |  kbbank://
농협카드nhappcardansimclick://  |  nhallonepayansimclick://  |  nonghyupcardansimclick://
롯데카드lottesmartpay://  |  lotteappcard://
삼성카드mpocket.online.ansimclick://  |  mpocket.ansimclick.cert://  |  vguardstart://  |  samsungpay://  |  monimopay://  |  monimopayauth://
신한카드shinhan-sr-ansimclick://  |  smshinhanansimclick://
우리카드com.wooricard.wcard://  |  newsmartpib://
씨티카드citispay://  |  citicardappkr://  |  citimobileapp://
하나카드cloudpay://  |  hanawalletmembers://
현대카드hdcardappcardansimclick://  |  smhyundaiansimclick://
ISP / 페이북 (BC·국민)ispmobile://
카카오페이kakaotalk://
카카오뱅크kakaobank://
네이버페이naversearchapp://
간편결제 (SGP페이)shinsegaeeasypayment://
PAYCOpayco://
L.pay (롯데멤버스)lpayapp://
뱅크페이bankpay://
페이나우 (LGU+)paynow://
xml — Info.plist
<key>LSApplicationQueriesSchemes</key>
<array>
    <!-- 토스 -->
    <string>supertoss</string>
    <!-- 국민카드 -->
    <string>kb-acp</string>
    <string>liivbank</string>
    <string>newliiv</string>
    <string>kbbank</string>
    <!-- 농협카드 -->
    <string>nhappcardansimclick</string>
    <string>nhallonepayansimclick</string>
    <string>nonghyupcardansimclick</string>
    <!-- 롯데카드 -->
    <string>lottesmartpay</string>
    <string>lotteappcard</string>
    <!-- 삼성카드 -->
    <string>mpocket.online.ansimclick</string>
    <string>mpocket.ansimclick.cert</string>
    <string>vguardstart</string>
    <string>samsungpay</string>
    <string>monimopay</string>
    <string>monimopayauth</string>
    <!-- 신한카드 -->
    <string>shinhan-sr-ansimclick</string>
    <string>smshinhanansimclick</string>
    <!-- 우리카드 -->
    <string>com.wooricard.wcard</string>
    <string>newsmartpib</string>
    <!-- 씨티카드 -->
    <string>citispay</string>
    <string>citicardappkr</string>
    <string>citimobileapp</string>
    <!-- 하나카드 -->
    <string>cloudpay</string>
    <string>hanawalletmembers</string>
    <!-- 현대카드 -->
    <string>hdcardappcardansimclick</string>
    <string>smhyundaiansimclick</string>
    <!-- ISP/페이북 -->
    <string>ispmobile</string>
    <!-- 카카오 -->
    <string>kakaotalk</string>
    <string>kakaobank</string>
    <!-- 네이버페이 -->
    <string>naversearchapp</string>
    <!-- 간편결제 -->
    <string>shinsegaeeasypayment</string>
    <string>payco</string>
    <string>lpayapp</string>
    <string>bankpay</string>
    <string>paynow</string>
</array>

Android — 패키지 목록 (AndroidManifest.xml)

AndroidManifest.xml의 <queries> 섹션에 아래 패키지를 추가하세요. Android 11(API 30) 이상에서 패키지 공개 상태 정책으로 인해 누락 시 카드사 앱 설치 여부 확인이 불가합니다.

카드사 / 기관패키지명
토스viva.republica.toss
카카오톡 (카카오페이)com.kakao.talk
카카오뱅크com.kakaobank.channel
네이버페이com.nhn.android.search
삼성페이com.samsung.android.spay  |  com.samsung.android.spaylite
모니모페이 (삼성카드)net.ib.android.smcard
삼성카드kr.co.samsungcard.mpocket
V-Guard (삼성 보안)kr.co.shiftworks.vguardweb
신한 슈퍼SOLcom.shinhan.smartcaremgr
신한페이판com.shcard.smartpay
신한페이판 (공동인증서)com.shinhancard.smartshinhan
현대카드com.hyundaicard.appcard
현대카드 (공동인증서)com.lumensoft.touchenappfree
국민카드 KB Paycom.kbcard.cxh.appcard
Liiv (KB국민은행)com.kbstar.liivbank
Liiv Reboot (KB국민은행)com.kbstar.reboot
스타뱅킹 (KB국민은행)com.kbstar.kbbank
ISP / 페이북kvp.jjy.MispAndroid320
농협 올원페이nh.smart.nhallonepay
롯데카드 (디지로카)com.lcacApp
하나카드com.hanaskcard.paycla  |  com.hanaskcard.rocomo.potal
하나멤버스kr.co.hanamembers.hmscustomer
씨티모바일kr.co.citibank.citimobile
우리페이com.wooricard.wpay
우리카드 (우리WON카드)com.wooricard.smartapp
우리WON뱅킹com.wooribank.smart.npib
SSG페이com.ssg.serviceapp.android.egiftcertificate
PAYCOcom.nhnent.payapp
L.POINT (롯데멤버스)com.lottemembers.android
페이나우 (LGU+)com.lguplus.paynow
뱅크페이com.kftc.bankpay.android
신한 트래블월렛com.mobiletoong.travelwallet
TouchEn mVaccine (신한)com.TouchEn.mVaccine.webs
V3 모바일플러스 (NH·현대 보안)com.ahnlab.v3mobileplus
xml — AndroidManifest.xml
<queries>
    <!-- 간편결제 -->
    <package android:name="viva.republica.toss" />         <!-- 토스 -->
    <package android:name="com.kakao.talk" />               <!-- 카카오톡/카카오페이 -->
    <package android:name="com.kakaobank.channel" />        <!-- 카카오뱅크 -->
    <package android:name="com.nhn.android.search" />       <!-- 네이버페이 -->
    <package android:name="com.samsung.android.spay" />     <!-- 삼성페이 -->
    <package android:name="com.samsung.android.spaylite" /> <!-- 삼성페이 Lite -->
    <package android:name="net.ib.android.smcard" />        <!-- 모니모페이 -->
    <package android:name="com.ssg.serviceapp.android.egiftcertificate" /> <!-- SSGPAY -->
    <package android:name="com.nhnent.payapp" />            <!-- PAYCO -->
    <package android:name="com.lottemembers.android" />     <!-- L.POINT -->
    <package android:name="com.lguplus.paynow" />           <!-- 페이나우 -->
    <package android:name="com.kftc.bankpay.android" />     <!-- 뱅크페이 -->

    <!-- 신한카드 -->
    <package android:name="com.shinhan.smartcaremgr" />     <!-- 신한 슈퍼SOL -->
    <package android:name="com.shcard.smartpay" />           <!-- 신한페이판 -->
    <package android:name="com.shinhancard.smartshinhan" /> <!-- 신한페이판 공동인증서 -->
    <package android:name="com.mobiletoong.travelwallet" /> <!-- 신한 트래블월렛 -->
    <package android:name="com.TouchEn.mVaccine.webs" />    <!-- TouchEn mVaccine -->

    <!-- 삼성카드 -->
    <package android:name="kr.co.samsungcard.mpocket" />    <!-- 삼성카드 -->
    <package android:name="kr.co.shiftworks.vguardweb" />   <!-- V-Guard -->

    <!-- 현대카드 -->
    <package android:name="com.hyundaicard.appcard" />       <!-- 현대카드 -->
    <package android:name="com.lumensoft.touchenappfree" />  <!-- 현대카드 공동인증서 -->

    <!-- 국민카드 -->
    <package android:name="com.kbcard.cxh.appcard" />       <!-- KB Pay -->
    <package android:name="com.kbstar.liivbank" />           <!-- Liiv -->
    <package android:name="com.kbstar.reboot" />             <!-- Liiv Reboot -->
    <package android:name="com.kbstar.kbbank" />             <!-- 스타뱅킹 -->
    <package android:name="kvp.jjy.MispAndroid320" />       <!-- ISP/페이북 -->

    <!-- 농협카드 -->
    <package android:name="nh.smart.nhallonepay" />          <!-- 올원페이 -->

    <!-- 롯데카드 -->
    <package android:name="com.lcacApp" />                   <!-- 롯데카드(디지로카) -->

    <!-- 하나카드 -->
    <package android:name="com.hanaskcard.paycla" />         <!-- 하나카드 -->
    <package android:name="com.hanaskcard.rocomo.potal" />   <!-- 하나카드 -->
    <package android:name="kr.co.hanamembers.hmscustomer" /> <!-- 하나멤버스 -->

    <!-- 씨티카드 -->
    <package android:name="kr.co.citibank.citimobile" />    <!-- 씨티모바일 -->

    <!-- 우리카드 -->
    <package android:name="com.wooricard.wpay" />            <!-- 우리페이 -->
    <package android:name="com.wooricard.smartapp" />        <!-- 우리WON카드 -->
    <package android:name="com.wooribank.smart.npib" />      <!-- 우리WON뱅킹 -->

    <!-- 보안앱 -->
    <package android:name="com.ahnlab.v3mobileplus" />      <!-- V3 모바일플러스 -->
</queries>

Chrome 80+ SameSite 쿠키 이슈

⚠️
크롬 80 이상 브라우저에서 가맹점의 rUrl에서 쿠키를 사용하고 있다면, 쿠키 획득이 불가하여 결제 실패가 발생할 수 있습니다.

해결 방법: 가맹점 사이트에 SSL 적용 후 쿠키 생성 시 아래 설정을 추가하세요.
SameSite=None; Secure; HttpOnly

⚖️차액 정산 서비스

대표 가맹점이 하위 가맹점을 대신하여 결제를 요청하는 구조에서 발생하는 수수료 차액을 정산하는 서비스입니다.

서비스 개요

하위몰이 중소/영세 등급이고 결제를 요청하는 대표 가맹점이 일반 등급일 때 적용되는 수수료 차이가 발생합니다. 차액정산 서비스는 이 수수료 차액을 정확하게 계산하여 대표 가맹점에게 차액분을 환급하는 서비스입니다.

서비스 이용 절차

1
2차 PG 사업자 정보 파일 준비

정산관리팀에서 제공하는 양식에 따라 각 하위몰의 사업자 정보(사업자명, 사업자번호, 대표자명 등)를 작성하여 파일을 준비합니다.

2
하위몰 등록 및 정상 응답 확인

가맹점관리자 사이트의 [하위몰 접수 내역] 메뉴에서 하위몰 정보 파일을 업로드하여 등록하고, 같은 메뉴에서 등록 결과를 확인합니다. 이후 정산관리팀에 해당 하위몰 사업자의 거래 차액 정산을 요청합니다.

3
거래 차액 정산 시작

정산관리팀 양식에 맞게 차액 정산 요청서를 작성합니다. 한 거래건에 여러 하위몰이 있을 경우, 모든 하위몰의 합계 금액이 원래 승인 금액과 일치하는지 반드시 확인해야 합니다.

하위몰 등록

📋
하위몰 등록은 SFTP로 송수신하지 않습니다.
가맹점관리자 사이트 > 하위몰 접수 내역 메뉴에서 하위몰 정보 파일(하위몰 등록 전문 규격)을 직접 업로드해야 하며, 등록 결과 파일도 같은 메뉴에서 다운로드할 수 있습니다.
업로드 파일명 형식: SFTP 정보 수령 시 함께 안내드립니다.

SFTP 파일 송수신

⚠️
파일 인코딩: 모든 파일은 EUC-KR 인코딩으로 생성해야 합니다.
파일명 형식: SFTP 정보 수령 시 함께 안내드립니다.
📤 송신 경로
/send
📥 수신 경로
/recv

파일 송수신 시간

파일 종류송신 기한응답 시간
차액정산 파일오전 04:00까지오후 16:00

※ 송수신 시간은 추후 변경될 수 있습니다.

SFTP 계정 신청 절차

📋
1. PG 담당자에게 SFTP 계정 신청 요청
2. 필수 정보 제공: SFTP 서버에 접속할 가맹점 IP 주소
3. SFTP 정보 수령: IP, ID, PASSWORD, 경로, 송수신 파일명, 하위몰 등록 업로드 파일명
4. 방화벽 설정: 가맹점 IP가 PG SFTP 서버에 접속할 수 있도록 방화벽 개방
5. SFTP 접속 테스트

📄 차액정산 전문 규격

고객사 → PG사 방향으로 송신하는 차액정산 요청 배치 파일 규격입니다.
범례: A(Alphabet), N(숫자), YYYY(연도), MM(월), DD(일) — N(숫자) 단독이면 우측정렬·0패딩, 문자포함 형식이면 좌측정렬·공백패딩

SEND 차액정산 요청 전문 (고객사 → PG사) 레코드길이: 250byte ▼
Data부 (레코드구분: DT)
항목형식길이설명비고
레코드구분A2DT로 고정
처리요청일자YYYYMMDD8처리 요청 일자
거래일자YYYYMMDD8실제 거래 발생 일자
승인/취소구분A1승인 및 취소 구분0: 승인 / 1: 취소
거래번호 (TID)AN15PG에서 발행된 거래 고유번호
취소거래번호AN15취소 시 전달받은 거래 고유번호승인 시는 공백
주문번호AN65고객사에서 발행하는 주문 고유번호
상점ID (MID)AN15PG에서 발행된 거래기준 MID
사업자번호A10대표 가맹점 사업자번호
하위사업자번호A10실제 물품 판매 하위사업자(최종 셀러) 사업자번호
거래금액N10거래구분에 따른 해당 Transaction 금액
하위사업자 매출액N15하위 사업자의 매출금액하나의 거래(TID) 총금액 ≥ 하위사업자 매출액의 합
공백AN76예약 필드SPACE
Trailer부 (레코드구분: TR) — 파일 마지막 1줄
💡
데이터부가 없을 경우에도 아래 Trailer를 반드시 포함하며, 모든 수치 항목을 0으로 채워서 생성합니다.
항목형식길이설명비고
레코드구분A2TR로 고정
파일 전체 라인수N8해당 파일 내 전체 라인수 (데이터부 + Trailer부)
승인거래건수N8승인/취소구분 0(승인)인 거래 총건수
취소거래건수N8승인/취소구분 1(취소)인 거래 총건수
총거래금액 부호A1총거래금액 부호양수: 0 / 음수: 1
총거래금액N15승인거래금액 − 취소거래금액
공백AN208예약 필드SPACE
RECV 차액정산 결과 전문 (PG사 → 고객사) 레코드길이: 250byte ▼
Data부 (레코드구분: DT)
항목형식길이설명비고
레코드구분A2DT로 고정
처리요청일자YYYYMMDD8처리 요청 일자
거래일자YYYYMMDD8실제 거래 발생 일자
승인/취소구분A1승인 및 취소 구분0: 정상 / 1: 취소 (취소 시 차감 수수료)
거래번호 (TID)AN15PG에서 발행된 거래 고유번호
취소거래번호AN15취소 시 전달받은 거래 고유번호승인 시는 공백
주문번호AN65고객사에서 발행하는 주문 고유번호
상점ID (MID)AN15PG에서 발행된 거래기준 MID
사업자번호A10대표 가맹점 사업자번호
하위사업자번호A10최종 셀러(하위사업자) 사업자번호
거래금액N10거래구분에 따른 해당 Transaction 금액
하위사업자 매출액N15하위 사업자의 매출금액하나의 거래(TID) 총금액 ≥ 합계
결과코드A4처리 결과 코드0000: 정상. 1xxx: PG사 실패, 2xxx: VAN/카드사 실패
영중소등급A2하위 사업자 등급00:영세 / 01:중소1 / 02:중소2 / 03:중소3 / 04:일반 (오류/실패 시 빈값)
차액 수수료율AN5소수점 둘째자리까지. 일반 등급은 0.00
차액정산 금액N15차액정산율에 따른 금액. 일반 등급은 000000000000000
차액정산 부가세N15차액정산 금액에 대한 부가세
차액정산 예정일YYYYMMDD8차액정산 입금 예정일. 일반 등급은 99999999
공백AN27예약 필드SPACE
Trailer부 (레코드구분: TR)
항목형식길이설명비고
레코드구분A2TR로 고정
파일전체라인수N8해당 파일 내 전체 라인수 (데이터부 + Trailer부)
승인거래건수N8승인/취소구분 0(정상)인 거래 총건수
취소거래건수N8승인/취소구분 1(취소)인 거래 총건수
총 거래금액 부호A1총거래금액 부호양수: 0 / 음수: 1
총 거래금액N15승인거래금액 − 취소거래금액
총 차액정산금액N15데이터부의 차액정산 금액 총 합계
총 차액정산 부가세N15데이터부의 차액정산 부가세 총 합계
공백AN178예약 필드SPACE

차액정산 반송코드

PG사 반송코드 (1xxx)

코드반송사유
1001해당 거래 없음
1002거래금액 상이
1099기타오류

VAN/카드사 반송코드 (2xxx)

코드반송사유
2001카드사별 구분값 오류 (미존재 또는 불일치)
2002매출금액 오류 (원매출금액과 하위사업자 매출액 SUM 불일치)
2003중복접수 (기 처리된 내역을 전송)
2004원매입 반송 (원매출 미존재 또는 매출금액 오류 등)
2005매입취소구분 오류 (원매출과 하위매출의 정상/취소 불일치)
2006매입전송일자 오류
2007승인일자 오류
2008승인번호 오류 (원승인번호에 해당하는 매출 미존재)
2009가맹점번호 오류1 (가맹점번호가 SPACE이거나 미등록 가맹점)
2010가맹점번호 오류2 (차액정산 가맹점 번호가 아님)
2011카드번호 오류
2012중간하위사업자 오류 (전자금융업자 미해당사업자 등)
2013차액정산 지연접수
2014카드사별 구분값 정상건 반송 (장바구니 거래에서 오류 건으로 인해 정상 건도 함께 반송되는 경우)
2015차액정산 이전 원거래 취소 (신한카드)
2099기타

📄 하위몰 정보 등록 전문 규격

차액정산 서비스 이용 전 하위몰 사업자 정보를 등록하는 파일 규격입니다. 레코드 길이: 500byte

⚠️
이 파일은 SFTP로 전송하지 않고, 가맹점관리자 사이트 > 하위몰 접수 내역 메뉴에서 직접 업로드합니다.
파일 인코딩: EUC-KR 고정길이 텍스트 파일 — 한 줄이라도 오류가 있으면 파일 전체가 등록되지 않습니다.
등록 결과는 같은 메뉴에서 조회 및 다운로드할 수 있습니다.
업로드 파일명 형식: SFTP 정보 수령 시 함께 안내드립니다.
SEND 하위몰 정보 등록 요청 전문 (고객사 → PG사) 레코드길이: 500byte ▼
Data부 (레코드구분: DT)
항목형식길이필수설명
레코드구분AN2ODT로 고정
등록구분A2O00: 신규 / 01: 해지 / 02: 변경
MIDAN15O중간표시자 생략
사업자등록번호 (하위몰)N10O최종 하위사업자 사업자등록번호
업종명 (하위몰)H20선택한글 10자
회사명 (하위몰)H40O한글 20자
주소 (하위몰)H100선택TEXT
대표자명 (하위몰)H40선택TEXT
전화번호 (하위몰)N11OTEXT
이메일 (하위몰)ANS40선택이메일 주소
웹사이트 URL (하위몰)ANS80OTEXT
공백AN140선택예약 필드 (SPACE)
Trailer부 (레코드구분: TR)
항목형식길이필수설명
레코드구분AN2OTR로 고정
총 건수 합계N10ODATA부 건수
공백AN488선택예약 필드 (SPACE)

하위몰 등록 반송코드

가맹점관리자 사이트 [하위몰 접수 내역] 메뉴에서 조회·다운로드하는 등록 결과의 반송코드입니다.

처리 결과 코드

코드반송사유
00정상처리
01등록구분 오류
02회사명 오류
03사업자등록번호(PG) 오류
04가맹점번호 오류
05사업자번호(하위몰) 오류
06필수값 누락(회사명)
07필수값 누락(URL)
08필수값 누락(전화번호)
11사업자등록번호(PG) 1차 하위몰 미등재
12기등재(1차 하위몰)
99기타

카드사 코드표

코드카드사
1101국민카드
1102현대카드
1103롯데카드
1104삼성카드
1105하나카드
1106비씨카드
1107신한카드
1108NH카드
1109씨티카드
1110우리카드

☕Java 샘플 코드

Java 환경에서 KOVAN PG 결제연동에 필요한 유틸리티 클래스입니다. 보안·안정성을 고려하여 운영 환경에서 바로 사용 가능한 수준으로 작성했습니다.

📦
필요 라이브러리 (Maven)
org.apache.httpcomponents:httpclient:4.5.14  |  commons-codec:commons-codec:1.16  |  com.fasterxml.jackson.core:jackson-databind:2.17

Config.java — 환경 설정

운영/개발 환경 전환을 IS_PROD 플래그 하나로 관리합니다. API KEY는 환경변수에서 읽도록 개선하여 소스코드에 직접 노출되지 않습니다.

⚠️
API KEY는 절대 소스코드에 하드코딩하지 마세요. 환경변수(KOVAN_API_KEY)나 Vault/Secrets Manager를 통해 주입하세요.
java — Config.java
package pay;

public class Config {

    // ★ 운영/개발 전환 플래그 (true = 운영, false = 개발)
    private static final boolean IS_PROD = false;

    // 상점 ID
    public static final String MID = IS_PROD
        ? System.getenv("KOVAN_MID")           // 운영: 환경변수
        : "M20200203113418";                    // 개발: 테스트 MID

    // API KEY — 절대 소스에 하드코딩 금지, 환경변수로 주입
    public static final String API_KEY = IS_PROD
        ? System.getenv("KOVAN_API_KEY")        // 운영: 환경변수
        : "796963983a56e1a28cf62ad564851ef2";   // 개발: 테스트 키

    // PG 도메인
    public static final String PG_DOMAIN = IS_PROD
        ? "https://epay.kovanpay.com"
        : "https://dev-epay.kovanpay.com";

    // API 엔드포인트
    public static final String URL_CANCEL   = PG_DOMAIN + "/webpay/cancel.pay";
    public static final String URL_INQUIRY  = PG_DOMAIN + "/webpay/getTransInfo.pay";
    public static final String URL_CASHBILL_APPROVE = "https://ema.kovanpay.com/cashbill/v1/approval.out";
    public static final String URL_CASHBILL_CANCEL  = "https://ema.kovanpay.com/cashbill/v1/cancel.out";

    // HTTP 타임아웃 (ms)
    public static final int CONNECT_TIMEOUT = 5_000;   // 연결 타임아웃: 5초
    public static final int SOCKET_TIMEOUT  = 30_000;  // 읽기 타임아웃: 30초

    private Config() {}
}

HmacSha256Enc.java — Hash 생성 & 검증

Hash 생성뿐 아니라 PG 응답의 CHECK_HASH 검증 기능을 추가했습니다. 응답 위변조를 반드시 서버에서 확인해야 합니다.

java — HmacSha256Enc.java
package pay;

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class HmacSha256Enc {

    private static final String ALGORITHM = "HmacSHA256";

    /**
     * HMAC-SHA256 Base64 해시 생성
     *
     * 결제요청:  orderno + orderdt + ordertm + buyReqamt
     * 결제취소:  tid + mid + cancelAmt
     * 내역조회:  tid + mid + cancelAmt
     * 현금영수증: orderno + orderdt + ordertm + approveAmt
     *
     * @param message  해시 대상 문자열
     * @param apiKey   32자리 API KEY
     * @return Base64 인코딩된 해시값
     */
    public static String getHmac(String message, String apiKey) {
        if (message == null || apiKey == null) {
            throw new IllegalArgumentException("message와 apiKey는 null일 수 없습니다.");
        }
        try {
            Mac mac = Mac.getInstance(ALGORITHM);
            SecretKeySpec keySpec = new SecretKeySpec(
                apiKey.getBytes(StandardCharsets.UTF_8), ALGORITHM
            );
            mac.init(keySpec);
            byte[] rawHash = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
            return Base64.encodeBase64String(rawHash);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("해시 생성 실패: " + e.getMessage(), e);
        }
    }

    /**
     * PG 응답의 CHECK_HASH 유효성 검증
     *
     * 결제 승인 응답 검증: RESULT_CODE + TID + ORDERNO
     *
     * @param resultCode  응답의 RESULT_CODE
     * @param tid         응답의 TID
     * @param orderNo     응답의 ORDERNO
     * @param receivedHash 응답의 CHECK_HASH
     * @param apiKey      API KEY
     * @return true = 정상, false = 위변조 의심
     */
    public static boolean verifyResponseHash(
            String resultCode, String tid, String orderNo,
            String receivedHash, String apiKey) {
        if (receivedHash == null || receivedHash.isEmpty()) return false;
        String expected = getHmac(resultCode + tid + orderNo, apiKey);
        return expected.equals(receivedHash);
    }
}

HttpRestClient.java — REST API 호출

CloseableHttpClient로 교체하고, TLS 1.2 강제·타임아웃·리소스 자동 해제·에러 핸들링을 모두 적용했습니다.

java — HttpRestClient.java
package pay;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;

public class HttpRestClient {

    private static final Logger log = Logger.getLogger(HttpRestClient.class.getName());

    /**
     * PG 서버에 JSON POST 요청
     *
     * @param url       요청 URL
     * @param jsonBody  JSON 형식 요청 본문
     * @return 응답 JSON 문자열 (실패 시 null)
     */
    public static String post(String url, String jsonBody) {
        log.info("[PG Request] URL=" + url + " BODY=" + jsonBody);

        // 타임아웃 설정
        RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(Config.CONNECT_TIMEOUT)
            .setSocketTimeout(Config.SOCKET_TIMEOUT)
            .build();

        try {
            // TLS 1.2 강제 설정
            SSLContext sslContext = SSLContexts.custom().build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslContext,
                new String[]{"TLSv1.2"},                              // TLS 1.2 필수
                null,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier() // 인증서 검증 활성화
            );

            // try-with-resources: 자동 자원 해제
            try (CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .setDefaultRequestConfig(requestConfig)
                    .build()) {

                HttpPost request = new HttpPost(url);
                request.setHeader("Accept", "application/json");
                request.setHeader("Content-Type", "application/json;charset=UTF-8");
                request.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8));

                try (CloseableHttpResponse response = httpClient.execute(request)) {
                    int statusCode = response.getStatusLine().getStatusCode();
                    String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);

                    log.info("[PG Response] status=" + statusCode + " body=" + responseBody);

                    if (statusCode != 200) {
                        log.warning("[PG Error] HTTP " + statusCode + " - " + responseBody);
                        return null;
                    }
                    return responseBody;
                }
            }
        } catch (IOException e) {
            log.severe("[PG IO Error] " + e.getMessage());
            return null;
        } catch (Exception e) {
            log.severe("[PG Unexpected Error] " + e.getMessage());
            return null;
        }
    }
}

ResponseValidator.java — 응답 검증 & 결제취소 예시

실제 쇼핑몰에서 필요한 입력값 검증, 이중결제 방지, 응답 Hash 검증을 통합한 클래스입니다.

java — ResponseValidator.java
package pay;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.logging.Logger;

public class ResponseValidator {

    private static final Logger log = Logger.getLogger(ResponseValidator.class.getName());
    private static final ObjectMapper mapper = new ObjectMapper();
    private static final String SUCCESS_CODE = "EC0000";

    // ── 결제취소 요청 예시 ────────────────────────────────────────
    public static void cancelPayment(String tid, String cancelAmt, String cancelReason) throws Exception {

        String mid = Config.MID;

        // 1. 입력값 검증
        validateCancelInput(tid, cancelAmt, mid);

        // 2. checkHash 생성: tid + mid + cancelAmt
        String message   = tid + mid + cancelAmt;
        String checkHash = HmacSha256Enc.getHmac(message, Config.API_KEY);

        // 3. 요청 JSON 구성
        String jsonBody = String.format(
            "{\"mid\":\"%s\",\"payGroup\":\"GEP\",\"payType\":\"CC\"," +
            "\"tid\":\"%s\",\"cancelAmt\":\"%s\"," +
            "\"cancelReason\":\"%s\",\"cancelRequester\":\"2\"," +
            "\"checkHash\":\"%s\"}",
            mid, tid, cancelAmt, cancelReason, checkHash
        );

        // 4. PG 서버 호출
        String responseJson = HttpRestClient.post(Config.URL_CANCEL, jsonBody);

        // 5. 응답 처리
        if (responseJson == null) {
            throw new RuntimeException("PG 서버 응답 없음 (타임아웃 또는 통신 오류)");
        }
        processResponse(responseJson, tid);
    }

    // ── 입력값 검증 ───────────────────────────────────────────────
    private static void validateCancelInput(String tid, String cancelAmt, String mid) {
        if (tid == null || tid.trim().isEmpty()) {
            throw new IllegalArgumentException("TID는 필수입니다.");
        }
        if (cancelAmt == null || !cancelAmt.matches("^[0-9]+$")) {
            throw new IllegalArgumentException("취소금액은 숫자만 입력 가능합니다.");
        }
        if (Integer.parseInt(cancelAmt) <= 0) {
            throw new IllegalArgumentException("취소금액은 0보다 커야 합니다.");
        }
        if (mid == null || mid.trim().isEmpty()) {
            throw new IllegalArgumentException("MID는 필수입니다.");
        }
    }

    // ── 응답 처리 & 위변조 검증 ───────────────────────────────────
    private static void processResponse(String responseJson, String originalTid) throws Exception {
        JsonNode root = mapper.readTree(responseJson);

        String resultCode = root.path("RESULT_CODE").asText();
        String resultMsg  = root.path("RESULT_MSG").asText();
        String tid        = root.path("TID").asText();
        String orderNo    = root.path("ORDERNO").asText();
        String checkHash  = root.path("CHECK_HASH").asText();

        // ★ 응답 Hash 검증 (위변조 탐지)
        if (!checkHash.isEmpty()) {
            boolean isValid = HmacSha256Enc.verifyResponseHash(
                resultCode, tid, orderNo, checkHash, Config.API_KEY
            );
            if (!isValid) {
                log.severe("[Security] 응답 Hash 불일치! 위변조 의심 TID=" + tid);
                throw new SecurityException("PG 응답 무결성 검증 실패 - 위변조 의심");
            }
        }

        // ★ TID 일치 여부 확인
        if (!originalTid.equals(tid)) {
            throw new SecurityException("요청 TID와 응답 TID 불일치");
        }

        if (SUCCESS_CODE.equals(resultCode)) {
            log.info("[Cancel OK] TID=" + tid + " cancelAmt=" + root.path("CANCEL_AMT").asText());
            // TODO: DB 취소 상태 업데이트
        } else {
            log.warning("[Cancel FAIL] code=" + resultCode + " msg=" + resultMsg);
            throw new RuntimeException("취소 실패: [" + resultCode + "] " + resultMsg);
        }
    }

    public static void main(String[] args) throws Exception {
        cancelPayment("210728130414390", "5000", "고객 변심");
    }
}

🐘PHP 샘플 코드

보안·안정성을 보완하여 운영 환경에서 바로 사용 가능한 수준으로 개선했습니다. API KEY 서버사이드 처리, 응답 Hash 검증, 이중결제 방지, cURL 타임아웃 등을 모두 적용했습니다.

⚠️
개선 사항 요약
① API KEY 클라이언트 노출 제거 → 서버 상수로 관리
② 응답 CHECK_HASH 재검증 추가 (위변조 탐지)
③ 이중결제 방지 로직 추가 (orderno 중복 체크)
④ 입력값 서버사이드 검증 추가
⑤ file_get_contents → cURL (타임아웃·에러 처리)
⑥ SSL verify_peer true (운영 환경 인증서 검증)
⑦ 결제 요청/응답 로깅 추가

config.php — 환경 설정

환경변수에서 API KEY를 읽고, 운영/개발 전환을 상수 하나로 관리합니다. 모든 PHP 파일에서 require_once로 포함하세요.

php — config.php
<?php
// ★ 운영/개발 전환 (true = 운영, false = 개발)
define('IS_PROD', false);

// 상점 ID (운영 시 환경변수로 주입)
define('PG_MID',     IS_PROD ? getenv('KOVAN_MID')     : 'M20200203113418');

// API KEY — 절대 클라이언트에 노출하거나 소스에 하드코딩 금지
define('PG_API_KEY', IS_PROD ? getenv('KOVAN_API_KEY') : '796963983a56e1a28cf62ad564851ef2');

// PG 도메인
define('PG_DOMAIN',  IS_PROD
    ? 'https://epay.kovanpay.com'
    : 'https://dev-epay.kovanpay.com');

// API 엔드포인트
define('URL_PAY_PC',     PG_DOMAIN . '/paypage/common/mainFrame.pay');
define('URL_PAY_MOBILE', PG_DOMAIN . '/mobilepage/common/mainFrame.pay');
define('URL_CANCEL',     PG_DOMAIN . '/webpay/cancel.pay');
define('URL_INQUIRY',    PG_DOMAIN . '/webpay/getTransInfo.pay');

// Return URL (가맹점 서버 주소로 변경)
define('RETURN_URL', IS_PROD
    ? 'https://your-shop.com/pg/simplepay_return.php'
    : 'http://localhost/sample_pg_php/simplepay/simplepay_return.php');

// 로그 경로
define('LOG_PATH', __DIR__ . '/logs/pg_' . date('Ymd') . '.log');

// cURL 타임아웃 (초)
define('CURL_CONNECT_TIMEOUT', 5);
define('CURL_TIMEOUT',        30);

PgHelper.php — 공통 유틸리티

Hash 생성/검증, cURL POST, 로깅, 입력값 검증을 한 곳에 모았습니다. 모든 파일에서 재사용합니다.

php — PgHelper.php
<?php
require_once __DIR__ . '/config.php';

class PgHelper {

    /**
     * HMAC-SHA256 Base64 해시 생성
     * 결제요청:   orderno + orderdt + ordertm + buyReqamt
     * 결제취소:   tid + mid + cancelAmt
     * 현금영수증: orderno + orderdt + ordertm + approveAmt
     */
    public static function getHash(string $message): string {
        $rawHash = hash_hmac('sha256', $message, PG_API_KEY, true);
        return base64_encode($rawHash);
    }

    /**
     * PG 응답의 CHECK_HASH 검증 (위변조 탐지)
     * 검증 message: RESULT_CODE + TID + ORDERNO
     */
    public static function verifyResponseHash(
        string $resultCode,
        string $tid,
        string $orderNo,
        string $receivedHash
    ): bool {
        if (empty($receivedHash)) return false;
        $expected = self::getHash($resultCode . $tid . $orderNo);
        return hash_equals($expected, $receivedHash); // 타이밍 공격 방지
    }

    /**
     * cURL JSON POST 요청 (타임아웃·SSL 검증 포함)
     */
    public static function curlPost(string $url, array $data): ?array {
        $jsonBody = json_encode($data, JSON_UNESCAPED_UNICODE);
        self::writeLog('REQUEST', $url, $jsonBody);

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => $jsonBody,
            CURLOPT_HTTPHEADER     => [
                'Accept: application/json',
                'Content-Type: application/json;charset=UTF-8',
            ],
            CURLOPT_CONNECTTIMEOUT => CURL_CONNECT_TIMEOUT,
            CURLOPT_TIMEOUT        => CURL_TIMEOUT,
            // ★ 운영: true / 개발: false
            CURLOPT_SSL_VERIFYPEER => IS_PROD,
            CURLOPT_SSL_VERIFYHOST => IS_PROD ? 2 : 0,
            CURLOPT_SSLVERSION     => CURL_SSLVERSION_TLSv1_2, // TLS 1.2 강제
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error    = curl_error($ch);
        curl_close($ch);

        if ($error) {
            self::writeLog('CURL_ERROR', $url, $error);
            return null;
        }
        if ($httpCode !== 200) {
            self::writeLog('HTTP_ERROR', $url, "HTTP {$httpCode}: {$response}");
            return null;
        }

        $decoded = json_decode($response, true);
        self::writeLog('RESPONSE', $url, $response);
        return $decoded;
    }

    /**
     * 입력값 검증
     */
    public static function validateAmount(string $amount, string $fieldName = '금액'): void {
        if (!preg_match('/^\d+$/', $amount) || (int)$amount <= 0) {
            throw new InvalidArgumentException("{$fieldName}은 양의 정수만 입력 가능합니다.");
        }
    }

    public static function validateRequired(array $params, array $requiredKeys): void {
        foreach ($requiredKeys as $key) {
            if (empty($params[$key])) {
                throw new InvalidArgumentException("필수 항목 누락: {$key}");
            }
        }
    }

    /**
     * 로그 기록
     */
    public static function writeLog(string $type, string $url, string $body): void {
        $dir = dirname(LOG_PATH);
        if (!is_dir($dir)) mkdir($dir, 0755, true);
        $line = sprintf("[%s] [%s] URL=%s BODY=%s\n",
            date('Y-m-d H:i:s'), $type, $url, $body);
        file_put_contents(LOG_PATH, $line, FILE_APPEND | LOCK_EX);
    }
}

simplepay_req.php — 결제요청

API KEY를 클라이언트에 노출하지 않고 서버에서만 Hash를 생성합니다. 페이지 로드 시 서버에서 checkHash를 미리 계산하여 hidden 필드에 삽입합니다.

✅
개선 포인트: 기존에는 API KEY를 form hidden으로 전송하고 JS Ajax로 Hash를 생성했으나, 이제는 페이지 렌더링 시 서버에서 Hash를 직접 계산하므로 API KEY가 브라우저에 노출되지 않습니다.
php — simplepay_req.php
<?php
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/PgHelper.php';

// ── 주문 정보 생성 (실제로는 DB에서 조회) ─────────────────────
$orderdt   = date('Ymd');
$ordertm   = date('His');
$orderno   = $orderdt . $ordertm . rand(1000, 9999); // 유니크 주문번호
$buyReqamt = '5000';  // 실제: DB에서 가져온 주문금액

// ★ Hash는 서버에서 계산 — API KEY 클라이언트 노출 없음
$checkHash = PgHelper::getHash($orderno . $orderdt . $ordertm . $buyReqamt);
?>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>결제 요청</title>
    <script>
        var PG_URL_PC     = '<?= URL_PAY_PC ?>';
        var PG_URL_MOBILE = '<?= URL_PAY_MOBILE ?>';

        function goPc() {
            openPayWindow(PG_URL_PC, 'pcPop', 815, 600);
        }
        function goMobile() {
            openPayWindow(PG_URL_MOBILE, 'mobilePop', 550, 653);
        }
        function openPayWindow(url, name, w, h) {
            window.name = 'myOpener';
            var left = (screen.width  - w) / 2;
            var top  = (screen.height - h) / 2;
            var opts = 'menubar=no,toolbar=no,status=no,resizable=no,'
                     + 'scrollbars=no,location=no'
                     + ',left=' + left + ',top=' + top
                     + ',width=' + w + ',height=' + h;
            window.open('', name, opts).focus();
            var form = document.getElementById('form_payment');
            form.action = url;
            form.target = name;
            form.submit();
        }

        // 결제그룹별 결제수단 동적 갱신
        var PAY_TYPES = {
            GEP: [{v:'CC',t:'신용카드'},{v:'BA',t:'계좌이체'},{v:'VA',t:'가상계좌'}],
            NVP: [{v:'CC',t:'네이버신용카드'},{v:'VO',t:'네이버포인트'}],
            KKP: [{v:'CC',t:'카카오신용카드'},{v:'VO',t:'카카오머니'}]
        };
        function categoryChange(sel) {
            var target = document.getElementById('payType');
            target.options.length = 0;
            (PAY_TYPES[sel.value] || []).forEach(function(d) {
                target.options.add(new Option(d.t, d.v));
            });
        }
    </script>
</head>
<body>
<form id="form_payment" name="form_payment" method="post">
    <!-- 상점 정보 -->
    <input type="hidden" name="mid"          value="<?= htmlspecialchars(PG_MID) ?>" />
    <input type="hidden" name="rUrl"         value="<?= htmlspecialchars(RETURN_URL) ?>" />
    <input type="hidden" name="rMethod"      value="POST" />

    <!-- 결제수단 -->
    <select name="payGroup" onchange="categoryChange(this)">
        <option value="GEP">일반결제(GEP)</option>
        <option value="NVP">네이버페이(NVP)</option>
        <option value="KKP">카카오페이(KKP)</option>
        <option value="TOT">통합결제(TOT)</option>
    </select>
    <select name="payType" id="payType">
        <option value="CC">신용카드</option>
    </select>

    <!-- 상품 정보 -->
    <input type="hidden" name="buyItemnm"    value="오이비누" />
    <input type="hidden" name="buyReqamt"    value="<?= htmlspecialchars($buyReqamt) ?>" />
    <input type="hidden" name="buyItemcd"    value="oiSoap" />

    <!-- 구매자 정보 -->
    <input type="hidden" name="buyerid"      value="gildonghong" />
    <input type="hidden" name="buyernm"      value="홍길동" />
    <input type="hidden" name="buyerEmail"   value="gildong2@naver.com" />

    <!-- 주문 정보 -->
    <input type="hidden" name="orderno"      value="<?= htmlspecialchars($orderno) ?>" />
    <input type="hidden" name="orderdt"      value="<?= htmlspecialchars($orderdt) ?>" />
    <input type="hidden" name="ordertm"      value="<?= htmlspecialchars($ordertm) ?>" />

    <!-- ★ checkHash 서버에서 계산 완료 — API KEY 미노출 -->
    <input type="hidden" name="checkHash"    value="<?= htmlspecialchars($checkHash) ?>" />

    <!-- 예약 필드 -->
    <input type="hidden" name="reserved01"   value="" />
    <input type="hidden" name="reserved02"   value="" />

    <!-- 모바일 App Scheme (앱 연동 시 필수, 예: myapp://) -->
    <input type="hidden" name="returnAppUrl" value="" />

    <button type="button" onclick="goPc()">PC 결제</button>
    <button type="button" onclick="goMobile()">Mobile 결제</button>
</form>
</body>
</html>

simplepay_return.php — 결제결과 수신

응답 Hash 검증, 이중결제 방지, 입력값 검증을 모두 적용했습니다. 실제 서비스에서는 DB 저장 로직을 추가하세요.

php — simplepay_return.php
<?php
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/PgHelper.php';

header('Content-Type: text/html; charset=utf-8');

// ── 1. 응답 파라미터 수신 ─────────────────────────────────────
$RESULT_CODE  = $_POST['RESULT_CODE']  ?? '';
$RESULT_MSG   = $_POST['RESULT_MSG']   ?? '';
$DRESULT_CODE = $_POST['DRESULT_CODE'] ?? '';
$DRESULT_MSG  = $_POST['DRESULT_MSG']  ?? '';
$PAY_METHOD   = $_POST['PAY_METHOD']   ?? '';
$TID          = $_POST['TID']          ?? '';
$ORDERNO      = $_POST['ORDERNO']      ?? '';
$CHECK_HASH   = $_POST['CHECK_HASH']   ?? '';
$RESERVED01   = $_POST['RESERVED01']   ?? '';
$RESERVED02   = $_POST['RESERVED02']   ?? '';

PgHelper::writeLog('RETURN_RECEIVE', RETURN_URL, json_encode($_POST));

// ── 2. 필수 파라미터 검증 ─────────────────────────────────────
if (empty($TID) || empty($ORDERNO) || empty($RESULT_CODE)) {
    PgHelper::writeLog('RETURN_ERROR', '', '필수 파라미터 누락');
    die('잘못된 요청입니다.');
}

// ── 3. 결제 성공 처리 ─────────────────────────────────────────
if ($RESULT_CODE === 'EC0000') {

    // ★ 3-1. 응답 Hash 검증 (위변조 탐지)
    if (!PgHelper::verifyResponseHash($RESULT_CODE, $TID, $ORDERNO, $CHECK_HASH)) {
        PgHelper::writeLog('HASH_FAIL', '', "TID={$TID} ORDERNO={$ORDERNO}");
        die('[보안 오류] 응답 무결성 검증 실패. 관리자에게 문의하세요.');
    }

    // ★ 3-2. 이중결제 방지 (DB에서 ORDERNO 중복 확인)
    // 실제 구현 시 아래 주석을 해제하고 DB 연동:
    // $db = new PDO(/* DSN */);
    // $stmt = $db->prepare('SELECT COUNT(*) FROM orders WHERE orderno = ? AND status = "paid"');
    // $stmt->execute([$ORDERNO]);
    // if ($stmt->fetchColumn() > 0) {
    //     PgHelper::writeLog('DUPLICATE', '', "ORDERNO={$ORDERNO} TID={$TID}");
    //     die('이미 처리된 주문입니다.');
    // }

    // ── 결제수단별 추가 파라미터 수신 ─────────────────────────
    if ($PAY_METHOD === 'CC') {
        // 신용카드
        $APPROVNO      = $_POST['APPROVNO']      ?? '';
        $APPRODT       = $_POST['APPRODT']       ?? '';
        $APPROTM       = $_POST['APPROTM']       ?? '';
        $APPROAMT      = $_POST['APPROAMT']      ?? '';
        $CARD_NO       = $_POST['CARD_NO']       ?? '';
        $ISSUE_CODE    = $_POST['ISSUE_CODE']    ?? '';
        $ISSUE_NAME    = $_POST['ISSUE_NAME']    ?? '';
        $PURCHASE_CODE = $_POST['PURCHASE_CODE'] ?? '';
        $PURCHASE_NAME = $_POST['PURCHASE_NAME'] ?? '';
        $NOINT         = $_POST['NOINT']         ?? '';
        $QUOTA_MONTHS  = $_POST['QUOTA_MONTHS']  ?? '';
        $CHECKCD       = $_POST['CHECKCD']       ?? '';

    } elseif ($PAY_METHOD === 'VA') {
        // 가상계좌
        $TRBEGIN    = $_POST['TRBEGIN']    ?? '';
        $TREND      = $_POST['TREND']      ?? '';
        $BUY_REQAMT = $_POST['BUY_REQAMT'] ?? '';
        $BANK_CD    = $_POST['BANK_CD']    ?? '';
        $BANK_NM    = $_POST['BANK_NM']    ?? '';
        $ACCT_NO    = $_POST['ACCT_NO']    ?? '';
        $ESCR_FLAG  = $_POST['ESCR_FLAG']  ?? '';

    } elseif ($PAY_METHOD === 'BA') {
        // 계좌이체
        $MID     = $_POST['MID']     ?? '';
        $BANK_CD = $_POST['BANK_CD'] ?? '';
        $BANK_NM = $_POST['BANK_NM'] ?? '';
        $ACCT_NO = $_POST['ACCT_NO'] ?? '';
    }

    // ★ 3-3. DB 저장 (실제 구현 시 해제)
    // $stmt = $db->prepare(
    //     'INSERT INTO orders (orderno, tid, pay_method, amount, status, created_at)
    //      VALUES (?, ?, ?, ?, "paid", NOW())'
    // );
    // $stmt->execute([$ORDERNO, $TID, $PAY_METHOD, $APPROAMT ?? $BUY_REQAMT ?? 0]);

    PgHelper::writeLog('PAYMENT_OK', '', "TID={$TID} ORDERNO={$ORDERNO} METHOD={$PAY_METHOD}");

} else {
    // 결제 실패
    PgHelper::writeLog('PAYMENT_FAIL', '', "CODE={$RESULT_CODE} MSG={$RESULT_MSG} TID={$TID}");
}

// XSS 방지를 위한 출력 이스케이프 함수
function h($str): string {
    return htmlspecialchars($str ?? '', ENT_QUOTES, 'UTF-8');
}
?>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <title>결제 결과</title>
    <script>
    document.addEventListener('DOMContentLoaded', function() {
        var pm = '<?= h($PAY_METHOD) ?>';
        var rc = '<?= h($RESULT_CODE) ?>';
        var show = (rc === 'EC0000') ? pm : 'FAIL';
        document.getElementById('creditDiv').style.display = (show === 'CC') ? '' : 'none';
        document.getElementById('vaDiv').style.display    = (show === 'VA') ? '' : 'none';
        document.getElementById('baDiv').style.display    = (show === 'BA') ? '' : 'none';
    });
    </script>
</head>
<body>
<h3>공통 응답</h3>
<table>
    <tr><td>결과코드(가맹점)</td><td><?= h($RESULT_CODE) ?></td></tr>
    <tr><td>결과메시지(가맹점)</td><td><?= h($RESULT_MSG) ?></td></tr>
    <tr><td>결과코드(사용자)</td><td><?= h($DRESULT_CODE) ?></td></tr>
    <tr><td>결과메시지(사용자)</td><td><?= h($DRESULT_MSG) ?></td></tr>
    <tr><td>결제수단</td><td><?= h($PAY_METHOD) ?></td></tr>
    <tr><td>거래번호(TID)</td><td><?= h($TID) ?></td></tr>
    <tr><td>주문번호</td><td><?= h($ORDERNO) ?></td></tr>
    <tr><td>예약필드1</td><td><?= h($RESERVED01) ?></td></tr>
    <tr><td>예약필드2</td><td><?= h($RESERVED02) ?></td></tr>
</table>

<div id="creditDiv">
<h3>신용카드 응답</h3>
<table>
    <tr><td>승인번호</td><td><?= h($APPROVNO ?? '') ?></td></tr>
    <tr><td>승인일자</td><td><?= h($APPRODT ?? '') ?></td></tr>
    <tr><td>승인시각</td><td><?= h($APPROTM ?? '') ?></td></tr>
    <tr><td>승인금액</td><td><?= h($APPROAMT ?? '') ?></td></tr>
    <tr><td>카드번호(마스킹)</td><td><?= h($CARD_NO ?? '') ?></td></tr>
    <tr><td>발급사</td><td><?= h(($ISSUE_CODE ?? '') . ' / ' . ($ISSUE_NAME ?? '')) ?></td></tr>
    <tr><td>매입사</td><td><?= h(($PURCHASE_CODE ?? '') . ' / ' . ($PURCHASE_NAME ?? '')) ?></td></tr>
    <tr><td>무이자여부</td><td><?= h($NOINT ?? '') ?></td></tr>
    <tr><td>할부개월수</td><td><?= h($QUOTA_MONTHS ?? '') ?></td></tr>
    <tr><td>카드구분(신용N/체크C)</td><td><?= h($CHECKCD ?? '') ?></td></tr>
</table>
</div>

<div id="vaDiv">
<h3>가상계좌 응답</h3>
<table>
    <tr><td>입금시작일</td><td><?= h($TRBEGIN ?? '') ?></td></tr>
    <tr><td>입금종료일</td><td><?= h($TREND ?? '') ?></td></tr>
    <tr><td>결제금액</td><td><?= h($BUY_REQAMT ?? '') ?></td></tr>
    <tr><td>은행코드</td><td><?= h($BANK_CD ?? '') ?></td></tr>
    <tr><td>은행명</td><td><?= h($BANK_NM ?? '') ?></td></tr>
    <tr><td>계좌번호</td><td><?= h($ACCT_NO ?? '') ?></td></tr>
    <tr><td>에스크로여부</td><td><?= h($ESCR_FLAG ?? '') ?></td></tr>
</table>
</div>

<div id="baDiv">
<h3>계좌이체 응답</h3>
<table>
    <tr><td>상점 ID</td><td><?= h($MID ?? '') ?></td></tr>
    <tr><td>은행코드</td><td><?= h($BANK_CD ?? '') ?></td></tr>
    <tr><td>은행명</td><td><?= h($BANK_NM ?? '') ?></td></tr>
    <tr><td>계좌번호</td><td><?= h($ACCT_NO ?? '') ?></td></tr>
</table>
</div>
</body>
</html>

card_cancel.php — 결제취소 (서버사이드 통합)

취소 요청과 결과 처리를 하나의 파일로 통합했습니다. 입력값 검증, cURL 호출, 에러 처리를 모두 포함합니다.

php — card_cancel.php
<?php
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/PgHelper.php';

header('Content-Type: text/html; charset=utf-8');

$result  = null;
$error   = null;

// XSS 방지
function h($str): string {
    return htmlspecialchars($str ?? '', ENT_QUOTES, 'UTF-8');
}

// ── POST 요청 처리 (취소 실행) ────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    try {
        // 1. 파라미터 수신
        $tid             = trim($_POST['tid']             ?? '');
        $cancelAmt       = trim($_POST['cancelAmt']       ?? '');
        $payGroup        = trim($_POST['payGroup']        ?? 'GEP');
        $payType         = trim($_POST['payType']         ?? 'CC');
        $cancelReason    = trim($_POST['cancelReason']    ?? '');
        $cancelRequester = trim($_POST['cancelRequester'] ?? '2');
        $reserved01      = trim($_POST['reserved01']      ?? '');
        $reserved02      = trim($_POST['reserved02']      ?? '');

        // 2. 입력값 검증
        PgHelper::validateRequired(
            ['tid' => $tid, 'cancelAmt' => $cancelAmt],
            ['tid', 'cancelAmt']
        );
        PgHelper::validateAmount($cancelAmt, '취소금액');

        // 3. checkHash 생성: tid + mid + cancelAmt (서버에서만 처리)
        $checkHash = PgHelper::getHash($tid . PG_MID . $cancelAmt);

        // 4. 요청 파라미터 구성
        $postData = [
            'mid'             => PG_MID,
            'payGroup'        => $payGroup,
            'payType'         => $payType,
            'tid'             => $tid,
            'cancelAmt'       => $cancelAmt,
            'cancelReason'    => $cancelReason,
            'cancelRequester' => $cancelRequester,
            'reserved01'      => $reserved01,
            'reserved02'      => $reserved02,
            'checkHash'       => $checkHash,
        ];

        // 5. PG 서버 호출
        $result = PgHelper::curlPost(URL_CANCEL, $postData);

        if ($result === null) {
            throw new RuntimeException('PG 서버와 통신에 실패했습니다. 잠시 후 다시 시도해주세요.');
        }

        // 6. 결과 로깅
        $code = $result['RESULT_CODE'] ?? '';
        PgHelper::writeLog(
            $code === 'EC0000' ? 'CANCEL_OK' : 'CANCEL_FAIL',
            URL_CANCEL,
            "TID={$tid} CODE={$code}"
        );

    } catch (InvalidArgumentException $e) {
        $error = '입력 오류: ' . $e->getMessage();
    } catch (RuntimeException $e) {
        $error = $e->getMessage();
    }
}

// 결제그룹별 결제수단 목록
$payTypes = [
    'GEP' => [['CC','신용카드'],['BA','계좌이체'],['VA','가상계좌']],
    'NVP' => [['CC','네이버신용카드'],['VO','네이버포인트']],
    'KKP' => [['CC','카카오신용카드'],['VO','카카오머니']],
];
?>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <title>결제취소</title>
    <script>
    var PAY_TYPES = <?= json_encode($payTypes, JSON_UNESCAPED_UNICODE) ?>;
    function categoryChange(sel) {
        var target = document.getElementById('payType');
        target.options.length = 0;
        (PAY_TYPES[sel.value] || []).forEach(function(d) {
            target.options.add(new Option(d[1], d[0]));
        });
    }
    </script>
</head>
<body>

<!-- 취소 요청 폼 -->
<?php if (!$result): ?>
<h3>결제취소 요청</h3>
<?php if ($error): ?>
    <p style="color:red;"><?= h($error) ?></p>
<?php endif; ?>
<form method="post">
    <table>
        <tr>
            <td>결제수단</td>
            <td>
                <select name="payGroup" onchange="categoryChange(this)">
                    <option value="GEP">일반(GEP)</option>
                    <option value="NVP">네이버페이(NVP)</option>
                    <option value="KKP">카카오페이(KKP)</option>
                </select>
                <select name="payType" id="payType">
                    <option value="CC">신용카드</option>
                </select>
            </td>
        </tr>
        <tr>
            <td>거래ID (TID)</td>
            <td><input type="text" name="tid" required placeholder="승인 시 받은 TID" /></td>
        </tr>
        <tr>
            <td>취소금액 (숫자만)</td>
            <td><input type="number" name="cancelAmt" min="1" required /></td>
        </tr>
        <tr>
            <td>취소사유</td>
            <td><input type="text" name="cancelReason" /></td>
        </tr>
        <tr>
            <td>취소요청자</td>
            <td>
                <select name="cancelRequester">
                    <option value="1">1 - 구매자</option>
                    <option value="2" selected>2 - 가맹점 관리자</option>
                </select>
            </td>
        </tr>
        <tr>
            <td>예약필드1</td>
            <td><input type="text" name="reserved01" /></td>
        </tr>
        <tr>
            <td>예약필드2</td>
            <td><input type="text" name="reserved02" /></td>
        </tr>
    </table>
    <button type="submit">결제취소 요청</button>
</form>

<!-- 취소 결과 표시 -->
<?php else: ?>
<h3>취소 결과</h3>
<?php
    $isOk = ($result['RESULT_CODE'] ?? '') === 'EC0000';
?>
<p style="color:<?= $isOk ? 'green' : 'red' ?>; font-weight:bold;">
    <?= $isOk ? '✅ 취소 성공' : '❌ 취소 실패' ?>
</p>
<table>
    <tr><td>결과코드</td><td><?= h($result['RESULT_CODE'] ?? '') ?></td></tr>
    <tr><td>결과메시지</td><td><?= h($result['RESULT_MSG'] ?? '') ?></td></tr>
    <tr><td>결제그룹</td><td><?= h($result['PAY_GROUP'] ?? '') ?></td></tr>
    <tr><td>결제수단</td><td><?= h($result['PAY_METHOD'] ?? '') ?></td></tr>
    <tr><td>거래번호(TID)</td><td><?= h($result['TID'] ?? '') ?></td></tr>
    <tr><td>취소금액</td><td><?= h($result['CANCEL_AMT'] ?? '') ?></td></tr>
    <tr><td>예약필드1</td><td><?= h($result['RESERVED01'] ?? '') ?></td></tr>
    <tr><td>예약필드2</td><td><?= h($result['RESERVED02'] ?? '') ?></td></tr>
</table>
<a href="card_cancel.php">← 다시 취소 요청</a>
<?php endif; ?>

</body>
</html>

🚀연동 데모

KOVAN PG 개발 서버(dev-epay.kovanpay.com)에 실제로 연동하는 데모입니다. 테스트 MID와 API KEY가 미리 설정되어 있으며, 결제창 호출부터 취소·조회까지 전체 플로우를 확인할 수 있습니다.

💡
테스트 계정 정보
MID: M20200203113418  |  API KEY: 796963983a56e1a28cf62ad564851ef2  |  서버: https://dev-epay.kovanpay.com
✅
별도 서버 설치 불필요
결제 결과는 이 페이지가 동작 중인 Spring Boot 서버()가 직접 수신합니다. PG 콜백 엔드포인트: /demo/return/{transId}

결제창 호출

아래 파라미터를 설정하고 PC결제창 열기 또는 모바일결제창 열기를 클릭하면 실제 KOVAN 개발 서버의 결제창이 팝업됩니다.

요청 파라미터

Return URL은 서버에서 자동 설정됩니다 (/demo/return/{transId})

생성된 요청 전문

파라미터를 입력하면 전문이 표시됩니다.

📋 결제 결과

결제창에서 결제를 완료하면 결과가 자동으로 표시됩니다.
java — Spring Controller (rUrl 수신)
@PostMapping("/auth/response.action")
public String pgResponse(HttpServletRequest req) {
    String resultCode = req.getParameter("RESULT_CODE");
    String tid        = req.getParameter("TID");
    String orderno    = req.getParameter("ORDERNO");
    String approAmt   = req.getParameter("APPROAMT");
    if ("EC0000".equals(resultCode)) {
        // 결제 성공 → DB 저장, 주문 처리
    }
    return "pg/response";
}
php — rUrl 수신 (response.php)
<?php
$RESULT_CODE = $_POST['RESULT_CODE'] ?? '';
$TID         = $_POST['TID']         ?? '';
$ORDERNO     = $_POST['ORDERNO']     ?? '';
$APPROAMT    = $_POST['APPROAMT']    ?? '';
if ($RESULT_CODE === 'EC0000') {
    // 결제 성공 → DB 저장
}
?>

결제취소

결제창 호출 후 승인된 거래를 취소합니다. 결제 성공 후 TID가 자동으로 입력됩니다.

요청 파라미터

응답 결과

취소 요청 결과가 여기에 표시됩니다.
요청 전문
—

결제내역 조회

TID로 결제내역을 조회합니다. 결제 성공 후 TID가 자동으로 입력됩니다.

요청 파라미터

응답 결과

조회 결과가 여기에 표시됩니다.

Hash 생성기

HMAC-SHA256 + Base64 방식으로 checkHash를 직접 생성해볼 수 있습니다.