hmk run dev

이니시스 모바일 결제 개발하기 본문

기타

이니시스 모바일 결제 개발하기

hmk run dev 2022. 3. 16. 10:35

이니시스 모바일 결제를 달아보자!

 

JSP 환경에서 구현했습니다.

 

소스 코드 및 개발문서는 아래 링크에서 확인하세요 :)

 

https://manual.inicis.com/mobile/

 

KG INICIS MANUAL

호출URL : https://mobile.inicis.com/smart/payment/ HTTP Method : POST Accept-charset : EUC-KR INIpay Mobile WEB example language="javascript"> function on_pay() {  myform = document.mobileweb;  myform.action = "https://mobile.inicis.com/smart/payment/"

manual.inicis.com

테이블 구조 

w_payment  : 결제 메인 테이블 

- 결제정보(결제 타입, 날짜, 금액 등등... 저장)

 

w_work : 작업 메인 테이블

- 현재 근무 중인 회사 기준 작업 당 결제가 이뤄지고 있음(작업에 대한 정보 w_payment와 join 관계)

 

w_work_estimate : 견적서 테이블

- 작업에 대한 견적 저장 실제 결제금액 조정(작업에 대한 정보 w_work와 join 관계)

 

w_vbank : 가상계좌 테이블

- 가상계좌 결제방식 선택 시 가상계좌에 대한 정보 저장(w_payment와 join 관계)

 

이외 매출, 결제정보 히스토리 데이터가 들어가는 등등의 테이블을 사용했습니다.

 


 

플로우는 간단합니다.

1. 견적서에서 결제하기 클릭 > 결제 데이터 생성 w_payment 테이블에 결제대기인 상태로 삽입

2. 결제가 정상적으로 이뤄지고 이니시스에서  상태코드 "00"(정상)으로 내려옴

3. 정상처리코드일 경우 w_payment 테이블 결제상태를 결제완료로 수정하고 고객에게 리마인드 메세지 전송

(가상계좌 발급일 경우엔 가상계좌를 발급하고 w_vbank 테이블에 저장 이니시스 측에 가상계좌 생성 데이터를 전송한고 가상계좌 리마인드 메세지 전송)

 


견적서 화면

- 결제할 금액을 확인시키고 취소 or 결제하기 선택

- 결제하기 버튼 클릭 시 오른쪽 화면으로 전환

결제하기 클릭 시 화면

- x,xxx 원 결제하기 클릭시 결제 데이터가 결제대기인 상태로 w_payment로 삽입

