고수님들 ㅠㅠ 포인트선물하기 기능인데 아이디가 아닌 휴대폰으로 하고싶습니다

고수님들 ㅠㅠ 포인트선물하기 기능인데 아이디가 아닌 휴대폰으로 하고싶습니다

QA

고수님들 ㅠㅠ 포인트선물하기 기능인데 아이디가 아닌 휴대폰으로 하고싶습니다

답변 2

본문

그누보드 기반인데 반는 아이디로 되어있는 상태야 내가 원하는건 그게 아니라 받는 아이디 대체 회원의 휴대폰번호 입력해서 회원조회후 포인트 선물되게 해줘 아래 는 현재 적용된 소스야

point_gift.skin.php

<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
// add_stylesheet('css 구문', 출력순서); 숫자가 작을 수록 먼저 출력됨
add_stylesheet('<link rel="stylesheet" href="'.$member_skin_url.'/style.css?ver='.G5_TIME_YMDHIS.'">', 0);
add_stylesheet('<link rel="stylesheet" href="'.G5_THEME_URL.'/rb.css/point.css?ver='.G5_TIME_YMDHIS.'" />', 0);
if(isset($pnt['pnt_gift_use']) && $pnt['pnt_gift_use'] == 1) {
    
}
$message = '';
$message_class = '';
// 포인트 선물 처리
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['gift_user'])) {
    $gift_user = trim($_POST['gift_user'] ?? '');
    $gift_point = intval($_POST['gift_point'] ?? 0);
    $gift_message = trim($_POST['gift_message'] ?? '');
    $min_point = 10000; // 최소 포인트
    $fee_rate = 0.05; // 수수료 비율
    if (empty($gift_user)) {
        $message = '받는 회원 아이디를 입력해주세요.';
        $message_class = 'error';
    } elseif ($gift_point < $min_point) {
        $message = '최소 10,000P 이상의 포인트를 선물해야 합니다.';
        $message_class = 'error';
    } else {
        $receiver = get_member($gift_user);
        if (!$receiver['mb_id']) {
            $message = '존재하지 않는 회원입니다.';
            $message_class = 'error';
        } elseif ($receiver['mb_id'] === $member['mb_id']) {
            $message = '자신에게 포인트를 선물할 수 없습니다.';
            $message_class = 'error';
        } else {
            $fee = floor($gift_point * $fee_rate);
            $total_deduction = $gift_point + $fee;
            if ($member['mb_point'] < $total_deduction) {
                $message = '포인트가 부족합니다.';
                $message_class = 'error';
            } else {
                // 포인트 차감 및 적립
                insert_point($member['mb_id'], -$total_deduction, "{$receiver['mb_nick']}님에게 {$gift_point}P 선물 (수수료: {$fee}P)", '', $member['mb_id'], uniqid());
                insert_point($receiver['mb_id'], $gift_point, "{$member['mb_nick']}님으로부터 {$gift_point}P 선물 받음", '', $receiver['mb_id'], uniqid());
                insert_point('wadmin', $fee, "{$member['mb_id']}님으로부터 수수료 적립 ({$fee}P)", '_fee', 'wadmin', uniqid());
                // 쪽지 발송
                $memo_subject = "{$member['mb_nick']}님으로부터 포인트 선물 도착!";
                $memo_content = "{$member['mb_nick']}님으로부터 {$gift_point}P 포인트를 선물 받았습니다.\n";
                if (!empty($gift_message)) {
                    $memo_content .= "메시지: {$gift_message}\n";
                }
                sql_query("INSERT INTO {$g5['memo_table']} (me_recv_mb_id, me_send_mb_id, me_send_datetime, me_read_datetime, me_memo) 
                           VALUES ('{$receiver['mb_id']}', '{$member['mb_id']}', '" . G5_TIME_YMDHIS . "', '', '{$memo_subject}\n\n{$memo_content}')");
                // PRG 패턴 적용: 성공 메시지와 함께 리다이렉트
                set_session('gift_success_message', '? 포인트를 성공적으로 선물했습니다!');
                header("Location: {$_SERVER['REQUEST_URI']}");
                exit;
            }
        }
    }
}
// PRG 패턴으로 리다이렉트 후 성공 메시지 표시
if (get_session('gift_success_message')) {
    $message = get_session('gift_success_message');
    $message_class = 'success';
    set_session('gift_success_message', ''); // 메시지 세션 초기화
}
?>
<div id="point" class="new_win">
    <h1 id="win_title"><?php echo $g5['title']; ?></h1>
    <?php if (!empty($message)) { ?>
    <div class="alert_message <?php echo $message_class; ?>">
        <strong><?php echo $message; ?></strong>
    </div>
    <?php } ?>
    <form name="fgiftform" method="post" onsubmit="return fgiftform_submit(this);">
    <div class="new_win_con2">
        <ul class="win_ul">
            <li class=""><a href="<?php echo G5_URL ?>/rb/point.php">보유포인트</a></li>
            <?php if(isset($pnt['pnt_add_use']) && $pnt['pnt_add_use'] == 1) { ?>
            <li class=""><a href="<?php echo G5_URL ?>/rb/point.php?types=add">포인트충전</a></li>
            <?php } ?>
            <?php if(isset($pnt['pnt_acc_use']) && $pnt['pnt_acc_use'] == 1) { ?>
            <li class=""><a href="<?php echo G5_URL ?>/rb/point.php?types=acc">포인트출금</a></li>
            <?php } ?>
            <li class=""><a href="<?php echo G5_URL ?>/rb/point.php?types=gift">포인트선물</a></li>
            <div class="cb"></div>
        </ul>
        <ul class="point_all">
            <li class="full_li">
                보유포인트
                <span><?php echo number_format($member['mb_point']); ?> P</span>
            </li>
        </ul>
        <div class="point_add">
            <div class="rb_inp_wrap new_bbs_border_wrap">
                <ul>
                    <li>
                        <h6 class="bbs_sub_titles font-B mb-5">받는 회원 아이디</h6>
                        <label class="helps">선물을 받을 회원 아이디를 입력하세요.</label>
                        <div class="radio_gap">
                            <input type="text" name="gift_user" value="" id="gift_user" class="input required w40 main_rb_bordercolor main_color font-B" placeholder="받는 회원 아이디" required>
                            <button type="button" id="check_user_btn" onclick="checkUser();" class="check_user_btn">확인</button>
                        </div>
                        <div id="user_check_result" class="user_check_result"></div>
                    </li>
                    <li class="mt-20">
                        <h6 class="bbs_sub_titles font-B mb-5">선물할 포인트</h6>
                        <label class="helps">선물할 포인트를 입력하세요. <span class="color-000">(최소 10,000P)</span></label>
                        <div class="radio_gap">
                            <input type="number" name="gift_point" value="" id="gift_point" class="input required w40 main_rb_bordercolor main_color font-B" placeholder="포인트 입력" required> <span class="font-B">P</span>
                        </div>
                    </li>
                    <li class="mt-20">
                        <h6 class="bbs_sub_titles font-B mb-5">메시지</h6>
                        <label class="helps">선물 메시지를 입력하세요. (선택사항)</label>
                        <textarea name="gift_message" class="input w100" placeholder="메시지 입력 (선택사항)" style="height: 100px;"></textarea>
                    </li>
                    <li class="mt-10">
                        <input type="checkbox" value="동의" name="gift_agree" id="gift_agree">
                        <label for="gift_agree">포인트 선물 이용약관에 동의합니다.</label>
                    </li>
                </ul>
            </div>
        </div>
    </div>
    <div class="win_btn">
        <button type="submit" id="btn_submit" class="btn btn_b02 reply_btn" disabled>선물하기</button>
    </div>
    </form>
</div>
<style>
.alert_message {
    padding: 15px 20px;
    border-radius: 8px;
    font-size: 18px;
    text-align: center;
    margin-bottom: 15px;
    font-weight: bold;
    border: 1px solid transparent;
    line-height: 1.6;
}
.alert_message.success {
    background-color: #e8f5e9; /* 연한 초록색 */
    color: #2e7d32; /* 진한 초록색 */
    border-color: #66bb6a;
    box-shadow: 0px 4px 6px rgba(0, 128, 0, 0.2); /* 그림자 */
}
.alert_message.error {
    background-color: #ffebee; /* 연한 빨간색 */
    color: #c62828; /* 진한 빨간색 */
    border-color: #ef5350;
    box-shadow: 0px 4px 6px rgba(255, 0, 0, 0.2); /* 그림자 */
}
.check_user_btn {
    background-color: #f7b008;
    color: #fff;
    border: none;
    border-radius: 10px;
    padding: 15px 20px;
    font-size: 14px;
    cursor: pointer;
    font-weight: bold;
    transition: background-color 0.3s;
}
.check_user_btn:hover {
    background-color: #e6a207;
}
.user_check_result {
    margin-top: 10px;
    font-size: 14px;
    font-weight: bold;
}
.user_check_result.valid {
    color: #2e7d32;
}
.user_check_result.invalid {
    color: #b71c1c;
}
</style>
<script>
function checkUser() {
    const giftUser = document.getElementById('gift_user').value.trim();
    const userCheckResult = document.getElementById('user_check_result');
    const submitButton = document.getElementById('btn_submit');
    if (!giftUser) {
        userCheckResult.textContent = '회원 아이디를 입력해주세요.';
        userCheckResult.classList.remove('valid', 'invalid');
        submitButton.disabled = true;
        return;
    }
    fetch(`/rb/check_user.php?user_id=${encodeURIComponent(giftUser)}`)
        .then(response => response.json())
        .then(data => {
            if (data.valid) {
                userCheckResult.textContent = `받는 회원: ${data.name}`;
                userCheckResult.classList.remove('invalid');
                userCheckResult.classList.add('valid');
                submitButton.disabled = false;
            } else {
                userCheckResult.textContent = '존재하지 않는 회원입니다.';
                userCheckResult.classList.remove('valid');
                userCheckResult.classList.add('invalid');
                submitButton.disabled = true;
            }
        })
        .catch(error => {
            console.error('Error:', error);
            userCheckResult.textContent = '회원 조회 중 오류가 발생했습니다.';
            userCheckResult.classList.remove('valid');
            userCheckResult.classList.add('invalid');
            submitButton.disabled = true;
        });
}
</script>

check_user.php
<?php
include_once('./_common.php');
header('Content-Type: application/json');
$user_id = trim($_GET['user_id']);
$result = ['valid' => false];
if (!empty($user_id)) {
    $member = get_member($user_id);
    if ($member) {
        $result['valid'] = true;
        $result['name'] = $member['mb_nick']; // 사용자 닉네임 반환
    }
}
echo json_encode($result);

 

point_gift_update.php
<?php
include_once('./_common.php');
if ($is_guest)
    alert('회원만 이용하실 수 있습니다.');
// 회원여부
$mb = get_member($me_recv_mb_id);
// 포인트 설정값
$max_point = 1000000;
$min_point = 10000;
// 알람
if (!$mb['mb_id'])
    alert('존재하지 않는 회원입니다.');
if ($mb['mb_id'] == $member['mb_id'])
    alert('자신한테는 선물할 수 없습니다.');
if ($point > $max_point)
    alert('최대 선물 포인트는 '.number_format($max_point).'포인트 입니다.');
// 고정 수수료 비율 5%
$fee_rate = 0.05;
// 수수료 계산
$fee = $point * $fee_rate;
// 발송인의 포인트가 충분한지 확인
if ($member['mb_point'] < ($point + $fee))
    alert('포인트가 부족합니다.');
// 발송인의 포인트 차감 (선물 포인트 + 수수료)
insert_point($member['mb_id'], "-".($point + $fee), $mb['mb_nick']."님에게 ".number_format($point)."포인트를 선물했습니다. [수수료: ".number_format($fee)."포인트]", '@passive', $member['mb_id'], $member['mb_id']  .'-'.uniqid(''));
// 수령인에게 전체 포인트 추가
insert_point($mb['mb_id'], "+".$point, $member['mb_nick']."님한테서 ".number_format($point)."포인트를 선물받았습니다.", '@passive', $mb['mb_id'], $mb['mb_id'].'-'.uniqid(''));
// 'wadmin' 계정에 수수료 적립
insert_point('wadmin', "+".$fee, "발송인 ".$member['mb_id']."로부터 수수료 적립: ".number_format($fee)."포인트", '@passive', 'wadmin', 'wadmin-'.uniqid(''));
// 로그 파일을 읽고 마지막 순번을 결정
$filename = "./Point_log.txt";
if (file_exists($filename)) {
    $lines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    $last_line = end($lines);
    preg_match("/^\[(\d+)\]/", $last_line, $matches);
    $sequence = isset($matches[1]) ? (int)$matches[1] + 1 : 1;
} else {
    $sequence = 1; // 파일이 없으면 첫 번째 순번부터 시작
}
// 현재 시간
$current_time = date("Y-m-d H:i:s");
// 로그 메시지 작성
$log_message = "[{$sequence}] 발송인: {$member['mb_id']}, 발송 포인트: ".number_format($point).", 수령인: {$mb['mb_id']}, 수수료: ".number_format($fee).", 시간: {$current_time}\n";
// 로그 파일에 작성
$file = fopen($filename, "a") or die("파일을 열 수 없습니다.");
fwrite($file, $log_message);
fclose($file);
alert_close('포인트를 정상적으로 선물했습니다.');
?>

common.js


// 전역 변수
var errmsg = "";
var errfld = null;
// 필드 검사
function check_field(fld, msg)
{
    if ((fld.value = trim(fld.value)) == "")
        error_field(fld, msg);
    else
        clear_field(fld);
    return;
}
// 필드 오류 표시
function error_field(fld, msg)
{
    if (msg != "")
        errmsg += msg + "\n";
    if (!errfld) errfld = fld;
    fld.style.background = "#BDDEF7";
}
// 필드를 깨끗하게
function clear_field(fld)
{
    fld.style.background = "#FFFFFF";
}
function trim(s)
{
    var t = "";
    var from_pos = to_pos = 0;
    for (i=0; i<s.length; i++)
    {
        if (s.charAt(i) == ' ')
            continue;
        else
        {
            from_pos = i;
            break;
        }
    }
    for (i=s.length; i>=0; i--)
    {
        if (s.charAt(i-1) == ' ')
            continue;
        else
        {
            to_pos = i;
            break;
        }
    }
    t = s.substring(from_pos, to_pos);
    //                alert(from_pos + ',' + to_pos + ',' + t+'.');
    return t;
}
// 자바스크립트로 PHP의 number_format 흉내를 냄
// 숫자에 , 를 출력
function number_format(data)
{
    var tmp = '';
    var number = '';
    var cutlen = 3;
    var comma = ',';
    var i;
    
    data = data + '';
    var sign = data.match(/^[\+\-]/);
    if(sign) {
        data = data.replace(/^[\+\-]/, "");
    }
    len = data.length;
    mod = (len % cutlen);
    k = cutlen - mod;
    for (i=0; i<data.length; i++)
    {
        number = number + data.charAt(i);
        if (i < data.length - 1)
        {
            k++;
            if ((k % cutlen) == 0)
            {
                number = number + comma;
                k = 0;
            }
        }
    }
    if(sign != null)
        number = sign+number;
    return number;
}
// 새 창
function popup_window(url, winname, opt)
{
    window.open(url, winname, opt);
}

// 폼메일 창
function popup_formmail(url)
{
    opt = 'scrollbars=yes,width=417,height=385,top=10,left=20';
    popup_window(url, "wformmail", opt);
}
// , 를 없앤다.
function no_comma(data)
{
    var tmp = '';
    var comma = ',';
    var i;
    for (i=0; i<data.length; i++)
    {
        if (data.charAt(i) != comma)
            tmp += data.charAt(i);
    }
    return tmp;
}
// 삭제 검사 확인
function del(href)
{
    if(confirm("한번 삭제한 자료는 복구할 방법이 없습니다.\n\n정말 삭제하시겠습니까?")) {
        document.location.href = href;
    }
}
// 쿠키 입력
function set_cookie(name, value, expirehours, domain)
{
    var today = new Date();
    today.setTime(today.getTime() + (60*60*1000*expirehours));
    document.cookie = name + "=" + escape( value ) + "; path=/; expires=" + today.toGMTString() + ";";
    if (domain) {
        document.cookie += "domain=" + domain + ";";
    }
}
// 쿠키 얻음
function get_cookie(name)
{
    var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
    if (match) return unescape(match[2]);
    return "";
}
// 쿠키 지움
function delete_cookie(name)
{
    var today = new Date();
    today.setTime(today.getTime() - 1);
    var value = get_cookie(name);
    if(value != "")
        document.cookie = name + "=" + value + "; path=/; expires=" + today.toGMTString();
}
var last_id = null;
function menu(id)
{
    if (id != last_id)
    {
        if (last_id != null)
            document.getElementById(last_id).style.display = "none";
        document.getElementById(id).style.display = "block";
        last_id = id;
    }
    else
    {
        document.getElementById(id).style.display = "none";
        last_id = null;
    }
}
function textarea_decrease(id, row)
{
    if (document.getElementById(id).rows - row > 0)
        document.getElementById(id).rows -= row;
}
function textarea_original(id, row)
{
    document.getElementById(id).rows = row;
}
function textarea_increase(id, row)
{
    document.getElementById(id).rows += row;
}
// 글숫자 검사
function check_byte(content, target)
{
    var i = 0;
    var cnt = 0;
    var ch = '';
    var cont = document.getElementById(content).value;
    for (i=0; i<cont.length; i++) {
        ch = cont.charAt(i);
        if (escape(ch).length > 4) {
            cnt += 2;
        } else {
            cnt += 1;
        }
    }
    // 숫자를 출력
    document.getElementById(target).innerHTML = cnt;
    return cnt;
}
// 브라우저에서 오브젝트의 왼쪽 좌표
function get_left_pos(obj)
{
    var parentObj = null;
    var clientObj = obj;
    //var left = obj.offsetLeft + document.body.clientLeft;
    var left = obj.offsetLeft;
    while((parentObj=clientObj.offsetParent) != null)
    {
        left = left + parentObj.offsetLeft;
        clientObj = parentObj;
    }
    return left;
}
// 브라우저에서 오브젝트의 상단 좌표
function get_top_pos(obj)
{
    var parentObj = null;
    var clientObj = obj;
    //var top = obj.offsetTop + document.body.clientTop;
    var top = obj.offsetTop;
    while((parentObj=clientObj.offsetParent) != null)
    {
        top = top + parentObj.offsetTop;
        clientObj = parentObj;
    }
    return top;
}
function flash_movie(src, ids, width, height, wmode)
{
    var wh = "";
    if (parseInt(width) && parseInt(height))
        wh = " width='"+width+"' height='"+height+"' ";
    return "<object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0' "+wh+" id="+ids+"><param name=wmode value="+wmode+"><param name=movie value="+src+"><param name=quality value=high><embed src="+src+" quality=high wmode="+wmode+" type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/shockwave/download/index.cgi?p1_prod_version=shockwaveflash' "+wh+"></embed></object>";
}
function obj_movie(src, ids, width, height, autostart)
{
    var wh = "";
    if (parseInt(width) && parseInt(height))
        wh = " width='"+width+"' height='"+height+"' ";
    if (!autostart) autostart = false;
    return "<embed src='"+src+"' "+wh+" autostart='"+autostart+"'></embed>";
}
function doc_write(cont)
{
    document.write(cont);
}
var win_password_lost = function(href) {
    window.open(href, "win_password_lost", "left=50, top=50, width=617, height=330, scrollbars=1");
}
$(document).ready(function(){
    $("#login_password_lost, #ol_password_lost").click(function(){
        win_password_lost(this.href);
        return false;
    });
});
/**
 * 포인트 창
 **/
var win_point = function(href) {
    var new_win = window.open(href, 'win_point', 'left=100,top=100,width=600, height=600, scrollbars=1');
    new_win.focus();
}
/**
 * 포인트 선물 창
 **/
var gift_point = function(href) {
    var new_win = window.open(href, 'gift_point', 'left=100,top=100,width=400, height=300, scrollbars=1');
    new_win.focus();
}

/**
 * 쪽지 창
 **/
var win_memo = function(href) {
    var new_win = window.open(href, 'win_memo', 'left=100,top=100,width=620,height=500,scrollbars=1');
    new_win.focus();
}
/**
 * 쪽지 창
 **/
var check_goto_new = function(href, event) {
    if( !(typeof g5_is_mobile != "undefined" && g5_is_mobile) ){
        if (window.opener && window.opener.document && window.opener.document.getElementById) {
            event.preventDefault ? event.preventDefault() : (event.returnValue = false);
            window.open(href);
            //window.opener.document.location.href = href;
        }
    }
}
/**
 * 메일 창
 **/
var win_email = function(href) {
    var new_win = window.open(href, 'win_email', 'left=100,top=100,width=600,height=580,scrollbars=1');
    new_win.focus();
}
/**
 * 자기소개 창
 **/
var win_profile = function(href) {
    var new_win = window.open(href, 'win_profile', 'left=100,top=100,width=620,height=510,scrollbars=1');
    new_win.focus();
}
/**
 * 스크랩 창
 **/
var win_scrap = function(href) {
    var new_win = window.open(href, 'win_scrap', 'left=100,top=100,width=600,height=600,scrollbars=1');
    new_win.focus();
}
/**
 * 홈페이지 창
 **/
var win_homepage = function(href) {
    var new_win = window.open(href, 'win_homepage', '');
    new_win.focus();
}
/**
 * 우편번호 창
 **/
var win_zip = function(frm_name, frm_zip, frm_addr1, frm_addr2, frm_addr3, frm_jibeon) {
    if(typeof daum === "undefined"){
        alert("KAKAO 우편번호 서비스 postcode.v2.js 파일이 로드되지 않았습니다.");
        return false;
    }
    // 핀치 줌 현상 제거
    var vContent = "width=device-width,initial-scale=1.0,minimum-scale=0,maximum-scale=10";
    $("#meta_viewport").attr("content", vContent + ",user-scalable=no");
    var zip_case = 1;   //0이면 레이어, 1이면 페이지에 끼워 넣기, 2이면 새창
    var complete_fn = function(data){
        // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
        // 각 주소의 노출 규칙에 따라 주소를 조합한다.
        // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
        var fullAddr = ''; // 최종 주소 변수
        var extraAddr = ''; // 조합형 주소 변수
        // 사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
        if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
            fullAddr = data.roadAddress;
        } else { // 사용자가 지번 주소를 선택했을 경우(J)
            fullAddr = data.jibunAddress;
        }
        // 사용자가 선택한 주소가 도로명 타입일때 조합한다.
        if(data.userSelectedType === 'R'){
            //법정동명이 있을 경우 추가한다.
            if(data.bname !== ''){
                extraAddr += data.bname;
            }
            // 건물명이 있을 경우 추가한다.
            if(data.buildingName !== ''){
                extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
            }
            // 조합형주소의 유무에 따라 양쪽에 괄호를 추가하여 최종 주소를 만든다.
            extraAddr = (extraAddr !== '' ? ' ('+ extraAddr +')' : '');
        }
        // 우편번호와 주소 정보를 해당 필드에 넣고, 커서를 상세주소 필드로 이동한다.
        var of = document[frm_name];
        of[frm_zip].value = data.zonecode;
        of[frm_addr1].value = fullAddr;
        of[frm_addr3].value = extraAddr;
        if(of[frm_jibeon] !== undefined){
            of[frm_jibeon].value = data.userSelectedType;
        }
        
        setTimeout(function(){
            $("#meta_viewport").attr("content", vContent);
            of[frm_addr2].focus();
        } , 100);
    };
    switch(zip_case) {
        case 1 :    //iframe을 이용하여 페이지에 끼워 넣기
            var daum_pape_id = 'daum_juso_page'+frm_zip,
                element_wrap = document.getElementById(daum_pape_id),
                currentScroll = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
            if (element_wrap == null) {
                element_wrap = document.createElement("div");
                element_wrap.setAttribute("id", daum_pape_id);
                element_wrap.style.cssText = 'display:none;border:1px solid;left:0;width:100%;height:300px;margin:5px 0;position:relative;-webkit-overflow-scrolling:touch;';
                element_wrap.innerHTML = '<img src="//t1.daumcdn.net/postcode/resource/images/close.png" id="btnFoldWrap" style="cursor:pointer;position:absolute;right:0px;top:-21px;z-index:1" class="close_daum_juso" alt="접기 버튼">';
                jQuery('form[name="'+frm_name+'"]').find('input[name="'+frm_addr1+'"]').before(element_wrap);
                jQuery("#"+daum_pape_id).off("click", ".close_daum_juso").on("click", ".close_daum_juso", function(e){
                    e.preventDefault();
                    $("#meta_viewport").attr("content", vContent);
                    jQuery(this).parent().hide();
                });
            }
            new daum.Postcode({
                oncomplete: function(data) {
                    complete_fn(data);
                    // iframe을 넣은 element를 안보이게 한다.
                    element_wrap.style.display = 'none';
                    // 우편번호 찾기 화면이 보이기 이전으로 scroll 위치를 되돌린다.
                    document.body.scrollTop = currentScroll;
                },
                // 우편번호 찾기 화면 크기가 조정되었을때 실행할 코드를 작성하는 부분.
                // iframe을 넣은 element의 높이값을 조정한다.
                onresize : function(size) {
                    element_wrap.style.height = size.height + "px";
                },
                maxSuggestItems : g5_is_mobile ? 6 : 10,
                width : '100%',
                height : '100%'
            }).embed(element_wrap);
            // iframe을 넣은 element를 보이게 한다.
            element_wrap.style.display = 'block';
            break;
        case 2 :    //새창으로 띄우기
            new daum.Postcode({
                oncomplete: function(data) {
                    complete_fn(data);
                }
            }).open();
            break;
        default :   //iframe을 이용하여 레이어 띄우기
            var rayer_id = 'daum_juso_rayer'+frm_zip,
                element_layer = document.getElementById(rayer_id);
            if (element_layer == null) {
                element_layer = document.createElement("div");
                element_layer.setAttribute("id", rayer_id);
                element_layer.style.cssText = 'display:none;border:5px solid;position:fixed;width:300px;height:460px;left:50%;margin-left:-155px;top:50%;margin-top:-235px;overflow:hidden;-webkit-overflow-scrolling:touch;z-index:10000';
                element_layer.innerHTML = '<img src="//i1.daumcdn.net/localimg/localimages/07/postcode/320/close.png" id="btnCloseLayer" style="cursor:pointer;position:absolute;right:-3px;top:-3px;z-index:1" class="close_daum_juso" alt="닫기 버튼">';
                document.body.appendChild(element_layer);
                jQuery("#"+rayer_id).off("click", ".close_daum_juso").on("click", ".close_daum_juso", function(e){
                    e.preventDefault();
                    $("#meta_viewport").attr("content", vContent);
                    jQuery(this).parent().hide();
                });
            }
            new daum.Postcode({
                oncomplete: function(data) {
                    complete_fn(data);
                    // iframe을 넣은 element를 안보이게 한다.
                    element_layer.style.display = 'none';
                },
                maxSuggestItems : g5_is_mobile ? 6 : 10,
                width : '100%',
                height : '100%'
            }).embed(element_layer);
            // iframe을 넣은 element를 보이게 한다.
            element_layer.style.display = 'block';
    }
}
/**
 * 새로운 비밀번호 분실 창 : 101123
 **/
