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 문자(이모지/한글), 과도한 길이

📊결제처리 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 결제의 경우 필수
신용카드 전용
cardCode카드사코드ANS-O결제 카드사코드 리스트 1107,1101
quota할부 개월 수NFIX 2O결제 할부 개월 수
billYnBillKey 등록 여부A1OBillKey 발급 요청 시 Y 설정. 결제 후 BILL_KEY가 응답에 포함됨
billKeyBillKey 결제A1O카드번호 대체 BillKey를 이용한 결제 시 Y 설정
가상계좌 전용
bankCode은행 코드ANS-O결제 은행 코드
trend종료일시NFIX 14O입금종료일시 (YYYYMMHH24MISS)
💡
아래 항목은 모든 결제수단 공통으로 포함됩니다:
RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02
응답 파라미터 — 일반 신용카드 (GEP · CC)
항목ID항목명타입길이(byte)설명
공통부
RESULT_CODE결제결과코드StringMax 20결과코드표 참조
RESULT_MSG결제결과메시지StringMax 1024
DRESULT_CODE가맹점결과코드StringMax 20
DRESULT_MSG가맹점결과메시지StringMax 1024
PAY_METHOD결제수단StringFIX 2CC/BA/VA/VO
TIDPG거래고유번호StringMax 15PG사 거래고유번호
ORDERNO주문번호StringMax 20상점 주문번호
RESERVED01가맹점예약필드1StringMax 1024
RESERVED02가맹점예약필드2StringMax 1024
CHECK_HASH무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO / secretKey : API KEY
신용카드 추가 항목
APPROVNO결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 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결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 16마스킹 처리된 카드번호
MID상점IDStringFIX 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결제그룹StringFIX 3KKP
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
MID상점IDStringFIX 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결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 16마스킹 처리된 카드번호
MID상점IDStringFIX 15상점ID (카카오페이만)
CHECK_HASH무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키StringMax 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결제그룹StringFIX 3NVP
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
MID상점IDStringFIX 15
BUY_REQAMT상품가격NumericMax 15
RESULT_DET_CODE결제결과 상세코드StringMax 20
RESULT_DET_MSG결제결과 상세메시지StringMax 1024
PAY_KEY인증추적키StringMax 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상점IDStringFIX 15상점
BANK_CD은행코드StringFIX 3결제 은행코드
BANK_NM은행명StringMax 20결제 은행명
ACCT_NO계좌번호StringMax 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무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO
TRBEGIN입금시작일StringFIX 14YYYYMMDDHHMMSS
TREND입금종료일StringFIX 14YYYYMMDDHHMMSS
BUY_REQAMT결제금액StringMax 15
BANK_CD은행코드StringFIX 3
BANK_NM은행명StringMax 20
ACCT_NO계좌번호StringMax 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
payGroup결제 그룹AFIX 3YGEP
payType결제수단ASMax 2YCC
orderno주문번호ANMax 20Y예시: ORDER20260429093952
orderdt주문 일자NFIX 8YYYYYMMDD
ordertm주문 시간NFIX 6YHHMMSS
checkHash무결성 검증 HashANSMax 128YHMAC-SHA256 Base64. message: orderno+orderdt+ordertm+buyReqamt
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=
apiKey=62a67bdc5e98b08e8c67cd3dd2a00b25
afterApprovYn=N
billYn=Y
rurl=http://220.117.220.108:50500/auth/response.action
rmethod=POST
응답 파라미터 — BILLKEY 발급
항목ID항목명타입길이(byte)설명
공통부
RESULT_CODE결과코드StringMax 200000 성공
RESULT_MSG결과메시지StringMax 1024
DRESULT_CODE가맹점결과코드StringMax 20EC0000 성공
DRESULT_MSG가맹점결과메시지StringMax 1024
MID상점 IDStringFIX 15
PAY_METHOD결제수단StringFIX 2CC
CHECK_HASH무결성 검증 HashStringMax 128
RESERVED01가맹점예약필드1StringMax 1024
RESERVED02가맹점예약필드2StringMax 1024
BILLKEY 발급 추가 항목
ISSUE_CODE발급사코드StringFIX 4예시: 1108
ISSUE_NAME발급사명StringMax 20예시: NH농협카드
BILL_KEYBillKeyStringMax 50발급된 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_KEYbillKey 파라미터로 전달하여 카드번호 없이 결제를 진행합니다.
최초 BILLKEY 발급 시 저장한 BILL_KEY 값을 그대로 사용합니다.

POST /payment/directApproval.pay