결제 요청(request.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html> 
<head> 
<title>INIpay</title> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="inicis">
<meta property="og:title" content="inicis">
<meta property="og:url" content="">
<meta property="og:description" content="inicis Mobile">
<title>inicis</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script type="text/javascript" src="/static/external/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="/static/external/js/ui.js"></script>
	
<script language="javascript"> 

function on_pay() { // 함수 호출 > 서버 에러가 없을 시 이니시스 결제창 호출
	
	$.ajax({
        url: "/inicis/paycheck",
        type: "post",
        // work_no 
        data:  {
    		work_no : '${workData.work_no}', // 작업번호
    		estimate_no : '${estimateData.estimate_no}', // 견적서 번호 
    		total_pay_amount : '${estimateData.total_pay_amount }', // 결제할 금액 > 임의로 script 수정을 고려해 백엔드에서 데이터(금액, 고객정보 등등...) 검사 후 이니시스 결제창으로 전환 추천
    		pay_type_str : $('#pay-type').val() // 결제 타입
    	},
        success: function(resultData) {
        	console.log('resultData :: ',resultData)
        	if(resultData.result_code == "200"){
            	// 서버 에러가 없을 시 이니시스 페이지로 전환
        		myform = document.mobileweb; 
            	myform.action = "https://mobile.inicis.com/smart/payment/";
            	myform.target = "_self";
            	myform.submit(); 
        	} else {
        		alert('결제 에러')
        		return
        	}
        	
        },
        error: function(jqXHR, textStatus, errorThrown) {
           alert('결제 에러')
        }
	});  
	
}  

function comma(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

$(function () {
	
	console.log('개발환경 :: ',window.location.hostname)
	
	let p_mid;
	// 개발 환경에 따라 t_mid(결제 키) 설정
	if (window.location.hostname == 'localhost'){
		p_mid = "INIpayTest"
	} else {
		//
		p_mid = "real_inicis_key";

	}
	$('[name=P_MID]').val(p_mid);
	
	$('#pay-btn').val(comma(parseInt('${estimateData.total_pay_amount }')) +"원"+ " 결제하기");
	
    // 결제 완료 혹은 결제 중간 취소 시 이동페이지
	let next_url = window.location.origin + '/inicis/complete' + '?work_no='+'${workData.work_no}' + '&estimate_no=' + '${estimateData.estimate_no}'
	
    let vbank_url = window.location.origin + '/inicis/vbank'
	$('[name=P_NEXT_URL]').val(next_url)
	$('[name=P_NOTI_URL]').val(vbank_url)
	
	$('[name=P_AMT]').val(comma(parseInt('${estimateData.total_pay_amount }')));
})


</script> 
</head> 

<body>
<%-- ${workData } </br>
${estimateData }  --%>
<!-- 인코딩 euc-kr 필수 -->
<form name="mobileweb" method="post" accept-charset="euc-kr"> 
<!--*************************필수 세팅 부분************************************-->
<!-- 리턴받는 가맹점 URL 세팅 -->
<input type="hidden" name="P_NEXT_URL" value=""> 
 
<!-- 지불수단 선택 (신용카드,계좌이체,가상계좌,휴대폰) -->
<!-- <input type="text" name="P_INI_PAYMENT" value="CARD">  -->
<!-- 복합/옵션 파라미터 -->
<!-- <input type="hidden" name="P_RESERVED" value="twotrs_isp=Y&block_isp=Y&twotrs_isp_noti=N"> -->
 <!-- 에스크로옵션 : useescrow=Y -->
<!-- workerman_mid : MOIiworker  / test : INIpayTest -->
<input type="hidden" name="P_MID" value=""> <!-- 에스크로테스트 : iniescrow0, 모바일빌링(정기과금)은 별도연동필요  -->
<!-- 주문번호  unique -->
<input type="hidden" name="P_OID" value="${workData.p_oid }">  
<input type="hidden" name="P_GOODS" value="테스트상품"> 
<input type="hidden" name="P_AMT" value=""> 
<input type="hidden" name="P_UNAME" value="${workData.req_name }"> 

<!--*************************선택 필수 세팅 부분************************************--> 

<!-- 가상계좌 입금 노티 사용시 필수 -->
<input type="hidden" name="P_NOTI_URL" value="">  

<!-- 휴대폰결제 필수 [1:컨텐츠, 2:실물] -->
<input type="hidden" name="P_HPP_METHOD" value="1">  
<div id="wrap-content">
	<label for="pay-type" id="type-label">결제타입</label>
	<select name="P_INI_PAYMENT" id="pay-type">
		<option value="CARD">카드</option>
		<option value="BANK">실시간계좌이체</option>
		<option value="VBANK">가상계좌</option>
		<!-- <option value="MOBILE">휴대폰</option> -->
	</select>
	<input type="button" id="pay-btn" name="pay" value="" onclick="on_pay()" >
</div>
</form> 
</body>
</html>

 

Controller

/inicis/paycheck

-  결제 x,xxx원 결제하기 버튼 누를 시 결제 금액과 견적서 금액 비교검사 & w_payment 결제 데이터 삽입

@ResponseBody
@PostMapping(value="/paycheck")
public Map<String, Object> paycheck(
    @RequestParam Map<String, Object> param) throws Exception {

    Map<String, Object> result = new HashMap<String, Object>();

    Long workNo = Long.parseLong((String) param.get("work_no"));
    Long estimateNo = Long.parseLong((String) param.get("estimate_no"));
	
    WorkVO vo = new WorkVO();
    vo.setWork_no(workNo);
    vo.setEstimate_no(estimateNo);

    WorkVO workInfo	= workService.selectWorkInfo(vo);

    String total_pay_amount_str = (String) param.get("total_pay_amount");

    Double total_pay_amount = Double.parseDouble(total_pay_amount_str);
    Double total_est_amount = workInfo.getTotal_est_amount();

    String pay_type_str = param.get("pay_type_str") + "";

    // 결제할 금액과 견적서 금액 비교
    if(total_pay_amount.compareTo(total_est_amount) == 0) {	
        // w_payment_insert
        if (pay_type_str.equals("CARD")) { // 카드결제
            System.out.println("CARD");
            param.put("pay_type", "01");
        } else if (pay_type_str.equals("BANK")) { // 실시간 계좌이체 > 결제 절차중 어플 설치가 필수라 결제 방식 채택보류
            System.out.println("BANK");
            param.put("pay_type", "06"); // 계좌이체 코드 06
        } else if (pay_type_str.equals("VBANK")) { // 가상계좌
            System.out.println("VBANK");
            param.put("pay_type", "02");
        } 				
        workInfo.setPay_type(param.get("pay_type") + "");

        paymentService.insertPay(workInfo);
        result.put("result_code","200"); 
    } else { 
        result.put("result_code","99"); 
    }

    return result;
}

 

Service

insertPay - 견적서에서 결제하기 버튼 클릭 시 결제대기인 상태로 insert 

public void insertPay (WorkVO workInfo) {

    Long work_no = workInfo.getWork_no(); 
    Long estimate_no = workInfo.getEstimate_no(); 
    Long member_no = workInfo.getMember_no();
    String pay_type = workInfo.getPay_type();
    Double getTotal_est_amount = workInfo.getTotal_est_amount();


    Map<String, Object> param = new HashMap<String,Object>();
    //// 
    param.put("work_no", work_no);
    int isPay = paymentMapper.getPaymentCnt(param);

    PaymentVO payVO = new PaymentVO();

    payVO.setWork_no(work_no);
    payVO.setEstimate_no(estimate_no);
    payVO.setWork_no(work_no);
    payVO.setPay_type(pay_type);
    payVO.setTotal_pay_price(getTotal_est_amount);
    payVO.setPaid_amount(getTotal_est_amount);
    payVO.setStat(Constants.WORK_PAY_STAT_WAIT); // 결제대기 상태

    String ordno = System.currentTimeMillis()+""+work_no+StringUtil.replaceNull(workInfo.getMember_no()+"","");
    payVO.setOrd_no(ordno);		

    if (isPay > 0) { // 결제가 생성된 경우
        paymentMapper.updatePayment(payVO);
    } else { // 결제를 생성하는 경우
        paymentMapper.insertPayment(payVO);
    }	
}

 

 

 

이니시스 결제화면 & 결제완료 화면

 

 

결제 완료(complete.jsp)

- 결제완료 화면은 화면 로드 시 P_STATUS가 "00"(결제성공)일 때만  응답 데이터들을 백엔드로 보내줌

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="java.io.*" %>
<%@page import="java.util.HashMap"%>
<%@page import="org.apache.commons.httpclient.*" %>
<%@page import="org.apache.commons.httpclient.methods.*"%>
<%@page import="org.apache.commons.httpclient.methods.GetMethod"%>
<%@page import="org.apache.commons.httpclient.params.HttpMethodParams"%>

<%
request.setCharacterEncoding("euc-kr");

String P_STATUS =request.getParameter("P_STATUS");       // 인증 상태
String P_RMESG1 = request.getParameter("P_RMESG1");      // 인증 결과 메시지
String P_TID = request.getParameter("P_TID");                   // 인증 거래번호
String P_REQ_URL = request.getParameter("P_REQ_URL");    // 결제요청 URL
String P_NOTI = request.getParameter("P_NOTI");              // 기타주문정보

// 현재 url
String now_address = javax.servlet.http.HttpUtils.getRequestURL(request).toString();

String P_MID ;  

// 접속 환경이 local인 경우에만 test키 적용
if (now_address.contains("localhost")){
	P_MID = "INIpayTest";
} else {
	P_MID = "real_inicis_key";
}


String P_TYPE = request.getParameter("P_TYPE"); // 결제타입 

System.out.println("초기 데이터 확인 :: " + request);

// 가상계좌 데이터
String P_VACT_NUM = ""; // 가상계좌 사용 시 가상계좌번호
String P_VACT_DATE = ""; // 발급날짜
String P_VACT_TIME = ""; // 발급시간
String P_VACT_NAME = ""; // 계좌이름
String P_VACT_CODE = ""; // 은행코드


/*  
	결제타입 종류 
	신용카드(안심클릭,ISP)	CARD
	실시간계좌이체	BANK
	가상계좌(무통장입금)	VBANK
	휴대폰	MOBILE
	도서문화상품권	BCSH
	문화상품권	CULTURE
	해피머니상품권	HPMN
	전자지갑	EWALLET
	알리페이,페이팔 외 기타 ETC_
*/
	
// 승인요청을 위한 P_MID, P_TID 세팅


if(P_STATUS.equals("01")){ // 인증결과가 실패일 경우
	//out.print(P_RMESG1);
} else { 


// -------------------- 승인결과 수신 -------------------------------------------------
  
	byte[] responseBody = method.getResponseBody(); 
	String[] values = new String(responseBody).split("&"); 
	  
	for( int x = 0; x < values.length; x++ ) 
	  {
	   System.out.println(values[x]);
	   
	   String [] arr = values[x].split("=");
	   // 시각적으로 데이터를 확인하고 name을 선택자로 value를 가져오기 위해서 데이터들을 input 형태로 화면에 출력함
	   if (arr.length > 1 && arr[0] != null && arr[1] != null){
		   System.out.println("key : " + values[x].split("=")[0]);
		   System.out.println("value : " + values[x].split("=")[1]);
		   out.print( values[x].split("=")[0] +"<input type=hidden name=" +  values[x].split("=")[0] + " value=" +   values[x].split("=")[1]  + ">");
	   }
	   
	   // 가상계좌 
	   if (values[x].equals("P_TYPE=VBANK")){
		   P_TYPE = "VBANK";
	   } 
	   // 계좌이체
	   if (values[x].equals("P_TYPE=BANK")){
		   P_TYPE = "BANK";
	   } 
	   // 카드
	   if (values[x].equals("P_TYPE=CARD")){
		   P_TYPE = "CARD";
	   } 
	   
	   out.print("<div>"  + values[x]  + "</div>");  // 승인결과를 출력
	   out.print("<br>");
	   }
	
	    } catch (HttpException e) {
	      //out.print("Fatal protocol violation: " + e.getMessage());
	      e.printStackTrace();
	    } catch (IOException e) {
	      //out.print("Fatal transport error: " + e.getMessage());
	      e.printStackTrace();
	    } finally {
	      method.releaseConnection();
	    }  
	
	}
%>

<html> 
<head> 
<title>INIpay</title> 
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr"/> 
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="WORKERMAN">
<meta property="og:title" content="WORKERMAN">
<meta property="og:url" content="">
<meta property="og:description" content="WORKERMAN Mobile">
<title>WORKERMAN</title>
<!-- <link href="https://fonts.googleapis.com/css?family=Noto+Sans+KR:300,400,500,700|Roboto:400,500,700" rel="stylesheet">		
<link rel="stylesheet" type="text/css" href="/static/external/css/base.css">    
<link rel="stylesheet" type="text/css" href="/static/external/css/common.css">
<link rel="stylesheet" type="text/css" href="/static/external/css/content.css"> -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script type="text/javascript" src="/static/external/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="/static/external/js/ui.js"></script>
</head> 
<style>
	#spinner-wrap {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%); 
	}
