※ 이 사이트는 Internet Explorer 10 이하 버전은 지원하지 않습니다. 최신 브라우저로 업데이트해 주세요.
VAN 빌링 연동
스마트로페이 결제모듈 연동을 위한 가이드입니다.
- 해당 매뉴얼의 Parameter 들은 가맹점에 통보 없이 응답값이 추가 될 수 있습니다. 응답값 추가도 고려하여 개발 진행하시길 권장합니다 .
- Test 연동시 체크 카드는 사용자제 부탁드립니다.체크 카드 결제시 Test 계에서는 당일 전체 취소만 가능 합니다 (부분취소 지원 불가)
- 빌링키 발급 시 해외카드는 지원되지 않습니다.(국내카드만 등록 가능)
- 스마트로 사업자번호로 제공된 테스트 Mid는 국민카드(카카오뱅크), 하나카드 결제가 불가합니다.
VAN 빌링
결제 정보를 암호화 처리 후 스마트로 VAN 망을 통해 PG사 인증서버로 전송하는 방식의 빌링 서비스입니다.
숫자만 입력 (문자 입력 시 10자 미만으로 설정 하셔야합니다. - 초과 시 승인 오류 발생)
BuyerEmail
구매자메일주소
60
필수
EdiDate
요청 거래일시
14
필수
VerifyValue
위·변조 검증값
가변
필수
SHA256 해시 암호화
EncodingType
인코딩 형식
6
선택
utf8(기본값), euckr
MallReserved
상점 예비필드
500
선택
Base64 인코딩필요
(평문으로 전달시 한글 및 특수문자가 정상적으로 전달되지 않음)
InitTitle
가맹점 Title 설정
5
선택
5자리 제한, 기본값: 결제정보등록
RtnUrlEncUse
응답 데이터 UrlEncoding 처리여부
1
선택
Y: 사용, N(기본값): 미사용
ReturnUrl
등록결과 전달 가맹점 URL
100
선택
Http 프로토콜 포함 전체 Url 설정
SkinColor
UI 스타일
10
선택
RED(기본값), GREEN, BLUE, PURPLE
파라미터
항목명
길이(char)
설명
TrId
가맹점 거래 일련번호
20
SspMallId
결제MALL ID
10
CoNo
가맹점 사업자번호
10
ResultCode
등록 결과
4
성공: 0000, 실패: 그 외
ResultMsg
등록 결과 메시지
가변
AppCardCode
발급사코드
2
AppCardName
발급사명
20
AcquCardCode
매입사코드
2
AcquCardName
매입사명
20
CardMerchantNo
카드사가맹점번호
15
CardNum
카드번호
16
7~12자리 Masking 처리
BillKey
빌링키
30
BillKeyPolicy
Bill-key 발급정책
16
USE_TO_ONE:고객번호 1개에 빌키 1개 발급, USER_TO_MULTI: 고객번호 1개에 빌키 다수 발급
DisplayCardNo
표시용 카드번호
20
실 카드번호 마스킹 처리
VerifyValue
위·변조 검증값
가변
SHA256 해시 암호화
BillKeyExpDate
Bill-key 유효기간
4
MallReserved
가맹점예비정보
500
가맹점에서 설정한 값 전달
STEP 1VAN빌링키 발급 요청 파라미터 설정하기
·JSP
String Mid = ""; // 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
String SspMallId = "SMTSSPAY0p" // VAN빌링키 테스트용 SspMallId (REAL 전환 시 가맹점 SspMallId로 변경)
String MallLicenseKey = ""; // 가맹점 MallLicenseKey 설정
String CoNo = ""; // 가맹점 사업자번호 설정
String EdiDate = getyyyyMMddHHmmss();
String EncryptData = encodeSHA256Base64(SspMallId + MallLicenseKey + CoNo + EdiDate);
String today = getyyyyMMddHHmm(); // 현재일자. 캐시방지용으로 사용
/* SHA256 암호화 */
public static final String encodeSHA256Base64(String strPW) {
String passACL = null;
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (Exception e) {
e.printStackTrace();
}
md.update(strPW.getBytes());
byte[] raw = md.digest();
byte[] encodedBytes = Base64.encodeBase64(raw);
passACL = new String(encodedBytes);
return passACL;
}
/* 현재일자 */
public static final String getyyyyMMddHHmmss() {
SimpleDateFormat yyyyMMddHHmmss = new SimpleDateFormat("yyyyMMddHHmmss");
return yyyyMMddHHmmss.format(new Date());
}
/* 현재일자 */
public static final String getyyyyMMddHHmm() {
SimpleDateFormat yyyyMMddHHmm = new SimpleDateFormat("yyyyMMddHHmm");
return yyyyMMddHHmm.format(new Date());
}
$Mid = ""; // 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
$SspMallId = "SMTSSPAY0p" // VAN빌링키 테스트용 SspMallId (REAL 전환 시 가맹점 SspMallId로 변경)
$MallLicenseKey = ""; // 가맹점 MallLicenseKey 설정
$CoNo = ""; // 가맹점 사업자번호 설정
$EdiDate = date("YmdHis");
$EncryptData = base64_encode(hash('sha256', $SspMallId.$MallLicenseKey.$CoNo.$EdiDate, true));
$today = date("YmdHi"); // 현재일자. 캐시방지용으로 사용
Mid = "" ' 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
SspMallId = "SMTSSPAY0p" // VAN빌링키 테스트용 SspMallId (REAL 전환 시 가맹점 SspMallId로 변경)
MallLicenseKey = ""; // 가맹점 MallLicenseKey 설정
CoNo = ""; // 가맹점 사업자번호 설정
EdiDate = Year(Now()) & right("0"&Month(Now()),2) & right("0"&Day(Now()),2) & right("0"&Hour(Now()),2) & right("0"&Minute(Now()),2) & right("0"&Second(Now()),2)
EncryptData = CryptoUtil.Sha256Encrypt(SspMallId & MallLicenseKey & CoNo & EdiDate)
today = Year(Now()) & right("0"&Month(Now()),2) & right("0"&Day(Now()),2) & right("0"&Hour(Now()),2) & right("0"&Minute(Now()),2) ' 현재일자. 캐시방지용으로 사용
const crypto = require('crypto');
// 발급받은 테스트 MID 설정 (운영 전환 시 실제 값 사용)
const Mid = "";
const SspMallId = ""; // VAN 빌링키 테스트용 SspMallId (REAL 전환 시 가맹점 SspMallId로 변경)
const MallLicenseKey = ""; // 가맹점 MallLicenseKey 설정
const CoNo = ""; // 가맹점 사업자번호 설정
const EdiDate = getyyyyMMddHHmmss(); // 현재 일자 (yyyyMMddHHmmss 형식)
const EncryptData = encodeSHA256Base64(SspMallId + MallLicenseKey + CoNo + EdiDate); // SHA256 + Base64 인코딩
const today = getyyyyMMddHHmm(); // 현재 일자 (캐시 방지용)
// SHA256 암호화 + Base64 인코딩 함수
function encodeSHA256Base64(data) {
const hash = crypto.createHash('sha256');
hash.update(data);
return Buffer.from(hash.digest()).toString('base64'); // 해시 결과를 Base64로 인코딩
}
// 현재 일자 (yyyyMMddHHmmss 형식)
function getyyyyMMddHHmmss() {
const now = new Date();
return now.toISOString().replace(/[-T:Z.]/g, '').slice(0, 14); // 'YYYYMMDDHHMMSS' 형식으로 변환
}
// 현재 일자 (yyyyMMddHHmm 형식)
function getyyyyMMddHHmm() {
const now = new Date();
return now.toISOString().replace(/[-T:Z.]/g, '').slice(0, 12); // 'YYYYMMDDHHMM' 형식으로 변환
}
// 결과 출력
console.log("EncryptData:", EncryptData);
console.log("today", today);
console.log("EdiDate", EdiDate);
- Python 모듈 소스의 경우 Django(v.5.0.7)를 기반으로 작성되었습니다.
import hashlib
import base64
import datetime
Mid = "" # 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
SspMallId = "" # VAN 빌링키 테스트용 SspMallId(Real 전환 시 운영 SspMallId로 변경)
MallLicenseKey = "" # 가맹점 MallLicenseKey 설정
CoNo = "" # 가맹점 사업자번호 설정
EdiDate = "" # EdiDate
today = "" # 현재일자, 캐시방지용으로 사용
# EdiDate 생성
def getyyyyMMddHHmmss():
return datetime.datetime.now().strftime("%Y%m%d%H%M%S")
EdiDate = getyyyyMMddHHmmss()
# today 생성
def getyyyyMMddHHmm():
return datetime.datetime.now().strftime("%Y%m%d%H%M")
today = getyyyyMMddHHmm()
# EncryptData 생성
def encodeSHA256Base64(strPW):
sha256_object = hashlib.sha256()
sha256_object.update(strPW.encode())
return base64.b64encode(sha256_object.digest()).decode("utf-8")
EncryptData = encodeSHA256Base64(SspMallId + MallLicenseKey + CoNo + EdiDate)
STEP 2VAN빌링키 Form데이터 설정
·JSP
SmartroPAY 연동가이드
import { useEffect } from 'react';
function Pay() {
// PC/Mobile 구분하여 도메인 변경 필요
// PC 환경에서 호출시 https://tpay.smartropay.co.kr/asset/js/SmartroPAY-1.0.min.js?version=현재일자
// Mobile 환경에서 호출시 https://tmpay.smartropay.co.kr/asset/js/SmartroPAY-1.0.min.js?version=현재일자
// 운영 전환 시 도메인 변경
// PC : tpay.smartropay.co.kr -> pay.smartropay.co.kr
// Mobile : tmpay.smartropay.co.kr -> mpay.smartropay.co.kr
// script 캐시방지를 위해 ?version=today를 추가 ex) SmartroPAY-1.0.min.js?version=20230101
useEffect(() => {
const script = document.createElement('script');
script.src = `https://tpay.smartropay.co.kr/asset/js/SmartroPAY-1.0.min.js?version=&{ today }`;
script.type = 'text/javascript';
document.head.appendChild(script);
return () => {
document.head.removeChild(script);
}
}
, []);
// 스마트로 페이 응답은 POST로 응답됩니다.
// POST 응답을 받을 수 있는 서버 url을 넣어주세요.
const ReturnUrl = "";
const goPay = () => {
window.smartropay.init({
mode : 'STG', // STG: 테스트, REAL: 운영(운영서버 전환 시 변경 필수!)
actionUri : '/ssvbill/interface.do'
});
// 스마트로페이 VAN빌링키 발급요청
window.smartropay.payment({
FormId : 'tranMgr' // 폼ID
});
}
return(
<>
0000 : success
PR01 : 멤버 정보 미존재
PA50 : 발급정보없음
* 그 외 응답 - 통합코드 조회 참고
ResultMsg
결과메시지
80
ResultData
*ResultCode=0000 시 응답
빌링키 상세 조회리스트
가변
하단 응답 예시 참고
파라미터
항목명
길이(char)
설명
RegMid
등록 Mid
10
BillTokenKey
고정식토큰(빌링키)
50
IssuerCardCd
발급사 코드
2
IssuerCardNm
발급사명
10
DisplayCardNo
표시용 카드번호
20
마스킹되어 전달
CardExpire
빌링키 유효기간
4
YYMM
실제 카드 유효기간 -2개월로 응답
RegDt
빌링키 등록 일자
8
YYYYMMDD
STEP 1VAN 빌링키 조회 파라미터 설정 및 UrlCall 조회 요청하기
·JSP
String url = "https://tapproval.smartropay.co.kr/payment/approval/vanBillKeyInquiry.do"; // 테스트
// String url = "https://approval.smartropay.co.kr/payment/approval/vanBillKeyInquiry.do"; // 운영
JSONObject body = new JSONObject();
JSONObject paramData = new JSONObject();
String MallLicenseKey = ""; // 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
String Mid = ""; // 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
String SspMallId = "SMTSSPAY0p"; // 테스트용 SspMallId
String MallUserId = ""; // 회원사 고객 ID
String BillTokenKey = ""; // 빌링키 발급을 통해 생성된 키
// 요청 파라미터 (각 값들은 가맹점 환경에 맞추어 설정해 주세요.)
paramData.put("SspMallId", SspMallId);
paramData.put("MallUserId", MallUserId);
paramData.put("BillTokenKey", BillTokenKey);
$url = "https://tapproval.smartropay.co.kr/payment/approval/vanBillKeyInquiry.do"; // 테스트
//$url = "https://approval.smartropay.co.kr/payment/approval/vanBillKeyInquiry.do"; // 운영
$MallLicenseKey = ""; // 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
$Mid = ""; // 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
$SspMallId = "SMTSSPAY0p"; // 테스트용 SspMallId
$MallUserId = ""; // 회원사 고객 ID
$BillTokenKey = ""; // 발급받은 빌링키
$paramData = array(
'SspMallId' => $SspMallId,
'MallUserId' => $MallUserId,
'BillTokenKey' => $BillTokenKey
);
url = "https://tapproval.smartropay.co.kr/payment/approval/vanBillKeyInquiry.do" ' 테스트
'url = "https://approval.smartropay.co.kr/payment/approval/vanBillKeyInquiry.do" ' 운영
MallLicenseKey = "" ' 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
Mid = "" ' 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
SspMallId = "SMTSSPAY0p" ' 테스트용 SspMallId
MallUserId = ""; ' 회원사 고객 ID
BillTokenKey = "" ' 발급받은 빌링키
Set paramData = jsObject()
paramData("SspMallId") = SspMallId
paramData("MallUserId") = MallUserId
paramData("BillTokenKey") = BillTokenKey
const axios = require('axios');
const crypto = require('crypto');
const domainUrl = 'https://tapproval.smartropay.co.kr/'; // 테스트 URL
// const domainUrl = 'https://approval.smartropay.co.kr/'; // 운영 URL
// AES256 암호화 함수
function AES256Encode(data, key) {
const iv = Buffer.alloc(16, 0);
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
let encrypted = cipher.update(data, 'utf8', 'base64');
encrypted += cipher.final('base64');
return encrypted;
}
async function inquiry() {
const restRequestUrl = domainUrl + 'payment/approval/vanBillKeyInquiry.do';
const MallLicenseKey = ''; // 발급받은 테스트 상점키 설정
const Mid = ''; // 발급받은 테스트 Mid 설정
const SspMallId = ''; // 테스트용 SspMallId
const MallUserId = ''; // 회원사 고객 ID
const BillTokenKey = ''; // 빌링키 발급을 통해 생성된 키
const body = {
SspMallId: SspMallId,
MallUserId: MallUserId,
BillTokenKey: BillTokenKey
};
// JSON 데이터 AES256 암호화
const sendObject = {
EncData: AES256Encode(JSON.stringify(body), merchantKey.substring(0, 32)),
Mid: Mid
};
// .... STEP2 요청 및 결과 받기
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
import requests
import base64
from Cryptodome.Cipher import AES
from Cryptodome import Random
@csrf_exempt
def inquiry(request):
# 빌링키 조회 요청
# 운영 : https://approval.smartropay.co.kr/payment/approval/vanBillKeyInquiry.do
# 테스트 : https://tapproval.smartropay.co.kr/payment/approval/vanBillKeyInquiry.do
Mid = "" # 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
MallLicenseKey = "" # 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
SspMallId = "" # 발급받은 SspMallId
MallUserId = "" # MallUserId
BillTokenKey = "" # 빌링키 발급을 통해 생성된 키
# 요청 파라미터 (각 값들은 가맹점 환경에 맞추어 설정해 주세요.)
paramData = {
'SspMallId' : SspMallId,
'MallUserId' : MallUserId,
'BillTokenKey' : BillTokenKey
}
# .... STEP2 요청 및 결과 받기
STEP 2VAN 빌링키 조회 결과 받기
·JSP
// json 데이터 AES256 암호화
try {
body.put("EncData", AES256Cipher.AES_Encode(paramData.toString(), MallLicenseKey.substring(0,32)));
body.put("SspMallId", SspMallId);
} catch(Exception e){
e.printStackTrace();
}
HashMap<String, Object> result = callApi(body, url);
public HashMap<String, Object> callApi(JSONObject json, String callUrl) {
StringBuilder responseBody = null;
HashMap<String, Object> result = new HashMap<>();
// http urlCall 승인 요청 및 TrAuthKey 유효성 검증
int connectTimeout = 1000;
int readTimeout = 10000; // 가맹점에 맞게 TimeOut 조절
URL url = null;
HttpsURLConnection connection = null;
try {
SSLContext sslCtx = SSLContext.getInstance("TLSv1.2");
sslCtx.init(null, null, new SecureRandom());
url = new URL(callUrl);
System.out.println(" url " + url.toString());
connection = (HttpsURLConnection)url.openConnection();
connection.setSSLSocketFactory(sslCtx.getSocketFactory());
connection.addRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("Accept", "application/json");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setConnectTimeout(connectTimeout);
connection.setReadTimeout(readTimeout);
OutputStreamWriter osw = new OutputStreamWriter(new BufferedOutputStream(connection.getOutputStream()) , "utf-8" );
char[] bytes = json.toString().toCharArray();
osw.write(bytes,0,bytes.length);
osw.flush();
osw.close();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
String line = null;
responseBody = new StringBuilder();
while ((line = br.readLine()) != null) {
System.out.println(" response " + line);
responseBody.append(line);
}
br.close();
// 결제결과
result = new ObjectMapper().readValue(responseBody.toString(), HashMap.class);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}