빌링 연동

스마트로페이 결제모듈 연동을 위한 가이드입니다.
- 해당 매뉴얼의 Parameter 들은 가맹점에 통보 없이 응답값이 추가 될 수 있습니다. 응답값 추가도 고려하여 개발 진행하시길 권장합니다 .
- Test 연동시 체크 카드는 사용자제 부탁드립니다. 체크 카드 결제시 Test 계에서는 당일 전체 취소만 가능 합니다 (부분취소 지원 불가)
- 빌링키 발급 시 해외카드는 지원되지 않습니다.(국내카드만 등록 가능)
- 스마트로 사업자번호로 제공된 테스트 Mid는 국민카드(카카오뱅크), 하나카드 결제가 불가합니다.

빌링연동(SS-Pay)

Online 신용카드 빌링
스마트로페이의 Online 신용카드 정기과금(빌링)서비스 연동에 대한 안내입니다.
* 스마트로페이의 응답은 POST입니다. 연동 시 참고해 주세요.
스마트로페이 SERVER IP
스마트로페이 서비스 IP 정보입니다.
구분 IP 비고
테스트 211.193.35.11 STG
운영 - 결제 211.193.35.20
운영 - 재통보 211.193.35.216
211.193.35.217
재통보 서비스 사용시

OPTIONS 빌링키 발급 정책
발급 정책 옵션
동일 카드 등록여부 거절 / 기등록 빌링키 정보 전달 / 삭제 후 신규 등록 / 미삭제 신규 등록
- 동일 카드 등록 여부 "거절" 설정 시 회원 기준 추가 카드 등록 미삭제 신규 등록 설정은 불가합니다.
추가 카드 등록여부 거절 / 삭제 후 신규 등록 / 미삭제 신규 등록
Bill-Key 발급 정책 회원 기준 1개 발급 / 회원 기준 다수개 발급
- 회원 기준 1개 발급 설정의 경우 미삭제 신규 등록 설정은 불가합니다.
본인인증 사용여부 미사용 / 휴대폰 인증
- 본인인증 미사용 옵션 시 타인의 카드 정보를 등록하여 결제 가능한 점 유의해주시길 바랍니다.
가맹점 정책에 맞는 옵션을 선택하여 영업담당자에게 요청 주시길 바랍니다.

빌링 키 발급

빌링 키 발급 파라미터

파라미터 항목명 길이(char) 필수여부 설명
PayMethod 결제수단 10 필수 CARD: 신용카드
Mid 상점 ID 10 필수
Moid 상품주문번호 40 필수
MallUserId 회원사 고객 ID 20 필수 회원가입 시 고객 구분값으로 사용
영어 대·소문자, 숫자 사용 가능(특수문자 포함 불가)
MallIp 상점 IP 20 선택 상점서버 IP
UserIp 고객 IP 20 선택 고객 IP
ReturnUrl 상점 인증결과 전송 URL 100 필수 Http 프로토콜 포함 전체 Url 설정
VerifyValue 위·변조 검증값 가변 필수 SHA256 해시 암호화
SspMallId 결제MALL ID 10 필수 발급받은 SspMallId
EdiDate 결제요청일시 14 필수
GoodsName 거래 상품명 40 옵션 값이 없는 경우 플러그인에 "빌링키인증" 이라는 문자로 안내
BuyerName 구매자명 30 선택
BuyerTel 구매자연락처 40 선택
BuyerEmail 구매자메일주소 60 선택
EncodingType 응답 Charset 6 선택 utf8(기본값), euckr
MallReserved 상점 예비필드 500 선택 Base64 인코딩필요
(평문으로 전달시 한글 및 특수문자가 정상적으로 전달되지 않음)
SkinColor 플러그인 SKIN 10 선택 RED(기본값), GREEN, BLUE, PURPLE
RtnUrlEncUse 응답 데이터 UrlEncoding 처리여부 1 선택 Y: 사용, N(기본값): 미사용
UseIfrmYn Iframe 사용 여부 1 선택 Y: Iframe 사용 , N(기본값): Iframe 미사용
파라미터 항목명 길이(char) 설명
PayMethod 결제수단 10 CARD: 신용카드
Mid 상점 ID 10
BuyerName 구매자명 30 본인확인서비스를 통하여 인증된 사용자명
Moid 주문번호 40
Tid 거래 ID 40
BillTokenKey 고정식 토큰(빌링키) 가변 AES 암호화되어 전달됩니다. Step1-3 발급 결과 받기를 참고하여 복호화 후
이용해주시길 바랍니다. (암호화키=상점키)
MallUserId 회원사 고객 ID 20 회원가입 시 고객 구분값으로 사용
ResultCode 등록 결과 4 성공: 3001, 실패: 그 외
ResultMsg 등록 결과 메시지 가변
MallReserved 상점 예비필드 500 요청한 값 응답
VerifyValue 위·변조 검증값 50 SHA256 해시 암호화
SspMallId 간편결제 가맹점 ID 10
IssuerCardCd 발급사코드 2
IssuerCardNm 발급사명 10
AcquCardCd 매입사코드 2
AcquCardNm 매입사명 10
DisplayCardNo 표시용 카드번호 20 실 카드번호 마스킹 처리
CardExpire 빌키 유효기간 4 카드의 유효기간이 아닌 빌키의 유효기간(YYMM) 입니다
EncodingType 응답 Charset 6 utf8(기본값), euckr
RtnUrlEncUse 응답 데이터 UrlEncoding 처리여부 1 Y: 사용, N(기본값): 미사용
OPTIONS 본인인증 추가 검증 옵션
본인인증을 사용하는 경우 추가 검증 옵션을 사용할 수 있습니다.
가맹점 정책에 맞는 옵션을 선택하여 영업담당자에게 요청 주시길 바랍니다.
옵션 비고
미사용 본인인증 성공 여부만 체크(default)
성명 일치 본인인증 성명과 구매자명(BuyerName) 일치여부 확인
휴대폰번호 일치 본인인증 휴대폰 번호와 구매자 휴대폰번호(BuyerTel) 일치여부 확인
성명&휴대폰번호 일치 본인인증 성명과 구매자명(BuyerName) 일치 &
본인인증 휴대폰 번호와 구매자 휴대폰번호(BuyerTel) 일치 확인