요청 파라미터 — BILLKEY 결제 (GEP · CC · billKey=Y)
항목ID항목명타입길이(byte)필수설명
공통 요청 파라미터 (결제요청 참고)
mid상점 IDANFIX 15Y예시: M20260114117276
payGroup결제 그룹AFIX 3YGEP
payType결제수단ASMax 2YCC
orderno주문번호ANMax 20Y예시: ORDER20260429093952
orderdt주문 일자NFIX 8YYYYYMMDD
ordertm주문 시간NFIX 6YHHMMSS
checkHash무결성 검증 HashANSMax 128YHMAC-SHA256 Base64. message: orderno+orderdt+ordertm+buyReqamt
BILLKEY 결제 전용
billKeyBillKeyA1YBillKey 결제 시 Y 설정. 발급받은 BILL_KEY를 카드번호 대체로 사용
요청 예시
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=
apiKey=62a67bdc5e98b08e8c67cd3dd2a00b25
afterApprovYn=N
billKey=Y
rurl=http://220.117.220.108:50500/auth/response.action
rmethod=POST
응답 파라미터 — BILLKEY 결제
항목ID항목명타입길이(byte)설명
공통부
RESULT_CODE결과코드StringMax 200000 성공
RESULT_MSG결과메시지StringMax 1024
DRESULT_CODE가맹점결과코드StringMax 20EC0000 성공
DRESULT_MSG가맹점결과메시지StringMax 1024
MID상점 IDStringFIX 15
PAY_METHOD결제수단StringFIX 2CC
CHECK_HASH무결성 검증 HashStringMax 128
RESERVED01가맹점예약필드1StringMax 1024
RESERVED02가맹점예약필드2StringMax 1024
BILLKEY 결제 추가 항목
ISSUE_CODE발급사코드StringFIX 4예시: 1108
ISSUE_NAME발급사명StringMax 20예시: NH농협카드
BILL_KEYBillKeyStringMax 50결제에 사용된 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
💡
아래 항목은 모든 결제수단 공통으로 포함됩니다:
RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02
응답 파라미터 — 애플페이 (APP · CC)
항목ID항목명타입길이(byte)설명
공통부 (RESULT_CODE, RESULT_MSG, DRESULT_CODE, DRESULT_MSG, PAY_METHOD, TID, ORDERNO, RESERVED01, RESERVED02)
APPROVNO결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 16마스킹 처리된 카드번호
MID상점IDStringFIX 15
CHECK_HASH무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키StringMax 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결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 16마스킹 처리된 카드번호
MID상점IDStringFIX 15
CHECK_HASH무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키StringMax 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결제그룹StringFIX 3TSP
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
MID상점IDStringFIX 15
BUY_REQAMT상품가격NumericMax 15
RESULT_DET_CODE결제결과 상세코드StringMax 20
RESULT_DET_MSG결제결과 상세메시지StringMax 1024
PAY_KEY인증추적키StringMax 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결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 16마스킹 처리된 카드번호
MID상점IDStringFIX 15
CHECK_HASH무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키StringMax 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결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 16마스킹 처리된 카드번호
MID상점IDStringFIX 15
CHECK_HASH무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키StringMax 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결제그룹StringFIX 3PCP
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
MID상점IDStringFIX 15
BUY_REQAMT상품가격NumericMax 15
RESULT_DET_CODE결제결과 상세코드StringMax 20
RESULT_DET_MSG결제결과 상세메시지StringMax 1024
PAY_KEY인증추적키StringMax 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결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 16마스킹 처리된 카드번호
MID상점IDStringFIX 15
CHECK_HASH무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키StringMax 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결제승인번호StringMax 20
APPRODT결제승인일자StringFIX 8YYYYMMDD
APPROTM결제승인시간StringFIX 6HHMMSS
APPROAMT결제승인금액NumericMax 15
ISSUE_CODE발급사코드StringFIX 4
ISSUE_NAME발급사명StringMax 20
PURCHASE_CODE매입사코드StringFIX 4
PURCHASE_NAME매입사명StringMax 20
QUOTA_MONTHS할부개월수StringFIX 2
NOINT무이자구분StringFIX 1
CHECKCD카드구분StringFIX 2신용카드 N / 체크카드 C
CARD_NO카드번호StringMax 16마스킹 처리된 카드번호
MID상점IDStringFIX 15
CHECK_HASH무결성 검증 HashStringMax 128message: RESULT_CODE+TID+ORDERNO
VAN_RECV_KEYVAN고유키StringMax 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발급유형StringFIX 2Y소득공제: 00 / 지출증빙: 10
idInfo발급정보StringMAX 30Y핸드폰번호, 사업자번호 등 현금영수증 발급 정보
응답 파라미터
항목ID항목명타입길이(byte)설명
RESULT_CODE처리 결과 코드StringMax 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지StringMax 1024
DRESULT_CODE가맹점결과코드StringMax 20
DRESULT_MSG가맹점결과메시지StringMax 1024
TIDPG거래고유번호StringMax 15
TAX세금NumericMAX 8승인금액에 대한 세금
CLRAMT공급가액NumericMAX 8승인금액 – 세금
ORDERNO상점주문번호StringMax 20
MID상점IDStringFIX 15
APPROV_NO승인번호StringFIX 9
APPROV_AMT승인금액Numeric-
POST /cashbill/v1/cancel.out 현금영수증 취소
Accept: application/json, Content-Type: application/json
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDStringFIX 15Y상점 별로 부여되는 상점 ID
tidPG원거래고유번호StringMax 15Y결제승인 시 PG사 원거래고유번호
cancelAmt취소금액NumericMax 8Y-5000 형식. 반드시 숫자만 포함
checkHash유효성 검증 HashStringMax 128Ymessage: tid+mid+cancelAmt
응답 파라미터
항목ID항목명타입길이(byte)설명
RESULT_CODE처리 결과 코드StringMax 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지StringMax 1024
DRESULT_CODE가맹점결과코드StringMax 20
DRESULT_MSG가맹점결과메시지StringMax 1024
TIDPG거래고유번호StringMax 15
TAX세금NumericMAX 8승인금액에 대한 세금
CLRAMT공급가액NumericMAX 8승인금액 – 세금
ORDERNO상점주문번호StringMax 20
MID상점IDStringFIX 15
APPROV_NO승인번호StringFIX 9
APPROV_AMT승인금액Numeric-

🔄결제취소 요청

