hmk run dev
이니시스 모바일 결제 개발하기 본문
이니시스 모바일 결제를 달아보자!
JSP 환경에서 구현했습니다.
소스 코드 및 개발문서는 아래 링크에서 확인하세요 :)
https://manual.inicis.com/mobile/
테이블 구조
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/
@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";
}
}
'기타' 카테고리의 다른 글
ajax + 개발자 도구로 크롤링하기 (0) | 2021.12.10 |
---|---|
PL/SQL 계층형 테이블에서 부모 카테고리 번호 구하기 (0) | 2021.12.09 |
SPA 어플리케이션과 SSR프레임워크 & 코드스플리팅 (0) | 2021.12.07 |
이니시스 & 아임포트 결제 연동 (0) | 2021.11.11 |