모듈 연동

스마트로페이 결제모듈 연동을 위한 가이드입니다
- 해당 메뉴얼의 Parameter 들은 가맹점에 통보 없이 응답값이 추가 될 수 있습니다. 응답값 추가도 고려하여 개발 진행하시길 권장합니다 .

간편결제(SS-Pay)

스마트로페이의 SS-Pay 간편결제 서비스 연동에 대한 안내입니다.
* 스마트로페이의 응답은 POST입니다. 연동 시 참고해 주세요.

스마트로페이 SERVER IP
스마트로페이 서비스 IP 정보입니다.
구분 IP 비고
테스트 211.193.35.11 STG
운영 - 결제 211.193.35.20
운영 - 재통보 211.193.35.215 재통보 서비스 사용시

상세 파라미터

파라미터 항목명 길이(char) 필수여부 설명
PayMethod 결제수단 10 필수 CARD: 신용카드
Mid 상점ID 10 필수
Amt 거래 금액 12 숫자만 가능, 문장부호 제외
Moid 상품주문번호 40 필수
MallUserId 회원사 고객 ID 20 필수 회원가입 시 고객 구분값으로 사용
GoodsName 상품명 40 필수
GoodsCnt 결제상품 개수 2 필수
MallReserved 상점예비정보 500 필수 Base64 인코딩필요
(평문으로 전달시 한글 및 특수문자가 정상적으로 전달되지 않음)
BuyerName 구매자명 30 필수
BuyerTel 구매자연락처 40 필수
BuyerEmail 구매자메일주소 60 필수
ReturnUrl 상점 결제결과 전송 URL 200 필수
EdiDate 전문생성일시 14 필수
EncryptData 암호화 데이터 필수 가변 위·변조 방지를 위해 전달
SspMallId 간편결제 가맹점 ID 10 필수 발급받은 SspMallId
PopCheck 팝카드 체크 유무 1 필수 Y: 체크, N: 미체크(기본값)
FnCd 카드사 코드 2 선택 통합코드조회 > 카드사코드 발급사코드로 호출
CardQuota 할부개월 2 선택 00: 일시불(기본값), 02, 03, ...
MallIp 상점 IP 20 선택 상점서버 IP
UserIp 고객 IP 20 선택 고객 IP
EncodingType 응답 Charset 6 선택 utf8(기본값), euckr
SkinColor UI 스타일 10 선택 RED(기본값), GREEN, BLUE, PURPLE
TaxCd 세금사용코드 1 선택 **: empty(기본값)
TaxAmt 과세 9 선택
TaxFreeAmt 비과세 9 선택
VatAmt 부가세 9 선택
파라미터 항목명 길이(char) 설명
PayMethod 지불수단 10 CARD
Mid 상점 ID 10
Amt 금액 12
GoodsName 상품명 40
Tid 거래번호 30
Moid 주문번호 100
BuyerName 구매자명 30
MallUserId 고객사회원ID 20 간편결제 고객 고유식별번호
AuthDate 승인일자 12 YYMMDDHHMMSS(형식)
AuthCode 승인번호 30
ResultCode 결과코드 4
ResultMsg 결과메시지 100
AppCardCode 발급사코드 2
AppCardName 발급사명 20
AcquCardCode 매입사코드 2
AcquCardName 매입사명 20
CardMerchantNo 카드사 가맹점번호 15
CardNum 카드번호 16 7~12자리 Masking 처리
MallReserved 상점예비정보 500
OPTIONS 본인인증 추가 검증 옵션
본인인증을 사용하는 경우 추가 검증 옵션을 사용할 수 있습니다.
가맹점 정책에 맞는 옵션을 선택하여 영업담당자에게 요청 주시길 바랍니다.
옵션 비고
미사용 본인인증 성공 여부만 체크(default)
성명 일치 본인인증 성명과 구매자명(BuyerName) 일치여부 확인
휴대폰번호 일치 본인인증 휴대폰 번호와 구매자 휴대폰번호(BuyerTel) 일치여부 확인
성명&휴대폰번호 일치 본인인증 성명과 구매자명(BuyerName) 일치 &
본인인증 휴대폰 번호와 구매자 휴대폰번호(BuyerTel) 일치 확인