</style>

<body>
<div>
	// DB에 데이터가 성공적으로 저장되기 전까지 스피너를 보여주고 창을 닫음
	<div id="spinner-wrap" class="spinner-border text-warning" role="status">
	  <span class="visually-hidden">Loading...</span>
	</div>
	<%-- ${pay_data}
	<br>
	${estimateData } --%>

	<%-- ${pay_data } --%>
	<%-- <input type="hidden" name="P_STATUS" value="<%=P_STATUS%>"/>
	<input type="hidden" name="P_RMESG1" value="<%=P_RMESG1%>"/>
	<input type="hidden" name="P_TID" value="<%=P_TID%>"/>
	<input type="hidden" name="P_REQ_URL" value="<%=P_REQ_URL%>"/>
	<input type="hidden" name="P_NOTI" value="<%=P_NOTI%>"/>
	<input type="hidden" name="P_MID" value="<%=P_MID%>"/>
	
	<input type="text" name="P_TYPE" value="<%=P_TYPE%>"/> --%>
	<input type="hidden" name="pay_type"  value="" />
	<!--  -->
	
	<!-- 테스트  -->
	<%-- <input type="text" name="P_STATUS" value="<%=P_STATUS%>"/>
	<input type="text" name="P_RMESG1" value="<%=P_RMESG1%>"/>
	<input type="text" name="P_TID" value="<%=P_TID%>"/>
	<input type="text" name="P_REQ_URL" value="<%=P_REQ_URL%>"/>
	<input type="text" name="P_NOTI" value="<%=P_NOTI%>"/>
	<input type="text" name="P_MID" value="<%=P_MID%>"/> --%>