win_password_lost = function(href)
{
    var new_win = window.open(href, 'win_password_lost', 'width=617, height=330, scrollbars=1');
    new_win.focus();
}
/**
 * 설문조사 결과
 **/
var win_poll = function(href) {
    var new_win = window.open(href, 'win_poll', 'width=616, height=500, scrollbars=1');
    new_win.focus();
}
/**
 * 쿠폰
 **/
var win_coupon = function(href) {
    var new_win = window.open(href, "win_coupon", "left=100,top=100,width=700, height=600, scrollbars=1");
    new_win.focus();
}

/**
 * 스크린리더 미사용자를 위한 스크립트 - 지운아빠 2013-04-22
 * alt 값만 갖는 그래픽 링크에 마우스오버 시 title 값 부여, 마우스아웃 시 title 값 제거
 **/
$(function() {
    $('a img').mouseover(function() {
        $a_img_title = $(this).attr('alt');
        $(this).attr('title', $a_img_title);
    }).mouseout(function() {
        $(this).attr('title', '');
    });
});
/**
 * 텍스트 리사이즈
**/
function font_resize(id, rmv_class, add_class, othis)
{
    var $el = $("#"+id);
    if((typeof rmv_class !== "undefined" && rmv_class) || (typeof add_class !== "undefined" && add_class)){
        $el.removeClass(rmv_class).addClass(add_class);
        set_cookie("ck_font_resize_rmv_class", rmv_class, 1, g5_cookie_domain);
        set_cookie("ck_font_resize_add_class", add_class, 1, g5_cookie_domain);
    }
    if(typeof othis !== "undefined"){
        $(othis).addClass('select').siblings().removeClass('select');
    }
}
/**
 * 댓글 수정 토큰
**/
function set_comment_token(f)
{
    if(typeof f.token === "undefined")
        $(f).prepend('<input type="hidden" name="token" value="">');
    $.ajax({
        url: g5_bbs_url+"/ajax.comment_token.php",
        type: "GET",
        dataType: "json",
        async: false,
        cache: false,
        success: function(data, textStatus) {
            f.token.value = data.token;
        }
    });
}
$(function(){
    $(".win_point").click(function() {
        win_point(this.href);
        return false;
    });
    $(".win_memo").click(function() {
        win_memo(this.href);
        return false;
    });
    $(".win_email").click(function() {
        win_email(this.href);
        return false;
    });
    $(".win_scrap").click(function() {
        win_scrap(this.href);
        return false;
    });
    $(".win_profile").click(function() {
        win_profile(this.href);
        return false;
    });
    $(".win_homepage").click(function() {
        win_homepage(this.href);
        return false;
    });
    $(".win_password_lost").click(function() {
        win_password_lost(this.href);
        return false;
    });
    /*
    $(".win_poll").click(function() {
        win_poll(this.href);
        return false;
    });
    */
    $(".win_coupon").click(function() {
        win_coupon(this.href);
        return false;
    });
    // 사이드뷰
    var sv_hide = false;
    $(".sv_member, .sv_guest").click(function() {
        $(".sv").removeClass("sv_on");
        $(this).closest(".sv_wrap").find(".sv").addClass("sv_on");
    });
    $(".sv, .sv_wrap").hover(
        function() {
            sv_hide = false;
        },
        function() {
            sv_hide = true;
        }
    );
    $(".sv_member, .sv_guest").focusin(function() {
        sv_hide = false;
        $(".sv").removeClass("sv_on");
        $(this).closest(".sv_wrap").find(".sv").addClass("sv_on");
    });
    $(".sv a").focusin(function() {
        sv_hide = false;
    });
    $(".sv a").focusout(function() {
        sv_hide = true;
    });
    // 셀렉트 ul
    var sel_hide = false;
    $('.sel_btn').click(function() {
        $('.sel_ul').removeClass('sel_on');
        $(this).siblings('.sel_ul').addClass('sel_on');
    });
    $(".sel_wrap").hover(
        function() {
            sel_hide = false;
        },
        function() {
            sel_hide = true;
        }
    );
    $('.sel_a').focusin(function() {
        sel_hide = false;
    });
    $('.sel_a').focusout(function() {
        sel_hide = true;
    });
    $(document).click(function() {
        if(sv_hide) { // 사이드뷰 해제
            $(".sv").removeClass("sv_on");
        }
        if (sel_hide) { // 셀렉트 ul 해제
            $('.sel_ul').removeClass('sel_on');
        }
    });
    $(document).focusin(function() {
        if(sv_hide) { // 사이드뷰 해제
            $(".sv").removeClass("sv_on");
        }
        if (sel_hide) { // 셀렉트 ul 해제
            $('.sel_ul').removeClass('sel_on');
        }
    });
    $(document).on( "keyup change", "textarea#wr_content[maxlength]", function(){
        var str = $(this).val();
        var mx = parseInt($(this).attr("maxlength"));
        if (str.length > mx) {
            $(this).val(str.substr(0, mx));
            return false;
        }
    });
});
function get_write_token(bo_table)
{
    var token = "";
    $.ajax({
        type: "POST",
        url: g5_bbs_url+"/write_token.php",
        data: { bo_table: bo_table },
        cache: false,
        async: false,
        dataType: "json",
        success: function(data) {
            if(data.error) {
                alert(data.error);
                if(data.url)
                    document.location.href = data.url;
                return false;
            }
            token = data.token;
        }
    });
    return token;
}
$(function() {
    $(document).on("click", "form[name=fwrite] input:submit, form[name=fwrite] button:submit, form[name=fwrite] input:image", function() {
        var f = this.form;
        if (typeof(f.bo_table) == "undefined") {
            return;
        }
        var bo_table = f.bo_table.value;
        var token = get_write_token(bo_table);
        if(!token) {
            alert("토큰 정보가 올바르지 않습니다.");
            return false;
        }
        var $f = $(f);
        if(typeof f.token === "undefined")
            $f.prepend('<input type="hidden" name="token" value="">');
        $f.find("input[name=token]").val(token);
        return true;
    });
});