샘플 소스
STEP 1 SS-Pay 결제요청 파라미터 설정

String Mid = "";                                                                                   // 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
String MerchantKey = "";                                                                  // 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
String EdiDate = getyyyyMMddHHmmss();
String Amt = "1004";
String EncryptData = encodeSHA256Base64(EdiDate + Mid + Amt + MerchantKey);
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 설정)
$MerchantKey = "";   // 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
$EdiDate = date("YmdHis");
$Amt = "1004";
$EncryptData = base64_encode(hash('sha256', $EdiDate.$Mid.$Amt.$MerchantKey, true));
$today = date("YmdHi");		// 현재일자. 캐시방지용으로 사용

Mid = ""			' 발급받은 테스트 Mid 설정(Real 전환 시 운영 Mid 설정)
MerchantKey = ""	' 발급받은 테스트 상점키 설정(Real 전환 시 운영 상점키 설정)
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)
Amt = "1004"
EncryptData = CryptoUtil.Sha256Encrypt(EdiDate & Mid & Amt & MerchantKey))
today = Year(Now()) & right("0"&Month(Now()),2) & right("0"&Day(Now()),2) & right("0"&Hour(Now()),2) & right("0"&Minute(Now()),2) 	' 현재일자. 캐시방지용으로 사용


// DLL 암호화 소스
using System;
using System.EnterpriseServices;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;

namespace SmartropayLib
{
	public class CryptoUtil : ServicedComponent
    {
        /// 
        /// SHA256 암호화
        /// 
        /// 문자열
        /// 암호화 문자열
        public string Sha256Encrypt(string text)
        {
            SHA256Managed sha256Managed = new SHA256Managed();
            byte[] encryptBytes = sha256Managed.ComputeHash(Encoding.UTF8.GetBytes(text));

            return Convert.ToBase64String(encryptBytes);
        }
    }
}

STEP 2 결제에 필요한 Form 데이터를 설정
                
<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: '/ssp/reqPay.do'
            });

            // 스마트로페이 간편결제 요청
            // PC 연동일 경우에만 Callback 함수를 구현합니다. (Mobile은 제외)
            smartropay.payment({
                FormId: 'tranMgr', 			// 폼ID
                Callback: function (res) {		// 인증/승인 분리일경우 콜백함수
                    // 승인호출
                    var approvalForm = document.approvalForm;
                    approvalForm.Tid.value = res.Tid;
                    approvalForm.TrAuthKey.value = res.TrAuthKey;
                    approvalForm.action = '가맹점 ReturnUrl';
                    approvalForm.submit();
                }
            });
        }
    </script>
</head>
<body>
    <form id="tranMgr" name="tranMgr" method="post">
        <!-- 각 값들을 가맹점에 맞게 설정해 주세요. -->
        <input type="text" name="PayMethod" value="CARD" placeholder=""/>
        <input type="text" name="GoodsCnt" maxlength="2" value="1" placeholder=""/>
        <input type="text" name="GoodsName" maxlength="40" value="거래 상품명" placeholder=""/>
        <input type="text" name="Amt" maxlength="12" value="설정한 Amt" placeholder=""/>
        <input type="text" name="Moid" maxlength="40" value="Moid_20210118154643" placeholder="특수문자 포함 불가"/>
        <input type="text" name="Mid" maxlength="10" value="설정한 Mid" placeholder=""/>
        <input type="text" name="PopCheck" maxlength="1" value="N" placeholder="Y or N"/>
        <input type="text" name="ReturnUrl" size="100" class="input" value="가맹점 ReturnUrl">
        <input type="text" name="MallUserId" maxlength="20" value="MallUserId" placeholder=""/>
        <input type="text" name="SspMallId" maxlength="20" value="SMTSSPAY0p" placeholder="테스트용 SspMallId"/>
        <input type="text" name="BuyerName" maxlength="30" value="구매자명" placeholder=""/>
        <input type="text" name="BuyerTel" maxlength="30" value="01099991111" placeholder=""/>
        <input type="text" name="BuyerEmail" maxlength="30" value="noname@smartro.co.kr" 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="EncryptData" maxlength="100" class="input" value="생성된 EncryptData"
               placeholder="위/변조방지 HASH 데이터">
        <input type="text" name="TransType" size="1" class="input" value="0">
        <input type="text" name="EncodingType" maxlength="14" value="" placeholder="utf-8 or euc-kr"/>
        <input type="text" name="EdiDate" maxlength="14" value="설정한 EdiDate" placeholder=""/>
        <button type="button" class="btn btn-primary" onclick="goPay();">결제하기</button>
    </form>

    <!-- PC 연동의 경우에만 아래 승인폼이 필요합니다. (Mobile은 제외) -->
    <form id="approvalForm" name="approvalForm" method="post">
        <input type="hidden" id="Tid" name="Tid"/>
        <input type="hidden" id="TrAuthKey" name="TrAuthKey"/>
    </form>