</div> 

<script type="text/javascript">
	
	function approvalProc() {
		$.ajax({
	        url: "/inicis/approvalProc",
	        type: "post", 
	        data:  {
	    		work_no : '${pay_data.work_no}',
	    		pay_type: $('pay_type').val(),
	    		approval_no : '',
	    		work_no : '${pay_data.work_no}',
	    		work_id : '${pay_data.work_id}',
	    		income_name : '${pay_data.req_name}', // 추후 실제 결제자 이름으로 교체
	    		req_name: '${pay_data.req_name}', // 고객이름
	    		estimate_no : '${pay_data.estimate_no}', // 견적서번호
	    		pay_type : $('[name=pay_type]').val(), // 결제 타입
	    		//pay_bill_number :'${pay_data.req_hp}',
	    		buyer_hp: '${pay_data.req_hp}', // 고객 전화번호
	    		paid_amount : $('[name=P_AMT]').val(), 
	    		agency : $('[name=P_VACT_BANK_CODE]').val(), // 은행코드
	    		total_pay_price : '${estimateData.total_pay_amount}' // 결제금액
	    	},
	        success: function(resultData) {
	        	// 카카오 창 닫기 & 브라우저 닫기 - 운영 배포 시 주석해제
	    		location.href = "kakaotalk://inappbrowser/close";
				window.close();
	 		
	        },
	        error: function(jqXHR, textStatus, errorThrown) {
	        	alert('결제 에러')
	        }
		});  
	}
	
	
	
	$(function (){
		let p_status = $('[name=P_STATUS]').val();

		if(p_status == '00'){// 00 이외의 코드는 실패	배포 시 00으로 수정!!
			let pay_type = $('[name=P_TYPE]').val();
				
			if(pay_type == "VBANK"){
				alert('가상계좌 발급');
				$('[name=pay_type]').val('02');
				approvalProc();
			} else if (pay_type == "BANK"){
				alert('계좌이체');
				$('[name=pay_type]').val('06');
				approvalProc()
			} else if (pay_type == "CARD") {
				$('[name=pay_type]').val('01');
				alert('카드결제');
				approvalProc();
			} else {
				alert('결제오류');
			}		
		} else {
			// 결제실패일 경우 요청화면으로 다시 전환
			location.href = '/inicis/mobile_request?work_no='+ '${pay_data.work_no}'; 
		}
	}) 
</script>
</body>
</html>

 

Contoller

/inicis/approvalProc

- 데이터 형식을 맞추고 service호출

