[security]KVE-2026-0882 race condition 잔액 부족 시 결제 취소 처리로 변경
이전 커밋(e53689ac3)의 미수금 처리 방식은 사용자에게 결제 금액과 다른 청구가 발생해 혼란/분쟁을 유발할 수 있어, 동시 주문 race 로 포인트 잔액이 부족하면 결제 자체를 취소하는 방식으로 변경. - PG 결제가 진행된 경우 (\$tno 존재): cancel_pg.inc.php 로 환불 요청 - 장바구니 복구: 기존 line 839 동일 패턴 (od_id = tmp_cart_id, ct_status = '쇼핑') - 주문 삭제: g5_shop_order_table 에서 od_id 제거 - 사용자에게 die 로 명확한 오류 메시지 표시 lock timeout 케이스도 동일하게 결제 취소 처리 (보수적). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
56b1958d37
commit
4c00c60006
+27
-12
@@ -708,27 +708,42 @@ if(!$result) {
|
||||
if ($is_member && $od_receipt_point) {
|
||||
$point_lock_key = 'g5pt_order_'.md5($member['mb_id']);
|
||||
$lock_row = sql_fetch(" select get_lock('$point_lock_key', 5) as lk ");
|
||||
$lock_acquired = !empty($lock_row['lk']);
|
||||
$point_shortage = false;
|
||||
|
||||
if (!empty($lock_row['lk'])) {
|
||||
if ($lock_acquired) {
|
||||
$current_point = (int) get_point_sum($member['mb_id']);
|
||||
|
||||
if ($current_point >= $od_receipt_point) {
|
||||
insert_point($member['mb_id'], (-1) * $od_receipt_point, "주문번호 $od_id 결제");
|
||||
} else {
|
||||
// race condition 으로 잔액 부족 — 사용 가능한 만큼만 차감하고 부족분은 미수금 처리
|
||||
$actual_point = $current_point > 0 ? $current_point : 0;
|
||||
$shortage = $od_receipt_point - $actual_point;
|
||||
|
||||
if ($actual_point > 0) {
|
||||
insert_point($member['mb_id'], (-1) * $actual_point, "주문번호 $od_id 결제");
|
||||
}
|
||||
sql_query(" update {$g5['g5_shop_order_table']}
|
||||
set od_receipt_point = '$actual_point',
|
||||
od_misu = od_misu + '$shortage'
|
||||
where od_id = '$od_id' ");
|
||||
$point_shortage = true;
|
||||
}
|
||||
|
||||
sql_query(" do release_lock('$point_lock_key') ");
|
||||
} else {
|
||||
// lock timeout — 안전을 위해 결제 취소 처리
|
||||
$point_shortage = true;
|
||||
}
|
||||
|
||||
if ($point_shortage) {
|
||||
// race condition 으로 잔액 부족 — PG 환불 + 장바구니 복구 + 주문 삭제
|
||||
if ($tno) {
|
||||
$cancel_msg = '포인트 잔액 부족으로 결제 취소 (동시 주문 race)';
|
||||
include G5_SHOP_PATH.'/cancel_pg.inc.php';
|
||||
}
|
||||
|
||||
// 장바구니 복구 (기존 line 839 동일 패턴)
|
||||
sql_query(" update {$g5['g5_shop_cart_table']} set od_id = '$tmp_cart_id', ct_status = '쇼핑' where od_id = '$od_id' ", false);
|
||||
|
||||
// 주문 삭제
|
||||
sql_query(" delete from {$g5['g5_shop_order_table']} where od_id = '$od_id' ");
|
||||
|
||||
if (function_exists('add_order_post_log')) {
|
||||
add_order_post_log("동시 주문 race 로 인한 포인트 잔액 부족. 주문 $od_id 취소.");
|
||||
}
|
||||
|
||||
die('<p>회원님의 포인트 잔액이 부족하여 주문이 완료되지 않았습니다.</p><p>'.strtoupper($od_pg).'를 이용한 전자결제(신용카드, 계좌이체, 가상계좌 등)은 자동 취소되었습니다.</p>');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user