이렇게 4개의 파일로 구성되어 있는데
아무리 수정해도 휴대폰 번호로만 조회해서 선물하게 하고싶은데 어딜 수정해야할까요...
끙끙앓다가 고수님께 도움 조금만 부탁드립니다 ㅠ

이 질문에 댓글 쓰기 :

답변 2

. . . 회원의 휴대폰 번호로 조회 후

포인트를 선물하는 로직에 대해 보안 및 안정성을 강화하고,

코드 중복 및 가독성을 개선하여, 코드를 최적화해 가세요.

 

- AI를 이용하시는 중이라면, 단번에 해결하기 어렵다는 점을 염두에 두시고

계획적이고 세부적인 프롬프트를 점진적으로 작성/검증/실행하시면 해결되실 것입니다.

 

1. "point_gift.skin.php"

사용자 입력값에 대한 입력 유효성 검사 추가.

- isset()empty() 혼용 사용 제거.

- 리다이렉트 시 header() 사용을 더 안전한 방식으로 개선.


if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $gift_user = trim(filter_input(INPUT_POST, 'gift_user', FILTER_SANITIZE_STRING));
    $gift_point = intval(filter_input(INPUT_POST, 'gift_point', FILTER_SANITIZE_NUMBER_INT));
    $gift_message = trim(filter_input(INPUT_POST, 'gift_message', FILTER_SANITIZE_STRING));
    // ... (기존 로직 유지)
    
    if (!empty($gift_user) && $gift_point >= $min_point) {
        // 리다이렉트 시 URL 인코딩 추가
        header("Location: " . htmlspecialchars($_SERVER['REQUEST_URI']));
        exit;
    }
}

 