@RequestMapping(value="/approvalProc", method =RequestMethod.POST)
@ResponseBody
public String approvalProc(
        @RequestParam Map<String, Object> param,
        Map<String, Object> map,
        Model model,
        Locale locale) throws Exception {

    /**
     * 모든 결제 수단은 payment 생성
     * 결제상태 w_work에 반영
     *
     */
    String result = "00";

    try {
        // 견적서 데이터
        Map estimateInfoMap = paymentService.getEstimateInfo(param);
        Map workInfoMap =  workerManService.selectWork(param);

        param.put("buyer_hp", String.valueOf( param.get("buyer_hp" )).replace("-", "") );
        param.put("pay_bill_number", String.valueOf( param.get("pay_bill_number" )).replace("-", "") );
        param.put("estimate_no", estimateInfoMap.get("estimate_no"));
        param.put("paid_amount", StringUtil.getDoubleToString((double)estimateInfoMap.get("total_pay_amount")));
        //param.put("admin_no", getAdminno());
        param.put("req_hp", workInfoMap.get("req_hp"));
        param.put("work_id", workInfoMap.get("work_id"));
        param.put("req_name", workInfoMap.get("req_name"));

        paymentService.payProc(param);

        }catch(Exception e) {
            result = "99";
        }
    return result;
}

 

Service

payProc

