구분 | IP | 비고 |
---|---|---|
테스트 | 211.193.35.11 | STG |
운영 - 결제 | 211.193.35.20 | |
운영 - 재통보 | 211.193.35.216 211.193.35.217 |
재통보 서비스 사용시 |
발급 정책 | 옵션 |
---|---|
동일 카드 등록여부 |
거절
/
기등록 빌링키 정보 전달
/
삭제 후 신규 등록
/
미삭제 신규 등록
- 동일 카드 등록 여부 "거절" 설정 시 회원 기준 추가 카드 등록 미삭제 신규 등록 설정은 불가합니다. |
추가 카드 등록여부 | 거절 / 삭제 후 신규 등록 / 미삭제 신규 등록 |
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(기본값): 미사용 |
옵션 | 비고 |
---|---|
미사용 | 본인인증 성공 여부만 체크(default) |
성명 일치 | 본인인증 성명과 구매자명(BuyerName) 일치여부 확인 |
휴대폰번호 일치 | 본인인증 휴대폰 번호와 구매자 휴대폰번호(BuyerTel) 일치여부 확인 |
성명&휴대폰번호 일치 |
본인인증 성명과 구매자명(BuyerName) 일치 & 본인인증 휴대폰 번호와 구매자 휴대폰번호(BuyerTel) 일치 확인 |
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());
}
SmartroPAY 연동가이드
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 | 결제 요청 시 설정한 값 전달 |
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;
}
// 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
파라미터는 아래와 같은 규칙으로 생성됩니다.
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 |
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);
// 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 회원 삭제 파라미터
파라미터 | 항목명 | 길이(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 | 요청한 값 응답 |
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");
// 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;
}
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) **/
(참고) 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'에서 확인할 수 있습니다.