STEP 1-1 빌링키 발급요청 파라미터 설정 및 발급 요청하기
·JSP

String Mid = "";           // 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
String MerchantKey = "";   // 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
String EdiDate = getyyyyMMddHHmmss();
String EncryptData = encodeSHA256Base64(EdiDate + Mid + Moid + "SMARTRO!@#");
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());
}

STEP 1-2 Form 데이터 설정
·JSP


<html lang="ko">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
    <meta name="description" content="" />
    <meta name="author" content="Smartro" />
    <title>SmartroPAY 연동가이드</title>

    <!-- 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 -->
    <script src="https://tpay.smartropay.co.kr/asset/js/SmartroPAY-1.0.min.js?version=현재일자"></script>
    <script type="text/javascript">
		function goPay() {
			// 스마트로페이 초기화
			smartropay.init({
				mode : 'STG', // STG: 테스트, REAL: 운영(운영서버 전환 시 변경 필수!)
				actionUri : '/ssb/interface.do'
			});
			// 스마트로페이 빌링키 발급요청
			smartropay.payment({
				FormId : 'tranMgr' // 폼ID
			});
		}
	</script>
</head>
<body>
    <form id="tranMgr" name="tranMgr" method="post">
        <!-- 각 값들을 가맹점에 맞게 설정해 주세요. -->
        <input type="text" name="PayMethod" value="CARD" placeholder="" />
        <input type="text" name="Mid" maxlength="10" value="설정한 Mid" placeholder="" />
        <input type="text" name="Moid" maxlength="40" value="설정한 Moid" placeholder="특수문자 포함 불가" />
        <input type="text" name="MallUserId" maxlength="20" value="MallUserId" placeholder="" />
        <input type="text" name="MallIp" maxlength="20" value="10.0.0.1" placeholder="" />
        <input type="text" name="UserIp" maxlength="20" value="10.0.0.1" placeholder="" />
        <input type="text" name="ReturnUrl" size="100" class="input" value="가맹점 ReturnUrl">
        <input type="text" name="VerifyValue" maxlength="100" class="input" value="생성된 EncryptData" placeholder="위/변조방지 HASH 데이터">
        <input type="text" name="EncodingType" maxlength="14" value="" placeholder="utf-8 or euc-kr" />
        <input type="text" name="SspMallId" maxlength="20" value="SMTSSPAY0p" placeholder="테스트용 SspMallId" />
        <input type="text" name="EdiDate" maxlength="14" value="설정한 EdiDate" placeholder="" />
        <button type="button" class="btn btn-primary" onclick="goPay();">결제하기</button>
    </form>