public Map<String, Object> payProc(Map<String, Object> param) {
		
    String payType = String.valueOf(param.get("pay_type"));
    String payStat = "";
    String msg_temp_type = "";
    String msg_send_type = "";
    Map vbankResultMap = new HashMap();
    Map resultMap = new HashMap();
    // 결제수단별 처리
    if(payType.equals(Constants.WORK_PAY_TYPE_CARD)) { // 카드
        payStat = Constants.WORK_PAY_STAT_SUCCESS_NEW;
        msg_temp_type = "payment_card_info";
        msg_send_type = Constants.WORK_MSG_TMPL_TYPE_PUSH_AT;
    }else if(payType.equals(Constants.WORK_PAY_TYPE_BANK)) { // 가상계좌
        // 가상계좌 발급
        // vbankPayProc2 변경 예정 > vbankPayProc2 삭제
        vbankResultMap = vbankPayProc(param);
        if (vbankResultMap.getOrDefault("resultCode", "99").equals("00")) {
            param.put("approval_no", vbankResultMap.get("vacct"));
            payStat = Constants.WORK_PAY_STAT_WAIT;
            msg_temp_type = "payment_vbank_info";
            msg_send_type = Constants.WORK_MSG_TMPL_TYPE_PUSH_AT;
        } else {
            payStat = Constants.WORK_PAY_STAT_FAILED;
        }
    }else if(payType.equals(Constants.WORK_PAY_TYPE_CASH)) { // 현금
        payStat = Constants.WORK_PAY_STAT_SUCCESS_NEW;
        msg_temp_type = "payment_card_info";
        msg_send_type = Constants.WORK_MSG_TMPL_TYPE_PUSH_AT;
    }else if (payType.equals(Constants.WORK_PAY_TYPE_SERVICE)) { // 무료
        payStat = Constants.WORK_PAY_STAT_SUCCESS_NEW;
        msg_temp_type = "payment_card_info";
        msg_send_type = Constants.WORK_MSG_TMPL_TYPE_PUSH_AT;
    } else if (payType.equals(Constants.WORK_PAY_TYPE_REAL_TIME_ACCOUNT)) { // 실시간 계좌이체
        payStat = Constants.WORK_PAY_STAT_SUCCESS_NEW;
        msg_temp_type = "payment_card_info";
        msg_send_type = Constants.WORK_MSG_TMPL_TYPE_PUSH_AT;
    } else {
        payStat = Constants.WORK_PAY_STAT_FAILED;
    }

    if (!payStat.equals("99")) {
        //결제 테이블에 인서트
        Map payParamMap = new HashMap();
        payParamMap.put("ord_no","0");
        payParamMap.put("work_no",param.get("work_no"));
        payParamMap.put("pay_type",payType);
        payParamMap.put("total_pay_price",param.get("paid_amount"));
        payParamMap.put("paid_amount",param.get("paid_amount"));
        payParamMap.put("estimate_no",param.get("estimate_no"));
        payParamMap.put("approval_no",param.get("approval_no"));
        payParamMap.put("admin_no",param.get("admin_no"));
        payParamMap.put("stat",payStat);

        if(exsitPayment(param)) { // 결제 생성여부 w_payment 존재 유무에 따라 insert or update
            paymentMapper.updatePay(payParamMap);
        }else {
            paymentMapper.insertPay(payParamMap);
        }
        /*
         * w_payment_hist 저장 (결제 히스토리)
         */
        paymentMapper.insertPaymentHist(payParamMap);

        if(payType.equals("01")) {
            TimeZone tz = TimeZone.getDefault();
            Calendar cal = Calendar.getInstance(tz);
            java.util.Date date = cal.getTime();
            SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
            String now = formater.format(date);

            Map salesConfirParamMap = new HashMap();
            salesConfirParamMap.put("pay_no",payParamMap.get("pay_no") );
            salesConfirParamMap.put("pay_type",payType );
            salesConfirParamMap.put("admin_no",param.get("admin_no") );
            salesConfirParamMap.put("confirm_date",now );

            paymentMapper.insertSalesConfirm(salesConfirParamMap); // 매출 테이블에 결제건 insert
        }

        /* w_vbank pay_no 업데이트
         *
         */
        if(payType.equals("02")) {
            Map vbankParamMap = new HashMap();
            vbankParamMap.put("vbank_no",vbankResultMap.get("vbank_no"));
            vbankParamMap.put("pay_no",payParamMap.get("pay_no"));
        }

        /*	w_work 상태값 반영
         *  work_no
         *  work_stat
         *  pay_type
         *  pay_amount
         *  pay_admin_no
         *  pay_bill_number
         *  pay_bill_type
         */
        Map workParamMap = new HashMap();
        workParamMap.put("work_no",param.get("work_no"));
        workParamMap.put("work_stat",param.get("work_stat"));
        workParamMap.put("pay_type",payType);
        workParamMap.put("pay_stat",payStat);
        workParamMap.put("pay_amount",param.get("paid_amount"));
        workParamMap.put("pay_admin_no",param.get("admin_no"));
        workParamMap.put("pay_bill_number",param.get("pay_bill_number"));
        workParamMap.put("pay_bill_type",param.get("pay_bill_type"));
        paymentMapper.updateWorkInfo(workParamMap); // 결제 완료를 main 테이블인 w_work에도 반영

        /* 문자발송ID 생성
         *
         */
        long time = System.currentTimeMillis();
        SimpleDateFormat dayTime = new SimpleDateFormat("yyyymmddhhss");
        String cmId = dayTime.format(new Date(time))+String.valueOf( param.get("req_hp"));

        /* 문자 템플릿
         *
         */

        Map<String, Object> templParam = new HashMap<String, Object>();
        templParam = new HashMap<String, Object>();
        templParam.put("tmpl_type", msg_send_type);
        templParam.put("tmpl_gb", msg_temp_type);
        Map<String, Object>	tmplInfo = workerManMapper.selectMsgTemplate(templParam);

        String expireDate;
        try {
            expireDate = CommonDateUtil.formatDate(String.valueOf(vbankResultMap.get("validDate")), "yyyy-MM-dd HH:mm");
        } catch (ParseException | java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            expireDate = String.valueOf(vbankResultMap.get("validDate"));
        }
        DecimalFormat dc = new DecimalFormat("###,###,###,###");
        String payAmount = StringUtil.getMoneyFormat(String.valueOf(payParamMap.get("paid_amount")));
        String payName = String.valueOf(param.get("income_name"));
        String payTypeStr = "";
        String bankName = "";
        String callTo = String.valueOf(param.get("req_hp"));
        String callFrom = systemProp.getProperty("sms.send.hp");
        String senderKey = systemProp.getProperty("biz.at.key");
        String smsTxt = String.valueOf( tmplInfo.get("content") );
        String subject = String.valueOf( tmplInfo.get("title") );
        String atTmplCode =  String.valueOf( tmplInfo.get("at_tmpl_code") );
        if(payType.equals("01")) {
            payTypeStr = "신용카드";
            param.get("req_hp");
        }else if(payType.equals("02")) {
            payTypeStr = "가상계좌";
            bankName = String.valueOf(getCodeInfo("vacct_bank_code",String.valueOf(vbankResultMap.get("vacctBankCode"))).get("code_name"));
            callTo = String.valueOf(param.get("buyer_hp"));
        }else if(payType.equals("03")) {
            payTypeStr = "현금";
        }else if(payType.equals("04")) {
            payTypeStr = "무료";
        }

        smsTxt = smsTxt.replace("#{USER_NAME}", String.valueOf(param.get("req_name")));
        smsTxt = smsTxt.replace("#{WORK_NO}", String.valueOf(param.get("work_id")));
        smsTxt = smsTxt.replace("#{PAY_METHOD}", payTypeStr );
        smsTxt = smsTxt.replace("#{TTL_AMOUNT}", payAmount+"원" );
        smsTxt = smsTxt.replace("#{ACCOUNT_INFO}", bankName+" "+String.valueOf(param.get("approval_no")) );
        smsTxt = smsTxt.replace("#{ACCOUNT_NAME}", payName );
        smsTxt = smsTxt.replace("#{PAY_TL}", expireDate);


        //비즈뿌리오 테이블에 인서트 문자발송
        if(!payType.equals("04")) {	// 무료일땐 안내문자 안나감
            Map<String, Object> bizParam = new HashMap<String, Object>();

            if(payType.matches("02")) {
                /* set extra */
                String attachedFile = cmId+".json";
                String extra = "{\"extra\" : {\"title\" : \""+expireDate+"\"}}"; // extra

                /* file attachements */
                Map<String, Object> fileMap = new HashMap<String, Object>();
                fileMap.put("msgKey", attachedFile);
                fileMap.put("seq", "1");
                fileMap.put("type", "JSON");
                fileMap.put("contents", extra);
                workerManMapper.insertBizAttachements(fileMap);
                bizParam.put("attachedFile", attachedFile);
            }
            else if(payType.matches("05")) {
                /* set extra */
                String attachedFile = cmId+".json";
                String extra = "{\"extra\" : {\"title\" : \""+payAmount+"원\"}}"; // extra

                /* file attachements */
                Map<String, Object> fileMap = new HashMap<String, Object>();
                fileMap.put("msgKey", attachedFile);
                fileMap.put("seq", "1");
                fileMap.put("type", "JSON");
                fileMap.put("contents", extra);
                workerManMapper.insertBizAttachements(fileMap);
                bizParam.put("attachedFile", attachedFile);
            }

            bizParam.put("cmId", cmId);
            bizParam.put("callTo", callTo);
            bizParam.put("callFrom", callFrom);
            bizParam.put("smsTxt", smsTxt);
            bizParam.put("msgType", "6");
            bizParam.put("atTmplCode", atTmplCode);
            bizParam.put("subject", subject);
            bizParam.put("senderKey", senderKey);
            workerManMapper.insertBizMsg(bizParam);
        }
    }
    return resultMap;
}

 