🔧 개발기
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상점 IDStringFIX 15Y상점 별로 부여되는 상점 ID
payGroup결제그룹StringFIX 3YDefault: GEP
payType결제수단StringFIX 2Y결제수단 코드
tidPG원거래고유번호StringMax 15Y결제승인 시 PG사 원거래고유번호
cancelAmt취소금액NumericMax 8Y반드시 숫자만 포함
checkHash유효성 검증 HashStringMax 128Ymessage: tid+mid+cancelAmt
cancelReason취소 사유StringMax 200Y취소사유
cancelRequester취소 요청자StringFIX 1Y1: 구매자, 2: 가맹점 관리자
reserved01가맹점예약필드1StringMax 1024O
reserved02가맹점예약필드2StringMax 1024O
taxExemptYn비과세 구분StringFIX 1O복합과세 Y / 비과세 D / 면세 F
taxExemptAmt면세/비과세금액StringMAX 8O반드시 숫자만 포함
가상계좌 취소 추가 항목
refundBank환불계좌 은행코드StringFIX 3Y은행코드표 참조
refundAcctno환불계좌 번호StringMAX 20Y
refundAcctholder환불계좌 예금주명StringMAX 20Y
응답 파라미터
항목ID항목명타입길이(byte)필수설명
RESULT_CODE처리 결과 코드StringMax 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지StringMax 1024
DRESULT_CODE가맹점결과코드StringMax 20
DRESULT_MSG가맹점결과메시지StringMax 1024
TIDPG거래고유번호StringMax 15
CANCEL_AMT취소금액NumericMAX 8승인금액에 대한 세금
RESERVED01가맹점예약필드1StringMax 1024
RESERVED02가맹점예약필드2StringMax 1024
응답 예시
json
{
  "RESULT_CODE": "EC0000",
  "RESULT_MSG": "정상결제취소",
  "DRESULT_CODE": "EC0000",
  "DRESULT_MSG": "성공",
  "TID": "201605280001",
  "CANCEL_AMT": "5000"
}
POST /offline/cancel.pay 오프라인(VAN방식) 결제취소
Accept: application/json, Content-Type: application/json
요청 파라미터
항목ID항목명타입길이(byte)필수설명
mid상점 IDStringFIX 15Y상점별로 부여되는 상점 ID
payType결제수단StringFIX 2Y결제수단
vanTidPG원거래고유번호StringMax 18Y결제승인시 VAN사 거래일련번호
cancelAmt취소금액NumericMax 8Y반드시 숫자만 포함 (양수)
checkHash유효성 검증 HashStringMax 128Ymessage: vanTid+mid+cancelAmt
reserved01가맹점예약필드1StringMax 1024O
reserved02가맹점예약필드2StringMax 1024O
taxExemptYn비과세 구분StringFIX 1O비과세거래: Y / 일반: N
taxExemptAmt비과세금액StringMAX 8O반드시 숫자만 포함
응답 파라미터
항목ID항목명타입길이(byte)필수설명
RESULT_CODE처리 결과 코드StringMax 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지StringMax 1024
DRESULT_CODE가맹점결과코드StringMax 20
DRESULT_MSG가맹점결과메시지StringMax 1024
VAN_TIDVAN원거래고유번호StringMax 15
CANCEL_AMT취소금액NumericMAX 8승인금액에 대한 세금
RESERVED01가맹점예약필드1StringMax 1024
RESERVED02가맹점예약필드2StringMax 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상점 IDStringFIX 15Y상점 별로 부여되는 상점 ID
payGroup결제그룹StringFIX 3YDefault: GEP
paymethod결제수단StringFIX 2Y결제수단 코드
tidPG원거래고유번호StringMax 15O결제승인 시 PG사 원거래고유번호
orderno가맹점고유번호StringMax 20O상점 주문번호
approv_amt결제승인금액NumericMax 8Otid/orderno 없을 때 필수
approvdt승인일자StringFIX 8O결제승인일자 (YYYYMMDD)
approv_no승인번호StringMax 15O결제승인번호
checkHash유효성 검증 HashStringMax 128Ymessage: tid+mid+cancelAmt
reserved01가맹점예약필드1StringMax 1024O
reserved02가맹점예약필드2StringMax 1024O
응답 파라미터
항목ID항목명타입설명
RESULT_CODE처리 결과 코드StringMax 20결제처리결과 코드 표 참조
RESULT_MSG처리 결과 메시지StringMax 1024
DRESULT_CODE가맹점결과코드StringMax 20
DRESULT_MSG가맹점결과메시지StringMax 1024
PAY_METHOD결제수단String결제 수단 코드
TIDPG원거래고유번호String결제승인시 PG사 원거래고유번호
ORDERNO상점주문번호String상점 주문번호
MID상점IDStringPG에서 부여한 상점 ID
BUY_ITEMNM상품명String상점 구매 상품명
TRANS_STATUS_NM거래상태명String거래 상태 명칭
TRANS_STATUS거래상태String거래 상태 코드표 참조
APPROAMT승인금액Numeric숫자만 포함
CANCEL_AMT취소금액Numeric취소 금액의 합계
APPRODT승인일자Stringyyyy-MM-dd hh:mm:ss
CANCEL_DT취소일자Stringyyyy-MM-dd hh:mm:ss
RESERVED01가맹점예약필드1StringMax 1024
RESERVED02가맹점예약필드2StringMax 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상점 IDStringFIX 15Y상점 별로 부여되는 상점 ID
payGroup결제그룹StringFIX 3YDefault: GEP
payMethod결제수단StringFIX 2Y결제수단 코드
tidPG원거래고유번호StringMax 15Y결제승인 시 PG사 원거래고유번호
amt결제승인금액NumericMax 8Y승인: 1004 / 취소: -1004
text_tr승인,취소구분StringFIX 2O승인: 00 / 취소: 99
checkHash유효성 검증 HashStringMax 128Ymessage: tid+mid+amt
orderno주문번호StringMax 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대표IDStringFIX 15YPG에서 부여한 상점 ID
orderno주문번호StringMax 20Y상점 주문번호
orderdt주문 일자NumberFIX 8YYYYYMMDD
ordertm주문 시간NumberFIX 6YHHMMSS
buyReqamt상품가격NMax 8Y상점 구매금액. 반드시 숫자만
checkHash무결성 검증 HashStringMax 128Ymessage: orderno+orderdt+ordertm+buyReqamt
phoneNum휴대폰번호NumberMax 15Y'-' 제외 숫자만
buyItemnm상품명StringMax 60Y상점 판매 상품명
buyernm구매자 명StringMax 50O상점 구매자명
goodsInfo상품추가정보StringMax 50O상점 판매 상품 추가 정보
payAbleTime결제 유효기간NumberMax 5O분 단위 (기본 1시간)
응답 파라미터
항목ID항목명타입설명
RESULT_CODE결제결과코드String결과코드표 참조
RESULT_MSG결제결과메시지String
POST /Morder/v1/merchant/urlPay.out URL 결제
Content-Type: application/json, Encoding: UTF-8
추가 파라미터 (메시지결제 파라미터 + 아래)
항목ID항목명타입길이(byte)필수설명
mid대표IDStringFIX 15YPG에서 부여한 상점 ID
orderno주문번호StringMax 20Y상점 주문번호
orderdt주문 일자NumberFIX 8YYYYYMMDD
ordertm주문 시간NumberFIX 6YHHMMSS
buyReqamt상품가격NMax 8Y상점 구매금액. 반드시 숫자만
checkHash무결성 검증 HashStringMax 128Ymessage: orderno+orderdt+ordertm+buyReqamt
phoneNum휴대폰번호NumberMax 15Y'-' 제외 숫자만
buyItemnm상품명StringMax 60Y상점 판매 상품명
buyernm구매자 명StringMax 50O상점 구매자명
goodsInfo상품추가정보StringMax 50O상점 판매 상품 추가 정보
payAbleTime결제 유효기간NumberMax 5O분 단위 (기본 1시간)
langType언어StringFIX 3OKOR 한국어, ENG 영어 (기본 KOR)
응답 파라미터
항목ID항목명타입설명
REQ_URL결제 URLString결제 URL (실패 시 공백)
RESULT_CODE결제결과코드String결과코드표 참조
RESULT_MSG결제결과메시지String