</body>
</html>
        

STEP 3 승인 요청 및 결과 받기
        
String url = "https://tapproval.smartropay.co.kr/payment/approval/urlCallApproval.do";		// 테스트
//String url = "https://approval.smartropay.co.kr/payment/approval/urlCallApproval.do";   	// 운영

String Tid       = request.getParameter("Tid")==null?"":request.getParameter("Tid");
String TrAuthKey = request.getParameter("TrAuthKey")==null?"":request.getParameter("TrAuthKey");

HashMap<String, Object> result = callApi(TrAuthKey , Tid, url);

public HashMap<String, Object> callApi(String TrAuthKey, String Tid, 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" );

    	JSONObject body = new JSONObject();
    	body.put("Tid" ,Tid);
    	body.put("TrAuthKey" ,TrAuthKey);

    	char[] bytes = body.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;
}
		
	
        
$url = "https://tapproval.smartropay.co.kr/payment/approval/urlCallApproval.do";	// 테스트 
//$url = "https://approval.smartropay.co.kr/payment/approval/urlCallApproval.do";	// 운영 
        
$approval_data = array(
	'Tid' => $_REQUEST['Tid'],
	'TrAuthKey' => $_REQUEST['TrAuthKey']
);

// json data
$json = json_encode($approval_data);

$http_status = 0;

// https 통신
$ret = Curl($url, $json, $http_status);

function Curl($url, $post_data, &$http_status, &$header = null) {

    $ch=curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_URL, $url);

    // post_data
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_HEADER, false);

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $response = curl_exec($ch);

    $body = null;
    // error
    if (!$response) {
        $body = curl_error($ch);
        // HostNotFound, No route to Host, etc  Network related error
        $http_status = -1;
        Log::error("CURL Error: = " . $body);
    } else {
       //parsing http status code
        $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if (!is_null($header)) {
            $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);

            $header = substr($response, 0, $header_size);
            $body = substr($response, $header_size);
        } else {
            $body = $response;
        }
    }
    curl_close($ch);
    return $body;
}
		
    
           
url = "https://tapproval.smartropay.co.kr/payment/approval/urlCallApproval.do" 	' 테스트
'url = "https://approval.smartropay.co.kr/payment/approval/urlCallApproval.do"	' 운영

Set json = jsObject()
json("Tid") = request("Tid")
json("TrAuthKey") = request("TrAuthKey")

result = sendPost(url, json)

Function sendPost(callUrl, objJson)

    Set httpRequest = Server.CreateObject("MSXML2.ServerXMLHTTP")
    httpRequest.open "POST", url, False
    httpRequest.setRequestHeader "Content-type","application/json"
	httpRequest.setRequestHeader "Accept","application/json"
    httpRequest.send objJson.jsString
    postResponse = httpRequest.ResponseText

	sendPost = postResponse
End Function
		
    

SS-PAY 회원 삭제

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

STEP 1 SS-Pay 회원 삭제 요청 파라미터 설정하기
        
        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 = "SMTPAY006m";    					// 발급받은 테스트 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 삭제 요청 및 결과 받기
        
 // 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 result = callApi(body, url);

    public static HashMap callApi(JSONObject json, String callUrl) {

        StringBuilder responseBody = null;
        HashMap 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;
    }
		
	

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