</body>
</html>
				
        

STEP 1-3 발급 결과 받기
·JSP

String tempVerifyValue = null;
boolean result = false;

String BillTokenKey = request.getParameter("BillTokenKey");
String Mid = request.getParameter("Mid");
String DisplayCardNo = request.getParameter("DisplayCardNo");
String ResultCode = request.getParameter("ResultCode");
String VerifyValue = request.getParameter("VerifyValue");

try {
    String merchantKey = "";   // 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)

    String mKey = merchantKey.substring(0,32);
    BillTokenKey = AESDecode(BillTokenKey, mKey);   // AESDecode 후 가맹점DB에 빌링키 저장
    String tempVerifyValueString = Mid + BillTokenKey + DisplayCardNo + ResultCode + "SMARTRO!@#";

    tempVerifyValue = encodeSHA256Base64(tempVerifyValueString);

    result = tempVerifyValue.equals(VerifyValue) ? true : false;

}catch(Exception e) {
    e.printStackTrace();
}

// Decode 함수
public static byte[] ivBytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

public static String AESDecode(String str, String key)	throws Exception {
	//byte[] textBytes =  Base64.decodeBase64(str.getBytes());
	String result = null;
	byte[] textBytes = Base64.decodeBase64(str);
	AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
	SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
	Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
	result = new String(cipher.doFinal(textBytes), "UTF-8");
	return result;
}


빌링 결제

빌링결제 파라미터

파라미터 항목명 길이(char) 필수여부 설명
PayMethod 지불수단 20 필수 CARD
GoodsCnt 결제상품 품목 개수 2 필수 기본값: 1
GoodsName 거래 상품명 40 필수
Amt 거래 금액 12 필수 숫자만 가능, 문장부호 제외
Moid 상품주문번호 40 필수 특수문자 포함 불가
MallUserId 회원사 고객 ID 20 필수 빌링 결제 요청시 고객 구분값으로 사용
Mid 상점아이디 10 필수
BillTokenKey 고정식 토큰(빌링키) 30 필수 복호화하여 전송
BuyerName 구매자명 30 필수
BuyerTel 구매자연락처 40 필수
BuyerEmail 구매자메일주소 60 필수
CardQuota 할부 개월 2 필수 00: 일시불(기본값), 02, 03, ...
VerifyValue 위·변조 검증값 50 필수 SHA256 해시 암호화
MallIp 상점 IP 20 선택 상점서버 IP
UserIp 고객 IP 20 선택 고객 IP
Currency 통화구분 3 선택 KRW(기본값)
TaxAmt 과세 9 선택 숫자만 가능, 문장부호 제외
TaxFreeAmt 비과세 9 선택 숫자만 가능, 문장부호 제외
VatAmt 부가세 9 선택 숫자만 가능, 문장부호 제외
CardPoint 포인트 사용여부 1 선택 신용카드 카드포인트 사용여부
파라미터 항목명 길이(char) 설명
Tid 거래번호 30
AuthDate 승인일자 12 YYMMDDHHMMSS(형식)
AuthCode 승인번호 30
ResultCode 결과코드 4
ResultMsg 결과메시지 100
AppCardCode 발급사코드 2
AppCardName 발급사명 20
CardNum 카드번호 20 실 카드번호 마스킹 처리
CardInterest 무이자여부 1 0: 일반, 1: 카드사 무이자, 2: 상점 무이자
Currency 결제통화 3
VerifyValue 위·변조 검증값 50 SHA256 해시 암호화 / URL Decoding 필요
MallReserved 상점예비정보 500 결제 요청 시 설정한 값 전달

STEP 1 빌링결제 요청 파라미터 설정하기
·JSP
        
String url = "https://tapproval.smartropay.co.kr/payment/approval/approvalUnionBill.do";		// 테스트
// String url = "https://approval.smartropay.co.kr/payment/approval/approvalUnionBill.do";	// 운영

JSONObject body = new JSONObject();
JSONObject paramData = new JSONObject();

String merchantKey = "";  				// 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
String Mid = "";    					// 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
String EdiDate = getyyyyMMddHHmmss();
String Moid = "";
String BillTokenKey = ""; 				// 빌링키 발급을 통해 생성된 키
String Amt = "1004";
// 검증값 SHA256 암호화(빌링키 + Mid + 금액)
String VerifyValue = encodeSHA256Base64(BillTokenKey + Mid + Amt);