🔔결제 Notification

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

준비사항

📋
가맹점 준비 사항
· KOVAN PG WAS와 가맹점 WEB 서버 간 방화벽 오픈 (운영/테스트 별도 작업 필요)
· HTTP/POST 방식의 Notification 전용 웹 서버 프로세스 필요
· Notify URL은 계약정보에 등록 필요 (PG 담당자 문의)
⚠️
실제 응답 시 주의사항
· CHECK_HASH는 일부 결제수단(계좌이체 등)에서 null로 수신될 수 있습니다. null 여부를 반드시 확인 후 검증하세요.
· 오프라인 VAN방식의 경우 mid(소문자), payGroup, payMethod, ORDER_NO 등 소문자 필드가 혼재하여 수신됩니다. 대소문자 구분 없이 파싱하세요.
· APPROVDT / APPROVAMT / APPROVTMAPPRODT / APPROAMT / APPROTM 두 가지 형태가 동시에 포함될 수 있습니다.
Content-Type: application/json;charset=UTF-8
전체 파라미터
항목ID타입설명예시값
RESULT_CODEString결과코드. 성공: EC0000EC0000
RESULT_MSGString결과메시지SUCCESS
DRESULT_CODEString사용자 결과코드EC0000
DRESULT_MSGString사용자 결과메시지SUCCESS
PAY_GROUPString결제그룹GEP
PAY_METHODString결제수단CC
TIDStringPG 거래고유번호260105130562200
ORDERNOString상점 주문번호ORDER20260105105237
RESERVED01String가맹점예약필드1reserved01
RESERVED02String가맹점예약필드2reserved02
CHECK_HASHString무결성 검증 Hash. message: RESULT_CODE+TID+ORDERNOrmKd+h8AM8Tu...
VAN_RECV_KEYStringVAN 거래고유키 (없을 경우 빈 문자열)
APPROVNOString카드사 승인번호21676259
APPRODTString결제승인일자 (YYYYMMDD)20260105
APPROTMString결제승인시간 (HHMMSS)105240
APPROAMTString결제승인금액1004
ISSUE_CODEString발급사코드1104
ISSUE_NAMEString발급사명삼성카드
PURCHASE_CODEString매입사코드1104
PURCHASE_NAMEString매입사명삼성카드
QUOTA_MONTHSString할부개월수. 일시불: 0000
NOINTString무이자구분. 무이자: Y / 일반: NN
CHECKCDString카드구분. 신용: N / 체크: CN
CARD_NOString마스킹 처리된 카드번호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_HASHnull로 수신됩니다. 계좌이체 Notification에서는 Hash 검증을 생략하고 RESULT_CODETID로 처리하세요.
전체 파라미터
항목ID타입설명예시값
RESULT_CODEString결과코드. 성공: EC0000EC0000
RESULT_MSGString결과메시지성공
DRESULT_CODEString사용자 결과코드EC0000
DRESULT_MSGString사용자 결과메시지SUCCESS
PAY_GROUPString결제그룹GEP
PAY_METHODString결제수단BA
TIDStringPG 거래고유번호260107130562229
ORDERNOString상점 주문번호ORDER20260107110442
MIDString상점IDM20200203113418
RESERVED01String가맹점예약필드1reserved01
RESERVED02String가맹점예약필드2reserved02
CHECK_HASHString무결성 검증 Hash. 계좌이체는 null로 수신null
BANK_CDString은행코드 (은행 코드표 참조)050
BANK_NMString은행명상호저축은행
ACCT_NOString계좌번호 (마스킹)45678
ESCR_FLAGString에스크로 여부
실제 수신 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_CODEString결과코드EC0000
RESULT_MSGString결과메시지SUCCESS
DRESULT_CODEString사용자 결과코드EC0000
DRESULT_MSGString사용자 결과메시지SUCCESS
PAY_GROUPString결제그룹KKP
PAY_METHODString결제수단CC
TIDStringPG 거래고유번호260201130562925
ORDERNOString상점 주문번호ORDER20260201202653
MIDString상점IDM20200203113418
RESERVED01String가맹점예약필드1reserved01
RESERVED02String가맹점예약필드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/APPROTMAPPROVAMT/APPROVDT/APPROVTM 두 가지 형태의 필드가 동시에 수신됩니다. 두 필드 모두 파싱하여 처리하세요.
전체 파라미터
항목ID타입설명예시값
RESULT_CODEString결과코드. 성공: EC0000EC0000
RESULT_MSGString결과메시지SUCCESS
DRESULT_CODEString사용자 결과코드EC0000
DRESULT_MSGString사용자 결과메시지SUCCESS
PAY_GROUPString결제그룹KKP
PAY_METHODString결제수단VO
TIDStringPG 거래고유번호260409130565072
ORDERNOString상점 주문번호ORDER20260409113324
MIDString상점IDM20200203113418
RESERVED01String가맹점예약필드1reserved01
RESERVED02String가맹점예약필드2reserved02
APPROAMTString결제승인금액1004
APPRODTString결제승인일자 (YYYYMMDD)20260409
APPROTMString결제승인시간 (HHMMSS)113736
APPROVAMTString결제승인금액 (중복 필드, 동시 수신)1004
APPROVDTString결제승인일자 (중복 필드, 동시 수신)20260409
APPROVTMString결제승인시간 (중복 필드, 동시 수신)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_CODEString결과코드EC0000
RESULT_MSGString결과메시지SUCCESS
DRESULT_CODEString사용자 결과코드EC0000
DRESULT_MSGString사용자 결과메시지SUCCESS
PAY_GROUPString결제그룹NVP
PAY_METHODString결제수단CC
TIDStringPG 거래고유번호260116130562552
ORDERNOString상점 주문번호ORDER20260116085029
RESERVED01String가맹점예약필드1reserved01
RESERVED02String가맹점예약필드2reserved02
CHECK_HASHString무결성 검증 Hash70+UtK3FU/WQ...
VAN_RECV_KEYStringVAN 거래고유키 (빈 문자열 가능)
APPROVNOString카드사 승인번호87101195
APPRODTString결제승인일자 (YYYYMMDD)20260116
APPROTMString결제승인시간 (HHMMSS)085102
APPROAMTString결제승인금액1004
ISSUE_CODEString발급사코드1110
ISSUE_NAMEString발급사명우리카드
PURCHASE_CODEString매입사코드1110
PURCHASE_NAMEString매입사명우리카드
QUOTA_MONTHSString할부개월수. 일시불: 0000
NOINTString무이자구분N
CHECKCDString카드구분. 신용: N / 체크: CC
CARD_NOString마스킹 처리된 카드번호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_CODEString결과코드EC1029
RESULT_MSGString결과메시지 (실패 시 원천사 오류 메시지 포함)원천사 결제(취소) 결과실패(...)
DRESULT_CODEString사용자 결과코드EC1029
DRESULT_MSGString사용자 결과메시지원천사 결제(취소) 결과실패(...)
PAY_GROUPString결제그룹NVP
PAY_METHODString결제수단VO
TIDStringPG 거래고유번호251121130561398
ORDERNOString상점 주문번호ORDER20251121160018
MIDString상점IDM20200203113418
RESERVED01String가맹점예약필드1reserved01
RESERVED02String가맹점예약필드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
⚠️
오프라인 PG방식은 APPROVAMT / APPROVDT / APPROVTM 필드를 사용합니다. 온라인의 APPROAMT/APPRODT/APPROTM과 다르니 주의하세요. 또한 EID, OPG_ID 필드가 추가로 수신됩니다.
전체 파라미터
항목ID타입설명예시값
RESULT_CODEString결과코드. 성공: EC0000EC0000
RESULT_MSGString결과메시지SUCCESS
PAY_GROUPString결제그룹GEP
PAY_METHODString결제수단CC
TIDStringPG 거래고유번호260223130563309
ORG_TIDString원거래 TID260223130563309
MIDString상점IDM20200203113418
EIDString가맹점IDE20200203113529
OPG_IDStringVAN 단말기ID1047401493
APPROVNOString카드사 승인번호83447351
APPROVDTString결제승인일자 (YYYYMMDD) ※온라인과 필드명 다름20260223
APPROVTMString결제승인시간 (HHMMSS) ※온라인과 필드명 다름162701
APPROVAMTNumber결제승인금액 ※숫자형(Integer)으로 수신5004
ISSUE_CODEString발급사코드1104
PURCHASE_CODEString매입사코드1104
CHECKCDString카드구분. 신용: N / 체크: CN
CARD_NOString마스킹 처리된 카드번호 (앞 6자리 + * 마스킹)536148**********
실제 수신 JSON 예시
json
{
  "RESULT_CODE": "EC0000", "RESULT_MSG": "SUCCESS",
  "PAY_GROUP": "GEP", "PAY_METHOD": "CC",
  "TID": "260223130563309", "ORG_TID": "260223130563309",
  "MID": "M20200203113418", "EID": "E20200203113529",
  "OPG_ID": "1047401493",
  "APPROVNO": "83447351",
  "APPROVDT": "20260223", "APPROVTM": "162701",
  "APPROVAMT": 5004,
  "ISSUE_CODE": "1104", "PURCHASE_CODE": "1104",
  "CHECKCD": "N", "CARD_NO": "536148**********"
}
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_CODEString결과코드. 성공: EC0000EC0000
RESULT_MSGString결과메시지SUCCESS
MIDString상점ID (대문자)M20200203113418
midString상점ID (소문자, 중복 수신)M20200203113418
TIDStringPG 거래고유번호260106130562218
ORG_TIDString원거래 TID260106130562218
ORDER_NOString주문번호 (VAN방식 전용 필드명)260106130562218
payGroupString결제그룹 (소문자)GEP
payMethodString결제수단 (소문자)CC
APPROVNOString카드사 승인번호21137313
APPRONOString카드사 승인번호 (중복 필드)21137313
APPRODTString결제승인일자 (YYYYMMDD)20251224
APPROVDTString결제승인일자 (중복 필드)20251224
APPROTMString결제승인시간 (HHMMSS)111300
APPROVTMString결제승인시간 (중복 필드)111300
APPROAMTString결제승인금액72000
APPROVAMTString결제승인금액 (중복 필드)72000
BUY_REQAMTString구매요청금액72000
ISSUE_CODEString발급사코드 (6자리 코드 수신 가능)112672
PURCHASE_CODEString매입사코드1106
CHECKCDString카드구분. 신용: N / 체크: CC
CARD_NOString마스킹 처리된 카드번호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
전체 파라미터
항목ID타입길이(byte)설명
RESULT_CODEStringMax 20결과코드. 성공: EC0000
RESULT_MSGStringMax 1024결과메시지
DRESULT_CODEStringMax 20사용자 결과코드
DRESULT_MSGStringMax 1024사용자 결과메시지
PAY_METHODStringFIX 2결제수단 (CC / VO)
PAY_GROUPStringFIX 3결제그룹 (GEP / KKP / NVP)
TIDStringFIX 15PG 취소 거래고유번호
CANCEL_AMTNumericMax 20취소금액
APPROAMTNumericMax 15원거래 승인금액
VAN_RECV_KEYStringMax 20VAN 거래고유키
PCH_TIDStringMax 15매입요청고유번호
EIDStringFIX 15가맹점ID
MIDStringFIX 15상점ID
RESERVED01StringMax 1024가맹점예약필드1 (원 결제요청 시 전달한 값)
RESERVED02StringMax 1024가맹점예약필드2 (원 결제요청 시 전달한 값)
Content-Type: application/json;charset=UTF-8
전체 파라미터
항목ID타입길이(byte)설명
RESULT_CODEStringMax 20결과코드. 성공: EC0000
RESULT_MSGStringMax 1024결과메시지
PAY_METHODStringFIX 2결제수단 (CC / VO)
PAY_GROUPStringFIX 3결제그룹 (GEP / KKP / NVP)
TIDStringFIX 15PG 취소 거래고유번호
CANCEL_AMTNumericMax 20취소금액
VAN_RECV_KEYStringMax 20VAN 거래고유키
EIDStringFIX 15가맹점ID
MIDStringFIX 15상점ID
OPG_IDStringFIX 15VAN TID
ORG_TIDStringFIX 15VAN 원거래 고유번호
Content-Type: application/json;charset=UTF-8
⚠️
가상계좌는 결제 승인 시점이 아닌 실제 입금 확인 시점에 Notification이 발생합니다. 반드시 입금 Notification 수신 후 주문을 처리하세요.
전체 파라미터
항목ID타입길이(byte)설명
TIDStringFIX 15PG사 거래고유번호
PAY_METHODStringFIX 2VA
TEXT_TRStringFIX 2입금: 00 / 입금취소: 99
ORDERNOStringMax 20상점 주문번호
TRANSDTStringFIX 14거래일자 (YYYYMMDDHHMMSS)
RESULTStringFIX 2처리결과코드. 성공: 00
RESULT_MSGStringMax 1024처리결과메시지. 성공: Success