가상계좌 발급일 경우

 

가상계좌 발급일 경우 절차가 더 붙는데 발급된 가상계좌 정보를 w_vbank에 삽입하고

inicis측에 가상계좌 데이터를 형식을 맞춰 post요청으로 전송해야 고객이 가상계좌에 입금 시 noti를 주는 것 같다( 확실 하진 않음... ) 

 

vbankPayProc

public Map<String, Object> vbankPayProc(Map<String, Object> param) {
		
    Date dateNow = new Date(System.currentTimeMillis()); // 현재시간을 가져와 Date형으로 저장한다//년월일시분초 14자리 포멧
    SimpleDateFormat fourteenFormat = new SimpleDateFormat("yyyyMMddHHmmss");
    int vbankIncomeInterval = 7;
    String type="Pay";
    String paymethod="Vacct";
    String timestamp=fourteenFormat.format(dateNow);
    String clientIp="192.0.0.1";
    String mid="real_inicis_key";

    String url = "company.com";
    String buyerEmail = "company@company.com";

    String bankCode = String.valueOf(param.get("agency"));

    String moid = (String) param.get("work_id");
    String goodName = (String) param.get("work_id");
    String buyerName = (String) param.get("req_name");
    String buyerTel = (String) param.get("pay_bill_number");
    String price = (String) param.get("paid_amount");
    String dtInput = DateUtil.add(dateNow,"yyyyMMdd",Calendar.DATE,vbankIncomeInterval) ;
    String tmInput = "2359";
    String nmInput = (String) param.get("income_name");

    //Hash 암호화
    String hashData = "";
    String key="123asd3215fjd4x"; 
     String data_hash=key+type+paymethod+timestamp+clientIp+mid+moid+price;
    try {
        hashData = makeSHA512(data_hash);
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

     // 전송 URL
    String APIURL="https://iniapi.inicis.com/api/v1/formpay"; // 전송 URL

    Map<String, String> vbankRequestParamMap = new HashMap<String, String>();
    vbankRequestParamMap.put("type", type);
    vbankRequestParamMap.put("paymethod", paymethod);
    vbankRequestParamMap.put("timestamp", timestamp);
    vbankRequestParamMap.put("clientIp", clientIp);
    vbankRequestParamMap.put("mid", mid);
    vbankRequestParamMap.put("url", url);
    vbankRequestParamMap.put("moid", moid);
    vbankRequestParamMap.put("goodName", goodName);
    vbankRequestParamMap.put("buyerName", buyerName);
    vbankRequestParamMap.put("buyerEmail", buyerEmail);
    vbankRequestParamMap.put("buyerTel", "");
    vbankRequestParamMap.put("price", price);
    vbankRequestParamMap.put("bankCode", bankCode);
    vbankRequestParamMap.put("dtInput", dtInput);
    vbankRequestParamMap.put("tmInput", tmInput);
    vbankRequestParamMap.put("nmInput", nmInput);
    vbankRequestParamMap.put("hashData", hashData);

	// 가상계좌 정보를 inicis측에 전송해 고객이 가상계좌 입금 시 notification을 받음
    String requestParam = Joiner.on("&").withKeyValueSeparator("=").join(vbankRequestParamMap);
    String resultJson = Utils.excutePost(APIURL ,requestParam, false);
    ObjectMapper mapper = new ObjectMapper();
    Map resultMap = new HashMap();
    try {
        resultMap = mapper.readValue(resultJson,Map.class);
        resultMap.put("income_name", nmInput);
        resultMap.put("use_yn", "Y" );
        // 
        Long pay_no = Long.parseLong(paymentMapper.getPaymentNo(param).get("pay_no") + "");
        String auth_date = (resultMap.get("authDate") + "") + (resultMap.get("authTime") + "");
        String valid_date = (resultMap.get("validDate") + "") + (resultMap.get("validTime") + "");

        resultMap.put("auth_date",auth_date );
        resultMap.put("valid_date",valid_date );
        resultMap.put("pay_no", pay_no);

        insertVbank(resultMap);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    // 채번정보 등록
    return  resultMap;
}

 

excutePost

post 요청 보내기 코드참고

public static String excutePost(String targetURL, String urlParameters, boolean isJson) {
    System.out.println("URL : "+targetURL);
    System.out.println("DATA : "+urlParameters);

    URL url;
    HttpURLConnection connection = null;
    try {
        // Create connection
        url = new URL(targetURL);
          connection = (HttpURLConnection)url.openConnection();
          connection.setRequestMethod("POST");
          connection.setRequestProperty("Content-Type", isJson ? "application/json" : "application/x-www-form-urlencoded");

          connection.setRequestProperty("Content-Length", "" + 
                   Integer.toString(urlParameters.getBytes().length));
          connection.setRequestProperty("Content-Language", "UTF-8");  

          connection.setUseCaches (false);
          connection.setDoInput(true);
          connection.setDoOutput(true);

        // Send request
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        wr.write( urlParameters.getBytes("UTF-8") );
        wr.flush();
        wr.close();

        // Get Response
        InputStream is = connection.getInputStream();

        //System.out.println(connection.getHeaderFields());

        BufferedReader rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));

        String line;
        StringBuffer response = new StringBuffer();
        while ((line = rd.readLine()) != null) {
            response.append(line);
            //response.append('\r');
        }
        rd.close();
        //System.out.println(response.toString());
        return response.toString();

    } catch (Exception e) {

        e.printStackTrace();
        return null;

    } finally {

        if (connection != null) {
            connection.disconnect();
        }
    }
}

 

 

 

 

 