// 요청 파라미터 (각 값들은 가맹점 환경에 맞추어 설정해 주세요.)
paramData.put("UserIp" ,"10.0.0.1");
paramData.put("MallIp" ,"10.0.0.1");
paramData.put("Mid" ,Mid);
paramData.put("BillTokenKey" ,BillTokenKey);
paramData.put("Moid" ,Moid);
paramData.put("EdiDate" ,EdiDate);
paramData.put("BuyerName" ,"구매자명");
paramData.put("BuyerTel" ,"01022223333");
paramData.put("BuyerEmail" ,"noname@smartro.co.kr");
paramData.put("CardQuota" ,"00");
paramData.put("CardPoint" ,"0");
paramData.put("GoodsCnt" ,"1");
paramData.put("GoodsName" ,"Peach Macarong");
paramData.put("Amt" ,Amt);
paramData.put("SvcAmt" ,"");
paramData.put("VatAmt" ,"");
paramData.put("TaxAmt" ,"");
paramData.put("TaxFreeAmt" ,"");
paramData.put("MallUserId" ,"");
paramData.put("VerifyValue", VerifyValue);

// 날짜 생성 함수
public static String getyyyyMMddHHmmss() {
    /** yyyyMMddHHmmss Date Format */
    SimpleDateFormat yyyyMMddHHmmss = new SimpleDateFormat("yyyyMMddHHmmss");
    return yyyyMMddHHmmss.format(new Date());
}

// 암호화 함수
public static final synchronized 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;
}
		
	

STEP 2 HTTPS URL Call로 승인 요청 후 결과 받기
·JSP
        
// json 데이터 AES256 암호화
try {
    body.put("EncData", AES256Cipher.AES_Encode(paramData.toString(), merchantKey.substring(0,32)));
    body.put("Mid", Mid);
} 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;
}
		
	
(추가) 빌링결제 결과 VerifyValue 생성 규칙

결제결과 시 전달받는 VerifyValue 파라미터는 아래와 같은 규칙으로 생성됩니다.

·JSP
				
String Mid = request.getParameter("Mid");
String AuthDate = request.getParameter("AuthDate");
String AuthCode = request.getParameter("AuthCode");
String Amt = request.getParameter("Amt");
String BillTokenKey = request.getParameter("BillTokenKey");

String VerifyValue = encodeSHA256Base64(Mid + AuthDate + AuthCode + Amt + BillTokenKey);
			

빌링 키 삭제

빌링키 삭제 파라미터

파라미터 항목명 길이(char) 필수여부 설명
Mid 상점ID 10 필수
SspMallId 결제MALL ID 10 필수
BillTokenKey 고정식 토큰(빌링키) 50 필수
ServiceType 삭제 유형 2 선택 CD(기본값): 카드 삭제
MallUserId 회원사 고객 ID 20 필수
MallReserved 상점예비정보 100 선택 Base64 인코딩필요
(평문으로 전달시 한글 및 특수문자가 정상적으로 전달되지 않음)
VerifyValue 위·변조 검증값 50 필수 SHA256 해시 암호화
파라미터 항목명 길이(char) 설명
ResultCode 결과코드 10 성공: PD00, 실패: 그 외
ResultMsg 결과메시지 10
Tid 삭제거래 ID 30
MallReserved 상점예비정보 100

STEP 1 빌링키 삭제 파라미터 설정 및 UrlCall 삭제 요청하기
·JSP
        
String url = "https://tapproval.smartropay.co.kr/payment/approval/ssbdel.do";		// 테스트
// String url = "https://approval.smartropay.co.kr/payment/approval/ssbdel.do";		// 운영

JSONObject body = new JSONObject();
JSONObject paramData = new JSONObject();

String merchantKey = "";  				// 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
String Mid = "";    					// 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
String SspMallId = "SMTSSPAY0p";    	// 테스트용 SspMallId
String BillTokenKey = ""; 				// 빌링키 발급을 통해 생성된 키
// 검증값 SHA256 암호화(Mid + SspMallId + 빌링키)
String VerifyValue = encodeSHA256Base64(Mid +SspMallId+ BillTokenKey);