📊정산 내역 조회

승인 대사 및 정산 대사 데이터를 조회하는 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상점ID/가맹점IDStringFIX 15Y상점 별로 부여되는 상점 ID 및 상위 가맹점 ID
stmtReqDt대사요청일StringFIX 8Y요청 일시 (YYYYMMDD)
stmtType대사타입StringFIX 1Y0: 승인대사, 1: 정산대사
ediDate전문요청일시StringFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값StringFIX 256Yid + ediDate + api key를 이용한 키
승인 응답 데이터 (stmtType=0)
항목ID항목명타입설명
resultCd결과코드String성공: 0000
resultMsg결과메시지String실패시에만 표시
id해당IDString요청한 ID
stmtDt대사일String요청한 일자
stmtType대사타입String0: 승인대사, 1: 정산대사
mbsNo사업자번호String가맹점의 사업자번호
stmtCnt대사건수String대사 합계 건수
stmtSumAmt대사 합계 금액String대사 합계 금액
stmtData (JSONArray)
Mid상점IDString(15)
appDtm승인일시String(14)YYYYMMDDHHMMSS 형식
canDtm취소일시String(14)YYYYMMDDHHMMSS 형식
payMethod결제수단String(10)CARD | BANK | VACNT
trxStCd거래상태코드String(1)0:승인, 1:전취소, 2:후취소, 3:부분취소
goodsNm상품명String(100)상품이름
goodsAmt상품금액String(15)결제금액
remainAmt잔액String(15)부분취소 후 남은 금액
quotaMon할부개월String(2)할부 개월 수
appNo승인번호String(10)카드사, 은행 승인번호
acqCardCd매입사코드String(4)신용카드: 카드사코드 / 계좌이체·가상계좌: 은행코드
appCardCd발급사코드String(4)카드사 코드
ezpAuthCd간편결제코드String(4)간편 결제사 코드 (미사용 시 공백)
cardType카드타입String(1)0: 체크 / 1: 신용
cartMid카트MIDString(10)장바구니 거래 시 MID (미사용 시 공백)
cartTid카트TIDString(30)장바구니 거래 시 TID (미사용 시 공백)
TidPG거래번호String(30)거래번호
Otid원거래 PG거래번호String(30)부분취소 시 원거래 번호
ordNo주문번호String(40)가맹점 주문번호
ordNm주문자명String(30)주문자 이름
ordTel주문자연락처String(20)주문자 연락처
mbsUsrId고객IDString(20)가맹점 고객 ID
trxCd에스크로여부String(1)0: 일반 / 1: 에스크로
mbsReserved가맹점예약필드String(500)가맹점 예약 필드
정산 응답 데이터 (stmtType=1) - 추가 필드
항목ID항목명타입설명
Mid상점IDString(15)
stmtDt입금일String(8)YYYYMMDD 형식
txtDt결제일String(8)승인/취소 일 (YYYYMMDD)
payMethod결제수단String(10)CARD | BANK | VACNT
fnCd금융사코드String(4)신용카드: 매입사 / 계좌이체·가상계좌: 금융사
appNo승인번호String(10)카드사, 은행 승인번호
amt금액String(15)결제금액 (취소 시 마이너스)
fee수수료String(15)취소 시 마이너스
vatVATString(15)취소 시 마이너스
refundFee환불 수수료String(15)
refundFeeVat환불 수수료 VATString(15)
smsFeeSMS 수수료String(15)
stmtAmt입금액String(15)최종입금 금액 (취소 시 마이너스)
cartMid카트MIDString(10)장바구니 거래 시 MID (미사용 시 공백)
cartTid카트TIDString(30)장바구니 거래 시 TID (미사용 시 공백)
tidPG거래번호String(30)거래번호
otid원거래 PG거래번호String(30)부분취소 시 원거래 번호
ordNo주문번호String(40)가맹점 주문번호
trxStCd거래상태코드String(1)0:승인, 2:후취소, 3:부분취소
remainAmt잔액String(15)부분취소 후 남은 금액
goodsNm상품명String(100)상품명
ordNm주문자명String(30)주문자 이름
mbsUsrId고객IDString(20)가맹점 고객 ID
mbsReserved가맹점예약필드String(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대표IDStringFIX 15Y지급대행을 관리하는 대표ID (KOVANPG 발급 EID)
editDate전문요청일시StringFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값StringFIX 256Yid + ediDate + api key를 이용한 키
oid가맹점IDString30Y가맹점에서 관리하는 가맹점 ID
shopNm상점명String100Y
phone전화번호String20Y상점 전화번호
csPhoneCS 전화번호String20OCS 전화번호
email이메일주소String30Y메일주소
응답 파라미터
항목ID항목명타입설명
resultCd결과코드String성공: 0000
resultMsg결과메시지String실패시에만 표시
data (JSONArray)
id대표IDString요청한 ID (PG가 발급한 EID)
oid상점ID-가맹점String가맹점에서 요청한 상점ID
rid상점ID-PGStringPG에서 발급한 상점ID
PUT /api/v1/entp/payagent/merchant 지급대행 가맹점 수정
요청 파라미터 (id는 EID가 아닌 RID 사용)
항목ID항목명타입길이(byte)필수설명
idRIDStringFIX 15Y지급대행용 RID
editDate전문요청일시StringFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값StringFIX 256Yid + ediDate + api key를 이용한 키
oid가맹점IDString30Y가맹점에서 관리하는 가맹점 ID
shopNm상점명String100Y
phone전화번호String20Y상점 전화번호
csPhoneCS 전화번호String20OCS 전화번호
email이메일주소String30Y메일주소
응답 파라미터
항목ID항목명타입설명
resultCd결과코드String성공: 0000
resultMsg결과메시지String실패시에만 표시
data (JSONArray)
id대표ID (RID)String(15)수정된 가맹점의 RID
oid상점ID-가맹점String(30)가맹점에서 요청한 상점ID
shopNm상점명String(100)
phone전화번호String(20)상점 전화번호
csPhoneCS 전화번호String(20)CS 전화번호
email이메일주소String(30)메일주소
GET /api/v1/entp/payagent/merchant 지급대행 가맹점 조회
요청 파라미터
항목ID항목명타입길이(byte)필수설명
idRIDStringFIX 15Y지급대행용 RID
editDate전문요청일시StringFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값StringFIX 256Yid + ediDate + api key를 이용한 키
oid가맹점IDString30Y가맹점에서 관리하는 가맹점 ID
응답 파라미터
항목ID항목명타입길이(byte)설명
resultCd결과코드StringMax 4성공: 0000, 실패: 그외
resultMsg결과메시지StringMax 100실패시에만 표시
data (JSONArray)
id대표ID (RID)String15조회된 가맹점의 RID
oid상점ID-가맹점String30가맹점에서 요청한 상점ID
shopNm상점명String100
phone전화번호String20상점 전화번호
csPhoneCS 전화번호String20CS 전화번호
email이메일주소String30메일주소

🏦지급대행 계좌 관리

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

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

💸지급 요청/취소/조회

🔧 개발기
http://220.117.220.108:30200
🚀 상용기
https://ema.kovanpay.com
POST /PayAgent/v1/merchant/settlements.out 지급대행 데이터 요청
요청 파라미터
항목ID항목명타입길이(byte)필수설명
id대표IDStringFIX 15Y지급대행을 관리하는 대표ID (EID)
ediDate전문요청일시StringFIX 14Y요청시 일시 (yyyymmddhhmmss)
encData해쉬암호화값StringFIX 256Yid + ediDate + api key를 이용한 키
payReqCnt지급요청건수String5Y지급요청건수
payReqList (배열)
ridPG 상점IDString30OPG에서 부여한 지급대행 가맹점 ID
oid상점ID(가맹점)String30Y지급대행 대상 상점 ID
shopNm상점명String100Y
payReqDt지급일String8YYYYYMMDD
payReqAmt지급액String15Y
shopSeqNo요청일련번호String50O가맹점 요청 일련번호
bankCd은행코드String3Y빈 값일 경우 가맹점 등록 시 계좌 정보 참조
acctNm예금주String30Y
acctNo계좌번호String50Y
memo메모String35O다중 지급 요청 시 가장 최근 메모 적용
응답 파라미터
항목ID항목명타입길이(byte)설명
id대표IDStringFIX 15요청한 EID
respDate전문응답일시StringFIX 14응답 일시 (yyyymmddhhmmss)
payResultCnt응답건수String5
resCode응답코드String40000: 성공 / 0010: 해시 불일치 / 0020: 지급 요청금액 오류
resMsg응답메시지StringMax 100실패시에만 표시
payResultList (JSONArray)
oid상점IDString30지급대행 대상 상점 ID
rid상점ID-PGStringFIX 15PG에서 발급한 상점ID
shopNm상점명String100
bankCd은행코드String3은행 코드표 참조
shopSeqNo요청일련번호String-가맹점 요청 일련번호
acctNm예금주String30
acctNo계좌번호String50
payReqDt지급일String8YYYYMMDD
payReqAmt지급액String15
resultCdDetail결과코드StringMax 4성공: 0000, 실패: 그외
resultMsgDetail결과메시지StringMax 100실패시에만 표시
POST /PayAgent/v1/merchant/settlements-cancel.out 지급대행 데이터 요청취소
요청 파라미터
항목ID항목명타입길이(byte)필수설명
id대표IDStringFIX 15YEID
ediDate전문요청일시StringFIX 14Yyyyymmddhhmmss
encData해쉬암호화값StringFIX 256Y
orgEdiDate(원)지급요청일String8Y원 지급요청전문의 ediDate
canType취소구분String10Y전체: ALL / 단일: TARGET
oid상점IDString30OcanType TARGET 시 필요
응답 파라미터
항목ID항목명타입길이(byte)설명
id대표IDStringFIX 15요청한 EID
respDate전문응답일시StringFIX 14응답 일시 (yyyymmddhhmmss)
canResultCnt응답건수String5
resCode응답코드String40000: 성공 / 0010: 해시 불일치 / 0020: 조회조건 오류
resMsg응답메시지StringMax 100실패시에만 표시
canResultList (JSONArray)
oid상점IDString30지급대행 대상 상점 ID
rid상점ID-PGStringFIX 15PG에서 발급한 상점ID
shopNm상점명String100
bankCd은행코드String3은행 코드표 참조
shopSeqNo요청일련번호String-가맹점 요청 일련번호
acctNm예금주String30
acctNo계좌번호String50
payReqDt지급일String8YYYYMMDD
payReqAmt지급액String15
resultCdDetail결과코드StringMax 4성공: 0000, 실패: 그외
resultMsgDetail결과메시지StringMax 100실패시에만 표시
POST /PayAgent/v1/merchant/settlements-history.out 지급대행 처리결과 조회
요청 파라미터
항목ID항목명타입길이(byte)필수설명
id대표IDStringFIX 15YEID
ediDate전문요청일시StringFIX 14Y
encData해쉬암호화값StringFIX 256Y
payDateFrom시작일String8Yyyyymmdd
payDateTo종료일String8Yyyyymmdd
schType조회구분String10Y전체: ALL / 단일: TARGET
oid상점IDString30OschType TARGET 시 필요
응답 파라미터
항목ID항목명타입길이(byte)설명
id대표IDStringFIX 15요청한 EID
respDate전문응답일시StringFIX 14응답 일시 (yyyymmddhhmmss)
payResultCnt응답건수String5
resCode응답코드String40000: 성공 / 0010: 해시 불일치 / 0020: 조회조건 오류
resMsg응답메시지StringMax 100실패시에만 표시
payResultList (JSONArray)
oid상점IDString30지급대행 대상 상점 ID
rid상점ID-PGStringFIX 15PG에서 발급한 상점ID
shopNm상점명String100
bankCd은행코드String3은행 코드표 참조
shopSeqNo요청일련번호String-가맹점 요청 일련번호
acctNm예금주String30
acctNo계좌번호String50
payReqDt지급일String8YYYYMMDD
payReqAmt지급액String15
resultCdDetail결과코드StringMax 4성공: 0000, 실패: 그외
resultMsgDetail결과메시지StringMax 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.plistLSApplicationQueriesSchemes에 아래 스키마를 추가하세요. 누락 시 콘솔에 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 파일 송수신

⚠️
파일 인코딩: 모든 파일은 EUC-KR 인코딩으로 생성해야 합니다.
파일명 형식: 파일명.요청일(yyyyMMdd) — 예: batch_settlement.20260406
📤 송신 경로
/send
📥 수신 경로
/recv

파일 송수신 시간

파일 종류송신 기한응답 시간
하위몰 정보 파일오전 08:00까지결과 처리 후 즉시 회신
차액정산 파일오후 13:50까지결과 처리 후 즉시 회신

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

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사) 레코드길이: 240byte
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사 → 고객사) 레코드길이: 240byte
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
차액정산 예정일YYYYMMDD8차액정산 입금 예정일. 일반 등급은 99999999
공백AN42예약 필드SPACE
Trailer부 (레코드구분: TR)
항목형식길이설명비고
레코드구분A2TR로 고정
파일전체라인수N8해당 파일 내 전체 라인수 (데이터부 + Trailer부)
승인거래건수N8승인/취소구분 0(정상)인 거래 총건수
취소거래건수N8승인/취소구분 1(취소)인 거래 총건수
총 거래금액 부호A1총거래금액 부호양수: 0 / 음수: 1
총 거래금액N15승인거래금액 − 취소거래금액
총 차액정산금액N15데이터부의 차액정산 금액 총 합계
공백AN193예약 필드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

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)
RECV 하위몰 정보 등록 결과 전문 (PG사 → 고객사) 레코드길이: 500byte
Data부 (레코드구분: DT)
항목형식길이설명
레코드구분A2DT로 고정
등록구분A200: 신규 / 01: 해지 / 02: 변경
MIDA15
사업자등록번호 (하위몰)N10최종 하위사업자
카드사N10카드사 코드 (코드표 참조)
업종명 (하위몰)HS20한글 10자 (특수기호 가능)
회사명 (하위몰)H40한글 20자
주소 (하위몰)H100TEXT
대표자명 (하위몰)H40TEXT
전화번호 (하위몰)N11TEXT
이메일 (하위몰)ANS40이메일 주소
웹사이트 URL (하위몰)ANS80TEXT
정보등록일YYYYMMDD8등록 처리 완료 일자
반송코드A200: 정상처리. 반송코드표 참조
공백AN120예약 필드 (SPACE)
Trailer부 (레코드구분: TR)
항목형식길이설명
레코드구분A2TR로 고정
총 건수 합계N10DATA부 건수
공백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를 직접 생성해볼 수 있습니다.