가상계좌 리마인드 메세지 작성중....

 

참고

https://manual.inicis.com/vacct/

 

KG INICIS MANUAL

해당 가상계좌 입금통보 부분은 PC 가상계좌에 대한 내용이며, 모바일 가상계좌 입금통보 처리는 모바일새창에서 확인하시면 됩니다. 상점 입금통보 수신 페이지는 고객이 가상계좌이체 서비스

manual.inicis.com

@ResponseBody
	@RequestMapping(value="vbankIncome", method =RequestMethod.POST)
	public String vbankIncome(
        @RequestParam Map<String, Object> param,
        Locale locale,
        HttpServletRequest request,HttpServletResponse response) throws Exception {

    String clientIp = Utils.getIP(request);
    String result = "";
    List<String> pgIpList = new ArrayList<String>(Arrays.asList("203.238.37.15","39.115.212.9","183.109.71"));
    if(pgIpList.contains(clientIp)) {
        String noTid = String.valueOf(param.get("no_tid"));  // 거래TID
        String noOid = String.valueOf(param.get("no_oid"));// 상점주문번호
        String cdBank = String.valueOf(param.get("cd_bank"));// 은행코드
        String cdDeal = String.valueOf(param.get("cd_deal"));  // 거래취급 기관코드(실제입금은행)
        String dtTrans = String.valueOf(param.get("dt_trans")); // 금융기관 발생 거래일자
        String tmTrans = String.valueOf(param.get("tm_trans"));   // 금융기관 발생 거래시각
        String noVacct = String.valueOf(param.get("no_vacct"));   // 계좌번호
        String amtInput = String.valueOf(param.get("amt_input"));   // 입금금액
        String flgClose = String.valueOf(param.get("flg_close"));   // 마감구분(0:당일마감전, 1:당일마감후)
        String clClose = String.valueOf(param.get("cl_close"));  // 마감구분코드(0:당일마감전, 1:당일마감후)
        String typeMsg = String.valueOf(param.get("type_msg")); // 거래구분(0200:정상, 0400:취소)
        String nmInputbank = String.valueOf(param.get("nm_inputbank")); // 입금은행명
        String nmInput = String.valueOf(param.get("nm_input")); // 입금자명
        String dtInputstd = String.valueOf(param.get("dt_inputstd"));// 입금기준일자
        String dtCalculstd = String.valueOf(param.get("dt_calculstd"));   // 정산기준일자
        String dtTransbase = String.valueOf(param.get("dt_transbase")); // 거래기준일자
        String clTrans = String.valueOf(param.get("cl_trans"));  // 거래구분코드
        String clKor = String.valueOf(param.get("cl_kor"));  // 한글구분코드
        String dtCshr = String.valueOf(param.get("dt_cshr"));   // 현금영수증 발급일자
        String tmCshr = String.valueOf(param.get("tm_cshr")); // 현금영수증 발급시간
        String noCshrAppl = String.valueOf(param.get("no_cshr_appl"));   // 현금영수증 발급번호r
        String noCshrTid = String.valueOf(param.get("no_cshr_tid"));   // 현금영수증 발급TID

        Map vbankInfo = apiService.getVbankInfoByIncomeNoti(param);

        if(!vbankInfo.isEmpty()) {
            Map<String,Object> vbankParamMap = new HashMap<String,Object>();
            vbankParamMap.put("pay_no", vbankInfo.get("pay_no"));
            vbankParamMap.put("stat", "10");
            paymentService.updatePaymentSalesConfirm(vbankParamMap);
//	    		map.put("result","OK");
            result = "OK";
        }
    }

 

 

 

Comments