// 요청 파라미터 (각 값들은 가맹점 환경에 맞추어 설정해 주세요.)
paramData.put("ServiceType" ,"CD");
paramData.put("Mid" ,Mid);
paramData.put("BillTokenKey" ,BillTokenKey);   	
paramData.put("SspMallId" ,SspMallId);
paramData.put("MallUserId" ,"");
paramData.put("VerifyValue" ,VerifyValue);
		
	

STEP 2 빌링키 삭제 결과 받기
·JSP
        
// json 데이터 AES256 암호화
try {
    body.put("EncData", AES256Cipher.AES_Encode(paramData.toString(), merchantKey.substring(0,32)));
    body.put("Mid", Mid);
} 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;
}
		
	

SS-PAY 회원 삭제

(참고) SS-Pay 회원 삭제 안내 사항
SS-PAY 회원은 간편결제와 빌링결제 ID가 함께 관리되는 점에 유의하시기 바랍니다.
SS-PAY 회원 삭제 서비스 진행 시 두 서비스 ID가 동시에 삭제되므로 신중하게 사용해 주세요.

SS-Pay 회원 삭제 파라미터

파라미터 항목명 길이(char) 필수여부 설명
Mid 상점 아이디 10 필수
SspMallId 결제MALL ID 10 필수 발급받은 SspMallId
MallUserId 회원사 고객 ID 20 필수 고객 구분값
ServiceType 서비스 타입 2 필수 회원 삭제 : MD
VerifyValue 위·변조 검증값 가변 필수 SHA256 해시 암호화
MallReserved 상점예비정보 100 선택 Base64 인코딩필요
(평문으로 전달시 한글 및 특수문자가 정상적으로 전달되지 않음)
파라미터 항목명 길이(char) 설명
SspMallId 결제MALL ID 10
ResultCode 결과코드 10 성공: PD00, PS40
실패: 그 외
PD00 : 회원정보와 등록된 카드 정보 삭제
PS40 : 등록된 카드 정보가 없는 경우 회원 정보 삭제
ResultMsg 결과메시지 80
MallReserved 상점 예비필드 500 요청한 값 응답

STEP 1 SS-Pay 회원 삭제 요청 파라미터 설정하기
·JSP
        
        String url = "https://tapproval.smartropay.co.kr/payment/approval/ssbMemberDel.do";		// 테스트
        // String url = "https://approval.smartropay.co.kr/payment/approval/ssbMemberDel.do";		// 운영

        JSONObject body = new JSONObject();
        JSONObject paramData = new JSONObject();

        String merchantKey =" ";                         /// 발급받은 MerchantKey
        String Mid = "";    					// 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
        String SspMallId = " ";    	                    // 발급받은 SspMallId
        String MallUserID =" ";                         // 발급받은 MallUserID

        String VerifyValue = encodeSHA256Base64(Mid +SspMallId+MallUserID);

    // 요청 파라미터 (각 값들은 가맹점 환경에 맞추어 설정해 주세요.)
        paramData.put("Mid" ,Mid);
        paramData.put("SspMallId" ,SspMallId);
        paramData.put("MallUserId" ,MallUserID);
        paramData.put("VerifyValue" ,VerifyValue);
        paramData.put("ServiceType" ,"MD");

		
	


STEP 2 삭제 요청 및 결과 받기
·JSP
        
// json 데이터 AES256 암호화
try {
    body.put("EncData", AES256Cipher.AES_Encode(paramData.toString(), merchantKey.substring(0,32)));
    body.put("Mid", Mid);
} 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;
}
		
	

(추가) AES256 암호화 함수(AES256Cipher)

·JSP
※ 암호화 실행 중 Illegal key size 예외가 발생했을 경우 여기를 클릭해 주세요.
				
import org.apache.commons.codec.binary.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

public class AES256Cipher {

    public static byte[] ivBytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

    public static String AES_Encode(String str, String key)	throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException,
                        NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,	IllegalBlockSizeException, BadPaddingException {
        byte[] textBytes = str.getBytes("UTF-8");
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
        Cipher cipher = null;
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
        return Base64.encodeBase64String(cipher.doFinal(textBytes));
    }

    public static String AES_Decode(String str, String key, byte[] ivBytes)	throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException,
                        NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        byte[] textBytes =  Base64.decodeBase64(str.getBytes());
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        SecretKeySpec newKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
        return new String(cipher.doFinal(textBytes), "UTF-8");
    }

    public static String AES_Decode(String str, String key)	throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException,
                        NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,	IllegalBlockSizeException, BadPaddingException {
    return AES_Decode(str, key, ivBytes);
    }
}
			

