나이스페이 결제 검증 및 취소 처리 보강

(cherry picked from commit 1e03160280e0a6b23e9d4b01a8bd726bddccf2cd)
This commit is contained in:
thisgun
2026-08-24 07:44:22 +00:00
parent f4d184979f
commit f7106379b8
9 changed files with 174 additions and 85 deletions
+1 -1
View File
@@ -208,7 +208,7 @@ function is_cancel_shop_pg_order($od){
$is_od_pg_cancel = true;
}
if ($od['od_pg'] === 'nicepay' && in_array($od['od_settle_case'], array('계좌이체', '휴대폰'))) {
if ($od['od_pg'] === 'nicepay' && (in_array($od['od_settle_case'], array('계좌이체', '휴대폰')) || ($od['od_settle_case'] === '가상계좌' && $od['od_status'] === '주문'))) {
$is_od_pg_cancel = true;
}
+8 -1
View File
@@ -385,11 +385,18 @@ if (in_array($_POST['ct_status'], $status_cancel)) {
$tno = $od['od_tno'];
$cancelAmt = $od['od_receipt_price'];
$cancelAmt = (int)$od['od_receipt_price'];
if($od['od_settle_case'] == '가상계좌' && $od['od_status'] == '주문' && $cancelAmt == 0)
$cancelAmt = (int)$od['od_misu'];
// 0:전체 취소, 1:부분 취소(별도 계약 필요)
$partialCancelCode = 0;
if($cancelAmt <= 0) {
$pg_res_cd = '';
$pg_res_msg = '취소 요청금액이 없습니다.';
break;
}
include G5_SHOP_PATH.'/nicepay/cancel_process.php';
+50 -25
View File
@@ -16,10 +16,11 @@ $txTid = isset($_POST['TxTid']) ? clean_xss_tags($_POST['TxTid']) : ''; //
$authToken = isset($_POST['AuthToken']) ? clean_xss_tags($_POST['AuthToken']) : ''; // authentication TOKEN
$payMethod = isset($_POST['PayMethod']) ? clean_xss_tags($_POST['PayMethod']) : ''; // payment method
$mid = isset($_POST['MID']) ? clean_xss_tags($_POST['MID']) : ''; // merchant id
$moid = isset($_POST['Moid']) ? addslashes(clean_xss_tags(stripslashes($_POST['Moid']))) : ''; // order number
$amt = isset($_POST['Amt']) ? (int) preg_replace('/[^0-9]/', '', $_POST['Amt']) : 0; // Amount of payment
$reqReserved = isset($_POST['ReqReserved']) ? clean_xss_tags($_POST['ReqReserved']) : ''; // mall custom field
$netCancelURL = isset($_POST['NetCancelURL']) ? clean_xss_tags($_POST['NetCancelURL']) : ''; // netCancelURL
$moid = isset($_POST['Moid']) ? addslashes(clean_xss_tags(stripslashes($_POST['Moid']))) : ''; // order number
$amt = isset($_POST['Amt']) ? (int) preg_replace('/[^0-9]/', '', $_POST['Amt']) : 0; // Amount of payment
$reqReserved = isset($_POST['ReqReserved']) ? clean_xss_tags($_POST['ReqReserved']) : ''; // mall custom field
$netCancelURL = isset($_POST['NetCancelURL']) ? clean_xss_tags($_POST['NetCancelURL']) : ''; // netCancelURL
$Signature = isset($_POST['Signature']) ? clean_xss_tags($_POST['Signature']) : ''; // authentication signature
if (isset($pp['pp_id']) && $pp['pp_id']) { //개인결제
$session_order_id = get_session('ss_personalpay_id');
@@ -36,12 +37,19 @@ if ($default['de_nicepay_mid'] != $mid) {
alert("요청한 상점 mid와 설정된 mid가 틀리므로 결제를 진행할수 없습니다.", G5_SHOP_URL);
}
if ($order_price != $amt) {
alert("요청한 결제금액이 틀리므로 결제를 진행할수 없습니다.", G5_SHOP_URL);
}
// API CALL foreach example
if (! function_exists('jsonRespDump')) {
if ($order_price != $amt) {
alert("요청한 결제금액이 틀리므로 결제를 진행할수 없습니다.", G5_SHOP_URL);
}
// hex(sha256(AuthToken+MID+Amt+MerchantKey)), 위변조 검증 데이터
$authSignData = bin2hex(hash('sha256', $authToken. $default['de_nicepay_mid'] . $order_price . $default['de_nicepay_key'], true));
if ($Signature != $authSignData) {
alert("유효성 검증이 틀려서 결제를 진행할수 없습니다.");
}
// API CALL foreach example
if (! function_exists('jsonRespDump')) {
function jsonRespDump($resp){
$respArr = json_decode($resp);
foreach ( $respArr as $key => $value ){
@@ -97,26 +105,43 @@ if($authResultCode === "0000"){
// A000 : 휴대폰 소액결제 성공코드
// 7001 : 현금영수증
// https://developers.nicepay.co.kr/manual-auth.php
*/
$response = nicepay_reqPost($data, $nextAppURL);
$respArr = json_decode($response, true);
$ResultCode = nicepay_res('ResultCode', $respArr);
$ResultMsg = nicepay_res('ResultMsg', $respArr);
$tno = nicepay_res('TID', $respArr);
$amount = (int) nicepay_res('Amt', $respArr, 0);
*/
$response = nicepay_reqPost($data, $nextAppURL);
if (! $response) {
alert('응답이 없거나 잘못된 url 입니다.', G5_SHOP_URL);
}
$respArr = json_decode($response, true);
$ResultCode = nicepay_res('ResultCode', $respArr);
$ResultMsg = nicepay_res('ResultMsg', $respArr);
$tno = nicepay_res('TID', $respArr);
$amount = (int) nicepay_res('Amt', $respArr, 0);
$app_time = nicepay_res('AuthDate', $respArr);
$pay_method = nicepay_res('PayMethod', $respArr);
$od_app_no = $app_no = nicepay_res('AuthCode', $respArr); // 승인 번호 (신용카드, 계좌이체, 휴대폰)
$pay_type = $NICEPAY_METHOD[$pay_method];
// 승인된 코드가 아니면 결제가 되지 않게 합니다.
if (! in_array($ResultCode, array('3001', '4000', '4100', 'A000', '7001'))) {
alert($ResultMsg.' 코드 : '.$ResultCode, G5_SHOP_URL);
die();
}
if ($ResultCode == '3001') { // 신용카드
// 승인된 코드가 아니면 결제가 되지 않게 합니다.
if (! in_array($ResultCode, array('3001', '4000', '4100', 'A000', '7001'))) {
alert($ResultMsg.' 코드 : '.$ResultCode, G5_SHOP_URL);
die();
}
if ($amount != $order_price) {
if($amount > 0) {
$od_id = $moid;
$cancel_msg = '결제금액 불일치';
$cancelAmt = $amount;
$partialCancelCode = 0;
include G5_SHOP_PATH.'/nicepay/cancel_process.php';
}
alert("승인된 결제금액이 틀리므로 결제를 진행할수 없습니다.", G5_SHOP_URL);
}
if ($ResultCode == '3001') { // 신용카드
$card_cd = nicepay_res('CardCode', $respArr); // 카드사 코드
$card_name = nicepay_res('CardName', $respArr); // 카드 종류
+14
View File
@@ -244,6 +244,13 @@ if(!$result) {
case 'inicis':
include G5_SHOP_PATH.'/inicis/inipay_cancel.php';
break;
case 'nicepay':
$od_id = $pp['pp_id'];
$tno = $pp_tno;
$cancelAmt = (int)$pg_price;
$partialCancelCode = 0;
include G5_SHOP_PATH.'/nicepay/cancel_process.php';
break;
default:
include G5_SHOP_PATH.'/kcp/pp_ax_hub_cancel.php';
break;
@@ -288,6 +295,13 @@ if($pp_receipt_price > 0 && $pp['pp_id'] && $pp['od_id']) {
case 'inicis':
include G5_SHOP_PATH.'/inicis/inipay_cancel.php';
break;
case 'nicepay':
$od_id = $pp['pp_id'];
$tno = $pp_tno;
$cancelAmt = (int)$pg_price;
$partialCancelCode = 0;
include G5_SHOP_PATH.'/nicepay/cancel_process.php';
break;
default:
include G5_SHOP_PATH.'/kcp/pp_ax_hub_cancel.php';
break;
+25 -14
View File
@@ -2,23 +2,34 @@
include_once('./_common.php');
include_once(G5_SHOP_PATH.'/settle_nicepay.inc.php');
$orderNumber = get_session('ss_order_id');
if (! $orderNumber) {
$orderNumber = get_session('ss_personalpay_id');
}
$orderNumber = get_session('ss_order_id');
$is_personalpay_order = false;
if (! $orderNumber) {
$orderNumber = get_session('ss_personalpay_id');
$is_personalpay_order = true;
}
if (! ($default['de_pg_service'] == 'nicepay' && $orderNumber)){
die(json_encode(array('error'=>'올바른 방법으로 이용해 주십시오.')));
}
$price = preg_replace('#[^0-9]#', '', $_POST['price']);
$price = isset($_POST['price']) ? preg_replace('#[^0-9]#', '', $_POST['price']) : '';
if (strlen($price) < 1) {
die(json_encode(array('error'=>'가격이 올바르지 않습니다.')));
}
if ($is_personalpay_order) {
$pp_id = preg_replace('/[^0-9]/', '', get_session('ss_personalpay_id'));
$pp = sql_fetch(" select pp_id, pp_price from {$g5['g5_shop_personalpay_table']} where pp_id = '$pp_id' and pp_use = '1' ");
if (! (isset($pp['pp_id']) && $pp['pp_id']) || (int)$pp['pp_price'] !== (int)$price) {
die(json_encode(array('error'=>'가격이 올바르지 않습니다.')));
}
}
$ediDate = preg_replace('/[^0-9]/', '', G5_TIME_YMDHIS);
$hashString = bin2hex(hash('sha256', $ediDate.$default['de_nicepay_mid'].$price.$default['de_nicepay_key'], true));
if (strlen($price) < 1) {
die(json_encode(array('error'=>'가격이 올바르지 않습니다.')));
}
$ediDate = preg_replace('/[^0-9]/', '', G5_TIME_YMDHIS);
$hashString = bin2hex(hash('sha256', $ediDate.$default['de_nicepay_mid'].$price.$default['de_nicepay_key'], true));
die(json_encode(array('error'=>'', 'ediDate'=>$ediDate, 'SignData'=>$hashString)));
die(json_encode(array('error'=>'', 'ediDate'=>$ediDate, 'SignData'=>$hashString)));
+19 -7
View File
@@ -122,13 +122,25 @@ if($authResultCode === "0000"){
$pay_type = $NICEPAY_METHOD[$pay_method];
// 승인된 코드가 아니면 결제가 되지 않게 합니다.
if (! in_array($ResultCode, array('3001', '4000', '4100', 'A000', '7001'))) {
alert($ResultMsg.' 코드 : '.$ResultCode, G5_SHOP_URL);
die();
}
if ($ResultCode == '3001') { // 신용카드
if (! in_array($ResultCode, array('3001', '4000', '4100', 'A000', '7001'))) {
alert($ResultMsg.' 코드 : '.$ResultCode, G5_SHOP_URL);
die();
}
if ($amount != $order_price) {
if($amount > 0) {
$od_id = $moid;
$cancel_msg = '결제금액 불일치';
$cancelAmt = $amount;
$partialCancelCode = 0;
include G5_SHOP_PATH.'/nicepay/cancel_process.php';
}
alert("승인된 결제금액이 틀리므로 결제를 진행할수 없습니다.", G5_SHOP_URL);
}
if ($ResultCode == '3001') { // 신용카드
$card_cd = nicepay_res('CardCode', $respArr); // 카드사 코드
$card_name = nicepay_res('CardName', $respArr); // 카드 종류
+13 -11
View File
@@ -70,17 +70,19 @@ $buyerTel = $buyertel;// 구매자 전화번호
$useOpt = $useopt;// 현금영수증 발행용도 ("1" - 소비자 소득공제용, "2" - 사업자 지출증빙용)
$regNum = $reg_num;// 현금결제자 주민등록번호
$ediDate = preg_replace('/[^0-9]/', '', G5_TIME_YMDHIS);
// 04 (현금영수증), 01 (매체구분 일반), 시간정보 (12자리), 랜덤 4자리숫자
$tid = $default['de_nicepay_mid'].'04'.'01'.substr($ediDate, 2).rand(1000, 9999);
$signData = bin2hex(hash('sha256', $default['de_nicepay_mid'].$amt_tot.$ediDate.$od['od_id'].$default['de_nicepay_key'], true));
$ediDate = preg_replace('/[^0-9]/', '', G5_TIME_YMDHIS);
$moid = ($tx == 'personalpay') ? $od['pp_id'] : $od['od_id'];
$receipt_tax_free_amt = ($tx == 'personalpay') ? 0 : (int)$od['od_free_mny'];
// 04 (현금영수증), 01 (매체구분 일반), 시간정보 (12자리), 랜덤 4자리숫자
$tid = $default['de_nicepay_mid'].'04'.'01'.substr($ediDate, 2).rand(1000, 9999);
$signData = bin2hex(hash('sha256', $default['de_nicepay_mid'].$amt_tot.$ediDate.$moid.$default['de_nicepay_key'], true));
$data = array(
'MID' => $default['de_nicepay_mid'],
'TID' => $tid,
'EdiDate' => $ediDate,
'Moid' => $od['od_id'],
'MID' => $default['de_nicepay_mid'],
'TID' => $tid,
'EdiDate' => $ediDate,
'Moid' => $moid,
'SignData' => $signData,
'GoodsName' => iconv('utf-8', 'euc-kr', $goodName),
'ReceiptAmt' => $amt_tot,
@@ -89,7 +91,7 @@ $data = array(
'ReceiptSupplyAmt' => $supPrice,
'ReceiptVAT' => $tax,
'ReceiptServiceAmt' => $srcvPrice,
'ReceiptTaxFreeAmt' => (int)$od['od_free_mny'],
'ReceiptTaxFreeAmt' => $receipt_tax_free_amt,
'CharSet' => 'utf-8',
);
@@ -193,4 +195,4 @@ function showreceipt() // 현금 영수증 출력
</div>
<?php
include_once(G5_PATH.'/tail.sub.php');
include_once(G5_PATH.'/tail.sub.php');
+14
View File
@@ -222,6 +222,13 @@ if(!$result) {
case 'inicis':
include G5_SHOP_PATH.'/inicis/inipay_cancel.php';
break;
case 'nicepay':
$od_id = $pp['pp_id'];
$tno = $pp_tno;
$cancelAmt = (int)$pg_price;
$partialCancelCode = 0;
include G5_SHOP_PATH.'/nicepay/cancel_process.php';
break;
default:
include G5_SHOP_PATH.'/kcp/pp_ax_hub_cancel.php';
break;
@@ -266,6 +273,13 @@ if($pp_receipt_price > 0 && $pp['pp_id'] && $pp['od_id']) {
case 'inicis':
include G5_SHOP_PATH.'/inicis/inipay_cancel.php';
break;
case 'nicepay':
$od_id = $pp['pp_id'];
$tno = $pp_tno;
$cancelAmt = (int)$pg_price;
$partialCancelCode = 0;
include G5_SHOP_PATH.'/nicepay/cancel_process.php';
break;
default:
include G5_SHOP_PATH.'/kcp/pp_ax_hub_cancel.php';
break;
+30 -26
View File
@@ -47,33 +47,37 @@ if (in_array($_SERVER['REMOTE_ADDR'], $pg_allow_ips)) {
$result = false;
$receipt_time = preg_replace("/([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/", "\\1-\\2-\\3 \\4:\\5:\\6", $AuthDate);
if($row['pp_id']) {
// 개인결제 UPDATE
$sql = " update {$g5['g5_shop_personalpay_table']}
set pp_receipt_price = '$Amt',
pp_receipt_time = '$receipt_time'
where pp_id = '$MOID'
and pp_app_no = '$VbankNum' ";
$result = sql_query($sql, false);
if($row['pp_id']) {
// 개인결제 UPDATE
$sql = " update {$g5['g5_shop_personalpay_table']}
set pp_receipt_price = '$Amt',
pp_receipt_time = '$receipt_time'
where pp_id = '$MOID'
and pp_app_no = '$VbankNum' ";
$result = sql_query($sql, false);
if($row['od_id']) {
// 주문서 UPDATE
$sql = " update {$g5['g5_shop_order_table']}
set od_receipt_price = od_receipt_price + '$Amt',
od_receipt_time = '$receipt_time',
od_shop_memo = concat(od_shop_memo, \"\\n개인결제 ".$row['pp_id']." 로 결제완료 - ".$receipt_time."\")
where od_id = '{$row['od_id']}' ";
$result = sql_query($sql, FALSE);
}
} else {
// 주문서 UPDATE
$sql = " update {$g5['g5_shop_order_table']}
set od_receipt_price = '$Amt',
od_receipt_time = '$receipt_time'
where od_id = '$MOID'
and od_app_no = '$VbankNum' ";
$result = sql_query($sql, FALSE);
}
if($row['od_id']) {
// 주문서 UPDATE
$sql = " update {$g5['g5_shop_order_table']}
set od_receipt_price = od_receipt_price + '$Amt',
od_receipt_time = '$receipt_time',
od_shop_memo = concat(od_shop_memo, \"\\n개인결제 ".$row['pp_id']." 로 결제완료 - ".$receipt_time."\")
where od_id = '{$row['od_id']}'
and od_status = '주문'
and od_cancel_price = '0' ";
$result = sql_query($sql, FALSE);
}
} else {
// 주문서 UPDATE
$sql = " update {$g5['g5_shop_order_table']}
set od_receipt_price = '$Amt',
od_receipt_time = '$receipt_time'
where od_id = '$MOID'
and od_app_no = '$VbankNum'
and od_status = '주문'
and od_cancel_price = '0' ";
$result = sql_query($sql, FALSE);
}
if($result) {
if ($row['od_id'])