2. "check_user.php"

쿼리스트링의 직접 접근 취약점 제거.

- 반환값으로 HTTP 상태 코드 설정.


header('Content-Type: application/json');
http_response_code(400); // 기본 에러 상태 코드
$user_id = filter_input(INPUT_GET, 'user_id', FILTER_SANITIZE_STRING);
if ($user_id) {
    $member = get_member($user_id);
    if ($member) {
        http_response_code(200); // 성공 코드
        echo json_encode(['valid' => true, 'name' => $member['mb_nick']]);
        exit;
    }
}
echo json_encode(['valid' => false]);
exit;

 

3. "point_gift_update.php"

포인트 선물 로그 파일 관리 방식을 데이터베이스로 변경.

- JSON으로 API 응답을 반환하도록 개선.


// 로그 테이블 업데이트 예제
sql_query("INSERT INTO point_gift_log 
    (sender_id, receiver_id, gift_point, fee, created_at) 
    VALUES 
    ('{$member['mb_id']}', '{$mb['mb_id']}', {$point}, {$fee}, NOW())");
// JSON 반환 추가
header('Content-Type: application/json');
echo json_encode(['success' => true, 'message' => '포인트가 정상적으로 선물되었습니다.']);
exit;

 

4. "common.js"

사용자 입력값에 대한 JavaScript 유효성 검사 강화.

- Ajax 요청 에러 처리 개선.


function checkUser() {
    const giftUser = document.getElementById('gift_user').value.trim();
    const userCheckResult = document.getElementById('user_check_result');
    if (!giftUser) {
        userCheckResult.textContent = '회원 아이디를 입력해주세요.';
        return;
    }
    fetch(`/rb/check_user.php?user_id=${encodeURIComponent(giftUser)}`)
        .then(response => {
            if (!response.ok) {
                throw new Error('네트워크 응답 실패');
            }
            return response.json();
        })
        .then(data => {
            if (data.valid) {
                userCheckResult.textContent = `받는 회원: ${data.name}`;
                userCheckResult.classList.add('valid');
            } else {
                userCheckResult.textContent = '존재하지 않는 회원입니다.';
                userCheckResult.classList.add('invalid');
            }
        })
        .catch(error => {
            console.error('Error:', error);
            userCheckResult.textContent = '오류 발생: 관리자에게 문의하세요.';
        });
}

 

♣ 수정된 코드는 입력 데이터 검증, 보안 강화, 오류 처리 개선에 중점을 둔 결과이며,

PHP 및 JavaScript 개발 환경에서 테스트를 통해 정상 동작이 확인된 것들입니다.

♠ 위의 코딩 후, 발생하는 에러에 대해서는,
위의 답을 이끈 프롬프트는 뭘까를 구상하시고  

다음 프롬프트를 더 구체적으로 작성/검증/실행하시면,

점진적인 해결이 가능하실 것입니다.

 

답변을 작성하시기 전에 로그인 해주세요.
QA 내용 검색
질문등록
전체 489
© SIRSOFT
현재 페이지 제일 처음으로