(추가) 과세 및 비과세 직접 계산 방식

과세 및 비과세 필드를 직접 계산하는 가맹점일 경우 아래와 같은 방식으로 계산하세요.

		
// 총금액(Amt) = 과세금액(TaxAmt) + 부가세(VatAmt) + 비과세(TaxFreeAmt)

// 비과세(TaxFreeAmt) 금액이 0원일 경우
tmp = Amt / 1.1;
VatAmt = (long)Math.floor(Amt - tmp);  // 부가세 절사
TaxAmt = Amt - VatAmt
/**  예시 : 총금액(Amt:5000) = 과세금액(TaxAmt:4546) + 부가세(VatAmt:454) **/


// 비과세(TaxFreeAmt) 금액이 0원 이상일 경우
tmp = (Amt- TaxFreeAmt) / 1.1;
VatAmt = (long)Math.floor(Amt - tmp - TaxFreeAmt);  // 부가세 절사
TaxAmt = Amt - VatAmt - TaxFreeAmt
/**  예시 : 총금액(Amt:5000) = 과세금액(TaxAmt:4364) + 부가세(VatAmt:436)+ 비과세(TaxFreeAmt:200) **/

		
	
- 위의 계산방식은 일반 연동을 사용하며 부가세를 직접 계산하는 가맹점일 경우에 한합니다.
- 비과세 가맹점인 경우 비과세금액(TaxFreeAmt)이 총금액(Amt)과 일치해야 하며 과세(TaxAmt)와 부가세(VatAmt)는 0 으로 세팅
- 간편 연동을 사용하거나 직접 계산을 하지 않는 경우, 비과세 가맹점에는 해당되지 않습니다.
※ 부가세 계산방식을 자동 계산 방식으로 변경 희망하시는 경우, 영업 담당자에게 문의 부탁드립니다.

(참고) AES256 암호화 중 예외 발생 시 조치사항

'java.security.InvalidKeyException: Illegal key size' 라는 예외가 발생했을 경우 아래와 같이 해결해 주세요.

1. 현재 사용중인 Java 버전에 맞춰 Unlimited Strength 정책 파일을 다운받습니다.

2. 다운받은 파일의 local_policy.jar, US_export_policy.jar 파일을 <JAVA_HOME>/jre/lib/security/ 폴더로 옮겨 기존 정책을 덮어씌웁니다.
그러면 JCE로 사용 가능한 모든 암호화의 키 길이 제한이 해제됩니다.

※ 8u151 Release Notes에서는 해당 버전부터 별도의 다운로드 없이 Unlimited Strength 정책을 설정할 수 있게 추가 번들이 같이 제공됩니다.
해당 버전에서 정책 파일은 <JAVA_HOME>/jre/lib/security/policy 경로에 limited와 unlimited 폴더로 구성되며,
unlimited 설정은 <JAVA_HOME>/jre/lib/security/java.security 파일을 열어 crypto.policy=unlimited 부분의 주석 처리를 지워주면 제한 해제된 정책을 사용할 수 있습니다.

※ 변경된 기본 정책
2018년 1월 업데이트된 Java8u161 Release Notes에 따르면, Java8u161 버전부터는 JCE 기본 정책이 unlimited이며,
길이를 제한하고 싶다면 crypto.policy=unlimited 부분을 주석처리하면 됩니다.
Unlimited를 기본으로 사용하는 Java 버전은 'JDK-8170157 : Enable unlimited cryptographic policy by default in Oracle JDK builds'에서 확인할 수 있습니다.


(추가) 가상키패드 지원사양
서비스 이용시 정상적인 가상키패드 이용을 위한 지원 사양으로, 아래 명시된 사양보다 이전 버전인 경우 정상적으로 이용이 불가할 수 있습니다.
Web Browser : Internet Explorer 11이상, Internet Explorer Edge 25이상, Chrome 32 이상, Safari 7 이상 (Windows 버전 제외)
Android : 4.0 이상 (공식지원 브라우저 : Chrome, 삼성브라우저)
iOS : 8.0 이상 (공식지원 브라우저 : Chrome, Safari)
INDEX

FAQ
기술 지원 문의
1:1 문의는 아래 이메일로 보내주세요.
필요정보 Mid
Moid or Tid
거래 일시
: