오프라인 취소 연동

스마트로페이 오프라인 결제 취소 연동을 위한 가이드입니다
- 해당 메뉴얼의 Parameter 들은 가맹점에 통보 없이 응답값이 추가 될 수 있습니다. 응답값 추가도 고려하여 개발 진행하시길 권장합니다.
- 오프라인 PG 거래 취소 연동 가이드입니다.
- 온라인 PG 거래 취소 가이드는 이곳에서 확인해주세요.

오프라인 결제 취소

UrlCall 취소 연동
오프라인 결제 취소 연동에 대한 안내입니다.
스마트로페이 SERVER IP
스마트로페이 서비스 IP 정보입니다.
구분 IP 비고
테스트 211.193.35.11 STG
운영 - 결제 211.193.35.20
운영 - 재통보 211.193.35.216
211.193.35.217
재통보 서비스 사용시
파라미터 항목명 길이(char) 필수여부 설명
Mid Mid 10 필수 Cat ID 또는 PG Mid
Tid 거래번호 30 필수 취소할 거래의 Tid
EdiDate 전문전송일시 14 필수 YYYYMMDDHHmmss(형식)
TraceNo 전문추적번호 4 필수 0001 ~ 9999 (가맹점에서 정한 임의의 값으로 세팅 하지만 동일거래건의 부분취소시 중복되지 않도록 설정)
AppNo 카드사 승인번호 12 필수
AppDt 원거래 승인일자 8 필수 YYYYMMDD
CancelAmt 취소금액 12 필수 숫자만 가능, 문장부호 제외
CancelSvcAmt 취소봉사료 12 선택 숫자만 가능, 문장부호 제외
CancelVatAmt 취소부가세 12 선택 숫자만 가능, 문장부호 제외
PartialCancelCode 부분취소 여부 1 필수 0: 전체, 1: 부분
CurrencyCode 통화코드 3 필수 410 : 원화
CancelPwd 취소 패스워드 16 선택 해외카드 취소패스워드
파라미터 항목명 길이(char)
Tid 거래번호 30
Mid 상점아이디 10
ResultCode 결과코드 10
ResultMsg 취소메세지 100
Moid 주문번호 100
PTid 부분취소 Tid(원거래 Tid와 상이) 30
CancelAmt 취소금액 12
AppNo 카드사 승인번호 12
AppCardCode 발급사 코드 2
AppCardName 발급사 명 18
AcquCardCode 매입사 코드 2
AcquCardName 매입사 명 18
CardMerchantNo 카드사 가맹점 번호 15
AcquInfoCode 매입코드 (DDC 유무(1:유, 2:무 , 3:포인트) 4:EDC , 5:전자상품 가맹점 , 6: DESC , C : CDC 조회) 1
TraceNo 전문 추적 번호 4
TransactionNo 거래 고유 번호 12
TrDt 거래 일시 (YYYYMMDDhhmmssN (N 0:일요일 ~ 6:토요일)) 15
ResultType 응답 업무구분 코드 (0 :default,1: 전자상품권) 1

샘플 소스
STEP 1 취소 요청 데이터 설정하기.
·JSP
        
String url = "https://tapproval.smartropay.co.kr/payment/approval/offCancel.do";  		// 테스트
// String url = "https://approval.smartropay.co.kr/payment/approval/offCancel.do"; 	// 운영

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

String Tid = "";						// 취소 요청할 Tid 입력
String Mid = "";						// 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
String CancelAmt = "1004";				// 취소할 거래금액
String Edidate = "202301231120734";	    // 전문전송일시
String PartialCancelCode = "0";			// 0: 전체취소, 1: 부분취소
String AppNo = "1234567890";			// 카드사 승인번호
String AppDt = "20231231";				// 원거래 승인일자
String TraceNo = "0006";				// 전문추적번호
String CurrencyCode = "410";			// 통화코드
String CancelPwd = "9999";				// 취소비밀번호
String MerchantKey = "";  				// 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)

// 취소 요청 파라미터 셋팅
paramData.put("Tid", Tid);
paramData.put("Mid", Mid);   
paramData.put("CancelAmt", CancelAmt);
paramData.put("Edidate", Edidate);
paramData.put("PartialCancelCode", PartialCancelCode);
paramData.put("AppNo", AppNo);
paramData.put("AppDt", AppDt);
paramData.put("TraceNo", TraceNo);
paramData.put("CurrencyCode", CurrencyCode);
paramData.put("CancelPwd", CancelPwd);
		
	

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);
    }
}
			

(참고) 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'에서 확인할 수 있습니다.


INDEX

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