diff --git a/adm/admin.js b/adm/admin.js index f6c0563c1..7ce8677f4 100644 --- a/adm/admin.js +++ b/adm/admin.js @@ -1,11 +1,115 @@ -function check_all(f) -{ - var chk = document.getElementsByName("chk[]"); +/** 공통 UI 모듈 */ +window.CommonUI = { + bindTabs(tabSelector, contentSelector, options = {}) { + const tabs = document.querySelectorAll(tabSelector); + const contents = document.querySelectorAll(contentSelector); - for (i=0; i { + tab.addEventListener('click', () => { + const tabName = tab.dataset.tab; + const target = document.getElementById(`tab-${tabName}`); + + tabs.forEach(t => t.classList.remove('active')); + tab.classList.add('active'); + + contents.forEach(c => c.classList.add('is-hidden')); + + if (target) target.classList.remove('is-hidden'); + + options.onChange?.(tabName, target); + }); + }); + } +}; + +function setHtml(el, markup) { + if (!el) return; + if (markup == null || markup === '') { + el.textContent = ''; + return; + } + const range = document.createRange(); + range.selectNodeContents(el); + el.replaceChildren(range.createContextualFragment(markup)); } +/** 팝업 관리 모듈 */ +window.PopupManager = { + open(id, options = {}) { + const el = document.getElementById(id); + if (el) { + el.classList.remove('is-hidden'); + this.bindOutsideClickClose(id); + + if (!options.disableOutsideClose) { + this.bindOutsideClickClose(id); + } else { + this.unbindOutsideClickClose(id); + } + } + }, + + close(id) { + const el = document.getElementById(id); + if (el) el.classList.add('is-hidden'); + }, + + toggle(id) { + const el = document.getElementById(id); + if (el) el.classList.toggle('is-hidden'); + }, + + bindOutsideClickClose(id) { + const el = document.getElementById(id); + if (!el) return; + el.onclick = () => this.close(id); + }, + + unbindOutsideClickClose(id) { + const el = document.getElementById(id); + if (!el) return; + el.onclick = null; + }, + + /** + * 팝업 콘텐츠 렌더링 (타이틀, 바디, 푸터 구성) + * @param {string} title - 팝업 제목 + * @param {string} body - 팝업 본문 HTML + * @param {string} [footer] - 푸터 HTML + * @param {object} [options] - 팝업 열기 옵션 + */ + render(title, body, footer = '', options = {}) { + const titleEl = document.getElementById('popupTitle'); + const bodyEl = document.getElementById('popupBody'); + const footerEl = document.getElementById('popupFooter'); + + if (titleEl) titleEl.textContent = title; + if (bodyEl) setHtml(bodyEl, body); + if (footerEl) setHtml(footerEl, footer); + + this.open('popupOverlay', options); + } +}; + +/** 형식 체크 */ +function check_all(target) { + const chkboxes = document.getElementsByName("chk[]"); + let chkall; + + if (target && target.tagName === "FORM") { + chkall = target.querySelector('input[name="chkall"]'); + } else if (target && target.type === "checkbox") { + chkall = target; + } + + if (!chkall) return; + + for (const checkbox of chkboxes) { + checkbox.checked = chkall.checked; + } +} + + function btn_check(f, act) { if (act == "update") // 선택수정 diff --git a/adm/admin.menu100.php b/adm/admin.menu100.php index 3cd9bfb22..8363f0af0 100644 --- a/adm/admin.menu100.php +++ b/adm/admin.menu100.php @@ -11,6 +11,7 @@ $menu['menu100'] = array( array('100900', '캐시파일 일괄삭제', G5_ADMIN_URL . '/cache_file_delete.php', 'cf_cache', 1), array('100910', '캡챠파일 일괄삭제', G5_ADMIN_URL . '/captcha_file_delete.php', 'cf_captcha', 1), array('100920', '썸네일파일 일괄삭제', G5_ADMIN_URL . '/thumbnail_file_delete.php', 'cf_thumbnail', 1), + array('100930', '회원관리파일 일괄삭제', G5_ADMIN_URL . '/member_list_file_delete.php', 'cf_memberlist', 1), array('100500', 'phpinfo()', G5_ADMIN_URL . '/phpinfo.php', 'cf_phpinfo') ); diff --git a/adm/admin.menu200.php b/adm/admin.menu200.php index 617d25638..1f3191072 100644 --- a/adm/admin.menu200.php +++ b/adm/admin.menu200.php @@ -2,6 +2,7 @@ $menu['menu200'] = array( array('200000', '회원관리', G5_ADMIN_URL . '/member_list.php', 'member'), array('200100', '회원관리', G5_ADMIN_URL . '/member_list.php', 'mb_list'), + array('200400', '회원관리파일', G5_ADMIN_URL . '/member_list_exel.php', 'mb_list'), array('200300', '회원메일발송', G5_ADMIN_URL . '/mail_list.php', 'mb_mail'), array('200800', '접속자집계', G5_ADMIN_URL . '/visit_list.php', 'mb_visit', 1), array('200810', '접속자검색', G5_ADMIN_URL . '/visit_search.php', 'mb_search', 1), diff --git a/adm/admin.tail.php b/adm/admin.tail.php index 5c95c1288..68b6dae12 100644 --- a/adm/admin.tail.php +++ b/adm/admin.tail.php @@ -14,7 +14,6 @@ $print_version = ($is_admin == 'super') ? 'Version ' . G5_GNUBOARD_VER : ''; 자바스크립트를 사용하지 않음으로 설정하신 경우는 수정이나 삭제시 별도의 경고창이 나오지 않으므로 이점 주의하시기 바랍니다.

- - + +
+
diff --git a/adm/board_form_update.php b/adm/board_form_update.php index b1c9af12d..b5f7364b7 100644 --- a/adm/board_form_update.php +++ b/adm/board_form_update.php @@ -36,10 +36,24 @@ if ($w == '' && in_array($bo_table, get_bo_table_banned_word())) { $bo_include_head = isset($_POST['bo_include_head']) ? preg_replace(array("#[\\\]+$#", "#(<\?php|<\?)#i"), "", substr($_POST['bo_include_head'], 0, 255)) : ''; $bo_include_tail = isset($_POST['bo_include_tail']) ? preg_replace(array("#[\\\]+$#", "#(<\?php|<\?)#i"), "", substr($_POST['bo_include_tail'], 0, 255)) : ''; -// 관리자가 자동등록방지를 사용해야 할 경우 -if ($board && (isset($board['bo_include_head']) && $board['bo_include_head'] !== $bo_include_head || $board['bo_include_tail'] !== $bo_include_tail) && function_exists('get_admin_captcha_by') && get_admin_captcha_by()) { - include_once(G5_CAPTCHA_PATH . '/captcha.lib.php'); +$check_captcha = false; +// 관리자가 자동등록방지 CAPTCHA를 사용해야 할 경우 +if ($w === 'u') { + if (isset($board['bo_include_head'], $board['bo_include_tail']) && + ($board['bo_include_head'] !== $bo_include_head || $board['bo_include_tail'] !== $bo_include_tail)) { + $check_captcha = true; + } +} elseif ($w === '') { + if ($bo_include_head !== '_head.php' || $bo_include_tail !== '_tail.php') { + $check_captcha = true; + } +} + +// 실제 CAPTCHA 검증 +if ($check_captcha) { + include_once(G5_CAPTCHA_PATH . '/captcha.lib.php'); + if (!chk_captcha()) { alert('자동등록방지 숫자가 틀렸습니다.'); } diff --git a/adm/config_form.php b/adm/config_form.php index 986112e79..4312a7001 100644 --- a/adm/config_form.php +++ b/adm/config_form.php @@ -422,6 +422,30 @@ if (!isset($config['cf_cert_kcp_enckey'])) { $config['cf_cert_kcp_enckey'] = ''; } +// 광고성 정보 수신 동의 사용 필드 추가 +if (!isset($config['cf_use_promotion'])) { + sql_query( + " ALTER TABLE `{$g5['config_table']}` + ADD `cf_use_promotion` tinyint(1) NOT NULL DEFAULT '0' AFTER `cf_privacy` ", + true + ); +} + +// 광고성 정보 수신 동의 여부 필드 추가 + 메일 / SMS 수신 일자 추가 +if (!isset($member['mb_marketing_agree'])) { + sql_query( + " ALTER TABLE `{$g5['member_table']}` + ADD `mb_marketing_agree` tinyint(1) NOT NULL DEFAULT '0' AFTER `mb_scrap_cnt`, + ADD `mb_marketing_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `mb_marketing_agree`, + ADD `mb_thirdparty_agree` tinyint(1) NOT NULL DEFAULT '0' AFTER `mb_marketing_date`, + ADD `mb_thirdparty_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `mb_thirdparty_agree`, + ADD `mb_agree_log` TEXT NOT NULL AFTER `mb_thirdparty_date`, + ADD `mb_mailling_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `mb_mailling`, + ADD `mb_sms_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `mb_sms` ", + true + ); +} + if (!$config['cf_faq_skin']) { $config['cf_faq_skin'] = "basic"; } @@ -963,6 +987,17 @@ if ($config['cf_sms_use'] && $config['cf_icode_id'] && $config['cf_icode_pw']) { + + + + 광고성 정보 수신 · 마케팅 목적의 개인정보 수집 및 이용 · 개인정보 제 3자 제공 여부를 설정합니다. SMS 또는 카카오톡 사용 시 개인정보 제3자 제공이 활성화됩니다.'); ?> + 카카오톡(친구톡)·문자로 광고성 메시지를 발송할 수 있습니다.'); ?> + 휴대전화번호 사용을 위해서는 기본환경설정 > 회원가입 > 휴대전화번호 입력[보이기] 또는 [필수입력]으로 설정해야 하며, 미설정 시 수집이 불가합니다.'); ?> + 광고성 정보 수신 동의를 매 2년마다 반드시 확인해야 합니다.'); ?> + > + + + @@ -1138,6 +1173,7 @@ if ($config['cf_sms_use'] && $config['cf_icode_id'] && $config['cf_icode_pw']) { > 회원만 사용 + @@ -1526,7 +1562,6 @@ if ($config['cf_sms_use'] && $config['cf_icode_id'] && $config['cf_icode_pw']) { -

여분필드 기본 설정

diff --git a/adm/config_form_update.php b/adm/config_form_update.php index 0e7c81bf9..a5a5dc7c2 100644 --- a/adm/config_form_update.php +++ b/adm/config_form_update.php @@ -141,6 +141,7 @@ $check_keys = array( 'cf_visit' => 'char', 'cf_stipulation' => 'text', 'cf_privacy' => 'text', + 'cf_use_promotion' => 'int', 'cf_open_modify' => 'int', 'cf_memo_send_point' => 'int', 'cf_mobile_new_skin' => 'char', @@ -300,6 +301,7 @@ $sql = " update {$g5['config_table']} cf_mobile_page_rows = '{$_POST['cf_mobile_page_rows']}', cf_stipulation = '{$_POST['cf_stipulation']}', cf_privacy = '{$_POST['cf_privacy']}', + cf_use_promotion = '{$_POST['cf_use_promotion']}', cf_open_modify = '{$_POST['cf_open_modify']}', cf_memo_send_point = '{$_POST['cf_memo_send_point']}', cf_mobile_new_skin = '{$_POST['cf_mobile_new_skin']}', diff --git a/adm/css/admin.css b/adm/css/admin.css index 75763206a..550314d97 100644 --- a/adm/css/admin.css +++ b/adm/css/admin.css @@ -28,6 +28,39 @@ box-sizing: border-box; h2{font-size: 1.083em;font-weight: bold;margin:10px 0} #wrapper {min-height:480px} + +/* admin 공통 */ +/* 공통 - display none/block */ +.is-hidden { display: none !important; } +.is-visible { display: block !important; } + +/* 공통 - 뷰포트 (pc / mobile) 별 display none/block */ +.pc-only { display: none; } +@media (min-width: 769px) { .pc-only { display: block !important; }} +.mobile-only { display: block; } +@media (min-width: 769px) { .mobile-only { display: none !important; }} + +/* 공통 - 레이어 팝업 */ +.popup-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.3); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); z-index: 9999; display: flex; justify-content: center; align-items: center; } +.popup-content { background: #fff; border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.15); width: 800px; overflow: hidden; } +.popup-header, .popup-footer { padding: 18px 20px; display: flex; align-items: center; } +.popup-header { justify-content: space-between; border-bottom: 1px solid #e0e0e0; } +.popup-footer { gap: 20px; border-top: 1px solid #e0e0e0;} +.popup-close-btn { background: none; border: none; color: #888; font-size: 20px; cursor: pointer; padding: 4px; display: flex; align-items: center; justify-content: center; transition: color 0.2s ease; } +.popup-close-btn:hover { color: #333; } +.popup-title { font-size: 18px; font-weight: 600; } +.popup-body { padding: 20px; max-height: 400px; overflow-y: auto; color: #333; } +.popup-footer button { background: #3d70ff; color: white; border: 1px solid #3d70ff; padding: 8px 16px; border-radius: 6px; font-weight: 600; cursor: pointer; transition: background 0.2s ease, border-color 0.2s ease; } +.popup-footer button:hover { background: #2b3d9f; border-color: #2b3d9f; } + +/* 공통 - tab */ +.tab-container { display: flex; flex-direction: column; width: 100%; } +.tab-header { position: relative; bottom: -1px; display: flex; } +.tab-btn { padding: 10px 14px; background: none; border: none; border-bottom: 2px solid transparent; cursor: pointer; color: inherit; font: inherit; } +.tab-btn.active { border-bottom-color: #000; font-weight: bold; } +.tab-body { width: 100%; border-top: 1px solid #ccc; } +.tab-content { padding: 16px 0; } + /* 레이아웃 */ #hd h1 {position:absolute;font-size:0;line-height:0;overflow:hidden} #hd_top{position:fixed;top:0;left:0;width:100%;height:50px;background:#3f51b5;z-index:1000} @@ -95,9 +128,11 @@ box-shadow: 2px 0 2px rgba(150,150,150,0.1);} #container.container-small #container_title{padding-left:70px} .container_wr{padding:20px} -/* 화면낭독기 사용자용 */ +/* 화면낭독기 사용자용 (스크린 리더 대응) */ +/* 일반적인 .blind/.sr-only 사용시에 .sound_only 사용 권장 */ #hd_login_msg {position:absolute;top:0;left:0;width:1px;height:1px;overflow:hidden} -.msg_sound_only, .sound_only {display:inline-block !important;position:absolute;top:0;left:0;margin:0 !important;padding:0 !important;width:1px !important;height:1px !important;font-size:0;line-height:0;border:0 !important;overflow:hidden !important} +.sound_only, .msg_sound_only {overflow:hidden;position:absolute;width:1px;height:1px;margin:-1px;padding:0;clip:rect(0,0,0,0)} + /* 본문 바로가기 */ #to_content a {z-index:100000;position:absolute;top:0;left:0;font-size:0;line-height:0;overflow:hidden} #to_content a:focus, #to_content a:active {width:100%;height:70px;background:#fff;font-size:2em;font-weight:bold;text-align:center;text-decoration:none;line-height:3.1em} @@ -247,18 +282,14 @@ legend {position:absolute;width:0;height:0;font-size:0;line-height:0;text-indent .anchor a {display:inline-block;padding:5px 10px;border:1px solid #c8ced1;background:#d6dde1;text-decoration:none} .anchor .selected{background:#3f51b5} - - - #sort_mb {width:800px} #sort_sodr {width:600px} - /* 하단 레이아웃 */ #ft{background:#f3f3f3;padding:0 25px;color:#777;text-align:center} #ft p{line-height:50px;} -.scroll_top{position:fixed;bottom:10px;right:10px;width:50px;height:50px;border:0;text-align:center;background:#ddd;background:rgba(0,0,0,0.1)} +.scroll_top{position:fixed;bottom:10px;right:10px;width:50px;height:50px;border:0;text-align:center;background:#ddd;background:rgba(0,0,0,0.1);z-index:50;} .scroll_top span.top_img{display:inline-block;width: 0; height: 0; border-left: 5px solid transparent;border-right: 5px solid transparent; border-bottom: 5px solid black;} .scroll_top span.top_txt{display:block} @@ -281,9 +312,59 @@ border-bottom: 5px solid black;} .local_sch03 button{height:30px;padding:0 5px;border:0;background:#9eacc6;color:#fff;} .local_sch03 .btn_submit{height:30px;padding:0 5px;border:0;color:#fff;} .local_sch03 .frm_input{height:30px;border:1px solid #dcdcdc;padding:0 5px;} + +/* 회원 관리 데이터 필터링 */ +.member_list_data { display: flex; flex-direction: column; padding: 20px; margin: 20px 0 40px; background: #f9f9f9; border: 1px solid #f2f2f2; color: #333; } +.sch_table { display: flex; flex-direction: column; gap: 10px; font-size: 11.5px; color: #333; } +.member_list_data .sch_row { display: flex; align-items: center; gap: 12px; min-height: 30px; } +.label { min-width: 120px; font-weight: 500; white-space: nowrap; display: flex; align-items: center; } +.label label {display: flex; gap: 10px;} +.field { flex: 1; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } +.field input[type="text"], .field input[type="number"], .field input[type="date"], .field select { height: 30px; min-width: 100px; padding: 0 10px; font-size: 11.5px; border: 1px solid #ddd; border-radius: 8px; background: #fff; transition: border-color 0.2s ease, box-shadow 0.2s ease; } +.field input[type="text"]:focus, .field input[type="number"]:focus, .field input[type="date"]:focus, .field select:focus { border-color: #6f809a; box-shadow: 0 0 0 2px rgba(63,81,181,0.1); outline: none; } +.field input::placeholder { color: #aaa; } +.field input[type="checkbox"], .field input[type="radio"] { width: 14px; height: 14px; accent-color: #536177; } +.radio_group { display: flex; gap: 15px; align-items: center; padding: 0 10px;} +.radio_group label {display: flex; align-items: center; gap: 5px;} +.ad_range_wrap {flex: 1; padding-left: 20px;} +.ad_range_box {display: flex;} +.ad_range_box .label {width: 109px;} +.sch_notice { font-size: 11px; color: #999; } +.sch_btn { display: flex; gap: 20px; justify-content: center; margin-top: 40px; } +.sch_btn { display: flex; gap: 10px; } + +.btn_reset { display: flex; align-items: center; gap: 6px; padding: 0 20px; height: 40px; background: #9eacc6; color: #fff; font-weight: 600; border: none; border-radius: 8px; cursor: pointer; transition: background 0.2s ease, transform 0.15s ease; } +.btn_reset:hover { background: #5f6e89; } +.sch_btn button:not(.btn_reset) { padding: 0 20px; height: 40px; border: 1px solid #ccd1d8; background-color: #fff; color: #444; font-weight: 600; border-radius: 8px; cursor: pointer; user-select: none; transition: border-color 0.2s ease, box-shadow 0.2s ease; box-shadow: 0 1px 2px rgba(0,0,0,0.03); } +.sch_btn button:not(.btn_reset):hover { border-color: #6f809a; box-shadow: 0 2px 4px rgba(111, 128, 154, 0.15); } +.sch_btn button:not(.btn_reset):active { box-shadow: inset 0 1px 2px rgba(0,0,0,0.1); } + +/* 회원 관리 다운로드 진행 팝업 */ +.excel-download-progress p { color: #374151; } +.excel-download-progress .progress-desc { padding: 40px 0 32px; text-align: center; } +.excel-download-progress .progress-summary { margin-bottom: 6px; font-size: 16px; font-weight: 500; color: #111827; } +.excel-download-progress .progress-message { font-size: 20px; font-weight: 600; color: #3b82f6; } +.excel-download-progress .progress-error { color:red; } +.progress-spinner { display: flex; flex-direction: column; align-items: center; gap: 45px; padding: 24px 0; transition: all 0.2s ease; } +.spinner { width: 48px; height: 48px; border: 5px solid #3b82f6; border-top: 5px solid #fff; border-radius: 50%; animation: spin 0.8s linear infinite; } +@keyframes spin { to { transform: rotate(360deg); } } +.loading-message { text-align: center; font-size: 14px; color: #374151; } +.excel-download-progress .progress-download-box { margin-top: 24px; background: #f9fafb; padding: 20px; border-radius: 8px; box-shadow: 0 1px 2px rgba(0,0,0,0.03); } +.excel-download-progress .progress-download-box a { display: block; width: 100%; height: auto; text-align: center; margin-top: 8px; font-weight: 600; font-size: 14px; padding: 10px 20px; background: #fff; border: 1px solid #ccd1d8; border-radius: 8px; color: #444; cursor: pointer; transition: border-color 0.2s ease, box-shadow 0.2s ease; box-shadow: 0 1px 2px rgba(0,0,0,0.03); } +.excel-download-progress .progress-download-box a:hover { border-color: #6f809a; box-shadow: 0 2px 4px rgba(111, 128, 154, 0.15); } +.excel-download-progress .progress-download-box a:active { box-shadow: inset 0 1px 2px rgba(0,0,0,0.1); } + +.field-select-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 15px; gap: 0px 10px; padding: 10px; background-color: #f9fafb; border: 1px solid #e5e7eb; border-radius: 8px; color: #374151; } +.field-select-form label { display: flex; align-items: center; cursor: pointer; padding: 6px 10px; border-radius: 4px; } +.field-select-form label:hover { background-color: #f3f4f6; } +.field-select-form input[type="checkbox"] { margin-right: 8px; transform: scale(1.2); } +.field-separator { grid-column: 1 / -1; border-top: 1px solid #d1d5db; margin: 8px 0; } +.selected-fields-preview { padding: 8px; background-color: #eef2f7; border: 1px solid #d1d5db; border-radius: 6px; margin: 10px 0px; color: #1f2937; display: flex; align-items: center; flex-wrap: wrap; gap: 8px; } +.selected-fields-preview strong { padding: 4px 8px; } +.selected-fields-preview .field-tag { background-color: #dbeafe; color: #1e40af; padding: 4px 8px; border-radius: 4px; } + /* 페이지 내 실행 */ .local_cmd {min-width:960px} - .local_cmd01 {margin:0 0 10px;padding:0 } .local_cmd01 .cmd_tit {font-weight:bold} .local_cmd01 .btn_submit {padding:3px 5px;border:1px solid #ff3061;color:#fff;font-size:0.95em;vertical-align:middle} @@ -298,7 +379,7 @@ border-bottom: 5px solid black;} .local_desc01 {margin:10px 0 10px ;padding:10px 20px;border:1px solid #f2f2f2;background:#f9f9f9} .local_desc01 strong {color:#ff3061} -.local_desc01 a {text-decoration:underline} +.local_desc01 a {text-decoration:underline;text-underline-offset:2px;} .local_desc02 {margin:10px 0 ;min-width:960px} /* 주로 온라인 서식 관련 안내 내용에 사용 */ .local_desc02 p {padding:0;line-height:1.8em} @@ -401,6 +482,7 @@ tfoot th {} .mb_leave_msg {color:#b6b6b6} .mb_intercept_msg {color:#ff0000} #point_mng {margin-top:50px} +.ad_agree_log {max-height: 150px !important;} /* 게시판추가/수정 */ #anc_bo_extra .td_grpset label {width:auto} @@ -504,6 +586,7 @@ td.td_grpset {width:160px;border-left:1px solid #e9ecee;text-align:center} .td_time{text-align:center;width:130px} .td_center{text-align:center;} .td_type{width:120px} +.td_consent{width:200px} .td_mng_s{width:60px} .td_mng_m{width:100px} @@ -656,14 +739,15 @@ a.nicepay_btn{display:inline-block;margin:5px 0 0;padding:5px 10px;background:#0 ul.de_pg_tab{margin:0;padding:0;zoom:1} ul.de_pg_tab:after{display:block;visibility:hidden;clear:both;content:"";} -ul.de_pg_tab li{position:relative;display:inline-block;float:left;text-align:center;margin:0;padding:0;width:120px} -ul.de_pg_tab li a{margin:0 2px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:2.5;background-color:#f7f7f7;color:#74777b;font-weight:bold;font-size:1.2em;text-decoration:none} +ul.de_pg_tab li{position:relative;display:inline-block;float:left;text-align:center;margin:0;padding:0;min-width:130px} +ul.de_pg_tab li a{margin:0 2px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:2.5;background-color:#f7f7f7;color:#74777b;font-weight:bold;font-size:1.2em;text-decoration:none; padding:0px 10px;} ul.de_pg_tab li a:hover{text-decoration:none} ul.de_pg_tab li.tab-current a{background:#2CC185;color:#fff} .pg_info_fld{position:relative} .kcp_info_fld th{background-color:#F6FCFF} .lg_info_fld th{background-color:#FFF4FA} +.lg_info_fld_v2 th{background-color:#ffe8f5} .inicis_info_fld th{background-color:#F6F1FF} .kakao_info_fld th{background-color:#FFFCED} .naver_info_fld th{background-color:#F3FFF3} @@ -1133,4 +1217,4 @@ input[type="text"]{max-width:200px} @media only screen and (max-device-width : 480px) and (orientation : portrait){ /* Styles */ input[type="text"]{max-width:200px} -} +} \ No newline at end of file diff --git a/adm/dbupgrade.php b/adm/dbupgrade.php index 48394b6ba..a6f1e3e76 100644 --- a/adm/dbupgrade.php +++ b/adm/dbupgrade.php @@ -269,6 +269,54 @@ while ($row = sql_fetch_array($result)){ } } +// SMS5 테이블 G5_TABLE_PREFIX 적용 +if($g5['sms5_prefix'] != 'sms5_' && sql_num_rows(sql_query("show tables like 'sms5_config'"))) +{ + $tables = array('config','write','history','book','book_group','form','form_group'); + + foreach($tables as $name){ + $old_table = 'sms5_' . $name; + $new_table = $g5['sms5_prefix'] . $name; + + // 기존 테이블이 있고, G5_TABLE_PREFIX 적용 테이블이 없을 경우 → 테이블명 변경 + if(sql_num_rows(sql_query("SHOW TABLES LIKE '{$old_table}' "))){ + if(!sql_num_rows(sql_query("SHOW TABLES LIKE '{$new_table}' "))){ + sql_query("RENAME TABLE {$old_table} TO {$new_table}", false); + } + } + } + + $is_check = true; +} + +// 광고성 정보 수신 동의 사용 필드 추가 +if (!isset($config['cf_use_promotion'])) { + sql_query( + " ALTER TABLE `{$g5['config_table']}` + ADD `cf_use_promotion` tinyint(1) NOT NULL DEFAULT '0' AFTER `cf_privacy` ", + true + ); + + $is_check = true; +} + +// 광고성 정보 수신 동의 여부 필드 추가 + 메일 / SMS 수신 일자 추가 +if (!isset($member['mb_marketing_agree'])) { + sql_query( + " ALTER TABLE `{$g5['member_table']}` + ADD `mb_marketing_agree` tinyint(1) NOT NULL DEFAULT '0' AFTER `mb_scrap_cnt`, + ADD `mb_marketing_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `mb_marketing_agree`, + ADD `mb_thirdparty_agree` tinyint(1) NOT NULL DEFAULT '0' AFTER `mb_marketing_date`, + ADD `mb_thirdparty_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `mb_thirdparty_agree`, + ADD `mb_agree_log` TEXT NOT NULL AFTER `mb_thirdparty_date`, + ADD `mb_mailling_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `mb_mailling`, + ADD `mb_sms_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `mb_sms` ", + true + ); + + $is_check = true; +} + $is_check = run_replace('admin_dbupgrade', $is_check); $db_upgrade_msg = $is_check ? 'DB 업그레이드가 완료되었습니다.' : '더 이상 업그레이드 할 내용이 없습니다.
현재 DB 업그레이드가 완료된 상태입니다.'; diff --git a/adm/member_form.php b/adm/member_form.php index 1e4e9d941..28287bd74 100644 --- a/adm/member_form.php +++ b/adm/member_form.php @@ -52,8 +52,11 @@ if ($w == '') { $sound_only = '필수'; $mb['mb_mailling'] = 1; + $mb['mb_sms'] = 1; $mb['mb_open'] = 1; $mb['mb_level'] = $config['cf_register_level']; + $mb['mb_marketing_agree'] = 0; + $mb['mb_thirdparty_agree'] = 0; $html_title = '추가'; } elseif ($w == 'u') { $mb = get_member($mb_id); @@ -139,6 +142,14 @@ $mb_sms_no = !$mb['mb_sms'] ? 'checked="checked"' : ''; $mb_open_yes = $mb['mb_open'] ? 'checked="checked"' : ''; $mb_open_no = !$mb['mb_open'] ? 'checked="checked"' : ''; +// 마케팅 목적의 개인정보 수집 및 이용 +$mb_marketing_agree_yes = $mb['mb_marketing_agree'] ? 'checked="checked"' : ''; +$mb_marketing_agree_no = !$mb['mb_marketing_agree'] ? 'checked="checked"' : ''; + +// 개인정보 제3자 제공 동의 +$mb_thirdparty_agree_yes = $mb['mb_thirdparty_agree'] ? 'checked="checked"' : ''; +$mb_thirdparty_agree_no = !$mb['mb_thirdparty_agree'] ? 'checked="checked"' : ''; + if (isset($mb['mb_certify'])) { // 날짜시간형이라면 drop 시킴 if (preg_match("/-/", $mb['mb_certify'])) { @@ -354,21 +365,64 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js - 메일 수신 + 광고성 이메일 수신 > > + + (동의 일자: ".$mb['mb_mailling_date'].")" : ''; + } ?> - + > > + (동의 일자: ".$mb['mb_sms_date'].")" : ''; + } ?> + + 마케팅 목적의
개인정보 수집 및 이용 + + > + + > + + + (동의 일자: ".$mb['mb_marketing_date'].")" : ''; + } ?> + + + + > + + > + + + (동의 일자: ".$mb['mb_thirdparty_date'].")" : ''; + } ?> + + + + + 약관동의 변경내역 + +
+
+ +
+
+ + + 정보 공개 @@ -376,6 +430,9 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js > + (동의 일자: ".$mb['mb_open_date'].")" : ''; + } ?> diff --git a/adm/member_form_update.php b/adm/member_form_update.php index 29e96a38c..1bf338e68 100644 --- a/adm/member_form_update.php +++ b/adm/member_form_update.php @@ -18,6 +18,10 @@ $mb_certify_case = isset($_POST['mb_certify_case']) ? preg_replace('/[^0-9a-z_]/ $mb_certify = isset($_POST['mb_certify']) ? preg_replace('/[^0-9a-z_]/i', '', $_POST['mb_certify']) : ''; $mb_zip = isset($_POST['mb_zip']) ? preg_replace('/[^0-9a-z_]/i', '', $_POST['mb_zip']) : ''; +// 광고성 정보 수신 +$mb_marketing_agree = isset($_POST['mb_marketing_agree']) ? clean_xss_tags($_POST['mb_marketing_agree'], 1, 1) : '0'; +$mb_thirdparty_agree = isset($_POST['mb_thirdparty_agree']) ? clean_xss_tags($_POST['mb_thirdparty_agree'], 1, 1) : '0'; + // 관리자가 자동등록방지를 사용해야 할 경우 ( 회원의 비밀번호 변경시 캡챠를 체크한다 ) if ($mb_password) { include_once(G5_CAPTCHA_PATH . '/captcha.lib.php'); @@ -86,8 +90,6 @@ foreach ($check_keys as $key) { } } -$mb_memo = isset($_POST['mb_memo']) ? $_POST['mb_memo'] : ''; - $sql_common = " mb_name = '{$posts['mb_name']}', mb_nick = '{$mb_nick}', mb_email = '{$mb_email}', @@ -109,8 +111,11 @@ $sql_common = " mb_name = '{$posts['mb_name']}', mb_mailling = '{$posts['mb_mailling']}', mb_sms = '{$posts['mb_sms']}', mb_open = '{$posts['mb_open']}', + mb_open_date = '".G5_TIME_YMDHIS."', mb_profile = '{$posts['mb_profile']}', mb_level = '{$posts['mb_level']}', + mb_marketing_agree = '{$mb_marketing_agree}', + mb_thirdparty_agree = '{$mb_thirdparty_agree}', mb_1 = '{$posts['mb_1']}', mb_2 = '{$posts['mb_2']}', mb_3 = '{$posts['mb_3']}', @@ -142,6 +147,36 @@ if ($w == '') { alert('이미 존재하는 이메일입니다.\\nID : ' . $row['mb_id'] . '\\n이름 : ' . $row['mb_name'] . '\\n닉네임 : ' . $row['mb_nick'] . '\\n메일 : ' . $row['mb_email']); } + $agree_items = []; + // 마케팅 목적의 개인정보 수집 및 이용 + if ($mb_marketing_agree == 1) { + $sql_common .= " , mb_marketing_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "마케팅 목적의 개인정보 수집 및 이용(동의)"; + } + + // 광고성 이메일 수신 + if ($mb_mailling == 1) { + $sql_common .= " , mb_mailling_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 이메일 수신(동의)"; + } + + // 광고성 SMS/카카오톡 수신 + if ($mb_sms == 1) { + $sql_common .= " , mb_sms_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 SMS/카카오톡 수신(동의)"; + } + + // 개인정보 제3자 제공 + if ($mb_thirdparty_agree == 1) { + $sql_common .= " , mb_thirdparty_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "개인정보 제3자 제공(동의)"; + } + + // 동의 로그 추가 + if (!empty($agree_items)) { + $agree_log = "[".G5_TIME_YMDHIS.", 관리자 회원추가] " . implode(' | ', $agree_items) . "\n"; + $sql_common .= " , mb_agree_log = CONCAT('{$agree_log}', IFNULL(mb_agree_log, ''))"; + } sql_query(" insert into {$g5['member_table']} set mb_id = '{$mb_id}', mb_password = '" . get_encrypt_string($mb_password) . "', mb_datetime = '" . G5_TIME_YMDHIS . "', mb_ip = '{$_SERVER['REMOTE_ADDR']}', mb_email_certify = '" . G5_TIME_YMDHIS . "', {$sql_common} "); } elseif ($w == 'u') { $mb = get_member($mb_id); @@ -193,10 +228,54 @@ if ($w == '') { $sql_certify = ""; } + // 현재 데이터 조회 + $row = sql_fetch("select * from {$g5['member_table']} where mb_id = '{$mb_id}' "); + $agree_items = []; + + // 마케팅 목적의 개인정보 수집 및 이용 + $sql_marketing_date = ""; + if ($row['mb_marketing_agree'] !== $mb_marketing_agree) { + $sql_marketing_date .= " , mb_marketing_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "마케팅 목적의 개인정보 수집 및 이용(" . ($mb_marketing_agree == 1 ? "동의" : "철회") . ")"; + } + + // 광고성 이메일 수신 + $sql_mailling_date = ""; + if ($row['mb_mailling'] !== $mb_mailling) { + $sql_mailling_date .= " , mb_mailling_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 이메일 수신(" . ($mb_mailling == 1 ? "동의" : "철회") . ")"; + } + + // 광고성 SMS/카카오톡 수신 + $sql_sms_date = ""; + if ($row['mb_sms'] !== $mb_sms) { + $sql_sms_date .= " , mb_sms_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 SMS/카카오톡 수신(" . ($mb_sms == 1 ? "동의" : "철회") . ")"; + } + + // 개인정보 제3자 제공 + $sql_thirdparty_date = ""; + if ($row['mb_thirdparty_agree'] !== $mb_thirdparty_agree) { + $sql_thirdparty_date .= " , mb_thirdparty_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "개인정보 제3자 제공(" . ($mb_thirdparty_agree == 1 ? "동의" : "철회") . ")"; + } + + // 동의 로그 추가 + $sql_agree_log = ""; + if (!empty($agree_items)) { + $agree_log = "[".G5_TIME_YMDHIS.", 관리자 회원수정] " . implode(' | ', $agree_items) . "\n"; + $sql_agree_log .= " , mb_agree_log = CONCAT('{$agree_log}', IFNULL(mb_agree_log, ''))"; + } + $sql = " update {$g5['member_table']} set {$sql_common} {$sql_password} {$sql_certify} + {$sql_mailling_date} + {$sql_sms_date} + {$sql_marketing_date} + {$sql_thirdparty_date} + {$sql_agree_log} where mb_id = '{$mb_id}' "; sql_query($sql); } else { diff --git a/adm/member_list.php b/adm/member_list.php index dc6348cdd..bb3be84c6 100644 --- a/adm/member_list.php +++ b/adm/member_list.php @@ -127,7 +127,7 @@ $colspan = 16; 본인확인 메일인증 정보공개 - 메일수신 + 광고성이메일수신 상태 휴대폰 최종접속 @@ -137,7 +137,7 @@ $colspan = 16; 이름 닉네임 - SMS수신 + 광고성SMS/카카오톡수신 성인인증 접근차단 권한 @@ -252,14 +252,15 @@ $colspan = 16; > - Yes' : 'No'; ?> - + Yes' : 'No'; ?> + value="1" id="mb_open_"> - + value="1" id="mb_mailling_"> + value="1" id="mb_sms_"> + diff --git a/adm/member_list_exel.lib.php b/adm/member_list_exel.lib.php new file mode 100644 index 000000000..bd5826de4 --- /dev/null +++ b/adm/member_list_exel.lib.php @@ -0,0 +1,288 @@ + [ + 'mb_id'=>'아이디', + 'mb_name'=>'이름', + 'mb_nick'=>'닉네임', + 'mb_email'=>'이메일', + 'mb_tel'=>'전화번호', + 'mb_hp'=>'휴대폰번호', + 'mb_addr1'=>'주소' + ], + 'point_cond_map' => [ + 'gte'=>'≥', + 'lte'=>'≤', + 'eq'=>'=' + ], + 'intercept_list' => [ + 'exclude'=>'차단회원 제외', + 'only'=>'차단회원만' + ], + 'ad_range_list' => [ + 'all' => '수신동의 회원 전체', + 'mailling_only' => '이메일 수신동의 회원만', + 'sms_only' => 'SMS/카카오톡 수신동의 회원만', + 'month_confirm' => date('m월').' 수신동의 확인 대상만', + 'custom_period' => '수신동의 기간 직접 입력' + ], + ]; + + return $type ? (isset($config[$type]) ? $config[$type] : []) : $config; +} + +/** + * 파라미터 수집 및 유효성 검사 + */ +function get_member_export_params() +{ + // 친구톡 양식 - 엑셀 양식에 포함할 항목 + $fieldArray = array_map('trim', explode(',', isset($_GET['fields']) ? $_GET['fields'] : '')); + $vars = []; + foreach ($fieldArray as $index => $field) { + if(!empty($field)){ + $vars['var' . ($index + 1)] = $field; + } + } + + $params = [ + 'page' => 1, + 'formatType' => (int)(isset($_GET['formatType']) ? $_GET['formatType'] : 1), + 'use_stx' => isset($_GET['use_stx']) ? $_GET['use_stx'] : 0, + 'stx_cond' => clean_xss_tags(isset($_GET['stx_cond']) ? $_GET['stx_cond'] : 'like'), + 'sfl' => clean_xss_tags(isset($_GET['sfl']) ? $_GET['sfl'] : ''), + 'stx' => clean_xss_tags(isset($_GET['stx']) ? $_GET['stx'] : ''), + 'use_level' => isset($_GET['use_level']) ? $_GET['use_level'] : 0, + 'level_start' => (int)(isset($_GET['level_start']) ? $_GET['level_start'] : 1), + 'level_end' => (int)(isset($_GET['level_end']) ? $_GET['level_end'] : 10), + 'use_date' => isset($_GET['use_date']) ? $_GET['use_date'] : 0, + 'date_start' => clean_xss_tags(isset($_GET['date_start']) ? $_GET['date_start'] : ''), + 'date_end' => clean_xss_tags(isset($_GET['date_end']) ? $_GET['date_end'] : ''), + 'use_point' => isset($_GET['use_point']) ? $_GET['use_point'] : 0, + 'point' => isset($_GET['point']) ? $_GET['point'] : '', + 'point_cond' => isset($_GET['point_cond']) ? $_GET['point_cond'] : 'gte', + 'use_hp_exist' => isset($_GET['use_hp_exist']) ? $_GET['use_hp_exist'] : 0, + 'ad_range_only' => isset($_GET['ad_range_only']) ? $_GET['ad_range_only'] : 0, + 'ad_range_type' => clean_xss_tags(isset($_GET['ad_range_type']) ? $_GET['ad_range_type'] : 'all'), + 'ad_mailling' => isset($_GET['ad_mailling']) ? $_GET['ad_mailling'] : 0, + 'ad_sms' => isset($_GET['ad_sms']) ? $_GET['ad_sms'] : 0, + 'agree_date_start' => clean_xss_tags(isset($_GET['agree_date_start']) ? $_GET['agree_date_start'] : ''), + 'agree_date_end' => clean_xss_tags(isset($_GET['agree_date_end']) ? $_GET['agree_date_end'] : ''), + 'use_intercept' => isset($_GET['use_intercept']) ? $_GET['use_intercept'] : 0, + 'intercept' => clean_xss_tags(isset($_GET['intercept']) ? $_GET['intercept'] : 'exclude'), + 'vars' => $vars, + ]; + + // 레벨 범위 검증 + if ($params['level_start'] > $params['level_end']) { + [$params['level_start'] , $params['level_end']] = [$params['level_end'], $params['level_start']]; + } + + // 가입기간 - 날짜 범위 검증 + if ($params['use_date'] && $params['date_start'] && $params['date_end']) { + if ($params['date_start'] > $params['date_end']) { + [$params['date_start'] , $params['date_end']] = [$params['date_end'], $params['date_start']]; + } + } + + // 수신동의기간 - 날짜 범위 검증 + if ($params['ad_range_type'] == 'custom_period' && $params['agree_date_start'] && $params['agree_date_end']) { + if ($params['agree_date_start'] > $params['agree_date_end']) { + [$params['agree_date_start'] , $params['agree_date_end']] = [$params['agree_date_end'], $params['agree_date_start']]; + } + } + + return $params; +} + +/** + * 전체 데이터 개수 조회 + */ +function member_export_get_total_count($params) +{ + global $g5; + + $where = member_export_build_where($params); + $sql = "SELECT COUNT(*) as cnt FROM {$g5['member_table']} {$where}"; + + $result = sql_query($sql); + if (!$result) { + throw new Exception("데이터 조회에 실패하였습니다. 다시 시도해주세요."); + } + + $row = sql_fetch_array($result); + return (int)$row['cnt']; +} + +/** + * WHERE 조건절 생성 + */ +function member_export_build_where($params) +{ + global $config; + $conditions = []; + + // 기본 조건 - 탈퇴하지 않은 사용자 + $conditions[] = "mb_leave_date = ''"; + + // 검색어 조건 (sql_escape_string 사용으로 보안 강화) + if (!empty($params['use_stx']) && $params['use_stx'] === '1') { + $sfl_list = get_export_config('sfl_list'); + $sfl = in_array($params['sfl'], array_keys($sfl_list)) ? $params['sfl'] : ''; + $stx = sql_escape_string($params['stx']); + + if(!empty($sfl) && !empty($stx)){ + if ($params['stx_cond'] === 'like') { + $conditions[] = "{$sfl} LIKE '%{$stx}%'"; + } else { + $conditions[] = "{$sfl} = '{$stx}'"; + } + } + } + + // 권한 조건 + if (!empty($params['use_level']) && $params['use_level'] === '1') { + $level_start = max(1, (int)$params['level_start']); + $level_end = min(10, (int)$params['level_end']); + + $conditions[] = "(mb_level BETWEEN {$level_start} AND {$level_end})"; + } + + // 가입기간 조건 + if (!empty($params['use_date']) && $params['use_date'] === '1') { + $date_start = isset($params['date_start']) ? sql_escape_string(trim($params['date_start'])) : ''; + $date_end = isset($params['date_end']) ? sql_escape_string(trim($params['date_end'])) : ''; + + if ($date_start && $date_end) { + $conditions[] = "mb_datetime BETWEEN '{$date_start} 00:00:00' AND '{$date_end} 23:59:59'"; + } elseif ($date_start) { + $conditions[] = "mb_datetime >= '{$date_start} 00:00:00'"; + } elseif ($date_end) { + $conditions[] = "mb_datetime <= '{$date_end} 23:59:59'"; + } + } + + // 포인트 조건 + if (!empty($params['use_point']) && $params['use_point'] === '1') { + $point = $params['point']; + $point_cond = $params['point_cond']; + + if ($point != '') { + $point = (int)$point; // 정수로 캐스팅 + + switch ($point_cond) { + case 'lte': + $conditions[] = "mb_point <= {$point}"; + break; + case 'eq': + $conditions[] = "mb_point = {$point}"; + break; + default: + $conditions[] = "mb_point >= {$point}"; + break; + } + } + } + + // 휴대폰 번호 존재 조건 + if (!empty($params['use_hp_exist']) && $params['use_hp_exist'] === '1') { + $conditions[] = "(mb_hp is not null and mb_hp != '')"; + } + + // 정보수신동의 조건 + if (!empty($params['ad_range_only']) && $params['ad_range_only'] === '1') { + $range = isset($params['ad_range_type']) ? $params['ad_range_type'] : ''; + + // 공통: 마케팅 목적 수집·이용 동의 + (필요 시) 제3자 동의 + $thirdparty_clause = $config['cf_sms_use'] !== '' ? " AND mb_thirdparty_agree = 1" : ""; + $base_marketing = "mb_marketing_agree = 1{$thirdparty_clause}"; + + if ($range === 'all') { + // 마케팅 동의 + (이메일 OR SMS 동의) + $conditions[] = "({$base_marketing} AND (mb_mailling = 1 OR mb_sms = 1))"; + } elseif ($range === 'mailling_only') { + // 마케팅 동의 + 이메일 동의 + $conditions[] = "({$base_marketing} AND mb_mailling = 1)"; + } elseif ($range === 'sms_only') { + // 마케팅 동의 + SMS/카카오톡 동의 + $conditions[] = "({$base_marketing} AND mb_sms = 1)"; + } elseif ($range === 'month_confirm' || $range === 'custom_period') { + // 채널 필터 체크 + $useEmail = !empty($params['ad_mailling']); + $useSms = !empty($params['ad_sms']); + + if ($range === 'month_confirm') { + // 23개월 전 그 달 + $start = date('Y-m-01 00:00:00', strtotime('-23 months')); + $end = date('Y-m-t 23:59:59', strtotime('-23 months')); + $emailDateCond = "mb_mailling_date BETWEEN '{$start}' AND '{$end}'"; + $smsDateCond = "mb_sms_date BETWEEN '{$start}' AND '{$end}'"; + + } else { + // 수신동의기간 직접 입력 - custom_period + $date_start = isset($params['agree_date_start']) ? $params['agree_date_start'] : ''; + $date_end = isset($params['agree_date_end']) ? $params['agree_date_end'] : ''; + + if ($date_start && $date_end) { + $emailDateCond = "mb_mailling_date BETWEEN '{$date_start} 00:00:00' AND '{$date_end} 23:59:59'"; + $smsDateCond = "mb_sms_date BETWEEN '{$date_start} 00:00:00' AND '{$date_end} 23:59:59'"; + } elseif ($date_start) { + $emailDateCond = "mb_mailling_date >= '{$date_start} 00:00:00'"; + $smsDateCond = "mb_sms_date >= '{$date_start} 00:00:00'"; + } elseif ($date_end) { + $emailDateCond = "mb_mailling_date <= '{$date_end} 23:59:59'"; + $smsDateCond = "mb_sms_date <= '{$date_end} 23:59:59'"; + } else { + $emailDateCond = "mb_mailling_date <> '0000-00-00 00:00:00'"; + $smsDateCond = "mb_sms_date <> '0000-00-00 00:00:00'"; + } + } + + if (!$useEmail && !$useSms) { + $conditions[] = "0=1"; // 둘 다 해제 ⇒ 결과 0건 + } else { + // 조건 조립 + $parts = []; + if ($useEmail) $parts[] = "(mb_mailling = 1 AND {$emailDateCond})"; + if ($useSms) $parts[] = "(mb_sms = 1 AND {$smsDateCond})"; + + $conditions[] = !empty($parts) ? '(' . implode(' OR ', $parts) . ')' : ''; + } + } + } + + // 차단 회원 조건 + if (!empty($params['use_intercept']) && $params['use_intercept'] === '1') { + switch ($params['intercept']) { + case 'exclude': + $conditions[] = "mb_intercept_date = ''"; + break; + case 'only': + $conditions[] = "mb_intercept_date != ''"; + break; + } + } + + return empty($conditions) ? '' : 'WHERE ' . implode(' AND ', $conditions); +} diff --git a/adm/member_list_exel.php b/adm/member_list_exel.php new file mode 100644 index 000000000..994ae979f --- /dev/null +++ b/adm/member_list_exel.php @@ -0,0 +1,483 @@ +getMessage(); // 메서드 호출 괄호 필수 +} + +$g5['title'] = '회원관리파일'; +require_once './admin.head.php'; +$colspan = 14; +?> + +

회원 엑셀 생성

+ +
+

회원수 건 초과 시 건 단위로 분리 저장되며, 엑셀 생성 최대 건수는 입니다. 초과 시 조건 추가 설정 후 재시도하시기 바랍니다.

+

수신동의 확인 대상은 만료일까지 1달 미만인 회원을 기준으로 필터링됩니다.

+ +
+

파일 생성 시 서버에 임시 생성된 파일 중 오늘 날짜를 제외 한 파일은 자동 삭제되며, 수동 삭제 필요 시 회원관리파일 일괄삭제에서 진행하시기 바랍니다.

+

회원 정보 수정은 회원 관리에서 진행하실 수 있습니다.

+
+ +
+ + 총건수 + + + + + + +
+ + +
+ +
+ 회원 검색 필터링 +
+ + +
+
+ +
+
+ + + + + + +
+
+ + +
+
+ +
+
+ ~ + +
+
+ + +
+
+ +
+
+ ~ + +
+
+ + +
+
+ +
+
+ + + + + + +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+ +
+

「정보통신망이용촉진및정보보호등에관한법률」에 따라 광고성 정보 수신동의 여부매2년마다 확인해야 합니다.

+
+
+ +
+
+
+
+ +
+
+ + +
+ +
+
+ ~ + +

* 광고성 정보 수신(이메일 또는 SMS/카카오톡) 동의일자 기준

+
+
+ + + 개인정보 제3자 제공' : ''; + + $ad_range_text = [ + 'all' => "* 광고성 정보 수신(이메일 또는 SMS/카카오톡) / 마케팅 목적의 개인정보 수집 및 이용{$thirdpartyLbl}에 모두 동의한 회원을 선택합니다.", + 'mailling_only' => "* 광고성 이메일 수신 / 마케팅 목적의 개인정보 수집 및 이용{$thirdpartyLbl}에 모두 동의한 회원을 선택합니다.", + 'sms_only' => "* 광고성 SMS/카카오톡 수신 / 마케팅 목적의 개인정보 수집 및 이용{$thirdpartyLbl}에 모두 동의한 회원을 선택합니다.", + 'month_confirm' => "* 23개월 전(" . date('Y년 m월', strtotime('-23 month')) . ") 광고성 정보 수신 동의(이메일 또는 SMS/카카오톡)한 회원을 선택합니다." + ]; + + if (isset($_GET['ad_range_only'], $_GET['ad_range_type']) && isset($ad_range_text[$_GET['ad_range_type']])) { + echo '

' . $ad_range_text[$_GET['ad_range_type']] . '

'; + } + ?> +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + + + +
+
+
+
+ +
+ + +
+
+
+
+ + + + + + false, 'error' => '데이터가 올바르게 전달되지 않아 작업에 실패하였습니다.']); + exit; +} + +// 기존 생성된 엑셀 파일 삭제 - LOG 및 오늘 날짜 폴더 제외 +$resultExcelDelete = member_export_delete(); + +// 서버 전송 이벤트(SSE)를 위한 헤더 설정 +member_export_set_sse_headers(); + +// 모드 확인 +$mode = isset($_GET['mode']) ? $_GET['mode'] : ''; +if ($mode !== 'start') { + member_export_send_progress("error", "잘못된 요청 입니다."); + member_export_write_log($params, ['success' => false, 'error' => '잘못된 요청 입니다.']); + exit; +} + +/** + * 회원 내보내기 처리 실행 (예외 처리 포함) + */ +try { + main_member_export($params); +} +catch (Exception $e) +{ + // 에러 로그 저장 및 SSE 에러 전송 + error_log("[Member Export Error] " . $e->getMessage()); + member_export_send_progress("error", $e->getMessage()); + member_export_write_log($params, ['success' => false, 'error' => $e->getMessage()]); +} + +/** + * 메인 내보내기 프로세스 + */ +function main_member_export($params) +{ + $total = member_export_get_total_count($params); + + if($total > MEMBER_EXPORT_MAX_SIZE){ + throw new Exception("엑셀 다운로드 가능 범위(최대 " . number_format(MEMBER_EXPORT_MAX_SIZE) . "건)를 초과했습니다.
조건을 추가로 설정하신 후 다시 시도해 주세요."); + } + + if($total <= 0){ + throw new Exception("조회된 데이터가 없어 엑셀 파일을 생성할 수 없습니다.
조건을 추가로 설정하신 후 다시 시도해 주세요."); + } + + $fileName = 'member_'.MEMBER_BASE_DATE; + $fileList = []; + $zipFileName = ''; + + if ($total > MEMBER_EXPORT_PAGE_SIZE) { + // 대용량 데이터 - 분할 처리 + $pages = (int)ceil($total / MEMBER_EXPORT_PAGE_SIZE); + member_export_send_progress("progress", "", 2, $total, 0, $pages, 0); + + for ($i = 1; $i <= $pages; $i++) { + $params['page'] = $i; + + member_export_send_progress("progress", "", 2, $total, ($pages == $i ? $total : $i * MEMBER_EXPORT_PAGE_SIZE), $pages, $i); + try { + $data = member_export_get_data($params); + $fileList[] = member_export_create_excel($data, $fileName, $i); + } catch (Exception $e) { + throw new Exception("총 {$pages}개 중 {$i}번째 파일을 생성하지 못했습니다
" . $e->getMessage()); + } + } + + // 압축 파일 생성 + if (count($fileList) > 1) { + member_export_send_progress("zipping", "", 2, $total, $total, $pages, $i); + $zipResult = member_export_create_zip($fileList, $fileName); // 압축 파일 생성 + + if($zipResult['error']){ + member_export_write_log($params, ['success' => false, 'error' => $zipResult['error']]); + member_export_send_progress("zippingError", $zipResult['error']); + } + + if ($zipResult && $zipResult['result']) { + member_export_delete($fileList); // 압축 후 엑셀 파일 제거 + $zipFileName = $zipResult['zipFile']; + } + } + + } else { + // 소용량 데이터 - 단일 파일 + member_export_send_progress("progress", "", 1, $total, 0); + $data = member_export_get_data($params); + member_export_send_progress("progress", "", 1, $total, $total/2); + $fileList[] = member_export_create_excel($data, $fileName, 0); + member_export_send_progress("progress", "", 1, $total, $total); + } + + member_export_write_log($params, ['success' => true, 'total' => $total, 'files' => $fileList, 'zip' => isset($zipFileName) ? $zipFileName : null]); + member_export_send_progress("done", "", 2, $total, $total, $pages, $pages, $fileList, $zipFileName); +} + +/** + * 진행률 전송 + */ +function member_export_send_progress($status, $message = "", $downloadType = 1, $total = 1, $current = 1, $totalChunks = 1, $currentChunk = 1, $files = [], $zipFile = '') +{ + // 연결 상태 확인 + if (connection_aborted()) return; + + $data = [ + 'status' => $status, + 'message' => $message, + 'downloadType' => $downloadType, + 'total' => $total, + 'current' => $current, + 'totalChunks' => $totalChunks, + 'currentChunk' => $currentChunk, + 'files' => $files, + 'zipFile' => $zipFile, + 'filePath' => G5_DATA_URL . "/" . MEMBER_BASE_DIR . "/" . MEMBER_BASE_DATE, + ]; + + echo "data: " . json_encode($data, JSON_UNESCAPED_UNICODE) . "\n\n"; + + // 더 안정적인 플러시 + if (ob_get_level()) ob_end_flush(); + flush(); +} + +/** + * 엑셀 내보내기 설정 + */ +function member_export_get_config() +{ + $type = 1; + $configs = [ + 1 => [ + 'title' => ["회원관리파일(일반)"], + 'headers' => ['아이디', '이름', '닉네임', '휴대폰번호', '전화번호', '이메일', '주소', '회원권한', '포인트', '가입일', '차단', + '광고성 이메일 수신동의', '광고성 이메일 동의일자', '광고성 SMS/카카오톡 수신동의', '광고성 SMS/카카오톡 동의일자', + '마케팅목적의개인정보수집및이용동의', '마케팅목적의개인정보수집및이용동의일자', '개인정보제3자제공동의', '개인정보제3자제공동의일자'], + 'fields' => ['mb_id', 'mb_name', 'mb_nick', 'mb_hp', 'mb_tel', 'mb_email', 'mb_addr1', 'mb_level', 'mb_point', 'mb_datetime', 'mb_intercept_date', + 'mb_mailling','mb_mailling_date', 'mb_sms','mb_sms_date', 'mb_marketing_agree', + 'mb_marketing_date', 'mb_thirdparty_agree', 'mb_thirdparty_date'], + 'widths' => [20, 20, 20, 20, 20, 30, 30, 10, 15, 25, 10, 20, 25, 20, 25, 20, 25, 20, 25], + ], + ]; + + return isset($configs[$type]) ? $configs[$type] : $configs[1]; +} + +/** + * SSE 헤더 설정 + */ +function member_export_set_sse_headers() +{ + header('Content-Type: text/event-stream'); + header('Cache-Control: no-cache'); + header('Connection: keep-alive'); + header('X-Accel-Buffering: no'); + + if (ob_get_level()) ob_end_flush(); + ob_implicit_flush(true); +} + +/** + * 엑셀 컬럼 문자 반환 + */ +function member_export_column_char($i) +{ + return chr(65 + $i); +} + +/** + * 회원 데이터 조회 + */ +function member_export_get_data($params) +{ + global $g5; + + $config = member_export_get_config(); + $fields = $config['fields']; + $fields = array_unique($fields); + + // SQL 변환 맵 (가공이 필요한 필드만 정의) + $sqlTransformMap = [ + 'mb_datetime' => "IF(mb_datetime = '0000-00-00 00:00:00', '', mb_datetime) AS mb_datetime", + 'mb_intercept_date' => "IF(mb_intercept_date != '', '차단됨', '정상') AS mb_intercept_date", + 'mb_sms' => "IF(mb_sms = '1', '동의', '미동의') AS mb_sms", + 'mb_sms_date' => "IF(mb_sms != '1' OR mb_sms_date = '0000-00-00 00:00:00', '', mb_sms_date) AS mb_sms_date", + 'mb_mailling' => "IF(mb_mailling = '1', '동의', '미동의') AS mb_mailling", + 'mb_mailling_date' => "IF(mb_mailling != '1' OR mb_mailling_date = '0000-00-00 00:00:00', '', mb_mailling_date) AS mb_mailling_date", + 'mb_marketing_agree' => "IF(mb_marketing_agree = '1', '동의', '미동의') AS mb_marketing_agree", + 'mb_marketing_date' => "IF(mb_marketing_agree != '1' OR mb_marketing_date = '0000-00-00 00:00:00', '', mb_marketing_date) AS mb_marketing_date", + 'mb_thirdparty_agree' => "IF(mb_thirdparty_agree = '1', '동의', '미동의') AS mb_thirdparty_agree", + 'mb_thirdparty_date' => "IF(mb_thirdparty_agree != '1' OR mb_thirdparty_date = '0000-00-00 00:00:00', '', mb_thirdparty_date) AS mb_thirdparty_date", + ]; + + // SQL 필드 생성 + $sqlFields = []; + foreach ($fields as $field) { + $sqlFields[] = isset($sqlTransformMap[$field]) ? $sqlTransformMap[$field] : $field; + } + $field_list = implode(', ', $sqlFields); + + $where = member_export_build_where($params); + + $page = (int)(isset($params['page']) ? $params['page'] : 1); + if ($page < 1) $page = 1; + $offset = ($page - 1) * MEMBER_EXPORT_PAGE_SIZE; + + $sql = "SELECT {$field_list} FROM {$g5['member_table']} {$where} ORDER BY mb_no DESC LIMIT {$offset}, " . MEMBER_EXPORT_PAGE_SIZE; + + $result = sql_query($sql); + if (!$result) { + throw new Exception("데이터 조회에 실패하였습니다"); + } + + $excelData = [$config['title'], $config['headers']]; + + while ($row = sql_fetch_array($result)) { + $rowData = []; + foreach ($fields as $field) { + $rowData[] = isset($row[$field]) ? $row[$field] : ''; + } + $excelData[] = $rowData; + } + + return $excelData; +} + +/** + * 엑셀 파일 생성 + */ +function member_export_create_excel($data, $fileName, $index = 0) +{ + $config = member_export_get_config(); + + if (!class_exists('PHPExcel')) { + error_log('[Member Export Error] PHPExcel 라이브러리를 찾을 수 없습니다.'); + throw new Exception('파일 생성 중 내부 오류가 발생했습니다: PHPExcel 라이브러리를 찾을 수 없습니다.'); + } + + // 현재 설정값 백업 + $currentCache = PHPExcel_Settings::getCacheStorageMethod(); + + // 캐싱 모드 설정 (엑셀 생성 전용) + $cacheMethods = [ + PHPExcel_CachedObjectStorageFactory::cache_to_discISAM, + PHPExcel_CachedObjectStorageFactory::cache_in_memory_serialized + ]; + + foreach ($cacheMethods as $method) { + if (PHPExcel_Settings::setCacheStorageMethod($method)) { + break; + } + } + + try { + $excel = new PHPExcel(); + $sheet = $excel->setActiveSheetIndex(0); + + // 헤더 스타일 적용 + $last_char = member_export_column_char(count($config['headers']) - 1); + $sheet->getStyle("A2:{$last_char}2")->applyFromArray([ + 'fill' => [ + 'type' => PHPExcel_Style_Fill::FILL_SOLID, + 'startcolor' => ['rgb' => 'D9E1F2'], // 연파랑 배경 + ], + ]); + + // 셀 정렬 및 줄바꿈 설정 + $sheet->getStyle("A:{$last_char}")->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER)->setWrapText(true); + + // 컬럼 너비 설정 + foreach ($config['widths'] as $i => $width) { + $sheet->getColumnDimension(member_export_column_char($i))->setWidth($width); + } + + // 데이터 입력 + $sheet->fromArray($data, NULL, 'A1'); + + // 디렉토리 확인 + member_export_ensure_directory(MEMBER_EXPORT_DIR); + + // 파일명 생성 + $subname = $index == 0 ? 'all' : sprintf("%02d", $index); + $filename = $fileName . "_" . $subname . ".xlsx"; + $filePath = MEMBER_EXPORT_DIR . "/" . $filename; + + // 파일 저장 + $writer = PHPExcel_IOFactory::createWriter($excel, 'Excel2007'); + $writer->setPreCalculateFormulas(false); + $writer->save($filePath); + + unset($excel, $sheet, $writer); // 생성 완료 후 메모리 해제 + } + catch (Exception $e) + { + throw new Exception("엑셀 파일 생성에 실패하였습니다: " . $e->getMessage()); + } + finally + { + // 캐싱 모드 원래 상태로 복원 + if ($currentCache) { + PHPExcel_Settings::setCacheStorageMethod($currentCache); + } + } + + return $filename; +} + +/** + * 압축 파일 생성 + */ +function member_export_create_zip($files, $zipFileName) +{ + if (!class_exists('ZipArchive')) { + error_log('[Member Export Error] ZipArchive 클래스를 사용할 수 없습니다.'); + return ['error' => '파일을 압축하는 중 문제가 발생했습니다. 개별 파일로 제공됩니다.
: ZipArchive 클래스를 사용할 수 없습니다.']; + } + + member_export_ensure_directory(MEMBER_EXPORT_DIR); + $destinationZipPath = rtrim(MEMBER_EXPORT_DIR, "/") . "/" . $zipFileName . ".zip"; + + $zip = new ZipArchive(); + if ($zip->open($destinationZipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) { + return ['error' => "파일을 압축하는 중 문제가 발생했습니다. 개별 파일로 제공됩니다."]; + } + + foreach ($files as $file) { + $filePath = MEMBER_EXPORT_DIR . "/" . $file; + if (file_exists($filePath)) { + $zip->addFile($filePath, basename($filePath)); + } + } + + $result = $zip->close(); + + return [ + 'result' => $result, + 'zipFile' => $zipFileName . ".zip", + 'zipPath' => $destinationZipPath, + ]; +} + +/** + * 디렉토리 생성 및 확인 + */ +function member_export_ensure_directory($dir) +{ + if (!is_dir($dir)) { + if (!@mkdir($dir, G5_DIR_PERMISSION, true)) { + throw new Exception("디렉토리 생성 실패"); + } + @chmod($dir, G5_DIR_PERMISSION); + } + + if (!is_writable($dir)) { + throw new Exception("디렉토리 쓰기 권한 없음"); + } +} + +/** + * 파일 삭제 - 값이 있으면 해당 파일만 삭제, 없으면 디렉토리 내 모든 파일 삭제 + * - 알집 생성 완료 시 엑셀 파일 제거 + * - 작업 전 오늘 날짜 폴더 및 log 폴더를 제외한 나머지 파일 모두 제거 + */ +function member_export_delete($fileList = []) +{ + $cnt = 0; + + // 파일 리스트가 있는 경우 -> 해당 파일만 삭제 + if (!empty($fileList)) { + foreach ($fileList as $file) { + $filePath = rtrim(MEMBER_EXPORT_DIR, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $file; + if (file_exists($filePath) && is_file($filePath) && @unlink($filePath)) { + $cnt++; + } + } + } + // 파일 리스트가 없는 경우 -> 디렉토리 내 모든 파일 삭제 + else { + $files = glob(rtrim(G5_DATA_PATH . "/" . MEMBER_BASE_DIR, '/') . '/*'); + + function deleteFolder($dir) { + foreach (glob($dir . '/{.,}*', GLOB_BRACE) as $item) { + if (in_array(basename($item), ['.', '..'])) continue; + is_dir($item) ? deleteFolder($item) : unlink($item); + } + rmdir($dir); + } + + foreach ($files as $file) { + $name = basename($file); + + // log 폴더와 오늘 날짜로 시작하는 폴더는 제외 + if ($name === 'log' || preg_match('/^' . date('Ymd') . '\d{6}$/', $name)) continue; + + if (is_file($file) && pathinfo($file, PATHINFO_EXTENSION) !== 'log' && @unlink($file)) { + $cnt++; + } elseif (is_dir($file)) { + deleteFolder($file); // 재귀 폴더 삭제 함수 사용 + $cnt++; + } + } + } + + return $cnt; +} + +/** + * 로그 작성 + */ +function member_export_write_log($params, $result = []) +{ + global $member; + + $maxSize = 1024 * 1024 * 2; // 2MB + $maxFiles = 10; // 최대 로그 파일 수 (필요시 조정) + $username = isset($member['mb_id']) ? $member['mb_id'] : 'guest'; + $datetime = date("Y-m-d H:i:s"); + + if (!is_dir(MEMBER_LOG_DIR)) { + @mkdir(MEMBER_LOG_DIR, G5_DIR_PERMISSION, true); + @chmod(MEMBER_LOG_DIR, G5_DIR_PERMISSION); + } + + $logFiles = glob(MEMBER_LOG_DIR . "/export_log_*.log") ?: []; + + // 최신 파일 기준 정렬 (최신 → 오래된) + usort($logFiles, fn($a, $b) => filemtime($b) - filemtime($a)); + + $latestLogFile = isset($logFiles[0]) ? $logFiles[0] : null; + + // 용량 기준으로 새 파일 생성 + if (!$latestLogFile || filesize($latestLogFile) >= $maxSize) { + $latestLogFile = MEMBER_LOG_DIR . "/export_log_" . date("YmdHi") . ".log"; + file_put_contents($latestLogFile, ''); + array_unshift($logFiles, $latestLogFile); + } + + // 최대 파일 수 초과 시 오래된 파일 제거 + if (count($logFiles) > $maxFiles) { + $filesToDelete = array_slice($logFiles, $maxFiles); + foreach ($filesToDelete as $file) { + @unlink($file); + } + } + + $success = isset($result['success']) && $result['success'] === true; + $status = $success ? '성공' : '실패'; + + // 조건 정리 + $condition = []; + + // 검색 조건 + if ($params['use_stx'] == 1 && !empty($params['stx'])) { + $sfl_list = get_export_config('sfl_list'); + + $label = isset($sfl_list[$params['sfl']]) ? $sfl_list[$params['sfl']] : ''; + $condition[] = "검색({$params['stx_cond']}) : {$label} - {$params['stx']}"; + } + + // 레벨 조건 + if ($params['use_level'] == 1 && ($params['level_start'] || $params['level_end'])) { + $condition[] = "레벨: {$params['level_start']}~{$params['level_end']}"; + } + + // 가입일 조건 + if ($params['use_date'] == 1 && ($params['date_start'] || $params['date_end'])) { + $condition[] = "가입일: {$params['date_start']}~{$params['date_end']}"; + } + + // 포인트 조건 + if ($params['use_point'] == 1 && $params['point'] !== '') { + $point_cond_map = get_export_config('point_cond_map'); + $symbol = isset($point_cond_map[$params['point_cond']]) ? $point_cond_map[$params['point_cond']] : '≥'; + $condition[] = "포인트 {$symbol} {$params['point']}"; + } + + // 휴대폰 여부 + if ($params['use_hp_exist'] == 1) { + $condition[] = "휴대폰번호 있는 경우만"; + } + + // 광고 수신 동의 + if ($params['ad_range_only'] == 1) { + $ad_range_list = get_export_config('ad_range_list'); + $label = isset($ad_range_list[$params['ad_range_type']]) ? $ad_range_list[$params['ad_range_type']] : ''; + $condition[] = "수신동의: 예 ({$label})"; + + if ($params['ad_range_type'] == "custom_period" && ($params['agree_date_start'] || $params['agree_date_end'])) { + $condition[] = "수신동의일: {$params['agree_date_start']}~{$params['agree_date_end']}"; + } + + if (in_array($params['ad_range_type'], ["month_confirm", "custom_period"])){ + $channels = array_filter([ + !empty($params['ad_mailling']) && (int)$params['ad_mailling'] === 1 ? '이메일' : null, + !empty($params['ad_sms']) && (int)$params['ad_sms'] === 1 ? 'SMS/카카오톡' : null, + ]); + + if ($channels) { + $condition[] = '수신채널: ' . implode(', ', $channels); + } + } + } + + // 차단회원 처리 + if ($params['use_intercept'] == 1) { + $intercept_list = get_export_config('intercept_list'); + $label = isset($intercept_list[$params['intercept']]) ? $intercept_list[$params['intercept']] : ''; + if ($label) $condition[] = $label; + } + + $conditionStr = !empty($condition) ? implode(', ', $condition) : '없음'; + $line1 = "[{$datetime}] [{$status}] 관리자: {$username}"; + + // 성공일 경우 추가 정보 + if ($success) { + $total = isset($result['total']) ? $result['total'] : 0; + $fileCount = isset($result['zip']) ? 1 : count(isset($result['files']) ? $result['files'] : []); + $line1 .= " | 총 {$total}건 | 파일: {$fileCount}개"; + } + + $logEntry = $line1 . PHP_EOL; + $logEntry .= "조건: {$conditionStr}" . PHP_EOL; + + if (!$success && !empty($result['error'])) { + $logEntry .= "오류 메시지: {$result['error']}" . PHP_EOL; + } + + $logEntry .= PHP_EOL; + + // 파일에 기록 + if (@file_put_contents($latestLogFile, $logEntry, FILE_APPEND | LOCK_EX) === false) { + error_log("[Member Export Error] 로그 파일 기록 실패: {$latestLogFile}"); + } +} \ No newline at end of file diff --git a/adm/member_list_file_delete.php b/adm/member_list_file_delete.php new file mode 100644 index 000000000..d6c1fb058 --- /dev/null +++ b/adm/member_list_file_delete.php @@ -0,0 +1,72 @@ + + +
+

+ 완료 메세지가 나오기 전에 프로그램의 실행을 중지하지 마십시오. +

+
+ +회원관리파일를 열지못했습니다.

'; +} + +$cnt = 0; +echo '' . PHP_EOL; +echo '

회원관리파일 ' . $cnt . '건 삭제 완료됐습니다.
프로그램의 실행을 끝마치셔도 좋습니다.

' . PHP_EOL; +?> + +(주의!) 토스페이먼츠 결제의 결제 설정이 현재 테스트결제로 되어 있습니다.
반드시 상점 API키[테스트]키로 설정한 후 테스트결제를 진행해야합니다.
쇼핑몰 운영 시에는 실결제로 전환하여 [라이브]키로 설정해 주시기 바랍니다.
아래 링크를 클릭하여 실결제로 설정하여 운영해 주세요.
'.$pg_test_conf_link.''; } else if ( $default['de_pg_service'] === 'inicis' && $default['de_inicis_mid'] && $default['de_inicis_sign_key'] ){ $pg_msg = 'KG이니시스'; } else if ( $default['de_pg_service'] === 'nicepay' && $default['de_nicepay_mid'] && $default['de_nicepay_key'] ){ @@ -147,7 +150,6 @@ function pg_setting_check($is_print=false){ } if( $pg_msg ){ - $pg_test_conf_link = G5_ADMIN_URL.'/shop_admin/configform.php#de_card_test1'; $msg .= '
(주의!) '.$pg_msg.' 결제의 결제 설정이 현재 테스트결제 로 되어 있습니다.
테스트결제시 실제 결제가 되지 않으므로, 쇼핑몰 운영중이면 반드시 실결제로 설정하여 운영하셔야 합니다.
아래 링크를 클릭하여 실결제로 설정하여 운영해 주세요.
'.$pg_test_conf_link.'
'; } @@ -170,6 +172,10 @@ function is_cancel_shop_pg_order($od){ $is_od_pg_cancel = true; } + if($od['od_pg'] === 'toss' && in_array($od['od_settle_case'], array('계좌이체', '휴대폰'))) { + $is_od_pg_cancel = true; + } + return $is_od_pg_cancel; } diff --git a/adm/shop_admin/configform.php b/adm/shop_admin/configform.php index 54bbaa6f2..95f3e54b3 100644 --- a/adm/shop_admin/configform.php +++ b/adm/shop_admin/configform.php @@ -215,6 +215,14 @@ if (! isset($default['de_nicepay_mid'])) { sql_query($sql, false); } +// 토스페이먼츠 client, secret key 추가 +if( ! isset($config['cf_toss_client_key']) ){ + $sql = "ALTER TABLE `{$g5['config_table']}` + ADD COLUMN `cf_toss_client_key` VARCHAR(100) NOT NULL DEFAULT '' AFTER `cf_lg_mert_key`, + ADD COLUMN `cf_toss_secret_key` VARCHAR(100) NOT NULL DEFAULT '' AFTER `cf_toss_client_key`; "; + sql_query($sql, false); +} + if( function_exists('pg_setting_check') ){ pg_setting_check(true); } @@ -636,17 +644,23 @@ if(!$default['de_kakaopay_cancelpwd']){ /settle_kcp_common.php - KG이니시스 가상계좌 입금통보 URL + KG이니시스 가상계좌
입금통보 URL KG이니시스 관리자 > 거래내역 > 가상계좌 > 입금통보방식선택 > URL 수신 설정에 넣으셔야 상점에 자동으로 입금 통보됩니다."); ?> /settle_inicis_common.php - NICEPAY 가상계좌 입금통보 URL + NICEPAY 가상계좌
입금통보 URL NICEPAY 관리자 > 가맹점관리자페이지 설정 (메인화면 → 가맹점정보 클릭)에 넣으셔야 상점에 자동으로 입금 통보됩니다."); ?> /settle_nicepay_common.php + + 토스페이먼츠 가상계좌
입금통보 URL + + 토스페이먼츠 상점관리자 > 개발자센터 > 웹훅 > 웹훅 등록하기에 URL에 넣으시고, 구독할 이벤트를 [DEPOSIT_CALLBACK]을 선택하셔야 상점에 자동으로 입금 통보됩니다."); ?> + /settle_toss_common.php + @@ -687,6 +701,7 @@ if(!$default['de_kakaopay_cancelpwd']){ + @@ -775,7 +790,8 @@ if(!$default['de_kakaopay_cancelpwd']){ @@ -833,12 +849,26 @@ if(!$default['de_kakaopay_cancelpwd']){ - + - 계약정보 -> 상점정보관리에서 확인하실 수 있습니다.\n예) 95160cce09854ef44d2edb2bfb05f9f3\n기본환경설정 > 본인확인 설정의 토스페이먼츠 MERT KEY와 동일합니다."); ?> + 개발자센터 -> API키 -> 머트 키에서 확인하실 수 있습니다.\n예) 95160cce09854ef44d2edb2bfb05f9f3"); ?> + + + + 개발자센터 -> API키 -> 클라이언트 키에서 확인하실 수 있습니다. 예) live_ck_tosspayment\n실결제용 [라이브] 키와 테스트용 [테스트] 키는 서로 다르므로, 테스트로 결제시에는 [테스트] 키로 변경하여 사용해주시기 바랍니다. 예) 테스트 키: test_ck_tosspayment"); ?> + + + + + + + 개발자센터 -> API키 -> 시크릿 키에서 확인하실 수 있습니다. 예) live_sk_tosspayment\n실결제용 [라이브] 키와 테스트용 [테스트] 키는 서로 다르므로, 테스트로 결제시에는 [테스트] 키로 변경하여 사용해주시기 바랍니다. 예) 테스트 키: test_sk_tosspayment"); ?> + + +
@@ -1070,6 +1100,9 @@ if(!$default['de_kakaopay_cancelpwd']){ 실결제 관리자 테스트 관리자 + @@ -1095,6 +1128,9 @@ if(!$default['de_kakaopay_cancelpwd']){ + @@ -1769,7 +1805,11 @@ function fconfig_check(f) } } else if ( f.de_pg_service.value == "lg" ) { if( f.cf_lg_mid.value && f.cf_lg_mert_key.value && parseInt(f.de_card_test.value) > 0 ){ - pg_msg = "토스페이먼츠"; + pg_msg = "토스페이먼츠(구버전)"; + } + } else if ( f.de_pg_service.value == "toss" ) { + if( f.cf_lg_mid.value && f.cf_toss_client_key.value && f.cf_toss_secret_key.value && parseInt(f.de_card_test.value) > 0 ){ + msg += "(주의!) 토스페이먼츠 결제의 결제 설정이 현재 테스트결제로 되어 있습니다.\n상점 API키를 [테스트]키로 설정한 후 테스트결제를 진행해주세요.\n쇼핑몰 운영중이면 반드시 실결제 전환 및 [라이브]키로 설정하여 운영하셔야 합니다.\n실결제로 변경하려면 결제설정 탭 -> 결제 테스트에서 실결제를 선택해 주세요.\n정말로 테스트결제로 설정하시겠습니까?"; } } else if ( f.de_pg_service.value == "inicis" ) { if( f.de_inicis_mid.value && f.de_inicis_sign_key.value && parseInt(f.de_card_test.value) > 0 ){ diff --git a/adm/shop_admin/configformupdate.php b/adm/shop_admin/configformupdate.php index edbe82937..adfb06ea8 100644 --- a/adm/shop_admin/configformupdate.php +++ b/adm/shop_admin/configformupdate.php @@ -159,6 +159,8 @@ $check_sanitize_keys = array( 'de_kcp_site_key', //NHN KCP SITE KEY 'cf_lg_mid', //LG유플러스 상점아이디 'cf_lg_mert_key', //LG유플러스 MERT KEY +'cf_toss_client_key', //토스페이먼츠 MERT KEY +'cf_toss_secret_key', //토스페이먼츠 MERT KEY 'de_inicis_mid', //KG이니시스 상점아이디 'de_inicis_iniapi_key', //KG이니시스 INIAPI KEY 'de_inicis_iniapi_iv', //KG이니시스 INIAPI IV @@ -465,7 +467,9 @@ $sql = " update {$g5['config_table']} cf_icode_server_port = '{$_POST['cf_icode_server_port']}', cf_icode_token_key = '{$cf_icode_token_key}', cf_lg_mid = '{$cf_lg_mid}', - cf_lg_mert_key = '{$cf_lg_mert_key}' "; + cf_lg_mert_key = '{$cf_lg_mert_key}', + cf_toss_client_key = '{$cf_toss_client_key}', + cf_toss_secret_key = '{$cf_toss_secret_key}' "; sql_query($sql); run_event('shop_admin_configformupdate'); diff --git a/adm/shop_admin/itemformupdate.php b/adm/shop_admin/itemformupdate.php index 9543b568f..52ee641ee 100644 --- a/adm/shop_admin/itemformupdate.php +++ b/adm/shop_admin/itemformupdate.php @@ -235,6 +235,14 @@ sql_query(" delete from {$g5['g5_shop_event_item_table']} where it_id = '$it_id' // 선택옵션 sql_query(" delete from {$g5['g5_shop_item_option_table']} where io_type = '0' and it_id = '$it_id' "); // 기존선택옵션삭제 +// 금지할 패턴 목록 +$forbidden_patterns = array( + '/<\s*script/i', // diff --git a/adm/shop_admin/itemsupply.php b/adm/shop_admin/itemsupply.php index 389c2bf62..955241001 100644 --- a/adm/shop_admin/itemsupply.php +++ b/adm/shop_admin/itemsupply.php @@ -55,12 +55,12 @@ if($ps_run) { ?> - - + + - - + + diff --git a/adm/shop_admin/orderform.php b/adm/shop_admin/orderform.php index 758f97295..a4f57e4c1 100644 --- a/adm/shop_admin/orderform.php +++ b/adm/shop_admin/orderform.php @@ -607,7 +607,7 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js switch($od['od_pg']) { case 'lg': $pg_url = 'https://app.tosspayments.com'; - $pg_test = '토스페이먼츠'; + $pg_test = '토스페이먼츠(구버전)'; if ($default['de_card_test']) { $pg_url = 'https://pgweb.tosspayments.com/tmert'; $pg_test .= ' 테스트 '; @@ -625,6 +625,10 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js $pg_url = 'https://npg.nicepay.co.kr/'; $pg_test = 'NICEPAY'; break; + case 'toss': + $pg_url = 'https://app.tosspayments.com'; + $pg_test = '토스페이먼츠 '; + break; default: $pg_url = 'http://admin8.kcp.co.kr'; $pg_test = 'KCP'; @@ -737,6 +741,8 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js break; } $cash_receipt_script = 'javascript:showCashReceipts(\''.$LGD_MID.'\',\''.$od['od_id'].'\',\''.$od['od_casseqno'].'\',\''.$trade_type.'\',\''.$CST_PLATFORM.'\');'; + } else if($od['od_pg'] == 'toss') { + $cash_receipt_script = 'window.open(\'https://dashboard.tosspayments.com/receipt/mids/si_'.$config['cf_lg_mid'].'/orders/'.$od['od_id'].'/cash-receipt?ref=dashboard\',\'receipt\',\'width=430,height=700\');'; } else if($od['od_pg'] == 'inicis') { $cash = unserialize($od['od_cash_info']); $cash_receipt_script = 'window.open(\'https://iniweb.inicis.com/DefaultWebApp/mall/cr/cm/Cash_mCmReceipt.jsp?noTid='.$cash['TID'].'&clpaymethod=22\',\'showreceipt\',\'width=380,height=540,scrollbars=no,resizable=no\');'; @@ -825,6 +831,7 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js
+ @@ -939,6 +946,7 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js
+ diff --git a/adm/shop_admin/orderformcartupdate.php b/adm/shop_admin/orderformcartupdate.php index b54bdfe6b..0cbcfba58 100644 --- a/adm/shop_admin/orderformcartupdate.php +++ b/adm/shop_admin/orderformcartupdate.php @@ -251,6 +251,10 @@ if (in_array($_POST['ct_status'], $status_cancel)) { $pg_res_msg = $xpay->Response_Msg(); } break; + case 'toss': + $cancel_msg = '쇼핑몰 운영자 승인 취소'; + include_once(G5_SHOP_PATH.'/toss/toss_cancel.php'); + break; case 'inicis': include_once(G5_SHOP_PATH.'/settle_inicis.inc.php'); $cancel_msg = '쇼핑몰 운영자 승인 취소'; diff --git a/adm/shop_admin/personalpayform.php b/adm/shop_admin/personalpayform.php index 6c0005511..d67df8d51 100644 --- a/adm/shop_admin/personalpayform.php +++ b/adm/shop_admin/personalpayform.php @@ -210,6 +210,8 @@ if(!sql_query(" select pp_cash from {$g5['g5_shop_personalpay_table']} limit 1 " break; } $cash_receipt_script = 'javascript:showCashReceipts(\''.$LGD_MID.'\',\''.$pp['pp_id'].'\',\''.$pp['pp_casseqno'].'\',\''.$trade_type.'\',\''.$CST_PLATFORM.'\');'; + } else if($pp['pp_pg'] == 'toss') { + $cash_receipt_script = 'window.open(\'https://dashboard.tosspayments.com/receipt/mids/si_'.$config['cf_lg_mid'].'/orders/'.$pp['pp_id'].'/cash-receipt?ref=dashboard\',\'receipt\',\'width=430,height=700\');'; } else if($pp['pp_pg'] == 'inicis') { $cash = unserialize($pp['pp_cash_info']); $cash_receipt_script = 'window.open(\'https://iniweb.inicis.com/DefaultWebApp/mall/cr/cm/Cash_mCmReceipt.jsp?noTid='.$cash['TID'].'&clpaymethod=22\',\'showreceipt\',\'width=380,height=540,scrollbars=no,resizable=no\');'; diff --git a/adm/sms_admin/_common.php b/adm/sms_admin/_common.php index e295daf97..8c13c71a9 100644 --- a/adm/sms_admin/_common.php +++ b/adm/sms_admin/_common.php @@ -5,6 +5,16 @@ include_once(G5_ADMIN_PATH.'/admin.lib.php'); include_once(G5_SMS5_PATH.'/sms5.lib.php'); if (!strstr($_SERVER['SCRIPT_NAME'], 'install.php')) { + // SMS5 테이블 G5_TABLE_PREFIX 적용 + if($g5['sms5_prefix'] != 'sms5_' && sql_num_rows(sql_query("show tables like 'sms5_config'"))) + { + echo ''; + exit; + } + if(!sql_num_rows(sql_query(" show tables like '{$g5['sms5_config_table']}' "))) goto_url('install.php'); diff --git a/bbs/db_table.optimize.php b/bbs/db_table.optimize.php index 58345832d..4ce6e631d 100644 --- a/bbs/db_table.optimize.php +++ b/bbs/db_table.optimize.php @@ -14,7 +14,9 @@ if($config['cf_visit_del'] > 0) { $tmp_before_date = date("Y-m-d", G5_SERVER_TIME - ($config['cf_visit_del'] * 86400)); $sql = " delete from {$g5['visit_table']} where vi_date < '$tmp_before_date' "; sql_query($sql); - sql_query(" OPTIMIZE TABLE `{$g5['visit_table']}`, `{$g5['visit_sum_table']}` "); + if (defined('G5_USE_OPTIMIZE_DBTABLE') && G5_USE_OPTIMIZE_DBTABLE) { + sql_query(" OPTIMIZE TABLE `{$g5['visit_table']}`, `{$g5['visit_sum_table']}` "); + } } // 설정일이 지난 인기검색어 삭제 @@ -22,7 +24,9 @@ if($config['cf_popular_del'] > 0) { $tmp_before_date = date("Y-m-d", G5_SERVER_TIME - ($config['cf_popular_del'] * 86400)); $sql = " delete from {$g5['popular_table']} where pp_date < '$tmp_before_date' "; sql_query($sql); - sql_query(" OPTIMIZE TABLE `{$g5['popular_table']}` "); + if (defined('G5_USE_OPTIMIZE_DBTABLE') && G5_USE_OPTIMIZE_DBTABLE) { + sql_query(" OPTIMIZE TABLE `{$g5['popular_table']}` "); + } } // 설정일이 지난 최근게시물 삭제 @@ -36,7 +40,9 @@ if($config['cf_new_del'] > 0) { if($config['cf_memo_del'] > 0) { $sql = " delete from {$g5['memo_table']} where (TO_DAYS('".G5_TIME_YMDHIS."') - TO_DAYS(me_send_datetime)) > '{$config['cf_memo_del']}' "; sql_query($sql); - sql_query(" OPTIMIZE TABLE `{$g5['memo_table']}` "); + if (defined('G5_USE_OPTIMIZE_DBTABLE') && G5_USE_OPTIMIZE_DBTABLE) { + sql_query(" OPTIMIZE TABLE `{$g5['memo_table']}` "); + } } // 탈퇴회원 자동 삭제 @@ -65,4 +71,8 @@ if($captcha_mp3 && is_array($captcha_mp3)) { // 실행일 기록 if(isset($config['cf_optimize_date'])) { sql_query(" update {$g5['config_table']} set cf_optimize_date = '".G5_TIME_YMD."' "); -} \ No newline at end of file + + run_event('cf_optimize_date_update', $config); +} + +run_event('db_table_optimize_end', $config); \ No newline at end of file diff --git a/bbs/memo_form.php b/bbs/memo_form.php index 02848e129..55ea41a36 100644 --- a/bbs/memo_form.php +++ b/bbs/memo_form.php @@ -20,7 +20,7 @@ $me_id = isset($_REQUEST['me_id']) ? clean_xss_tags($_REQUEST['me_id'] if ($me_recv_mb_id) { $mb = get_member($me_recv_mb_id); - if (!$mb['mb_id']) + if (!(isset($mb['mb_id']) && $mb['mb_id'])) alert_close('회원정보가 존재하지 않습니다.\\n\\n탈퇴하였을 수 있습니다.'); if (!$mb['mb_open'] && $is_admin != 'super') diff --git a/bbs/qawrite_update.php b/bbs/qawrite_update.php index b6752f849..d7d279162 100644 --- a/bbs/qawrite_update.php +++ b/bbs/qawrite_update.php @@ -86,6 +86,7 @@ $qa_related = 0; $qa_email_recv = (isset($_POST['qa_email_recv']) && $_POST['qa_email_recv']) ? 1 : 0; $qa_sms_recv = (isset($_POST['qa_sms_recv']) && $_POST['qa_sms_recv']) ? 1 : 0; $qa_status = 0; +$qa_html = (isset($_POST['qa_html']) && $_POST['qa_html']) ? (int) $_POST['qa_html'] : 0; $answer_id = null; for ($i=1; $i<=5; $i++) { diff --git a/bbs/register_form_update.php b/bbs/register_form_update.php index 08cd81ead..cbcbc7e02 100644 --- a/bbs/register_form_update.php +++ b/bbs/register_form_update.php @@ -50,8 +50,8 @@ $mb_addr_jibeon = isset($_POST['mb_addr_jibeon']) ? trim($_POST['mb_addr_jibeo $mb_signature = isset($_POST['mb_signature']) ? trim($_POST['mb_signature']) : ""; $mb_profile = isset($_POST['mb_profile']) ? trim($_POST['mb_profile']) : ""; $mb_recommend = isset($_POST['mb_recommend']) ? trim($_POST['mb_recommend']) : ""; -$mb_mailling = isset($_POST['mb_mailling']) ? trim($_POST['mb_mailling']) : ""; -$mb_sms = isset($_POST['mb_sms']) ? trim($_POST['mb_sms']) : ""; +$mb_mailling = isset($_POST['mb_mailling']) ? trim($_POST['mb_mailling']) : "0"; +$mb_sms = isset($_POST['mb_sms']) ? trim($_POST['mb_sms']) : "0"; $mb_open = isset($_POST['mb_open']) ? trim($_POST['mb_open']) : "0"; $mb_1 = isset($_POST['mb_1']) ? trim($_POST['mb_1']) : ""; $mb_2 = isset($_POST['mb_2']) ? trim($_POST['mb_2']) : ""; @@ -63,8 +63,7 @@ $mb_7 = isset($_POST['mb_7']) ? trim($_POST['mb_7']) $mb_8 = isset($_POST['mb_8']) ? trim($_POST['mb_8']) : ""; $mb_9 = isset($_POST['mb_9']) ? trim($_POST['mb_9']) : ""; $mb_10 = isset($_POST['mb_10']) ? trim($_POST['mb_10']) : ""; - -$mb_name = clean_xss_tags($mb_name); +$mb_name = clean_xss_tags($mb_name, 1, 1); $mb_email = get_email_address($mb_email); $mb_homepage = clean_xss_tags($mb_homepage); $mb_tel = clean_xss_tags($mb_tel); @@ -75,6 +74,9 @@ $mb_addr2 = clean_xss_tags($mb_addr2); $mb_addr3 = clean_xss_tags($mb_addr3); $mb_addr_jibeon = preg_match("/^(N|R)$/", $mb_addr_jibeon) ? $mb_addr_jibeon : ''; +$mb_marketing_agree = isset($_POST['mb_marketing_agree']) ? trim($_POST['mb_marketing_agree']) : "0"; +$mb_thirdparty_agree = isset($_POST['mb_thirdparty_agree']) ? trim($_POST['mb_thirdparty_agree']) : "0"; + run_event('register_form_update_before', $mb_id, $w); if ($w == '' || $w == 'u') { @@ -250,12 +252,46 @@ if ($w == '') { mb_7 = '{$mb_7}', mb_8 = '{$mb_8}', mb_9 = '{$mb_9}', - mb_10 = '{$mb_10}' + mb_10 = '{$mb_10}', + mb_marketing_agree = '{$mb_marketing_agree}', + mb_thirdparty_agree = '{$mb_thirdparty_agree}' {$sql_certify} "; // 이메일 인증을 사용하지 않는다면 이메일 인증시간을 바로 넣는다 if (!$config['cf_use_email_certify']) $sql .= " , mb_email_certify = '".G5_TIME_YMDHIS."' "; + + $agree_items = []; + // 마케팅 목적의 개인정보 수집 및 이용 + if ($mb_marketing_agree == 1) { + $sql .= " , mb_marketing_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "마케팅 목적의 개인정보 수집 및 이용(동의)"; + } + + // 광고성 이메일 수신 + if ($mb_mailling == 1) { + $sql .= " , mb_mailling_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 이메일 수신(동의)"; + } + + // 광고성 SMS/카카오톡 수신 + if ($mb_sms == 1) { + $sql .= " , mb_sms_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 SMS/카카오톡 수신(동의)"; + } + + // 개인정보 제3자 제공 + if ($mb_thirdparty_agree == 1) { + $sql .= " , mb_thirdparty_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "개인정보 제3자 제공(동의)"; + } + + // 동의 로그 추가 + if (!empty($agree_items)) { + $agree_log = "[".G5_TIME_YMDHIS.", 회원가입] " . implode(' | ', $agree_items) . "\n"; + $sql .= " , mb_agree_log = CONCAT('{$agree_log}', IFNULL(mb_agree_log, ''))"; + } + sql_query($sql); // 회원가입 포인트 부여 @@ -346,6 +382,43 @@ if ($w == '') { if ($old_email != $mb_email && $config['cf_use_email_certify']) $sql_email_certify = " , mb_email_certify = '' "; + $agree_items = []; + + // 마케팅 목적의 개인정보 수집 및 이용 + $sql_marketing_date = ""; + if ($mb_marketing_agree_default !== $mb_marketing_agree) { + $sql_marketing_date .= " , mb_marketing_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "마케팅 목적의 개인정보 수집 및 이용(" . ($mb_marketing_agree == 1 ? "동의" : "철회") . ")"; + } + + // 광고성 이메일 수신 + $sql_mailling_date = ""; + if ($mb_mailling_default !== $mb_mailling) { + $sql_mailling_date .= " , mb_mailling_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 이메일 수신(" . ($mb_mailling == 1 ? "동의" : "철회") . ")"; + } + + // 광고성 SMS/카카오톡 수신 + $sql_sms_date = ""; + if ($mb_sms_default !== $mb_sms) { + $sql_sms_date .= " , mb_sms_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 SMS/카카오톡 수신(" . ($mb_sms == 1 ? "동의" : "철회") . ")"; + } + + // 개인정보 제3자 제공 + $sql_thirdparty_date = ""; + if ($mb_thirdparty_agree_default !== $mb_thirdparty_agree) { + $sql_thirdparty_date .= " , mb_thirdparty_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "개인정보 제3자 제공(" . ($mb_thirdparty_agree == 1 ? "동의" : "철회") . ")"; + } + + // 동의 로그 추가 + $sql_agree_log = ""; + if (!empty($agree_items)) { + $agree_log = "[".G5_TIME_YMDHIS.", 회원 정보 수정] " . implode(' | ', $agree_items) . "\n"; + $sql_agree_log .= " , mb_agree_log = CONCAT('{$agree_log}', IFNULL(mb_agree_log, ''))"; + } + $sql = " update {$g5['member_table']} set mb_nick = '{$mb_nick}', mb_mailling = '{$mb_mailling}', @@ -371,12 +444,19 @@ if ($w == '') { mb_7 = '{$mb_7}', mb_8 = '{$mb_8}', mb_9 = '{$mb_9}', - mb_10 = '{$mb_10}' + mb_10 = '{$mb_10}', + mb_marketing_agree = '{$mb_marketing_agree}', + mb_thirdparty_agree = '{$mb_thirdparty_agree}' {$sql_password} {$sql_nick_date} {$sql_open_date} {$sql_email_certify} {$sql_certify} + {$sql_mailling_date} + {$sql_sms_date} + {$sql_marketing_date} + {$sql_thirdparty_date} + {$sql_agree_log} where mb_id = '$mb_id' "; sql_query($sql); diff --git a/bbs/view_comment.php b/bbs/view_comment.php index 447c125fc..2f143bde6 100644 --- a/bbs/view_comment.php +++ b/bbs/view_comment.php @@ -7,7 +7,7 @@ if ($is_guest && $board['bo_comment_level'] < 2) { $captcha_html = captcha_html('_comment'); } -$c_id = isset($_GET['c_id']) ? clean_xss_tags($_GET['c_id'], 1, 1) : ''; +$c_id = isset($_GET['c_id']) ? preg_replace('/[\'",]/', '', clean_xss_tags($_GET['c_id'], 1, 1)) : ''; $c_wr_content = ''; @include_once($board_skin_path.'/view_comment.head.skin.php'); diff --git a/css/default.css b/css/default.css index b32a453e0..05ec8c8a2 100644 --- a/css/default.css +++ b/css/default.css @@ -55,6 +55,16 @@ border:1px solid #558ab7 !important; #container_wr, #ft_wr {width:1200px} +/* 공통 - display none/block */ +.is-hidden { display: none !important; } +.is-visible { display: block !important; } + +/* 공통 - 뷰포트 (pc / mobile) 별 display none/block */ +.pc-only { display: none; } +@media (min-width: 769px) { .pc-only { display: block !important; }} +.mobile-only { display: block; } +@media (min-width: 769px) { .mobile-only { display: none !important; }} + /* 팝업레이어 */ #hd_pop {z-index:1000;position:relative;margin:0 auto;height:0} #hd_pop h2 {position:absolute;font-size:0;line-height:0;overflow:hidden} @@ -332,6 +342,8 @@ box-shadow:inset 0 1px 1px rgba(0, 0, 0, .075); .tbl_frm01 a {text-decoration:none} .tbl_frm01 .frm_file {display:block;margin-bottom:5px} .tbl_frm01 .frm_info {display:block;padding:0 0 5px;line-height:1.4em} +.frm_info.add_info { margin-top: 10px !important; padding: 8px 12px; background: #fff; border: 1px solid #ddd; border-radius: 6px; line-height: 1.6; } +.btn_info_toggle { display: block; margin: 5px 0 0 21px; font-size: 12px; color: #3f51b5; background: none; border: none; cursor: pointer; text-decoration: underline; } /*기본 리스트*/ .list_01 ul {border-top:1px solid #ececec} diff --git a/css/default_shop.css b/css/default_shop.css index ec5188f20..8f6191f2e 100644 --- a/css/default_shop.css +++ b/css/default_shop.css @@ -812,6 +812,7 @@ box-shadow: 1px 2px 2px #eee;} #sod_frm_paysel .inicis_kakaopay em{position:absolute;top:15px;left:45px;width:70px;height:30px;background:url('../img/kakao.png') no-repeat 50% 50% #ffeb00;overflow:hidden;text-indent:-999px;border-radius:30px} #sod_frm_paysel .kakaopay_icon{background:url('../img/kakao.png') no-repeat 50% 50% #fff;overflow:hidden;text-indent:-999px} #sod_frm_paysel .naverpay_icon{background:url('../img/ico-default-naverpay.png') no-repeat 50% 50% #fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .naverpay_icon.nhnkcp_icon{text-indent:0;background-position: 50% 30%;padding-top:35px;padding-left:0;text-align:center} #sod_frm_paysel .samsungpay_icon{background:url('../img/samsungpay.png') no-repeat 50% 50% #fff;display:inline-block;overflow:hidden;text-indent:-999px} #sod_frm_paysel .ssgpay_icon{background:url('../img/ssgpay_icon.png') no-repeat 50% 50% #fff;display:inline-block;overflow:hidden;text-indent:-999px} #sod_frm_paysel .skpay_icon{background:url('../img/skpay11_icon.png') no-repeat 50% 50% #fff; background-size: 70px;display:inline-block;overflow:hidden;text-indent:-999px} @@ -1151,6 +1152,8 @@ box-shadow: 1px 2px 2px #eee;} .sod_frm_mobile #m_sod_frm_paysel .inicis_lpay{background:url(../img/lpay_logo.png) no-repeat;width:35px;height:12px;overflow:hidden;text-indent:-999px;display:inline-block;background-size:100%} .sod_frm_mobile #m_sod_frm_paysel .inicis_kakaopay{background:url(../img/kakao.png) no-repeat 50% 50% #f4dc34;border-radius:30px;height:22px;width:74px;display:inline-block;overflow:hidden;text-indent:-999px;background-size:35px auto} .sod_frm_mobile #m_sod_frm_paysel .kakaopay_icon{background:url(../img/kakao.png) no-repeat 50% 50% #f4dc34;border-radius:30px;height:22px;width:74px;display:inline-block;overflow:hidden;text-indent:-999px;background-size:35px auto} +.sod_frm_mobile #m_sod_frm_paysel .naverpay_icon{background:url(../img/ico-default-naverpay.png) no-repeat 50% 50% #fff;border-radius:30px;height:22px;width:50px;display:inline-block;overflow:hidden;text-indent:-999px;background-size:35px auto} +.sod_frm_mobile #m_sod_frm_paysel .naverpay_icon.nhnkcp_icon{text-indent:0;padding-left:50px;padding-top:2px;width:83px} .sod_frm_mobile #m_sod_frm_paysel .applepay_icon{background:url(../img/ico-mobile-applepay.png) no-repeat 50% 50% #fff;border-radius:30px;height:23px;width:50px;display:inline-block;overflow:hidden;text-indent:-999px;background-size:35px auto} .sod_frm_mobile #m_sod_frm_paysel .samsung_pay{margin-left:-23px;background:url(../img/samsungpay.png) no-repeat 24px 3px;height:25px;width:106px;display:inline-block;overflow:hidden;text-indent:-999px} .sod_frm_mobile #sod_frm_pay{border-top:1px solid #f3f3f3} diff --git a/css/mobile_shop.css b/css/mobile_shop.css index 07849cb09..748730fc3 100644 --- a/css/mobile_shop.css +++ b/css/mobile_shop.css @@ -228,6 +228,7 @@ box-shadow: 0 0 6px rgba(0,0,0,0.2);} #m_sod_frm_paysel .inicis_kakaopay{background:url('../img/kakao.png') no-repeat 50% 50% #ffeb00;border-radius:30px;height:26px;width:74px;display:inline-block;overflow:hidden;text-indent:-999px;background-size:36px auto} #m_sod_frm_paysel .kakaopay_icon{background:url('../img/ico-mobile-kakaopay.png') no-repeat #fff;height:23px;width:63px;display:inline-block;overflow:hidden;text-indent:-999px;background-size:45px auto;background-position: 10% 40%} #m_sod_frm_paysel .naverpay_icon{background:url('../img/ico-mobile-naverpay.png') no-repeat #fff;height:23px;width:60px;display:inline-block;overflow:hidden;text-indent:-999px;background-size:45px auto;background-position: 0% 30%} +#m_sod_frm_paysel .naverpay_icon.nhnkcp_icon{text-indent:0;padding-left:50px;padding-top:2px;width:83px} #m_sod_frm_paysel .applepay_icon{background:url('../img/ico-mobile-applepay.png') no-repeat #fff;height:30px;width:60px;display:inline-block;overflow:hidden;text-indent:-999px;background-size:43px auto} #m_sod_frm_paysel .ssgpay_icon{background:url('../img/ssgpay_icon.png') no-repeat 0px 3px #fff;width:55px;height:20px;background-size:100%;display:inline-block;overflow:hidden;text-indent:-999px} #m_sod_frm_paysel .skpay_icon{background:url('../img/skpay11_icon.png') no-repeat 0px 3px #fff;width:55px;height:20px;background-size:100%;display:inline-block;overflow:hidden;text-indent:-999px} @@ -914,6 +915,7 @@ box-shadow:0 0 8px rgba(65,98,255,0.8)} #sod_frm_paysel .inicis_kakaopay{background:url('../img/kakao.png') no-repeat 50% 50% #f4dc34;overflow:hidden;text-indent:-999px} #sod_frm_paysel .kakaopay_icon{background:url('../img/kakao.png') no-repeat 50% 50% #f4dc34;overflow:hidden;text-indent:-999px} #sod_frm_paysel .naverpay_icon{background:url('../img/ico-default-naverpay.png') no-repeat 50% 50% #fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .naverpay_icon.nhnkcp_icon{text-indent:0;background-position: 50% 30%;padding-top:35px;padding-left:0;text-align:center} #sod_frm_paysel .samsungpay_icon{background:url('../img/samsungpay.png') no-repeat 50% 50% #fff;display:inline-block;overflow:hidden;text-indent:-999px} #sod_frm_paysel .ssgpay_icon{background:url('../img/ssgpay_icon.png') no-repeat 50% 50% #fff;display:inline-block;overflow:hidden;text-indent:-999px} #sod_frm_paysel .skpay_icon{background:url('../img/skpay11_icon.png') no-repeat 50% 50% #fff; background-size: 70px;display:inline-block;overflow:hidden;text-indent:-999px} diff --git a/extend/sms5.extend.php b/extend/sms5.extend.php index 3c0212d42..a31d43f28 100644 --- a/extend/sms5.extend.php +++ b/extend/sms5.extend.php @@ -20,7 +20,7 @@ define('G5_ICODE_LMS_MAX_LENGTH', 1500); // 구버전 LMS 최대길이 define('G5_ICODE_JSON_MAX_LENGTH', 2000); // JSON 버전 LMS 최대길이 // SMS 테이블명 -$g5['sms5_prefix'] = 'sms5_'; +$g5['sms5_prefix'] = G5_TABLE_PREFIX.'sms5_'; $g5['sms5_config_table'] = $g5['sms5_prefix'] . 'config'; $g5['sms5_write_table'] = $g5['sms5_prefix'] . 'write'; $g5['sms5_history_table'] = $g5['sms5_prefix'] . 'history'; diff --git a/install/gnuboard5.sql b/install/gnuboard5.sql index ddb7b99cf..fcc6676b6 100644 --- a/install/gnuboard5.sql +++ b/install/gnuboard5.sql @@ -276,6 +276,7 @@ CREATE TABLE IF NOT EXISTS `g5_config` ( `cf_max_po_id` int(11) NOT NULL DEFAULT '0', `cf_stipulation` text NOT NULL, `cf_privacy` text NOT NULL, + `cf_use_promotion` tinyint(1) NOT NULL DEFAULT '0', `cf_open_modify` int(11) NOT NULL DEFAULT '0', `cf_memo_send_point` int(11) NOT NULL DEFAULT '0', `cf_mobile_new_skin` varchar(50) NOT NULL DEFAULT '', @@ -298,6 +299,8 @@ CREATE TABLE IF NOT EXISTS `g5_config` ( `cf_cert_kcp_enckey` varchar(100) NOT NULL DEFAULT '', `cf_lg_mid` varchar(100) NOT NULL DEFAULT '', `cf_lg_mert_key` varchar(100) NOT NULL DEFAULT '', + `cf_toss_client_key` varchar(100) NOT NULL DEFAULT '', + `cf_toss_secret_key` varchar(100) NOT NULL DEFAULT '', `cf_cert_limit` int(11) NOT NULL DEFAULT '0', `cf_cert_req` tinyint(4) NOT NULL DEFAULT '0', `cf_sms_use` varchar(255) NOT NULL DEFAULT '', @@ -520,13 +523,20 @@ CREATE TABLE IF NOT EXISTS `g5_member` ( `mb_memo` text NOT NULL, `mb_lost_certify` varchar(255) NOT NULL, `mb_mailling` tinyint(4) NOT NULL default '0', + `mb_mailling_date` datetime NOT NULL default '0000-00-00 00:00:00', `mb_sms` tinyint(4) NOT NULL default '0', + `mb_sms_date` datetime NOT NULL default '0000-00-00 00:00:00', `mb_open` tinyint(4) NOT NULL default '0', `mb_open_date` date NOT NULL default '0000-00-00', `mb_profile` text NOT NULL, `mb_memo_call` varchar(255) NOT NULL default '', `mb_memo_cnt` int(11) NOT NULL DEFAULT '0', `mb_scrap_cnt` int(11) NOT NULL default '0', + `mb_marketing_agree` tinyint(1) NOT NULL default '0', + `mb_marketing_date` datetime NOT NULL default '0000-00-00 00:00:00', + `mb_thirdparty_agree` tinyint(1) NOT NULL default '0', + `mb_thirdparty_date` datetime NOT NULL default '0000-00-00 00:00:00', + `mb_agree_log` TEXT NOT NULL, `mb_1` varchar(255) NOT NULL default '', `mb_2` varchar(255) NOT NULL default '', `mb_3` varchar(255) NOT NULL default '', @@ -542,7 +552,6 @@ CREATE TABLE IF NOT EXISTS `g5_member` ( KEY `mb_today_login` (`mb_today_login`), KEY `mb_datetime` (`mb_datetime`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -- -------------------------------------------------------- -- @@ -956,4 +965,4 @@ CREATE TABLE IF NOT EXISTS `g5_menu` ( `me_use` tinyint(4) NOT NULL DEFAULT '0', `me_mobile_use` tinyint(4) NOT NULL DEFAULT '0', PRIMARY KEY (`me_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/lib/common.lib.php b/lib/common.lib.php index 7100a04c5..e5b436715 100644 --- a/lib/common.lib.php +++ b/lib/common.lib.php @@ -257,7 +257,13 @@ function url_auto_link($str) { global $g5; global $config; - + + if ($replace_str = run_replace('url_auto_link_before', '', $str)) { + return $replace_str; + } + + $ori_str = $str; + // 140326 유창화님 제안코드로 수정 // http://sir.kr/pg_lecture/461 // http://sir.kr/pg_lecture/463 @@ -290,7 +296,7 @@ function url_auto_link($str) $str = preg_replace("/\t_gt_\t/", ">", $str); */ - return run_replace('url_auto_link', $str); + return run_replace('url_auto_link', $str, $ori_str); } @@ -1131,7 +1137,11 @@ function insert_point($mb_id, $point, $content='', $rel_table='', $rel_id='', $r function insert_use_point($mb_id, $point, $po_id='') { global $g5, $config; - + + if ($replace_insert = run_replace('insert_use_point_before', '', $mb_id, $point, $po_id)) { + return $replace_insert; + } + if($config['cf_point_term']) $sql_order = " order by po_expire_date asc, po_id asc "; else @@ -3411,6 +3421,9 @@ function clean_xss_tags($str, $check_entities=0, $is_remove_tags=0, $cur_str_len $result = preg_replace('#([^\p{L}]|^)(?:javascript|jar|applescript|vbscript|vbs|wscript|jscript|behavior|mocha|livescript|view-source)\s*:(?:.*?([/\\\;()\'">]|$))#ius', '$1$2', $result); + // 따옴표 + 속성으로 강제 진입 차단 (예: "style=..., 'onerror=...) + $result = preg_replace('/["\']\s*(?:on\w+|style)\s*=\s*/i', '', $result); + if((string)$result === (string)$str) break; $str = $result; @@ -3667,6 +3680,10 @@ function check_url_host($url, $msg='', $return_url=G5_URL, $is_redirect=false) alert('url 에 올바르지 않은 값이 포함되어 있습니다.'); } + if (preg_match('#//[^/@]+@#', $url)) { + alert('url에 사용자 정보가 포함되어 있어 접근할 수 없습니다.'); + } + while ( ( $replace_url = preg_replace(array('/\/{2,}/', '/\\@/'), array('//', ''), urldecode($url)) ) != $url ) { $url = $replace_url; } @@ -4224,8 +4241,8 @@ function is_include_path_check($path='', $is_input='') //echo 'Caught exception: ', $e->getMessage(), "\n"; return false; } - - if( preg_match('/\/data\/(file|editor|qa|cache|member|member_image|session|tmp)\/[A-Za-z0-9_]{1,20}\//i', $replace_path) ){ + + if (preg_match('/\/data\/(file|editor|qa|cache|member|member_image|session|tmp)\/[A-Za-z0-9_]{1,20}\//i', $replace_path) || preg_match('/pe(?:ar|cl)(?:cmd)?\.php/i', $replace_path)){ return false; } if( preg_match('/'.G5_PLUGIN_DIR.'\//i', $replace_path) && (preg_match('/'.G5_OKNAME_DIR.'\//i', $replace_path) || preg_match('/'.G5_KCPCERT_DIR.'\//i', $replace_path) || preg_match('/'.G5_LGXPAY_DIR.'\//i', $replace_path)) || (preg_match('/search\.skin\.php/i', $replace_path) ) ){ diff --git a/lib/pbkdf2.compat.php b/lib/pbkdf2.compat.php index b1e18001b..995f16d37 100644 --- a/lib/pbkdf2.compat.php +++ b/lib/pbkdf2.compat.php @@ -50,6 +50,7 @@ function create_hash($password, $force_compat = false) $salt = base64_encode(mcrypt_create_iv(PBKDF2_COMPAT_SALT_BYTES, MCRYPT_DEV_URANDOM)); } elseif (@file_exists('/dev/urandom') && $fp = @fopen('/dev/urandom', 'r')) { $salt = base64_encode(fread($fp, PBKDF2_COMPAT_SALT_BYTES)); + fclose($fp); // 파일 닫기 } else { $salt = ''; for ($i = 0; $i < PBKDF2_COMPAT_SALT_BYTES; $i += 2) { diff --git a/lib/shop.lib.php b/lib/shop.lib.php index 561a0c8b6..6a9693298 100644 --- a/lib/shop.lib.php +++ b/lib/shop.lib.php @@ -1010,7 +1010,7 @@ function get_item_options($it_id, $subject, $is_div='', $is_first_option_title=' for($k=0; $k<$opt_count; $k++) { $opt_val = $opt[$k]; if(strlen($opt_val)) { - $select .= ''.PHP_EOL; + $select .= ''.PHP_EOL; } } $select .= ''.PHP_EOL; @@ -1046,7 +1046,7 @@ function get_item_options($it_id, $subject, $is_div='', $is_first_option_title=' else $soldout = ''; - $select .= ''.PHP_EOL; + $select .= ''.PHP_EOL; } $select .= ''.PHP_EOL; @@ -1101,7 +1101,7 @@ function get_item_supply($it_id, $subject, $is_div='', $is_first_option_title='' else $soldout = ''; - $options[$opt_id[0]][] = ''; + $options[$opt_id[0]][] = ''; } } @@ -1122,7 +1122,7 @@ function get_item_supply($it_id, $subject, $is_div='', $is_first_option_title='' $first_option_title = $is_first_option_title ? $subj[$i] : '선택'; $select = ''.PHP_EOL; + echo ''.PHP_EOL; } echo ''.PHP_EOL; @@ -262,12 +262,12 @@ if($enc_data != '' && $enc_info != '' && $tran_cd != '') {
- + - - - - + + + + - + @@ -294,13 +294,13 @@ if($enc_data != '' && $enc_info != '' && $tran_cd != '') { - + - + - + - + @@ -311,29 +311,29 @@ if($enc_data != '' && $enc_info != '' && $tran_cd != '') { - + - + - + - + - + - + - + - + - + - + - + @@ -343,7 +343,7 @@ if($enc_data != '' && $enc_info != '' && $tran_cd != '') { - + - - - + + + +

결제가 실패한 경우 아래 돌아가기 버튼을 클릭해주세요.

- 돌아가기 + 돌아가기
-

회원가입약관

+

(필수) 회원가입약관

@@ -31,7 +31,7 @@ add_stylesheet('',
-

개인정보 수집 및 이용

+

(필수) 개인정보 수집 및 이용

diff --git a/mobile/skin/member/basic/register_form.skin.php b/mobile/skin/member/basic/register_form.skin.php index 90f33137b..e44fa71e3 100644 --- a/mobile/skin/member/basic/register_form.skin.php +++ b/mobile/skin/member/basic/register_form.skin.php @@ -45,8 +45,7 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi

개인정보 입력

    -
  • - +
  • + 간편인증'.PHP_EOL; } @@ -67,11 +68,10 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi echo '(필수)'; echo ''.PHP_EOL; - } ?> 본인확인성인인증 완료
- + +
  • class="frm_input full_input " placeholder="이름 (필수)"> @@ -129,7 +130,7 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi
  • - " maxlength="20" placeholder="전화번호 (필수)"> + " maxlength="20" placeholder="전화번호 (필수)">
  • @@ -218,26 +219,6 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi -
  • - class="selec_chk"> - - 정보 메일을 받겠습니다. -
  • - - -
  • - class="selec_chk"> - - 휴대폰 문자메세지를 받겠습니다. -
  • - -
  • class="selec_chk"> @@ -246,7 +227,7 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi 정보공개 다른분들이 나의 정보를 볼 수 있도록 합니다. - + 정보공개를 바꾸시면 앞으로 일 이내에는 변경이 안됩니다. @@ -276,20 +257,129 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi
  • - -
  • - 자동등록방지 - -
  • + + +
    +

    수신설정

    + +
      + +
    • + + +
      마케팅 목적의 개인정보 수집·이용에 대한 안내입니다. 자세히보기를 눌러 전문을 확인할 수 있습니다.
      + + + +
    • + + + + + + + '아이코드']; + + $usedCompanies = []; + foreach ($configKeys as $key) { + if (!empty($config[$key]) && isset($companies[$config[$key]])) { + $usedCompanies[] = $companies[$config[$key]]; + } + } + ?> + +
    • + + +
      개인정보 제3자 제공 동의에 대한 안내입니다. 자세히보기를 눌러 전문을 확인할 수 있습니다.
      + + + +
    • + +
    +
    + + +
    +

    자동등록방지

    +
      +
    • + 자동등록방지 + +
    • +
    +
    + + + \ No newline at end of file diff --git a/mobile/skin/member/basic/style.css b/mobile/skin/member/basic/style.css index c9fc6c292..66edd7a6e 100644 --- a/mobile/skin/member/basic/style.css +++ b/mobile/skin/member/basic/style.css @@ -5,6 +5,8 @@ .mbskin h1 {font-size:1.75em;margin:40px 0 25px} .mbskin p {padding-bottom:20px;border-bottom:1px solid #c8c8c8} .mbskin p strong {color:#4162ff;padding-bottom:5px;display:block;font-size:1.083em} + +/* 버튼 */ .mbskin .btn_submit {display:block;width:100%;height:40px;line-height:40px;padding:0 10px;border:0;font-weight:bold;background:#3a8afd;color:#fff;border-radius:3px} /* ### 기본 스타일 커스터마이징 끝 ### */ @@ -68,7 +70,10 @@ .fregister_agree input[type="checkbox"]:checked + label {color:#000} .fregister_agree input[type="checkbox"]:checked + label span {background:url('./img/chk.png') no-repeat 50% 50% #3a8afd;border-color:#1471f6;border-radius:3px} .fregister_agree.chk_all input[type="checkbox"] + label span {top:15px} - +#fregisterform .consent-line {display: flex; align-items: baseline;} +#fregisterform .consent-date { margin: 5px 0 0 20px !important; } +#fregisterform .consent-group .sub-consents {padding: 10px 20px 0;} +#fregisterform .js-open-consent {flex:1 0 auto; margin-left: 10px; text-align: right; font-size: 12px; color: #3f51b5; background: none; border: none; cursor: pointer; text-decoration: underline; } /* 회원가입 완료 */ #reg_result {padding:20px 10px 10px} @@ -135,8 +140,9 @@ #flogin {background:#fff;margin:20px 0} #mb_login_notmb {background:#fff;border-bottom:1px solid #ccc;padding:20px} +#mb_login_notmb .chk_box input[type="checkbox"] + label{padding-left:20px} #mb_login_notmb h2 {font-size:1.25em;padding:10px;background:#f3f3f3} -#mb_login_notmb p {border:0;padding:0;margin:10px;color:#} +#mb_login_notmb p {border:0;padding:0;margin:10px;} #guest_privacy {border:1px solid #ccc;text-align:left;line-height:1.6em;color:#666;background:#fafafa;padding:10px;height:200px;margin:10px 0;overflow-y:auto} #mb_login_notmb .btn_submit {width:100%;display:block;height:40px;line-height:40px} @@ -154,7 +160,6 @@ #mb_login #sns_login .sns-icon:nth-child(odd) {margin-right:2%} #mb_login #sns_login .txt {font-size:0.95em;padding-left:5px !important;border-left:0 !important} - /* 쪽지 */ .memo_list {border-top:1px solid #ececec;} .memo_list li {border-bottom:1px solid #ececec;background:#fff;padding:10px 15px;list-style:none;position:relative} @@ -198,7 +203,7 @@ .memo_from li.memo_view_date {display:block;color:#555;line-height:24px} .memo_from li.memo_op_btn {position:absolute} .memo_from li.list_btn {right:53px;} -.memo_from li.del_btn {right:15px;padding} +.memo_from li.del_btn {right:15px;} .memo_from:after {display:block;visibility:hidden;clear:both;content:""} .memo_btn {width:100%} @@ -292,7 +297,6 @@ .chk_box input[type="radio"]:checked + label span {border-color:#3a8afd} .chk_box input[type="radio"]:checked + label span:before {width:7px;height:7px;background:#3a8afd;content:'';position:absolute;top:3px;left:3px;border-radius:50%} - /* 자기소개 */ #profile section {margin:10px} #profile h2 {margin:0} diff --git a/mobile/skin/social/consent_modal.inc.php b/mobile/skin/social/consent_modal.inc.php new file mode 100644 index 000000000..cd4f1525d --- /dev/null +++ b/mobile/skin/social/consent_modal.inc.php @@ -0,0 +1,85 @@ + + + +
    +
    +

    안내

    +
    +
    +
    + + +
    + +
    + + + + + + \ No newline at end of file diff --git a/mobile/skin/social/social_register_member.skin.php b/mobile/skin/social/social_register_member.skin.php index 8a8d19dc5..dc247994d 100644 --- a/mobile/skin/social/social_register_member.skin.php +++ b/mobile/skin/social/social_register_member.skin.php @@ -145,6 +145,108 @@ $email_msg = $is_exists_email ? '등록할 이메일이 중복되었습니다. + + +
    +

    수신설정

    + +
      + +
    • + + +
      마케팅 목적의 개인정보 수집·이용에 대한 안내입니다. 자세히보기를 눌러 전문을 확인할 수 있습니다.
      + (동의일자: ".$member['mb_marketing_date'].")"; ?> + + +
    • + + + + + + + '아이코드']; + + $usedCompanies = []; + foreach ($configKeys as $key) { + if (!empty($config[$key]) && isset($companies[$config[$key]])) { + $usedCompanies[] = $companies[$config[$key]]; + } + } + ?> + +
    • + + +
      개인정보 제3자 제공 동의에 대한 안내입니다. 자세히보기를 눌러 전문을 확인할 수 있습니다.
      + (동의일자: ".$member['mb_thirdparty_date'].")"; ?> + + +
    • + +
    +
    + +
    취소 @@ -196,6 +298,8 @@ $email_msg = $is_exists_email ? '등록할 이메일이 중복되었습니다.
    + + \ No newline at end of file diff --git a/mobile/skin/social/style.css b/mobile/skin/social/style.css index 12d53c965..f3c72683f 100644 --- a/mobile/skin/social/style.css +++ b/mobile/skin/social/style.css @@ -130,6 +130,9 @@ #fregisterform .rgs_name_li button {margin:5px 0 0;width:auto} #fregisterform .reg_mb_img_file {margin-bottom:30px} #fregisterform .reg_mb_img_file img {max-width:100%;height:auto} +#fregisterform .consent-line {display: flex; align-items: baseline;} +#fregisterform .consent-group .sub-consents {padding: 10px 20px 0;} +#fregisterform .js-open-consent {flex:1 0 auto; margin-left: 10px; text-align: right; font-size: 12px; color: #3f51b5; background: none; border: none; cursor: pointer; text-decoration: underline; } .filebox .fileName {display:inline-block;position:relative;width:100%;height:45px;padding-left:10px;margin-right:5px;line-height:30px;border: 1px solid #d0d3db;background-color:#fff;color:red;vertical-align:middle} .filebox .btn_file {display:inline-block;position:absolute;right:8px;top:8px;border:1px solid #3a8afd;border-radius:3px;width:70px;height:30px;color:#3a8afd;font-size:1em;line-height:30px;font-weight:bold;text-align:center;vertical-align:middle} diff --git a/plugin/htmlpurifier/extend.video.php b/plugin/htmlpurifier/extend.video.php index 5c8ec59d2..e81a0c2e4 100644 --- a/plugin/htmlpurifier/extend.video.php +++ b/plugin/htmlpurifier/extend.video.php @@ -77,4 +77,33 @@ if( !class_exists('HTMLPurifier_Filter_Iframevideo') ){ } } } +} + +if( !class_exists('HTMLPurifierContinueParamFilter') ){ + class HTMLPurifierContinueParamFilter extends HTMLPurifier_URIFilter + { + public $name = 'ContinueParamFilter'; + + public function filter(&$uri, $config, $context) + { + // 쿼리 파라미터 검사 + $query = $uri->query; + $path = $uri->path; + + if ($path && preg_match('#[\\\\/]logout#i', $path)) { + return false; + } + + if ($query) { + + parse_str($query, $query_params); + + if (isset($query_params['continue']) || isset($query_params['pcurl'])) { + return false; + } + } + + return true; // 조건 통과 시 허용 + } + } } \ No newline at end of file diff --git a/plugin/kcaptcha/kcaptcha.lib.php b/plugin/kcaptcha/kcaptcha.lib.php index 0678c7bbb..43141f6b3 100644 --- a/plugin/kcaptcha/kcaptcha.lib.php +++ b/plugin/kcaptcha/kcaptcha.lib.php @@ -278,6 +278,8 @@ function captcha_html($class="captcha") $html .= "\n".'#captcha.m_captcha {border:1px solid #ddd; width: 100%; padding: 10px; box-sizing: border-box; border-radius: 6px; text-align:center}'; $html .= "\n".''; return $html; + + return run_replace('kcaptcha_captcha_html', $html, $class); } diff --git a/plugin/social/register_member_update.php b/plugin/social/register_member_update.php index 2c61e2a8b..9f0826089 100644 --- a/plugin/social/register_member_update.php +++ b/plugin/social/register_member_update.php @@ -97,6 +97,44 @@ if( defined('G5_SOCIAL_CERTIFY_MAIL') && G5_SOCIAL_CERTIFY_MAIL && $config['cf_u $mb_mailling = (isset($_POST['mb_mailling']) && $_POST['mb_mailling']) ? 1 : 0; //회원 정보 공개 $mb_open = (isset($_POST['mb_open']) && $_POST['mb_open']) ? 1 : 0; +//회원 SMS 동의 +$mb_sms = isset($_POST['mb_sms']) ? trim($_POST['mb_sms']) : "0"; +//마케팅 목적의 개인정보 수집 및 이용 동의 +$mb_marketing_agree = isset($_POST['mb_marketing_agree']) ? trim($_POST['mb_marketing_agree']) : "0"; +//개인정보 제3자 제공 동의 +$mb_thirdparty_agree = isset($_POST['mb_thirdparty_agree']) ? trim($_POST['mb_thirdparty_agree']) : "0"; + +$agree_items = []; +$sql_agree = ""; +// 마케팅 목적의 개인정보 수집 및 이용 +if ($mb_marketing_agree == 1) { + $sql_agree .= " , mb_marketing_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "마케팅 목적의 개인정보 수집 및 이용(동의)"; +} + +// 광고성 이메일 수신 +if ($mb_mailling == 1) { + $sql_agree .= " , mb_mailling_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 이메일 수신(동의)"; +} + +// 광고성 SMS/카카오톡 수신 +if ($mb_sms == 1) { + $sql_agree .= " , mb_sms_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "광고성 SMS/카카오톡 수신(동의)"; +} + +// 개인정보 제3자 제공 +if ($mb_thirdparty_agree == 1) { + $sql_agree .= " , mb_thirdparty_date = '".G5_TIME_YMDHIS."' "; + $agree_items[] = "개인정보 제3자 제공(동의)"; +} + +// 동의 로그 추가 +if (!empty($agree_items)) { + $agree_log = "[".G5_TIME_YMDHIS.", ". $provider_name ." 회원가입] " . implode(' | ', $agree_items) . "\n"; + $sql_agree .= " , mb_agree_log = CONCAT('{$agree_log}', IFNULL(mb_agree_log, ''))"; +} //=============================================================== // 본인확인 @@ -164,9 +202,12 @@ $sql = " insert into {$g5['member_table']} mb_level = '{$config['cf_register_level']}', mb_login_ip = '{$_SERVER['REMOTE_ADDR']}', mb_mailling = '{$mb_mailling}', - mb_sms = '0', + mb_sms = '{$mb_sms}', mb_open = '{$mb_open}', - mb_open_date = '".G5_TIME_YMD."' + mb_open_date = '".G5_TIME_YMD."', + mb_marketing_agree = '{$mb_marketing_agree}', + mb_thirdparty_agree = '{$mb_thirdparty_agree}' + {$sql_agree} {$sql_certify} "; $result = sql_query($sql, false); diff --git a/shop/kcp/global_nhn_kcp_order.script.php b/shop/kcp/global_nhn_kcp_order.script.php index 9d72cb5b8..633d5b6bb 100644 --- a/shop/kcp/global_nhn_kcp_order.script.php +++ b/shop/kcp/global_nhn_kcp_order.script.php @@ -28,6 +28,14 @@ jQuery(function($){ if( nhnkcp_settle_case == "naverpay" ){ if(typeof nhnkcp_pay_form.naverpay_direct !== "undefined") nhnkcp_pay_form.naverpay_direct.value = "Y"; + + var is_money = jQuery("input[name='od_settle_case']:checked" ).attr("data-money"); + + if (is_money) { // 머니/포인트 결제 + jQuery(nhnkcp_pay_form).find("input[name='naverpay_point_direct']").val("Y"); + } else { // 카드 결제 + jQuery(nhnkcp_pay_form).find("input[name='naverpay_point_direct']").val(""); + } } nhnkcp_pay_form.pay_method.value = "100000000000"; diff --git a/shop/kcp/pp_ax_hub.php b/shop/kcp/pp_ax_hub.php index 4e7606ef4..61fcd41ad 100644 --- a/shop/kcp/pp_ax_hub.php +++ b/shop/kcp/pp_ax_hub.php @@ -293,11 +293,14 @@ if ( $req_tx == "pay" ) $kcp_pay_method = $c_PayPlus->mf_get_res_data( "pay_method" ); // 카카오페이 결제수단 // 카드 코드는 PACA, 카카오머니 코드는 PAKM - + // https://developer.kcp.co.kr/page/document/directpay + if( $kcp_pay_method == "PAKM" ){ // 카카오머니 $card_mny = $kakaomny_mny = $c_PayPlus->mf_get_res_data( "kakaomny_mny" ); $app_time = $app_kakaomny_time = $c_PayPlus->mf_get_res_data( "app_kakaomny_time" ); $od_other_pay_type = 'NHNKCP_KAKAOMONEY'; + } else if( $kcp_pay_method == "PANP" ){ // 네이버페이머니 + $od_other_pay_type = 'NHNKCP_NAVERMONEY'; } /* = -------------------------------------------------------------- = */ diff --git a/shop/orderform.sub.php b/shop/orderform.sub.php index 8e26b1969..cc8d7787c 100644 --- a/shop/orderform.sub.php +++ b/shop/orderform.sub.php @@ -84,6 +84,9 @@ if($is_kakaopay_use) { $comm_free_mny = 0; // 면세금액 $tot_tax_mny = 0; + // 토스페이먼츠 escrowProducts 배열 생성 + $escrow_products = array(); + for ($i=0; $row=sql_fetch_array($result); $i++) { @@ -152,6 +155,15 @@ if($is_kakaopay_use) { $point = $sum['point']; $sell_price = $sum['price']; + // 토스페이먼츠 escrowProducts 배열에 상품 정보 추가 + $escrow_products[] = array( + 'id' => $row['ct_id'], + 'name' => $row['it_name'], + 'code' => $row['it_id'], + 'unitPrice' => (int) $row['ct_price'], + 'quantity' => (int) $row['ct_qty'] + ); + // 쿠폰 $cp_button = ''; if($is_member) { @@ -669,7 +681,8 @@ if($is_kakaopay_use) { // 계좌이체 사용 if ($default['de_iche_use']) { $multi_settle++; - echo ''.PHP_EOL; + // 토스페이먼츠 v2 - 퀵계좌이체 명칭 사용 + echo ''.PHP_EOL; $checked = ''; } @@ -713,7 +726,15 @@ if($is_kakaopay_use) { $easypay_prints['nhnkcp_payco'] = ''; } if( in_array('nhnkcp_naverpay', $de_easy_pay_service_array) ){ - $easypay_prints['nhnkcp_naverpay'] = ''; + + if(isset($default['de_easy_pay_services']) && in_array('used_nhnkcp_naverpay_point', explode(',', $default['de_easy_pay_services'])) ){ + $easypay_prints['nhnkcp_naverpay_card'] = ''; + + $easypay_prints['nhnkcp_naverpay_money'] = ''; + } else { + $easypay_prints['nhnkcp_naverpay_card'] = ''; + } + } if( in_array('nhnkcp_kakaopay', $de_easy_pay_service_array) ){ $easypay_prints['nhnkcp_kakaopay'] = ''; @@ -748,7 +769,14 @@ if($is_kakaopay_use) { } if( ! isset($easypay_prints['nhnkcp_naverpay']) && function_exists('is_use_easypay') && is_use_easypay('global_nhnkcp') ){ - $easypay_prints['nhnkcp_naverpay'] = ''; + + if(isset($default['de_easy_pay_services']) && in_array('used_nhnkcp_naverpay_point', explode(',', $default['de_easy_pay_services'])) ){ + $easypay_prints['nhnkcp_naverpay_card'] = ''; + + $easypay_prints['nhnkcp_naverpay_money'] = ''; + } else { + $easypay_prints['nhnkcp_naverpay'] = ''; + } } if($easypay_prints) { @@ -1123,7 +1151,7 @@ $(function() { $("#settle_bank").show(); }); - $("#od_settle_iche,#od_settle_card,#od_settle_vbank,#od_settle_hp,#od_settle_easy_pay,#od_settle_kakaopay,#od_settle_nhnkcp_payco,#od_settle_nhnkcp_naverpay,#od_settle_nhnkcp_kakaopay,#od_settle_inicislpay,#od_settle_inicis_kakaopay").bind("click", function() { + $("#od_settle_iche,#od_settle_card,#od_settle_vbank,#od_settle_hp,#od_settle_easy_pay,#od_settle_kakaopay,#od_settle_nhnkcp_payco,#od_settle_nhnkcp_naverpay,#od_settle_nhnkcp_naverpay_money,#od_settle_nhnkcp_kakaopay,#od_settle_inicislpay,#od_settle_inicis_kakaopay").bind("click", function() { $("#settle_bank").hide(); }); @@ -1572,10 +1600,19 @@ function forderform_check(f) case "간편결제": f.pay_method.value = "100000000000"; - var nhnkcp_easy_pay = jQuery("input[name='od_settle_case']:checked" ).attr("data-pay"); + var nhnkcp_easy_pay = jQuery("input[name='od_settle_case']:checked").attr("data-pay"); if(nhnkcp_easy_pay === "naverpay"){ if(typeof f.naverpay_direct !== "undefined") f.naverpay_direct.value = "Y"; + + var is_money = jQuery("input[name='od_settle_case']:checked").attr("data-money"); + + if (is_money) { // 머니/포인트 결제 + jQuery(f).find("input[name='naverpay_point_direct']").val("Y"); + } else { // 카드 결제 + jQuery(f).find("input[name='naverpay_point_direct']").val(""); + } + } else if(nhnkcp_easy_pay === "kakaopay"){ if(typeof f.kakaopay_direct !== "undefined") f.kakaopay_direct.value = "Y"; } else { @@ -1628,6 +1665,28 @@ function forderform_check(f) f.LGD_CUSTOM_FIRSTPAY.value = "무통장"; break; } + + switch(settle_method) + { + case "계좌이체": + f.method.value = "TRANSFER"; + break; + case "가상계좌": + f.method.value = "VIRTUAL_ACCOUNT"; + break; + case "휴대폰": + f.method.value = "MOBILE_PHONE"; + break; + case "신용카드": + f.method.value = "CARD"; + break; + case "간편결제": + f.method.value = "CARD"; + break; + default: + f.method.value = "무통장"; + break; + } switch(settle_method) { @@ -1763,6 +1822,62 @@ function forderform_check(f) f.submit(); } + + + f.orderId.value = ''; + f.orderName.value = ''; + + f.customerName.value = f.od_name.value; + f.customerEmail.value = f.od_email.value; + f.customerMobilePhone.value = f.od_hp.value.replace(/[^0-9]/g, ''); + if (f.customerMobilePhone.value == '') { + f.customerMobilePhone.value = f.od_tel.value.replace(/[^0-9]/g, ''); + } + + f.cardUseCardPoint.value = false; + f.cardUseAppCardOnly.value = false; + + + f.cardUseEscrow.value = 'true'; + f.escrowProducts.value = JSON.stringify(); + + + if(settle_method == "간편결제") { + f.cardflowMode.value = 'DIRECT'; + } + + f.amountCurrency.value = 'KRW'; + f.amountValue.value = f.good_mny.value; + + f.taxFreeAmount.value = f.comm_free_mny.value; + + f.windowTarget.value = 'iframe'; + + if(f.method.value != "무통장") { + // 주문정보 임시저장 + var order_data = $(f).serialize(); + var save_result = ""; + $.ajax({ + type: "POST", + data: order_data, + url: g5_url+"/shop/ajax.orderdatasave.php", + cache: false, + async: false, + success: function(data) { + save_result = data; + } + }); + + if(save_result) { + alert(save_result); + return false; + } + + launchCrossPlatform(f); + } else { + f.submit(); + } + f.price.value = f.good_mny.value; diff --git a/shop/orderformupdate.php b/shop/orderformupdate.php index 77302667f..e36af95ba 100644 --- a/shop/orderformupdate.php +++ b/shop/orderformupdate.php @@ -1001,6 +1001,1030 @@ if($is_member) { // 주문 처리 완료 후 이벤트 실행 run_event('fg_orderformupdate_after', $od_id); +goto_url(G5_SHOP_URL.'/orderinquiryview.php?od_id='.$od_id.'&uid='.$uid); +?> + + + 주문정보 기록 + + + $it_stock_qty) + $error .= "{$row['ct_option']} 의 재고수량이 부족합니다. 현재고수량 : $it_stock_qty 개\\n\\n"; +} + +if($i == 0) { + if(function_exists('add_order_post_log')) add_order_post_log('장바구니가 비어 있습니다.'); + alert('장바구니가 비어 있습니다.\\n\\n이미 주문하셨거나 장바구니에 담긴 상품이 없는 경우입니다.', G5_SHOP_URL.'/cart.php'); +} + +if ($error != "") +{ + $error .= "다른 고객님께서 {$od_name}님 보다 먼저 주문하신 경우입니다. 불편을 끼쳐 죄송합니다."; + if(function_exists('add_order_post_log')) add_order_post_log($error); + alert($error); +} + +$i_price = isset($_POST['od_price']) ? (int) $_POST['od_price'] : 0; +$i_send_cost = isset($_POST['od_send_cost']) ? (int) $_POST['od_send_cost'] : 0; +$i_send_cost2 = isset($_POST['od_send_cost2']) ? (int) $_POST['od_send_cost2'] : 0; +$i_send_coupon = isset($_POST['od_send_coupon']) ? abs((int) $_POST['od_send_coupon']) : 0; +$i_temp_point = isset($_POST['od_temp_point']) ? (int) $_POST['od_temp_point'] : 0; + +// 주문금액이 상이함 +$sql = " select SUM(IF(io_type = 1, (io_price * ct_qty), ((ct_price + io_price) * ct_qty))) as od_price, + COUNT(distinct it_id) as cart_count + from {$g5['g5_shop_cart_table']} where od_id = '$tmp_cart_id' and ct_select = '1' "; +$row = sql_fetch($sql); +$tot_ct_price = $row['od_price']; +$cart_count = $row['cart_count']; +$tot_od_price = $tot_ct_price; + +// 쿠폰금액계산 +$tot_cp_price = $tot_it_cp_price = $tot_od_cp_price = 0; +if($is_member) { + // 상품쿠폰 + $it_cp_cnt = (isset($_POST['cp_id']) && is_array($_POST['cp_id'])) ? count($_POST['cp_id']) : 0; + $arr_it_cp_prc = array(); + for($i=0; $i<$it_cp_cnt; $i++) { + $cid = isset($_POST['cp_id'][$i]) ? clean_xss_tags($_POST['cp_id'][$i], 1, 1) : ''; + $it_id = isset($_POST['it_id'][$i]) ? safe_replace_regex($_POST['it_id'][$i], 'it_id') : ''; + $sql = " select cp_id, cp_method, cp_target, cp_type, cp_price, cp_trunc, cp_minimum, cp_maximum + from {$g5['g5_shop_coupon_table']} + where cp_id = '$cid' + and mb_id IN ( '{$member['mb_id']}', '전체회원' ) + and cp_start <= '".G5_TIME_YMD."' + and cp_end >= '".G5_TIME_YMD."' + and cp_method IN ( 0, 1 ) "; + $cp = sql_fetch($sql); + if(! (isset($cp['cp_id']) && $cp['cp_id'])) + continue; + + // 사용한 쿠폰인지 + if(is_used_coupon($member['mb_id'], $cp['cp_id'])) + continue; + + // 분류할인인지 + if($cp['cp_method']) { + $sql2 = " select it_id, ca_id, ca_id2, ca_id3 + from {$g5['g5_shop_item_table']} + where it_id = '$it_id' "; + $row2 = sql_fetch($sql2); + + if(!$row2['it_id']) + continue; + + if($row2['ca_id'] != $cp['cp_target'] && $row2['ca_id2'] != $cp['cp_target'] && $row2['ca_id3'] != $cp['cp_target']) + continue; + } else { + if($cp['cp_target'] != $it_id) + continue; + } + + // 상품금액 + $sql = " select SUM( IF(io_type = '1', io_price * ct_qty, (ct_price + io_price) * ct_qty)) as sum_price + from {$g5['g5_shop_cart_table']} + where od_id = '$tmp_cart_id' + and it_id = '$it_id' + and ct_select = '1' "; + $ct = sql_fetch($sql); + $item_price = $ct['sum_price']; + + if($cp['cp_minimum'] > $item_price) + continue; + + $dc = 0; + if($cp['cp_type']) { + $dc = floor(($item_price * ($cp['cp_price'] / 100)) / $cp['cp_trunc']) * $cp['cp_trunc']; + } else { + $dc = $cp['cp_price']; + } + + if($cp['cp_maximum'] && $dc > $cp['cp_maximum']) + $dc = $cp['cp_maximum']; + + if($item_price < $dc) + continue; + + $tot_it_cp_price += $dc; + $arr_it_cp_prc[$it_id] = $dc; + } + + $tot_od_price -= $tot_it_cp_price; + + // 주문쿠폰 + if(isset($_POST['od_cp_id']) && $_POST['od_cp_id']) { + $sql = " select cp_id, cp_type, cp_price, cp_trunc, cp_minimum, cp_maximum + from {$g5['g5_shop_coupon_table']} + where cp_id = '{$_POST['od_cp_id']}' + and mb_id IN ( '{$member['mb_id']}', '전체회원' ) + and cp_start <= '".G5_TIME_YMD."' + and cp_end >= '".G5_TIME_YMD."' + and cp_method = '2' "; + $cp = sql_fetch($sql); + + // 사용한 쿠폰인지 + $cp_used = is_used_coupon($member['mb_id'], $cp['cp_id']); + + $dc = 0; + if(!$cp_used && $cp['cp_id'] && ($cp['cp_minimum'] <= $tot_od_price)) { + if($cp['cp_type']) { + $dc = floor(($tot_od_price * ($cp['cp_price'] / 100)) / $cp['cp_trunc']) * $cp['cp_trunc']; + } else { + $dc = $cp['cp_price']; + } + + if($cp['cp_maximum'] && $dc > $cp['cp_maximum']) + $dc = $cp['cp_maximum']; + + if($tot_od_price < $dc) + die('Order coupon error.'); + + $tot_od_cp_price = $dc; + $tot_od_price -= $tot_od_cp_price; + } + } + + $tot_cp_price = $tot_it_cp_price + $tot_od_cp_price; +} + +if ((int)($row['od_price'] - $tot_cp_price) !== $i_price) { + if(function_exists('add_order_post_log')) add_order_post_log('쿠폰금액 최종 계산 Error.'); + die("Error."); +} + +// 배송비가 상이함 +$send_cost = get_sendcost($tmp_cart_id); + +$tot_sc_cp_price = 0; +if($is_member && $send_cost > 0) { + // 배송쿠폰 + if(isset($_POST['sc_cp_id']) && $_POST['sc_cp_id']) { + $sql = " select cp_id, cp_type, cp_price, cp_trunc, cp_minimum, cp_maximum + from {$g5['g5_shop_coupon_table']} + where cp_id = '{$_POST['sc_cp_id']}' + and mb_id IN ( '{$member['mb_id']}', '전체회원' ) + and cp_start <= '".G5_TIME_YMD."' + and cp_end >= '".G5_TIME_YMD."' + and cp_method = '3' "; + $cp = sql_fetch($sql); + + // 사용한 쿠폰인지 + $cp_used = is_used_coupon($member['mb_id'], $cp['cp_id']); + + $dc = 0; + if(!$cp_used && $cp['cp_id'] && ($cp['cp_minimum'] <= $tot_od_price)) { + if($cp['cp_type']) { + $dc = floor(($send_cost * ($cp['cp_price'] / 100)) / $cp['cp_trunc']) * $cp['cp_trunc']; + } else { + $dc = $cp['cp_price']; + } + + if($cp['cp_maximum'] && $dc > $cp['cp_maximum']) + $dc = $cp['cp_maximum']; + + if($dc > $send_cost) + $dc = $send_cost; + + $tot_sc_cp_price = $dc; + } + } +} + +if ((int)($send_cost - $tot_sc_cp_price) !== (int)($i_send_cost - $i_send_coupon)) { + if(function_exists('add_order_post_log')) add_order_post_log('배송비 최종 계산 Error..'); + die("Error.."); +} + +// 추가배송비가 상이함 +$od_b_zip = preg_replace('/[^0-9]/', '', $od_b_zip); +$od_b_zip1 = substr($od_b_zip, 0, 3); +$od_b_zip2 = substr($od_b_zip, 3); +$zipcode = $od_b_zip; +$sql = " select sc_id, sc_price from {$g5['g5_shop_sendcost_table']} where sc_zip1 <= '$zipcode' and sc_zip2 >= '$zipcode' "; +$tmp = sql_fetch($sql); +if(! (isset($tmp['sc_id']) && $tmp['sc_id'])) + $send_cost2 = 0; +else + $send_cost2 = (int) $tmp['sc_price']; + +if($send_cost2 !== $i_send_cost2){ + if(function_exists('add_order_post_log')) add_order_post_log('추가배송비 최종 계산 Error...'); + die("Error..."); +} + +// 결제포인트가 상이함 +// 회원이면서 포인트사용이면 +$temp_point = 0; +if ($is_member && $config['cf_use_point']) +{ + if($member['mb_point'] >= $default['de_settle_min_point']) { + $temp_point = (int)$default['de_settle_max_point']; + + if($temp_point > (int)$tot_od_price) + $temp_point = (int)$tot_od_price; + + if($temp_point > (int)$member['mb_point']) + $temp_point = (int)$member['mb_point']; + + $point_unit = (int)$default['de_settle_point_unit']; + $temp_point = (int)((int)($temp_point / $point_unit) * $point_unit); + } +} + +if (($i_temp_point > (int)$temp_point || $i_temp_point < 0) && $config['cf_use_point']) { + if(function_exists('add_order_post_log')) add_order_post_log('포인트 최종 계산 Error....'); + die("Error...."); +} + +if ($od_temp_point) +{ + if ($member['mb_point'] < $od_temp_point) { + if(function_exists('add_order_post_log')) add_order_post_log('회원님의 포인트가 부족하여 포인트로 결제 할 수 없습니다.'); + alert('회원님의 포인트가 부족하여 포인트로 결제 할 수 없습니다.'); + } +} + +$i_price = $i_price + $i_send_cost + $i_send_cost2 - $i_temp_point - $i_send_coupon; +$order_price = $tot_od_price + $send_cost + $send_cost2 - $tot_sc_cp_price - $od_temp_point; + +// PG사의 가상계좌 또는 계좌이체의 자동 현금영수증 초기배열값 +$pg_receipt_infos = array( + 'od_cash' => 0, + 'od_cash_no' => '', + 'od_cash_info' => '', +); + +$od_status = '주문'; +$od_tno = ''; + +if (function_exists('check_payment_method')) { + check_payment_method($od_settle_case); +} + +if ($od_settle_case == "무통장") +{ + $od_receipt_point = $i_temp_point; + $od_receipt_price = 0; + $od_misu = $i_price - $od_receipt_price; + if($od_misu == 0) { + $od_status = '입금'; + $od_receipt_time = G5_TIME_YMDHIS; + } +} +else if ($od_settle_case == "계좌이체") +{ + switch($default['de_pg_service']) { + case 'lg': + include G5_SHOP_PATH.'/lg/xpay_result.php'; + break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + break; + case 'inicis': + include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; + break; + case 'nicepay': + include G5_SHOP_PATH.'/nicepay/nicepay_result.php'; + break; + default: + include G5_SHOP_PATH.'/kcp/pp_ax_hub.php'; + $bank_name = iconv("cp949", "utf-8", $bank_name); + break; + } + + $od_tno = $tno; + $od_receipt_price = $amount; + $od_receipt_point = $i_temp_point; + $od_receipt_time = preg_replace("/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/", "\\1-\\2-\\3 \\4:\\5:\\6", $app_time); + $od_deposit_name = $od_name; + $od_bank_account = $bank_name; + $pg_price = $amount; + $od_misu = $i_price - $od_receipt_price; + if($od_misu == 0) + $od_status = '입금'; +} +else if ($od_settle_case == "가상계좌") +{ + switch($default['de_pg_service']) { + case 'lg': + include G5_SHOP_PATH.'/lg/xpay_result.php'; + $od_receipt_time = '0000-00-00 00:00:00'; + break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + $od_receipt_time = '0000-00-00 00:00:00'; + break; + case 'inicis': + include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; + $od_app_no = $app_no; + break; + case 'nicepay': + include G5_SHOP_PATH.'/nicepay/nicepay_result.php'; + break; + default: + include G5_SHOP_PATH.'/kcp/pp_ax_hub.php'; + $bankname = iconv("cp949", "utf-8", $bankname); + $depositor = iconv("cp949", "utf-8", $depositor); + break; + } + + $od_receipt_point = $i_temp_point; + $od_tno = $tno; + $od_receipt_price = 0; + $od_bank_account = $bankname.' '.$account; + $od_deposit_name = $depositor; + $pg_price = $amount; + $od_misu = $i_price - $od_receipt_price; +} +else if ($od_settle_case == "휴대폰") +{ + switch($default['de_pg_service']) { + case 'lg': + include G5_SHOP_PATH.'/lg/xpay_result.php'; + break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + break; + case 'inicis': + include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; + break; + case 'nicepay': + include G5_SHOP_PATH.'/nicepay/nicepay_result.php'; + break; + default: + include G5_SHOP_PATH.'/kcp/pp_ax_hub.php'; + break; + } + + $od_tno = $tno; + $od_receipt_price = $amount; + $od_receipt_point = $i_temp_point; + $od_receipt_time = preg_replace("/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/", "\\1-\\2-\\3 \\4:\\5:\\6", $app_time); + $od_bank_account = $commid . ($commid ? ' ' : '').$mobile_no; + $pg_price = $amount; + $od_misu = $i_price - $od_receipt_price; + if($od_misu == 0) + $od_status = '입금'; +} +else if ($od_settle_case == "신용카드") +{ + switch($default['de_pg_service']) { + case 'lg': + include G5_SHOP_PATH.'/lg/xpay_result.php'; + break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + break; + case 'inicis': + include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; + break; + case 'nicepay': + include G5_SHOP_PATH.'/nicepay/nicepay_result.php'; + break; + default: + include G5_SHOP_PATH.'/kcp/pp_ax_hub.php'; + $card_name = iconv("cp949", "utf-8", $card_name); + break; + } + + $od_tno = $tno; + $od_app_no = $app_no; + $od_receipt_price = $amount; + $od_receipt_point = $i_temp_point; + $od_receipt_time = preg_replace("/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/", "\\1-\\2-\\3 \\4:\\5:\\6", $app_time); + $od_bank_account = $card_name; + $pg_price = $amount; + $od_misu = $i_price - $od_receipt_price; + if($od_misu == 0) + $od_status = '입금'; +} +else if ($od_settle_case == "간편결제" || (($od_settle_case == "lpay" || $od_settle_case == "inicis_kakaopay") && $default['de_pg_service'] === 'inicis') ) +{ + switch($default['de_pg_service']) { + case 'lg': + include G5_SHOP_PATH.'/lg/xpay_result.php'; + break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + break; + case 'inicis': + include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; + break; + case 'nicepay': + include G5_SHOP_PATH.'/nicepay/nicepay_result.php'; + break; + default: + include G5_SHOP_PATH.'/kcp/pp_ax_hub.php'; + $card_name = iconv("cp949", "utf-8", $card_name); + break; + } + + $od_tno = $tno; + $od_app_no = $app_no; + $od_receipt_price = $amount; + $od_receipt_point = $i_temp_point; + $od_receipt_time = preg_replace("/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/", "\\1-\\2-\\3 \\4:\\5:\\6", $app_time); + $od_bank_account = $card_name; + $pg_price = $amount; + $od_misu = $i_price - $od_receipt_price; + if($od_misu == 0) + $od_status = '입금'; +} +else if ($od_settle_case == "KAKAOPAY") +{ + include G5_SHOP_PATH.'/kakaopay/kakaopay_result.php'; + + $od_tno = $tno; + $od_app_no = $app_no; + $od_receipt_price = $amount; + $od_receipt_point = $i_temp_point; + $od_receipt_time = preg_replace("/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/", "\\1-\\2-\\3 \\4:\\5:\\6", $app_time); + $od_bank_account = $card_name; + $pg_price = $amount; + $od_misu = $i_price - $od_receipt_price; + if($od_misu == 0) + $od_status = '입금'; +} +else +{ + die("od_settle_case Error!!!"); +} + +$od_pg = $default['de_pg_service']; +if($od_settle_case == 'KAKAOPAY') + $od_pg = 'KAKAOPAY'; + +$tno = isset($tno) ? $tno : ''; +$od_receipt_time = isset($od_receipt_time) ? $od_receipt_time : ''; +$od_app_no = isset($od_app_no) ? $od_app_no : ''; + +// 주문금액과 결제금액이 일치하는지 체크 +if($tno) { + if((int)$order_price !== (int)$pg_price) { + $cancel_msg = '결제금액 불일치'; + switch($od_pg) { + case 'lg': + include G5_SHOP_PATH.'/lg/xpay_cancel.php'; + break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_cancel.php'; + break; + case 'inicis': + include G5_SHOP_PATH.'/inicis/inipay_cancel.php'; + break; + case 'nicepay': + $cancelAmt = (int)$pg_price; + include G5_SHOP_PATH.'/nicepay/cancel_process.php'; + break; + case 'KAKAOPAY': + $_REQUEST['TID'] = $tno; + $_REQUEST['Amt'] = $amount; + $_REQUEST['CancelMsg'] = $cancel_msg; + $_REQUEST['PartialCancelCode'] = 0; + include G5_SHOP_PATH.'/kakaopay/kakaopay_cancel.php'; + break; + default: + include G5_SHOP_PATH.'/kcp/pp_ax_hub_cancel.php'; + break; + } + + if(function_exists('add_order_post_log')) add_order_post_log($cancel_msg); + die("Receipt Amount Error"); + } +} + +if ($is_member) + $od_pwd = $member['mb_password']; +else + $od_pwd = isset($_POST['od_pwd']) ? get_encrypt_string($_POST['od_pwd']) : get_encrypt_string(mt_rand()); + +// 주문번호를 얻는다. +$od_id = get_session('ss_order_id'); + +$od_escrow = 0; +if(isset($escw_yn) && $escw_yn === 'Y') + $od_escrow = 1; + +// 복합과세 금액 +$od_tax_mny = round($i_price / 1.1); +$od_vat_mny = $i_price - $od_tax_mny; +$od_free_mny = 0; +if($default['de_tax_flag_use']) { + $od_tax_mny = isset($_POST['comm_tax_mny']) ? (int) $_POST['comm_tax_mny'] : 0; + $od_vat_mny = isset($_POST['comm_vat_mny']) ? (int) $_POST['comm_vat_mny'] : 0; + $od_free_mny = isset($_POST['comm_free_mny']) ? (int) $_POST['comm_free_mny'] : 0; +} + +$od_email = get_email_address($od_email); +$od_name = clean_xss_tags($od_name); +$od_tel = clean_xss_tags($od_tel); +$od_hp = clean_xss_tags($od_hp); +$od_zip = preg_replace('/[^0-9]/', '', $od_zip); +$od_zip1 = substr($od_zip, 0, 3); +$od_zip2 = substr($od_zip, 3); +$od_addr1 = clean_xss_tags($od_addr1); +$od_addr2 = clean_xss_tags($od_addr2); +$od_addr3 = clean_xss_tags($od_addr3); +$od_addr_jibeon = preg_match("/^(N|R)$/", $od_addr_jibeon) ? $od_addr_jibeon : ''; +$od_b_name = clean_xss_tags($od_b_name); +$od_b_tel = clean_xss_tags($od_b_tel); +$od_b_hp = clean_xss_tags($od_b_hp); +$od_b_addr1 = clean_xss_tags($od_b_addr1); +$od_b_addr2 = clean_xss_tags($od_b_addr2); +$od_b_addr3 = clean_xss_tags($od_b_addr3); +$od_b_addr_jibeon = preg_match("/^(N|R)$/", $od_b_addr_jibeon) ? $od_b_addr_jibeon : ''; +$od_memo = clean_xss_tags($od_memo, 1, 1, 0, 0); +$od_deposit_name = clean_xss_tags($od_deposit_name); +$od_tax_flag = $default['de_tax_flag_use']; + +// 주문서에 입력 +$sql = " insert {$g5['g5_shop_order_table']} + set od_id = '$od_id', + mb_id = '{$member['mb_id']}', + od_pwd = '$od_pwd', + od_name = '$od_name', + od_email = '$od_email', + od_tel = '$od_tel', + od_hp = '$od_hp', + od_zip1 = '$od_zip1', + od_zip2 = '$od_zip2', + od_addr1 = '$od_addr1', + od_addr2 = '$od_addr2', + od_addr3 = '$od_addr3', + od_addr_jibeon = '$od_addr_jibeon', + od_b_name = '$od_b_name', + od_b_tel = '$od_b_tel', + od_b_hp = '$od_b_hp', + od_b_zip1 = '$od_b_zip1', + od_b_zip2 = '$od_b_zip2', + od_b_addr1 = '$od_b_addr1', + od_b_addr2 = '$od_b_addr2', + od_b_addr3 = '$od_b_addr3', + od_b_addr_jibeon = '$od_b_addr_jibeon', + od_deposit_name = '$od_deposit_name', + od_memo = '$od_memo', + od_cart_count = '$cart_count', + od_cart_price = '$tot_ct_price', + od_cart_coupon = '$tot_it_cp_price', + od_send_cost = '$od_send_cost', + od_send_coupon = '$tot_sc_cp_price', + od_send_cost2 = '$od_send_cost2', + od_coupon = '$tot_od_cp_price', + od_receipt_price = '$od_receipt_price', + od_receipt_point = '$od_receipt_point', + od_bank_account = '$od_bank_account', + od_receipt_time = '$od_receipt_time', + od_misu = '$od_misu', + od_pg = '$od_pg', + od_tno = '$od_tno', + od_app_no = '$od_app_no', + od_escrow = '$od_escrow', + od_tax_flag = '$od_tax_flag', + od_tax_mny = '$od_tax_mny', + od_vat_mny = '$od_vat_mny', + od_free_mny = '$od_free_mny', + od_status = '$od_status', + od_shop_memo = '', + od_hope_date = '$od_hope_date', + od_time = '".G5_TIME_YMDHIS."', + od_ip = '$REMOTE_ADDR', + od_settle_case = '$od_settle_case', + od_other_pay_type = '$od_other_pay_type', + od_cash = '{$pg_receipt_infos['od_cash']}', + od_cash_no = '{$pg_receipt_infos['od_cash_no']}', + od_cash_info = '{$pg_receipt_infos['od_cash_info']}', + od_test = '{$default['de_card_test']}' + "; +$result = sql_query($sql, false); + +// 정말로 insert 가 되었는지 한번더 체크한다. +$exists_sql = "select od_id, od_tno, od_ip from {$g5['g5_shop_order_table']} where od_id = '$od_id'"; +$exists_order = sql_fetch($exists_sql); + +// 주문정보 입력 오류시 결제 취소 +if(! $result || ! (isset($exists_order['od_id']) && $od_id && $exists_order['od_id'] === $od_id)) { + if($tno) { + $cancel_msg = '주문정보 입력 오류 : '.$sql; + switch($od_pg) { + case 'lg': + include G5_SHOP_PATH.'/lg/xpay_cancel.php'; + break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_cancel.php'; + break; + case 'inicis': + include G5_SHOP_PATH.'/inicis/inipay_cancel.php'; + break; + case 'nicepay': + $cancelAmt = (int)$pg_price; + include G5_SHOP_PATH.'/nicepay/cancel_process.php'; + break; + case 'KAKAOPAY': + $_REQUEST['TID'] = $tno; + $_REQUEST['Amt'] = $amount; + $_REQUEST['CancelMsg'] = $cancel_msg; + $_REQUEST['PartialCancelCode'] = 0; + include G5_SHOP_PATH.'/kakaopay/kakaopay_cancel.php'; + break; + default: + include G5_SHOP_PATH.'/kcp/pp_ax_hub_cancel.php'; + break; + } + } + + // 관리자에게 오류 알림 메일발송 + $error = 'order'; + include G5_SHOP_PATH.'/ordererrormail.php'; + + if(function_exists('add_order_post_log')) add_order_post_log($cancel_msg); + die('

    고객님의 주문 정보를 처리하는 중 오류가 발생해서 주문이 완료되지 않았습니다.

    '.strtoupper($od_pg).'를 이용한 전자결제(신용카드, 계좌이체, 가상계좌 등)은 자동 취소되었습니다.'); +} + +// 장바구니 상태변경 +// 신용카드로 주문하면서 신용카드 포인트 사용하지 않는다면 포인트 부여하지 않음 +$cart_status = $od_status; +$sql_card_point = ""; +if ($od_receipt_price > 0 && !$default['de_card_point']) { + $sql_card_point = " , ct_point = '0' "; +} + +// 회원 아이디 값 변경 +$sql_mb_id = ""; +if ($is_member) { + $sql_mb_id = " , mb_id = '{$member['mb_id']}' "; +} + +$sql = "update {$g5['g5_shop_cart_table']} + set od_id = '$od_id', + ct_status = '$cart_status' + $sql_card_point + $sql_mb_id + where od_id = '$tmp_cart_id' + and ct_select = '1' "; +$result = sql_query($sql, false); + +// 주문정보 입력 오류시 결제 취소 +if(!$result) { + if($tno) { + $cancel_msg = '주문상태 변경 오류'; + switch($od_pg) { + case 'lg': + include G5_SHOP_PATH.'/lg/xpay_cancel.php'; + break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_cancel.php'; + break; + case 'inicis': + include G5_SHOP_PATH.'/inicis/inipay_cancel.php'; + break; + case 'nicepay': + $cancelAmt = (int)$pg_price; + include G5_SHOP_PATH.'/nicepay/cancel_process.php'; + break; + case 'KAKAOPAY': + $_REQUEST['TID'] = $tno; + $_REQUEST['Amt'] = $amount; + $_REQUEST['CancelMsg'] = $cancel_msg; + $_REQUEST['PartialCancelCode'] = 0; + include G5_SHOP_PATH.'/kakaopay/kakaopay_cancel.php'; + break; + default: + include G5_SHOP_PATH.'/kcp/pp_ax_hub_cancel.php'; + break; + } + } + + // 관리자에게 오류 알림 메일발송 + $error = 'status'; + include G5_SHOP_PATH.'/ordererrormail.php'; + + if(function_exists('add_order_post_log')) add_order_post_log($cancel_msg); + // 주문삭제 + sql_query(" delete from {$g5['g5_shop_order_table']} where od_id = '$od_id' "); + + die('

    고객님의 주문 정보를 처리하는 중 오류가 발생해서 주문이 완료되지 않았습니다.

    '.strtoupper($od_pg).'를 이용한 전자결제(신용카드, 계좌이체, 가상계좌 등)은 자동 취소되었습니다.'); +} + +// 회원이면서 포인트를 사용했다면 테이블에 사용을 추가 +if ($is_member && $od_receipt_point) + insert_point($member['mb_id'], (-1) * $od_receipt_point, "주문번호 $od_id 결제"); + +$od_memo = nl2br(htmlspecialchars2(stripslashes($od_memo))) . " "; + + +// 쿠폰사용내역기록 +if($is_member) { + $it_cp_cnt = (isset($_POST['cp_id']) && is_array($_POST['cp_id'])) ? count($_POST['cp_id']) : 0; + for($i=0; $i<$it_cp_cnt; $i++) { + $cid = isset($_POST['cp_id'][$i]) ? clean_xss_tags($_POST['cp_id'][$i], 1, 1) : ''; + $cp_it_id = isset($_POST['it_id'][$i]) ? clean_xss_tags($_POST['it_id'][$i], 1, 1) : ''; + $cp_prc = isset($arr_it_cp_prc[$cp_it_id]) ? (int) $arr_it_cp_prc[$cp_it_id] : 0; + + if(trim($cid)) { + $sql = " insert into {$g5['g5_shop_coupon_log_table']} + set cp_id = '$cid', + mb_id = '{$member['mb_id']}', + od_id = '$od_id', + cp_price = '$cp_prc', + cl_datetime = '".G5_TIME_YMDHIS."' "; + sql_query($sql); + } + + // 쿠폰사용금액 cart에 기록 + $sql = " update {$g5['g5_shop_cart_table']} + set cp_price = '$cp_prc' + where od_id = '$od_id' + and it_id = '$cp_it_id' + and ct_select = '1' + order by ct_id asc + limit 1 "; + sql_query($sql); + } + + if(isset($_POST['od_cp_id']) && $_POST['od_cp_id']) { + $sql = " insert into {$g5['g5_shop_coupon_log_table']} + set cp_id = '{$_POST['od_cp_id']}', + mb_id = '{$member['mb_id']}', + od_id = '$od_id', + cp_price = '$tot_od_cp_price', + cl_datetime = '".G5_TIME_YMDHIS."' "; + sql_query($sql); + } + + if(isset($_POST['sc_cp_id']) && $_POST['sc_cp_id']) { + $sql = " insert into {$g5['g5_shop_coupon_log_table']} + set cp_id = '{$_POST['sc_cp_id']}', + mb_id = '{$member['mb_id']}', + od_id = '$od_id', + cp_price = '$tot_sc_cp_price', + cl_datetime = '".G5_TIME_YMDHIS."' "; + sql_query($sql); + } +} + + +include_once(G5_SHOP_PATH.'/ordermail1.inc.php'); +include_once(G5_SHOP_PATH.'/ordermail2.inc.php'); + +// SMS BEGIN -------------------------------------------------------- +// 주문고객과 쇼핑몰관리자에게 SMS 전송 +if($config['cf_sms_use'] && ($default['de_sms_use2'] || $default['de_sms_use3'])) { + $is_sms_send = (function_exists('is_sms_send')) ? is_sms_send('orderformupdate') : false; + + if($is_sms_send) { + $sms_contents = array($default['de_sms_cont2'], $default['de_sms_cont3']); + $recv_numbers = array($od_hp, $default['de_sms_hp']); + $send_numbers = array($default['de_admin_company_tel'], $default['de_admin_company_tel']); + + $sms_count = 0; + $sms_messages = array(); + + for($s=0; $s $recv_number, 'send' => $send_number, 'cont' => $sms_content); + $sms_count++; + } + } + + // 무통장 입금 때 고객에게 계좌정보 보냄 + if($od_settle_case == '무통장' && $default['de_sms_use2'] && $od_misu > 0) { + $sms_content = $od_name."님의 입금계좌입니다.\n금액:".number_format($od_misu)."원\n계좌:".$od_bank_account."\n".$default['de_admin_company_name']; + + $recv_number = preg_replace("/[^0-9]/", "", $od_hp); + $send_number = preg_replace("/[^0-9]/", "", $default['de_admin_company_tel']); + + $sms_messages[] = array('recv' => $recv_number, 'send' => $send_number, 'cont' => $sms_content); + $sms_count++; + } + + // SMS 전송 + if($sms_count > 0) { + if($config['cf_sms_type'] == 'LMS') { + include_once(G5_LIB_PATH.'/icode.lms.lib.php'); + + $port_setting = get_icode_port_type($config['cf_icode_id'], $config['cf_icode_pw']); + + // SMS 모듈 클래스 생성 + if($port_setting !== false) { + $SMS = new LMS; + $SMS->SMS_con($config['cf_icode_server_ip'], $config['cf_icode_id'], $config['cf_icode_pw'], $port_setting); + + for($s=0; $sAdd($strDest, $strCallBack, $strCaller, $strSubject, $strURL, $strData, $strDate, $nCount); + + $SMS->Send(); + $SMS->Init(); // 보관하고 있던 결과값을 지웁니다. + } + } + } else { + include_once(G5_LIB_PATH.'/icode.sms.lib.php'); + + $SMS = new SMS; // SMS 연결 + $SMS->SMS_con($config['cf_icode_server_ip'], $config['cf_icode_id'], $config['cf_icode_pw'], $config['cf_icode_server_port']); + + for($s=0; $sAdd($recv_number, $send_number, $config['cf_icode_id'], $sms_content, ""); + } + + $SMS->Send(); + $SMS->Init(); // 보관하고 있던 결과값을 지웁니다. + } + } + } +} +// SMS END -------------------------------------------------------- + +// orderview 에서 사용하기 위해 session에 넣고 +$uid = md5($od_id.G5_TIME_YMDHIS.$REMOTE_ADDR); +set_session('ss_orderview_uid', $uid); + +// 주문 정보 임시 데이터 삭제 +if($od_pg == 'inicis') { + $sql = " delete from {$g5['g5_shop_order_data_table']} where od_id = '$od_id' and dt_pg = '$od_pg' "; + sql_query($sql); +} + +if(function_exists('add_order_post_log')) add_order_post_log('', 'delete'); + +// 주문번호제거 +set_session('ss_order_id', ''); + +// 기존자료 세션에서 제거 +if (get_session('ss_direct')) + set_session('ss_cart_direct', ''); + +// 배송지처리 +if($is_member) { + $sql = " select * from {$g5['g5_shop_order_address_table']} + where mb_id = '{$member['mb_id']}' + and ad_name = '$od_b_name' + and ad_tel = '$od_b_tel' + and ad_hp = '$od_b_hp' + and ad_zip1 = '$od_b_zip1' + and ad_zip2 = '$od_b_zip2' + and ad_addr1 = '$od_b_addr1' + and ad_addr2 = '$od_b_addr2' + and ad_addr3 = '$od_b_addr3' "; + $row = sql_fetch($sql); + + // 기본배송지 체크 + if($ad_default) { + $sql = " update {$g5['g5_shop_order_address_table']} + set ad_default = '0' + where mb_id = '{$member['mb_id']}' "; + sql_query($sql); + } + + $ad_subject = isset($_POST['ad_subject']) ? clean_xss_tags($_POST['ad_subject']) : ''; + + if(isset($row['ad_id']) && $row['ad_id']){ + $sql = " update {$g5['g5_shop_order_address_table']} + set ad_default = '$ad_default', + ad_subject = '$ad_subject', + ad_jibeon = '$od_b_addr_jibeon' + where mb_id = '{$member['mb_id']}' + and ad_id = '{$row['ad_id']}' "; + } else { + $sql = " insert into {$g5['g5_shop_order_address_table']} + set mb_id = '{$member['mb_id']}', + ad_subject = '$ad_subject', + ad_default = '$ad_default', + ad_name = '$od_b_name', + ad_tel = '$od_b_tel', + ad_hp = '$od_b_hp', + ad_zip1 = '$od_b_zip1', + ad_zip2 = '$od_b_zip2', + ad_addr1 = '$od_b_addr1', + ad_addr2 = '$od_b_addr2', + ad_addr3 = '$od_b_addr3', + ad_jibeon = '$od_b_addr_jibeon' "; + } + + sql_query($sql); +} + goto_url(G5_SHOP_URL.'/orderinquiryview.php?od_id='.$od_id.'&uid='.$uid); ?> diff --git a/shop/orderinquirycancel.php b/shop/orderinquirycancel.php index aefa943a1..6c0a4f92b 100644 --- a/shop/orderinquirycancel.php +++ b/shop/orderinquirycancel.php @@ -64,6 +64,10 @@ if($od['od_tno']) { alert($msg); } break; + case 'toss': + $cancel_msg = '주문자 본인 취소-'.$cancel_memo; + include_once(G5_SHOP_PATH.'/toss/toss_cancel.php'); + break; case 'inicis': include_once(G5_SHOP_PATH.'/settle_inicis.inc.php'); $cancel_msg = '주문자 본인 취소-'.$cancel_memo; diff --git a/shop/orderinquiryview.php b/shop/orderinquiryview.php index 297c5208d..bba85f21f 100644 --- a/shop/orderinquiryview.php +++ b/shop/orderinquiryview.php @@ -334,6 +334,8 @@ if($od['od_pg'] == 'lg') { $LGD_HASHDATA = md5($LGD_MID.$LGD_TID.$LGD_MERTKEY); $hp_receipt_script = 'showReceiptByTID(\''.$LGD_MID.'\', \''.$LGD_TID.'\', \''.$LGD_HASHDATA.'\');'; + } else if($od['od_pg'] == 'toss') { + $hp_receipt_script = 'window.open(\'https://dashboard.tosspayments.com/receipt/phone?transactionId='.$od['od_tno'].'&ref=PX\',\'receipt\',\'width=430,height=700\');'; } else if($od['od_pg'] == 'inicis') { $hp_receipt_script = 'window.open(\'https://iniweb.inicis.com/DefaultWebApp/mall/cr/cm/mCmReceipt_head.jsp?noTid='.$od['od_tno'].'&noMethod=1\',\'receipt\',\'width=430,height=700\');'; } else if($od['od_pg'] == 'nicepay') { @@ -355,6 +357,8 @@ if($od['od_pg'] == 'lg') { $LGD_HASHDATA = md5($LGD_MID.$LGD_TID.$LGD_MERTKEY); $card_receipt_script = 'showReceiptByTID(\''.$LGD_MID.'\', \''.$LGD_TID.'\', \''.$LGD_HASHDATA.'\');'; + } else if($od['od_pg'] == 'toss') { + $card_receipt_script = 'window.open(\'https://dashboard.tosspayments.com/receipt/redirection?transactionId='.$od['od_tno'].'&ref=PX\',\'receipt\',\'width=430,height=700\');'; } else if($od['od_pg'] == 'inicis') { $card_receipt_script = 'window.open(\'https://iniweb.inicis.com/DefaultWebApp/mall/cr/cm/mCmReceipt_head.jsp?noTid='.$od['od_tno'].'&noMethod=1\',\'receipt\',\'width=430,height=700\');'; } else if($od['od_pg'] == 'nicepay') { @@ -429,6 +433,8 @@ if($od['od_pg'] == 'lg') { break; } $cash_receipt_script = 'javascript:showCashReceipts(\''.$LGD_MID.'\',\''.$od['od_id'].'\',\''.$od['od_casseqno'].'\',\''.$trade_type.'\',\''.$CST_PLATFORM.'\');'; + } else if($od['od_pg'] == 'toss') { + $cash_receipt_script = 'window.open(\'https://dashboard.tosspayments.com/receipt/mids/si_'.$config['cf_lg_mid'].'/orders/'.$od['od_id'].'/cash-receipt?ref=dashboard\',\'receipt\',\'width=430,height=700\');'; } else if($od['od_pg'] == 'inicis') { $cash = unserialize($od['od_cash_info']); $cash_receipt_script = 'window.open(\'https://iniweb.inicis.com/DefaultWebApp/mall/cr/cm/Cash_mCmReceipt.jsp?noTid='.$cash['TID'].'&clpaymethod=22\',\'showreceipt\',\'width=380,height=540,scrollbars=no,resizable=no\');'; diff --git a/shop/personalpayform.sub.php b/shop/personalpayform.sub.php index c83a5ade6..fc1513ebc 100644 --- a/shop/personalpayform.sub.php +++ b/shop/personalpayform.sub.php @@ -62,8 +62,18 @@ require_once(G5_SHOP_PATH.'/'.$default['de_pg_service'].'/orderform.1.php'); $checked = ''; $escrow_title = ""; + $escrow_products = array(); // 토스페이먼츠 escrowProducts 배열 생성 if ($default['de_escrow_use']) { $escrow_title = "에스크로
    "; + + // 토스페이먼츠 escrowProducts 배열에 상품 정보 추가 + $escrow_products[] = array( + 'id' => $pp['pp_id'], + 'name' => $pp['pp_name'].'님 개인결제', + 'code' => $pp['pp_id'], + 'unitPrice' => (int) $pp['pp_price'], + 'quantity' => (int) 1 + ); } if ($default['de_vbank_use'] || $default['de_iche_use'] || $default['de_card_use'] || $default['de_hp_use']) { @@ -89,7 +99,7 @@ require_once(G5_SHOP_PATH.'/'.$default['de_pg_service'].'/orderform.1.php'); // 계좌이체 사용 if ($default['de_iche_use']) { $multi_settle++; - echo ' '.PHP_EOL; + echo ' '.PHP_EOL; $checked = ''; } ?> @@ -235,6 +245,28 @@ function forderform_check(f) f.LGD_CUSTOM_FIRSTPAY.value = "무통장"; break; } + + switch(settle_method) + { + case "계좌이체": + f.method.value = "TRANSFER"; + break; + case "가상계좌": + f.method.value = "VIRTUAL_ACCOUNT"; + break; + case "휴대폰": + f.method.value = "MOBILE_PHONE"; + break; + case "신용카드": + f.method.value = "CARD"; + break; + case "간편결제": + f.method.value = "CARD"; + break; + default: + f.method.value = "무통장"; + break; + } switch(settle_method) { @@ -312,6 +344,59 @@ function forderform_check(f) f.submit(); } + + + f.orderId.value = ''; + f.orderName.value = ''; + + f.customerName.value = f.pp_name.value; + f.customerEmail.value = f.pp_email.value; + f.customerMobilePhone.value = f.pp_hp.value.replace(/[^0-9]/g, ''); + + f.cardUseCardPoint.value = false; + f.cardUseAppCardOnly.value = false; + + + f.cardUseEscrow.value = 'true'; + f.escrowProducts.value = JSON.stringify(); + + + if(settle_method == "간편결제") { + f.cardflowMode.value = 'DIRECT'; + } + + f.amountCurrency.value = 'KRW'; + f.amountValue.value = f.good_mny.value; + + f.taxFreeAmount.value = f.comm_free_mny.value; + + f.windowTarget.value = 'iframe'; + + if(f.method.value != "무통장") { + // 주문정보 임시저장 + var order_data = $(f).serialize(); + var save_result = ""; + $.ajax({ + type: "POST", + data: order_data, + url: g5_url+"/shop/ajax.orderdatasave.php", + cache: false, + async: false, + success: function(data) { + save_result = data; + } + }); + + if(save_result) { + alert(save_result); + return false; + } + + launchCrossPlatform(f); + } else { + f.submit(); + } + f.price.value = f.good_mny.value; f.buyername.value = f.pp_name.value; diff --git a/shop/personalpayformupdate.php b/shop/personalpayformupdate.php index 6a25e8af6..2e09e09d5 100644 --- a/shop/personalpayformupdate.php +++ b/shop/personalpayformupdate.php @@ -2,28 +2,42 @@ include_once('./_common.php'); include_once(G5_LIB_PATH.'/mailer.lib.php'); +$page_return_url = G5_SHOP_URL.'/personalpayform.php?pp_id='.get_session('ss_personalpay_id'); + $pp_id = $_POST['pp_id'] = isset($_POST['pp_id']) ? preg_replace('/[^0-9]/', '', $_POST['pp_id']) : 0; $good_mny = $_POST['good_mny'] = isset($_POST['good_mny']) ? preg_replace('/[^0-9]/', '', $_POST['good_mny']) : 0; $post_lgd_paykey = isset($_POST['LGD_PAYKEY']) ? $_POST['LGD_PAYKEY'] : ''; +$paymentKey = isset($_POST['paymentKey']) ? $_POST['paymentKey'] : ''; $pp_deposit_name = ''; if($default['de_pg_service'] == 'lg' && ! $post_lgd_paykey) - alert('결제등록 요청 후 결제해 주십시오.'); + alert('결제등록 요청 후 결제해 주십시오.', $page_return_url); + +if($default['de_pg_service'] == 'toss' && ! $paymentKey) + alert('결제등록 요청 후 주문해 주십시오.', $page_return_url); + +set_session('ss_order_id', $pp_id); // 개인결제 정보 $pp_check = false; $sql = " select * from {$g5['g5_shop_personalpay_table']} where pp_id = '{$pp_id}' and pp_use = '1' "; $pp = sql_fetch($sql); if(! (isset($pp['pp_id']) && $pp['pp_id'])) - alert('개인결제 정보가 존재하지 않습니다.'); + alert('개인결제 정보가 존재하지 않습니다.', $page_return_url); if($pp['pp_tno']) - alert('이미 결제하신 개인결제 내역입니다.'); + alert('이미 결제하신 개인결제 내역입니다.', $page_return_url); $hash_data = md5($pp_id.$good_mny.$pp['pp_time']); if($pp_id != get_session('ss_personalpay_id') || $hash_data != get_session('ss_personalpay_hash')) die('개인결제 정보가 올바르지 않습니다.'); +// PG사의 가상계좌 또는 계좌이체의 자동 현금영수증 초기배열값 +$pg_receipt_infos = array( + 'od_cash' => 0, + 'od_cash_no' => '', + 'od_cash_info' => '', +); if ($pp_settle_case == "계좌이체") { @@ -31,6 +45,9 @@ if ($pp_settle_case == "계좌이체") case 'lg': include G5_SHOP_PATH.'/lg/xpay_result.php'; break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + break; case 'inicis': include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; break; @@ -56,6 +73,9 @@ else if ($pp_settle_case == "가상계좌") case 'lg': include G5_SHOP_PATH.'/lg/xpay_result.php'; break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + break; case 'inicis': include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; break; @@ -81,6 +101,9 @@ else if ($pp_settle_case == "휴대폰") case 'lg': include G5_SHOP_PATH.'/lg/xpay_result.php'; break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + break; case 'inicis': include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; break; @@ -104,6 +127,9 @@ else if ($pp_settle_case == "신용카드") case 'lg': include G5_SHOP_PATH.'/lg/xpay_result.php'; break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_result.php'; + break; case 'inicis': include G5_SHOP_PATH.'/inicis/inistdpay_result.php'; break; @@ -134,6 +160,9 @@ if((int)$pp['pp_price'] !== (int)$pg_price) { case 'lg': include G5_SHOP_PATH.'/lg/xpay_cancel.php'; break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_cancel.php'; + break; case 'inicis': include G5_SHOP_PATH.'/inicis/inipay_cancel.php'; break; @@ -164,7 +193,10 @@ $sql = " update {$g5['g5_shop_personalpay_table']} pp_bank_account = '$pp_bank_account', pp_deposit_name = '$pp_deposit_name', pp_receipt_time = '$pp_receipt_time', - pp_receipt_ip = '{$_SERVER['REMOTE_ADDR']}' + pp_receipt_ip = '{$_SERVER['REMOTE_ADDR']}', + pp_cash = '{$pg_receipt_infos['od_cash']}', + pp_cash_no = '{$pg_receipt_infos['od_cash_no']}', + pp_cash_info = '{$pg_receipt_infos['od_cash_info']}' where pp_id = '{$pp['pp_id']}' "; $result = sql_query($sql, false); @@ -202,6 +234,9 @@ if($pp_receipt_price > 0 && $pp['pp_id'] && $pp['od_id']) { od_settle_case = '$pp_settle_case', od_deposit_name = '$pp_deposit_name', od_bank_account = '$pp_bank_account', + od_cash = '{$pg_receipt_infos['od_cash']}', + od_cash_no = '{$pg_receipt_infos['od_cash_no']}', + od_cash_info = '{$pg_receipt_infos['od_cash_info']}', od_shop_memo = concat(od_shop_memo, \"\\n개인결제 ".$pp['pp_id']." 로 결제완료 - ".$pp_receipt_time."\") where od_id = '{$pp['od_id']}' "; $result = sql_query($sql, false); @@ -213,9 +248,12 @@ if($pp_receipt_price > 0 && $pp['pp_id'] && $pp['od_id']) { case 'lg': include G5_SHOP_PATH.'/lg/xpay_cancel.php'; break; + case 'toss': + include G5_SHOP_PATH.'/toss/toss_cancel.php'; + break; case 'inicis': - include G5_SHOP_PATH.'/inicis/inipay_cancel.php'; - break; + include G5_SHOP_PATH.'/inicis/inipay_cancel.php'; + break; default: include G5_SHOP_PATH.'/kcp/pp_ax_hub_cancel.php'; break; diff --git a/shop/personalpayresult.php b/shop/personalpayresult.php index 9113bd97d..150eb4eae 100644 --- a/shop/personalpayresult.php +++ b/shop/personalpayresult.php @@ -149,6 +149,8 @@ if($pp['pp_pg'] == 'lg') { $LGD_HASHDATA = md5($LGD_MID.$LGD_TID.$LGD_MERTKEY); $hp_receipt_script = 'showReceiptByTID(\''.$LGD_MID.'\', \''.$LGD_TID.'\', \''.$LGD_HASHDATA.'\');'; + } else if($pp['pp_pg'] == 'toss') { + $hp_receipt_script = 'window.open(\'https://dashboard.tosspayments.com/receipt/phone?transactionId='.$pp['pp_tno'].'&ref=PX\',\'receipt\',\'width=430,height=700\');'; } else if($pp['pp_pg'] == 'inicis') { $hp_receipt_script = 'window.open(\'https://iniweb.inicis.com/DefaultWebApp/mall/cr/cm/mCmReceipt_head.jsp?noTid='.$pp['pp_tno'].'&noMethod=1\',\'receipt\',\'width=430,height=700\');'; } else if($pp['pp_pg'] == 'nicepay') { @@ -170,6 +172,8 @@ if($pp['pp_pg'] == 'lg') { $LGD_HASHDATA = md5($LGD_MID.$LGD_TID.$LGD_MERTKEY); $card_receipt_script = 'showReceiptByTID(\''.$LGD_MID.'\', \''.$LGD_TID.'\', \''.$LGD_HASHDATA.'\');'; + } else if($pp['pp_pg'] == 'toss') { + $card_receipt_script = 'window.open(\'https://dashboard.tosspayments.com/receipt/redirection?transactionId='.$pp['pp_tno'].'&ref=PX\',\'receipt\',\'width=430,height=700\');'; } else if($pp['pp_pg'] == 'inicis') { $card_receipt_script = 'window.open(\'https://iniweb.inicis.com/DefaultWebApp/mall/cr/cm/mCmReceipt_head.jsp?noTid='.$pp['pp_tno'].'&noMethod=1\',\'receipt\',\'width=430,height=700\');'; } else if($pp['pp_pg'] == 'nicepay') { @@ -225,6 +229,8 @@ if($pp['pp_pg'] == 'lg') { break; } $cash_receipt_script = 'javascript:showCashReceipts(\''.$LGD_MID.'\',\''.$pp['pp_id'].'\',\''.$pp['pp_casseqno'].'\',\''.$trade_type.'\',\''.$CST_PLATFORM.'\');'; + } else if($pp['pp_pg'] == 'toss') { + $cash_receipt_script = 'window.open(\'https://dashboard.tosspayments.com/receipt/mids/si_'.$config['cf_lg_mid'].'/orders/'.$pp['pp_id'].'/cash-receipt?ref=dashboard\',\'receipt\',\'width=430,height=700\');'; } else if($pp['pp_pg'] == 'inicis') { $cash = unserialize($pp['pp_cash_info']); $cash_receipt_script = 'window.open(\'https://iniweb.inicis.com/DefaultWebApp/mall/cr/cm/Cash_mCmReceipt.jsp?noTid='.$cash['TID'].'&clpaymethod=22\',\'showreceipt\',\'width=380,height=540,scrollbars=no,resizable=no\');'; diff --git a/shop/settle_lg_common.php b/shop/settle_lg_common.php index 21d6662c3..9213a6ff6 100644 --- a/shop/settle_lg_common.php +++ b/shop/settle_lg_common.php @@ -1,6 +1,7 @@ setPaymentHeader(); \ No newline at end of file diff --git a/shop/settle_toss_common.php b/shop/settle_toss_common.php new file mode 100644 index 000000000..2c7f48f71 --- /dev/null +++ b/shop/settle_toss_common.php @@ -0,0 +1,422 @@ +setPaymentHeader(); + +$orderResult = $toss->getPaymentByOrderId($TOSS_ORDERID); +$order_info = $toss->responseData; + +if (!$orderResult || $order_info['secret'] !== $TOSS_SECRET) { + $error_msg = isset($order_info['message']) ? $order_info['message'] : '주문 정보 조회 실패'; + $error_code = isset($order_info['code']) ? $order_info['code'] : 'UNKNOWN_ERROR'; + write_toss_log("주문 정보 조회 실패 - {$error_code} : {$error_msg}", $TOSS_ORDERID, $TOSS_STATUS); + http_response_code(400); + exit; +} + +// 결제 정보 +$paymentKey = isset($order_info["paymentKey"]) ? clean_xss_tags($order_info["paymentKey"]) : ''; // 결제 키 +$customerName = isset($order_info["virtualAccount"]["customerName"]) ? clean_xss_tags($order_info["virtualAccount"]["customerName"]) : ''; // 주문자명 (가상계좌 발급 시 고객명) +$depositorName = isset($order_info["virtualAccount"]["depositorName"]) ? clean_xss_tags($order_info["virtualAccount"]["depositorName"]) : ''; // 입금자명 (실제 입금자 입력 이름) +$totalAmount = isset($order_info["totalAmount"]) ? clean_xss_tags($order_info["totalAmount"]) : ''; // 입금 금액 (결제 총액) +$bankCode = isset($order_info["virtualAccount"]["bankCode"]) ? clean_xss_tags($order_info["virtualAccount"]["bankCode"]) : ''; // 은행코드 (가상계좌 발급 은행, 예: 11 → 농협) +$accountNumber = isset($order_info["virtualAccount"]["accountNumber"]) ? clean_xss_tags($order_info["virtualAccount"]["accountNumber"]) : ''; // 가상계좌 입금계좌번호 +$approvedAt = isset($order_info['approvedAt']) ? clean_xss_tags($order_info['approvedAt']) : ''; //입금일시 +$dueDate = isset($order_info["virtualAccount"]['dueDate']) ? clean_xss_tags($order_info['virtualAccount']['dueDate']) : ''; // 만료일시 +$receipt_time = $approvedAt ? (strtotime($approvedAt) !== false ? date("Y-m-d H:i:s", strtotime($approvedAt)) : '') : ''; +$due_time = $dueDate ? (strtotime($dueDate) !== false ? date("Y-m-d H:i:s", strtotime($dueDate)) : '') : ''; + +// 가상계좌 채번시 현금영수증 자동발급신청이 되었을 경우 전달되며 +// RcptTID에 값이 있는 경우만 발급처리 됨 +$RcptTID = isset($order_info['cashReceipt']['receiptKey']) ? clean_xss_tags($order_info['cashReceipt']['receiptKey']) : ''; // 현금영수증 거래번호 +$RcptAuthCode = isset($order_info['cashReceipt']['issueNumber']) ? clean_xss_tags($order_info['cashReceipt']['issueNumber']) : ''; // 현금영수증 승인번호 +// 현금영수증 구분(0:미발행, 1:소득공제용, 2:지출증빙용) +$RcptType = isset($order_info['cashReceipt']['type']) ? clean_xss_tags($order_info['cashReceipt']['type'] === '소득공제' ? '1' : ($order_info['cashReceipt']['type'] === '지출증빙' ? '2' : '0')) : '0'; +$RcptReceiptUrl = isset($order_info['cashReceipt']['receiptUrl']) ? clean_xss_tags($order_info['cashReceipt']['receiptUrl']) : ''; // 현금영수증 URL + +$result = false; + +/** + * 입금 완료 처리 + */ +if($TOSS_STATUS == "DONE"){ + + // 입금결과 처리 + $sql = " select pp_id, od_id from {$g5['g5_shop_personalpay_table']} where pp_id = '{$TOSS_ORDERID}' and pp_tno = '{$paymentKey}'"; + $row = sql_fetch($sql); + + if($row['pp_id']) { + // 개인결제 UPDATE + $add_update_sql = ''; + + // 현금영수증 발급시 1 또는 2 이면 + if ($RcptType) { + $add_update_sql = " + , pp_cash = '1', + pp_cash_no = '".$RcptAuthCode."', + pp_cash_info = '".serialize(array('TID'=>$RcptTID, 'ApplNum'=>$RcptAuthCode, 'AuthDate'=>$approvedAt, 'receiptUrl'=>$RcptReceiptUrl))."' + "; + } + + $sql = " update {$g5['g5_shop_personalpay_table']} + set pp_receipt_price = '$totalAmount', + pp_receipt_time = '$receipt_time', + pp_deposit_name = '$depositorName' + $add_update_sql + where pp_id = '$TOSS_ORDERID'"; + $result = sql_query($sql, false); + + if($row['od_id']) { + // 주문서 UPDATE + $sql = " update {$g5['g5_shop_order_table']} + set od_receipt_price = od_receipt_price + '$totalAmount', + od_receipt_time = '$receipt_time', + od_deposit_name = '$depositorName', + 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 { + // 주문내역에 secret 검증 추가 + $sql = " select od_id from {$g5['g5_shop_order_table']} where od_id = '$TOSS_ORDERID' and od_tno = '$paymentKey'"; + $row = sql_fetch($sql); + if(!$row['od_id']) { + write_toss_log("주문내역 조회 실패", $TOSS_ORDERID, $TOSS_STATUS); + http_response_code(400); + exit; + } + + // 주문서 UPDATE + $sql = " update {$g5['g5_shop_order_table']} + set od_receipt_price = '$totalAmount', + od_receipt_time = '$receipt_time', + od_deposit_name = '$depositorName' + where od_id = '$TOSS_ORDERID' + and od_tno = '$paymentKey'"; + $result = sql_query($sql, FALSE); + } + + if($result) { + if (isset($row['od_id']) && $row['od_id']) + $od_id = $row['od_id']; + else + $od_id = $TOSS_ORDERID; + + // 주문정보 체크 + $sql = " select count(od_id) as cnt + from {$g5['g5_shop_order_table']} + where od_id = '$od_id' + and od_status = '주문' "; + $row = sql_fetch($sql); + + if($row['cnt'] == 1) { + // 미수금 정보 업데이트 + $info = get_order_info($od_id); + + $add_update_sql = ''; + + // 현금영수증 발급시 1 또는 2 이면 + if ($RcptType) { + $add_update_sql = " + , od_cash = '1', + od_cash_no = '".$RcptAuthCode."', + od_cash_info = '".serialize(array('TID'=>$RcptTID, 'ApplNum'=>$RcptAuthCode, 'AuthDate'=>$approvedAt, 'receiptUrl'=>$RcptReceiptUrl))."' + "; + } + + $sql = " update {$g5['g5_shop_order_table']} + set od_misu = '{$info['od_misu']}' $add_update_sql "; + if($info['od_misu'] == 0) + $sql .= " , od_status = '입금' "; + $sql .= " where od_id = '$od_id' "; + sql_query($sql, FALSE); + + // 장바구니 상태변경 + if($info['od_misu'] == 0) { + $sql = " update {$g5['g5_shop_cart_table']} + set ct_status = '입금' + where od_id = '$od_id' "; + sql_query($sql, FALSE); + } + } + } +} + +/** + * 입금 오류 처리 (입금 오류로 인해 WAITING_FOR_DEPOSIT으로 되돌아온 경우) + */ +elseif($TOSS_STATUS == "WAITING_FOR_DEPOSIT") +{ + // 개인결제 정보 조회 + $sql = " select pp_id, od_id, pp_name, pp_hp, pp_tel from {$g5['g5_shop_personalpay_table']} where pp_id = '{$TOSS_ORDERID}' and pp_tno = '{$paymentKey}'"; + $row = sql_fetch($sql); + + if($row['pp_id']) { + // 개인결제 정보 롤백 + $sql = " update {$g5['g5_shop_personalpay_table']} + set pp_receipt_price = 0, + pp_receipt_time = '', + pp_cash = 0, + pp_cash_no = '', + pp_cash_info = '' + where pp_id = '{$TOSS_ORDERID}' and pp_tno = '{$paymentKey}'"; + $result = sql_query($sql, FALSE); + + if($row['od_id']) { + // 주문서에서 개인결제 금액 차감 + $sql = " update {$g5['g5_shop_order_table']} + set od_receipt_price = od_receipt_price - '$totalAmount', + od_shop_memo = concat(od_shop_memo, \"\\n개인결제 ".$row['pp_id']." 가상계좌 입금 오류로 취소 - ".date('Y-m-d H:i:s')."\") + where od_id = '{$row['od_id']}' "; + $result = sql_query($sql, FALSE); + } + } else { + // 일반 주문 롤백 전에 데이터 존재 확인 + $sql = " select od_id, od_name, od_hp, od_tel from {$g5['g5_shop_order_table']} where od_id = '{$TOSS_ORDERID}' and od_tno = '{$paymentKey}'"; + $row = sql_fetch($sql); + if(empty($row['od_id'])) { + write_toss_log("주문 데이터가 존재하지 않음", $TOSS_ORDERID, $TOSS_STATUS); + http_response_code(400); + exit; + } + + // 일반 주문 입금완료 - 주문 상태 롤백 (입금 → 주문) + $sql = " update {$g5['g5_shop_order_table']} + set od_status = '주문', + od_receipt_price = 0, + od_receipt_time = '', + od_shop_memo = concat(od_shop_memo, \"\\n가상계좌 입금 오류로 취소 - ".date('Y-m-d H:i:s')."\"), + od_cash = 0, + od_cash_no = '', + od_cash_info = '' + where od_id = '{$TOSS_ORDERID}' and od_tno = '{$paymentKey}' "; + $result = sql_query($sql, FALSE); + } + + // 공통 처리: 미수금 정보 재계산 및 상태 롤백 + if($result) { + if (isset($row['od_id']) && $row['od_id']) + $od_id = $row['od_id']; + else + $od_id = $TOSS_ORDERID; + + // 미수금 정보 재계산 + $info = get_order_info($od_id); + + if($info) { + $sql = " update {$g5['g5_shop_order_table']} + set od_misu = '{$info['od_misu']}', + od_status = '주문', + od_cash = 0, + od_cash_no = '', + od_cash_info = '' + where od_id = '{$od_id}' "; + sql_query($sql, FALSE); + + // 장바구니 상태 롤백 (입금 → 주문) + $sql = " update {$g5['g5_shop_cart_table']} + set ct_status = '주문' + where od_id = '{$od_id}' "; + sql_query($sql, FALSE); + } + + // SMS 발송 - 재입금 안내 + $sms_message = ''; + + // 개인결제인지 일반주문인지 확인하여 연락처 조회 + if($row['pp_id']) { + // 개인결제인 경우 + $customer_name = $row['pp_name']; + $customer_phone = $row['pp_hp'] ? $row['pp_hp'] : ($row['pp_tel'] ? $row['pp_tel'] : ''); + $title = "개인결제번호 {$TOSS_ORDERID}"; + } else { + // 일반주문인 경우 + $customer_name = $row['od_name']; + $customer_phone = $row['od_hp'] ? $row['od_hp'] : ($row['od_tel'] ? $row['od_tel'] : ''); + $title = "주문번호 {$od_id}"; + } + + if($customer_phone) { + $sms_message = "{$customer_name}님, {$title} 가상계좌 입금이 완료되지 않았습니다. 재입금 또는 관리자 문의 바랍니다.\n"; + $sms_message .= $default['de_admin_company_name']; + } + + // 전화번호가 있고 SMS 발송 설정이 활성화된 경우에만 발송 + if($customer_phone && $sms_message && $config['cf_icode_id'] && $config['cf_icode_pw']) { + // SMS 발송 + $sms_messages = array(); + $receive_number = preg_replace("/[^0-9]/", "", $customer_phone); // 수신자번호 + $send_number = preg_replace("/[^0-9]/", "", $default['de_admin_company_tel']); // 발신자번호 + $sms_messages[] = array('recv' => $receive_number, 'send' => $send_number, 'cont' => $sms_message); + + // SMS 발송 처리 + if($config['cf_sms_type'] == 'LMS') { + include_once(G5_LIB_PATH.'/icode.lms.lib.php'); + + $port_setting = get_icode_port_type($config['cf_icode_id'], $config['cf_icode_pw']); + + if($port_setting !== false) { + $SMS = new LMS; + $SMS->SMS_con($config['cf_icode_server_ip'], $config['cf_icode_id'], $config['cf_icode_pw'], $port_setting); + + for($s=0; $sAdd($strDest, $strCallBack, $strCaller, $strSubject, $strURL, $strData, $strDate, $nCount); + $SMS->Send(); + $SMS->Init(); + } + } + } else { + include_once(G5_LIB_PATH.'/icode.sms.lib.php'); + + $SMS = new SMS; + $SMS->SMS_con($config['cf_icode_server_ip'], $config['cf_icode_id'], $config['cf_icode_pw'], $config['cf_icode_server_port']); + + for($s=0; $sAdd($recv_number, $send_number, $config['cf_icode_id'], $sms_content, ""); + } + + $SMS->Send(); + $SMS->Init(); + } + + // SMS 발송 로그 기록 + write_toss_log("가상계좌 재입금 안내 SMS 발송 완료", $TOSS_ORDERID, "SMS_SENT"); + } + } +} + +/** + * 입금 전 취소 처리 + */ +elseif($TOSS_STATUS == "CANCELED") +{ + $sql = " update {$g5['g5_shop_order_table']} + set od_shop_memo = concat(od_shop_memo, \"\\n가상계좌 입금 전 취소 - ".date('Y-m-d H:i:s')."\") + where od_id = '{$TOSS_ORDERID}' "; + $result = sql_query($sql, FALSE); +} + +//************************************************************************************ +// 위에서 상점 데이터베이스에 등록 성공유무에 따라서 성공시에는 성공응답인 `HTTP 200` 상태 코드를 리턴해야 합니다. +// (주의) 성공응답인 `HTTP 200` 상태 코드를 리턴하지 않으면 토스페이먼츠에서 7회까지 재전송에 실패하면 웹훅 상태가 실패로 변경됩니다. + +// 로그 기록 +if($payLog) { + $logfile = fopen($log_file, "a+"); + + // 은행명 조회 + $bankName = ''; + if($bankCode && isset($toss->bankCode[$bankCode])) { + $bankName = $toss->bankCode[$bankCode]; + } + + fwrite( $logfile,"************************************************\r\n"); + fwrite( $logfile,"GoodsName : 토스페이먼츠 가상계좌\r\n"); + fwrite( $logfile,"OrderId : ".$TOSS_ORDERID."\r\n"); + fwrite( $logfile,"Status : ".$TOSS_STATUS."\r\n"); + fwrite( $logfile,"ResultMsg : ".($result ? "SUCCESS" : "FAIL")."\r\n"); + fwrite( $logfile,"Amt : ".$totalAmount."\r\n"); + fwrite( $logfile,"name : ".$customerName."\r\n"); + fwrite( $logfile,"TID : ".$paymentKey."\r\n"); + fwrite( $logfile,"AuthDate : ".$approvedAt."\r\n"); + fwrite( $logfile,"VbankNum : ".$accountNumber."\r\n"); + fwrite( $logfile,"VbankCode : ".$bankCode."\r\n"); + fwrite( $logfile,"VbankName : ".$bankName."\r\n"); + fwrite( $logfile,"VbankInputName: ".$depositorName."\r\n"); + fwrite( $logfile,"RcptTID : ".$RcptTID."\r\n"); + fwrite( $logfile,"RcptAuthCode : ".$RcptAuthCode."\r\n"); + fwrite( $logfile,"RcptType : ".$RcptType."\r\n"); + fwrite( $logfile,"************************************************\r\n"); + + fclose( $logfile ); +} + +if ($result) +{ + http_response_code(200); // 절대로 지우지마세요 + echo "OK"; + exit; +} +else +{ + http_response_code(400); + echo "FAIL"; + exit; +} + +//************************************************************************************* \ No newline at end of file diff --git a/shop/toss/_common.php b/shop/toss/_common.php new file mode 100644 index 000000000..c7ed3c4ee --- /dev/null +++ b/shop/toss/_common.php @@ -0,0 +1,2 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shop/toss/orderform.3.php b/shop/toss/orderform.3.php new file mode 100644 index 000000000..04b7d01e6 --- /dev/null +++ b/shop/toss/orderform.3.php @@ -0,0 +1,16 @@ + + +

    + + + diff --git a/shop/toss/orderform.4.php b/shop/toss/orderform.4.php new file mode 100644 index 000000000..4e5ea2114 --- /dev/null +++ b/shop/toss/orderform.4.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/shop/toss/orderpartcancel.inc.php b/shop/toss/orderpartcancel.inc.php new file mode 100644 index 000000000..59044418e --- /dev/null +++ b/shop/toss/orderpartcancel.inc.php @@ -0,0 +1,61 @@ +setPaymentHeader(); + +$od_id = isset($od['od_id']) ? $od['od_id'] : (isset($pp['pp_id']) ? $pp['pp_id'] : ''); + +if (!$toss->getPaymentByOrderId($od_id)) { + alert('결제정보를 가져올 수 없습니다.'); +} + +$toss->setCancelData(array( + 'paymentKey' => $toss->responseData['paymentKey'], + 'cancelReason' => $mod_memo, + 'cancelAmount' => (int)$tax_mny + (int)$free_mny, + 'taxFreeAmount' => (int)$free_mny, +)); +if (!$toss->cancelPayment()) { + $msg = '결제 부분취소 요청이 실패하였습니다.\\n\\n'; + if (isset($toss->responseData['message'])) { + $msg .= '사유 : ' . $toss->responseData['message'] . '\\n'; + } + if (isset($toss->responseData['code'])) { + $msg .= '코드 : ' . $toss->responseData['code']; + } + alert($msg); +} + +// 환불금액 기록 +$mod_mny = (int)$tax_mny + (int)$free_mny; +$sql = " update {$g5['g5_shop_order_table']} + set od_refund_price = od_refund_price + '$mod_mny', + od_shop_memo = concat(od_shop_memo, \"$mod_memo\") + where od_id = '{$od['od_id']}'"; +sql_query($sql); + +// 미수금 등의 정보 업데이트 +$info = get_order_info($od_id); + +$sql = " update {$g5['g5_shop_order_table']} + set od_misu = '{$info['od_misu']}', + od_tax_mny = '{$info['od_tax_mny']}', + od_vat_mny = '{$info['od_vat_mny']}', + od_free_mny = '{$info['od_free_mny']}' + where od_id = '$od_id' "; +sql_query($sql); \ No newline at end of file diff --git a/shop/toss/returnurl.php b/shop/toss/returnurl.php new file mode 100644 index 000000000..434cf9ad5 --- /dev/null +++ b/shop/toss/returnurl.php @@ -0,0 +1,67 @@ + + +'.PHP_EOL; + +echo make_order_field($data, $exclude); + +echo ''.PHP_EOL; +?> + + + + + + + +
    +

    + +
    +

    주문정보

    + +
    +
    개인정보 수집 및 이용
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    주문 번호
    상품 정보
    주문자 이름
    주문자 E-Mail
    주문자 전화번호
    +
    +
    + +
    +

    현금영수증 발급 정보

    + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    원 거래 시각
    발행 용도 + + + + +
    + + + ("-" 생략) +
    거래금액 총합
    공급가액
    봉사료
    부가가치세
    +
    + +
    + + + + +
    + +
    +
    + + \ No newline at end of file diff --git a/shop/toss/taxsave_result.php b/shop/toss/taxsave_result.php new file mode 100644 index 000000000..188c0a283 --- /dev/null +++ b/shop/toss/taxsave_result.php @@ -0,0 +1,192 @@ +개인결제 내역이 존재하지 않습니다.

    '); + + $od_tno = $od['pp_tno']; + $goods_name = $od['pp_name'].'님 개인결제'; + $settle_case = $od['pp_settle_case']; + $order_price = $od['pp_receipt_price']; + $od_casseqno = $od['pp_casseqno']; + $od_name = $od['pp_name']; + $od_email = $od['pp_email']; + $od_tel = $od['pp_hp']; +} else { + $od = sql_fetch(" select * from {$g5['g5_shop_order_table']} where od_id = '$od_id' "); + if (!$od) + die('

    주문서가 존재하지 않습니다.

    '); + + $od_tno = $od['od_tno']; + $goods = get_goods($od['od_id']); + $goods_name = $goods['full_name']; + $settle_case = $od['od_settle_case']; + $order_price = $od['od_tax_mny'] + $od['od_vat_mny'] + $od['od_free_mny']; + $od_casseqno = $od['od_casseqno']; + $od_name = $od['od_name']; + $od_email = $od['od_email']; + $od_tel = $od['od_tel']; +} + +switch($settle_case) { + case '가상계좌': + case '계좌이체': + case '무통장': + // 토스페이먼츠는 결제수단 구분 없이 현금영수증 발급 가능 + break; + default: + die('

    현금영수증은 무통장, 가상계좌, 계좌이체에 한해 발급요청이 가능합니다.

    '); + break; +} + +// 토스페이먼츠 현금영수증 발급 요청 +$orderId = $od_id; +$amount = $order_price; +$type = ($_POST['tr_code'] == '0') ? '소득공제' : '지출증빙'; +$customerIdentityNumber = $_POST['id_info']; +$orderName = $od_name; +$customerEmail = $_POST['buyeremail'] ?: $od_email; +$customerMobilePhone = $_POST['buyertel'] ?: $od_tel; + +// 토스페이먼츠 현금영수증 발급 API 호출 +$toss->setCashReceiptsData([ + 'orderId' => $orderId, + 'amount' => $amount, + 'type' => $type, + 'customerIdentityNumber' => $customerIdentityNumber, + 'orderName' => $goods_name, +]); +$toss_result = $toss->issueCashReceipt(); + +/* + * 토스페이먼츠 현금영수증 발급 요청 결과처리 + */ +if ($toss_result && isset($toss->responseData['receiptKey'])) { + // 현금영수증 발급 성공 + $data = $toss->responseData; + $receiptKey = $data['receiptKey']; // 현금영수증 발급 키 + $cash_no = $data['issueNumber']; // 현금영수증 발급 번호 + $approvedAt = $data['requestedAt']; + + $cash = array(); + $cash['receiptKey'] = $receiptKey; + $cash['approvedAt'] = $approvedAt; + $cash['orderId'] = $data['orderId']; + $cash['amount'] = $data['amount']; + $cash['type'] = $data['type']; + $cash['receiptUrl'] = $data['receiptUrl']; + $cash_info = serialize($cash); + + if($tx == 'personalpay') { + $sql = " update {$g5['g5_shop_personalpay_table']} + set pp_cash = '1', + pp_cash_no = '$cash_no', + pp_cash_info = '$cash_info' + where pp_id = '$orderId' "; + } else { + $sql = " update {$g5['g5_shop_order_table']} + set od_cash = '1', + od_cash_no = '$cash_no', + od_cash_info = '$cash_info' + where od_id = '$orderId' "; + } + + $result = sql_query($sql, false); + + if(!$result) { // DB 정보갱신 실패시 취소 + $cancel_result = $toss->cancelCashReceipt($receiptKey, 'DB 업데이트 실패로 인한 취소'); + + if (!$cancel_result) { + $msg = '현금영수증 취소 요청처리가 정상적으로 완료되지 않았습니다.\\n'. $toss->responseData['message']; + alert_close($msg); + } + } + +} else { + // API 요청 실패 화면처리 + $msg = '현금영수증 발급 요청처리가 정상적으로 완료되지 않았습니다.\\n'. $toss->responseData['message']; + alert($msg); +} + +$g5['title'] = ''; +include_once(G5_PATH.'/head.sub.php'); +?> + + + + +
    +

    현금영수증 - 토스페이먼츠

    + +
    + + + + + + + responseData['receiptKey'])): ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    결과발급 완료
    현금영수증 발급번호responseData['issueNumber']; ?>
    주문번호responseData['orderId']; ?>
    발급 유형responseData['type']; ?>
    금액responseData['amount']); ?>원
    승인시간responseData['requestedAt'])); ?>
    현금영수증 확인 + +

    영수증 확인은 실 등록의 경우에만 가능합니다.

    +
    결과발급 실패
    오류 메시지
    +
    + +
    + + '한국산업은행', + '03' => 'IBK기업은행', + '06' => 'KB국민은행', + '07' => 'Sh수협은행', + '11' => 'NH농협은행', + '12' => '단위농협(지역농축협)', + '20' => '우리은행', + '23' => 'SC제일은행', + '27' => '씨티은행', + '31' => 'iM뱅크(대구)', + '32' => '부산은행', + '34' => '광주은행', + '35' => '제주은행', + '37' => '전북은행', + '39' => '경남은행', + '45' => '새마을금고', + '48' => '신협', + '50' => '저축은행중앙회', + '54' => '홍콩상하이은행', + '64' => '산림조합', + '71' => '우체국예금보험', + '81' => '하나은행', + '88' => '신한은행', + '89' => '케이뱅크', + '90' => '카카오뱅크', + '92' => '토스뱅크', + + // 증권 + 'S0' => '유안타증권', + 'S2' => '신한금융투자', + 'S3' => '삼성증권', + 'S4' => 'KB증권', + 'S5' => '미래에셋증권', + 'S6' => '한국투자증권', + 'S8' => '교보증권', + 'S9' => '아이엠증권', + 'SA' => '현대차증권', + 'SB' => '키움증권', + 'SD' => 'SK증권', + 'SE' => '대신증권', + 'SG' => '한화투자증권', + 'SH' => '하나금융투자', + 'SI' => 'DB금융투자', + 'SJ' => '유진투자증권', + 'SK' => '메리츠증권', + 'SM' => '부국증권', + 'SN' => '신영증권', + 'SO' => 'LIG투자증권', + 'SP' => 'KTB투자증권(다올투자증권)', + 'SQ' => '카카오페이증권', + 'SR' => '펀드온라인코리아(한국포스증권)', + 'ST' => '토스증권' + ); + + public array $cardCode = array( + '3K' => '기업 BC', + '46' => '광주은행', + '71' => '롯데카드', + '30' => '한국산업은행', + '31' => 'BC카드', + '51' => '삼성카드', + '38' => '새마을금고', + '41' => '신한카드', + '62' => '신협', + '36' => '씨티카드', + '33' => '우리BC카드(BC 매입)', + 'W1' => '우리카드(우리 매입)', + '37' => '우체국예금보험', + '39' => '저축은행중앙회', + '35' => '전북은행', + '42' => '제주은행', + '15' => '카카오뱅크', + '3A' => '케이뱅크', + '24' => '토스뱅크', + '21' => '하나카드', + '61' => '현대카드', + '11' => 'KB국민카드', + '91' => 'NH농협카드', + '34' => 'Sh수협은행', + 'PCP' => '페이코', + 'KBS' => 'KB증권' + ); + + // 간편결제 제공업체 코드 + public array $easyPayCode = array( + 'TOSSPAY' => '토스페이', + 'NAVERPAY' => '네이버페이', + 'SAMSUNGPAY' => '삼성페이', + 'APPLEPAY' => '애플페이', + 'LPAY' => '엘페이', + 'KAKAOPAY' => '카카오페이', + 'PINPAY' => '핀페이', + 'PAYCO' => '페이코', + 'SSG' => 'SSG페이' + ); + + public function __construct(string $clientKey, string $secretKey, string $mId) { + $this->clientKey = $clientKey; + $this->secretKey = $secretKey; + $this->mId = $mId; + } + + /** + * 헤더 시크릿 키 설정 + * @return void + */ + private function setHeaderSecretKey(): void + { + $this->headerSecretKey = base64_encode($this->secretKey . ':'); + } + + /** + * 헤더 설정 + * @return void + */ + public function setPaymentHeader(): void + { + $this->setHeaderSecretKey(); + + $this->headers = array( + 'Authorization: Basic ' . $this->headerSecretKey, + 'Content-Type' => 'Content-Type: application/json' + ); + } + + /** + * 결제 데이터 설정 + * + * @param array $request + * @return void + */ + public function setPaymentData(array $request): void + { + $this->paymentData = array( + 'amount' => $request['amount'], + 'orderId' => $request['orderId'], + 'paymentKey' => $request['paymentKey'], + ); + } + + /** + * 주문번호로 결제정보 조회 + * + * @param string $orderId + * @return bool + */ + public function getPaymentByOrderId(string $orderId): bool + { + if (empty($orderId)) { + return false; + } + + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, str_replace('{orderId}', $orderId, $this->paymentUrl)); + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->headers); + curl_setopt($curl, CURLOPT_SSLVERSION, 6); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_TIMEOUT, 20); + + $response = curl_exec($curl); + + $return_status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $this->responseData = json_decode($response, true); + + curl_close($curl); + + // 결제 실패 상황인 경우 + if ($return_status != 200) { + return false; + } + + return true; + } + + /** + * 결제 승인 + * + * @return bool + */ + public function approvePayment(): bool { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $this->acceptUrl); + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->headers); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($this->paymentData)); + curl_setopt($curl, CURLOPT_SSLVERSION, 6); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_TIMEOUT, 20); + + $response = curl_exec($curl); + + $return_status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $this->responseData = json_decode($response, true); + + curl_close($curl); + + // 결제 실패 상황인 경우 + if ($return_status != 200 || ($this->responseData['status'] != 'DONE' && $this->responseData['status'] != 'WAITING_FOR_DEPOSIT')) { + return false; + } + + return true; + } + + /** + * 결제 취소 데이터 설정 + * + * @param array $request + * @return void + */ + public function setCancelData(array $request): void + { + $this->cancelData = array( + 'paymentKey' => $request['paymentKey'], + 'cancelReason' => $request['cancelReason'], + ); + + // 부분취소 금액이 있는 경우 + if (isset($request['cancelAmount']) && $request['cancelAmount'] > 0) { + $this->cancelData['cancelAmount'] = $request['cancelAmount']; + } + + // 면세금액이 있는 경우 + if (isset($request['taxFreeAmount']) && $request['taxFreeAmount'] > 0) { + $this->cancelData['taxFreeAmount'] = $request['taxFreeAmount']; + } + + // 환불 계좌정보가 있는 경우 (가상계좌) + if (isset($request['refundReceiveAccount']) && is_array($request['refundReceiveAccount'])) { + $this->cancelData['refundReceiveAccount'] = array( + 'bank' => $request['refundReceiveAccount']['bank'], + 'accountNumber' => $request['refundReceiveAccount']['accountNumber'], + 'holderName' => $request['refundReceiveAccount']['holderName'], + ); + } + } + + /** + * 결제 취소 + * + * @return bool + */ + public function cancelPayment(): bool + { + // 취소에 필요한 결제 키가 있는지 여부 + if (empty($this->cancelData['paymentKey'])) { + return false; + } + + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, str_replace('{paymentKey}', $this->cancelData['paymentKey'], $this->cancelUrl)); + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->headers); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($this->cancelData)); + curl_setopt($curl, CURLOPT_SSLVERSION, 6); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_TIMEOUT, 20); + + $response = curl_exec($curl); + + $return_status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $this->responseData = json_decode($response, true); + + curl_close($curl); + + // 결제 실패 상황인 경우 + if ($return_status != 200) { + return false; + } + + return true; + } + + /** + * 현금영수증 발급 데이터 설정 + */ + public function setCashReceiptsData(array $request): void + { + $this->cashReceiptsData = array( + 'amount' => $request['amount'], + 'orderId' => $request['orderId'], + 'type' => $request['type'], + 'customerIdentityNumber' => $request['customerIdentityNumber'], + 'orderName' => $request['orderName'], + ); + } + + /** + * 현금영수증 발급 + */ + public function issueCashReceipt(): bool + { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $this->cashReceiptsUrl); + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->headers); + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($this->cashReceiptsData)); + curl_setopt($curl, CURLOPT_SSLVERSION, 6); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_ENCODING, ""); + curl_setopt($curl, CURLOPT_MAXREDIRS, 10); + curl_setopt($curl, CURLOPT_TIMEOUT, 20); + curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); + + $response = curl_exec($curl); + + $return_status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $this->responseData = json_decode($response, true); + + curl_close($curl); + + // 결제 실패 상황인 경우 + if ($return_status != 200) { + return false; + } + + return true; + } + + /** + * 현금영수증 발급 취소 + */ + public function cancelCashReceipt($receiptKey): bool + { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $this->cashReceiptsUrl."/".$receiptKey."/cancel"); + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->headers); + curl_setopt($curl, CURLOPT_SSLVERSION, 6); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_ENCODING, ""); + curl_setopt($curl, CURLOPT_MAXREDIRS, 10); + curl_setopt($curl, CURLOPT_TIMEOUT, 20); + curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); + + $response = curl_exec($curl); + + $return_status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $this->responseData = json_decode($response, true); + + curl_close($curl); + + // 결제 실패 상황인 경우 + if ($return_status != 200) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/shop/toss/toss_approval.php b/shop/toss/toss_approval.php new file mode 100644 index 000000000..c31311ae6 --- /dev/null +++ b/shop/toss/toss_approval.php @@ -0,0 +1,79 @@ +setPaymentData([ + 'orderId' => $orderId, + 'amount' => $amount, + 'paymentKey' => $paymentKey, +]); + +// 장바구니 ID 설정 (바로구매 여부 확인) +$ss_cart_id = get_session('ss_direct') ? get_session('ss_cart_direct') : get_session('ss_cart_id'); + +// 임시데이터에 결제 데이터 저장 +$addQuery = ""; +if (isset($orderId)) { + $addQuery .= " AND od_id = '$orderId'"; +} +if (isset($ss_cart_id)) { + $addQuery .= " AND cart_id = '$ss_cart_id'"; +} +if (isset($member['mb_id'])) { + $addQuery .= " AND mb_id = '{$member['mb_id']}'"; +} + +if (empty($orderId) && empty($ss_cart_id)) { + alert('주문정보가 올바르지 않습니다.'); + exit; +} + +// 기존 dt_data 가져오기 +$sql = " + SELECT * FROM {$g5['g5_shop_order_data_table']} + WHERE 1=1 + {$addQuery} + LIMIT 1 +"; +$res = sql_fetch($sql); +$dt_data = []; +if (isset($res['dt_data'])) { + $dt_data = unserialize(base64_decode($res['dt_data'])); +} + +// dt_data 에 결제 키 추가 +if (isset($paymentKey)) { + $dt_data['paymentKey'] = $paymentKey; + $dt_data_new = base64_encode(serialize($dt_data)); + + // 업데이트 + $sql = " + UPDATE {$g5['g5_shop_order_data_table']} SET + dt_data = '".$dt_data_new."' + WHERE od_id = '$orderId' + {$addQuery} + "; + sql_query($sql); +} + +if(isset($payReqMap['pp_id']) && $payReqMap['pp_id']) { + $page_return_url = G5_SHOP_URL.'/personalpayform.php?pp_id='.$payReqMap['pp_id']; +} else { + $page_return_url = G5_SHOP_URL.'/orderform.php'; + if ($_SESSION['ss_direct']) { + $page_return_url .= '?sw_direct=1'; + } +} +?> diff --git a/shop/toss/toss_cancel.php b/shop/toss/toss_cancel.php new file mode 100644 index 000000000..8738a0597 --- /dev/null +++ b/shop/toss/toss_cancel.php @@ -0,0 +1,38 @@ +setPaymentHeader(); + +$od_id = isset($od['od_id']) ? $od['od_id'] : (isset($pp['pp_id']) ? $pp['pp_id'] : ''); + +if (!$toss->getPaymentByOrderId($od_id)) { + alert('결제정보를 가져올 수 없습니다.'); +} + +$toss->setCancelData(array( + 'paymentKey' => $toss->responseData['paymentKey'], + 'cancelReason' => $cancel_msg, +)); +if (!$toss->cancelPayment()) { + $msg = '결제 취소에 실패하였습니다.\\n'; + if (isset($toss->responseData['message'])) { + $msg .= '사유 : ' . $toss->responseData['message'] . '\\n'; + } + if (isset($toss->responseData['code'])) { + $msg .= '코드 : ' . $toss->responseData['code']; + } + alert($msg); +} \ No newline at end of file diff --git a/shop/toss/toss_result.php b/shop/toss/toss_result.php new file mode 100644 index 000000000..6e86aa212 --- /dev/null +++ b/shop/toss/toss_result.php @@ -0,0 +1,108 @@ +setPaymentData([ + 'amount' => $amount, + 'orderId' => $orderId, + 'paymentKey' => $paymentKey +]); +$toss->setPaymentHeader(); + +// 결제승인 요청 +$result = $toss->approvePayment(); + +if ($result) { + // 결제승인 성공시 처리 + $status = isset($toss->responseData['status']) ? $toss->responseData['status'] : ''; + $method = isset($toss->responseData['method']) ? $toss->responseData['method'] : ''; + + // 가상계좌(VIRTUAL_ACCOUNT)만 입금대기(WAITING_FOR_DEPOSIT) 상태 값을 가질 수 있음 + if ($status === 'DONE' || ($status === 'WAITING_FOR_DEPOSIT' && $method === '가상계좌')) { + // 공통 DB처리 변수 설정 + $tno = isset($toss->responseData['paymentKey']) ? $toss->responseData['paymentKey'] : ''; + $amount = isset($toss->responseData['totalAmount']) ? $toss->responseData['totalAmount'] : 0; + $escw_yn = $toss->responseData['useEscrow'] === true ? 'Y' : 'N'; + $app_time = isset($toss->responseData['approvedAt']) ? date('Y-m-d H:i:s', strtotime($toss->responseData['approvedAt'])) : ''; + + // 결제수단별 데이터 처리 (카드, 가상계좌, 계좌이체, 휴대폰, 간편결제 순) + if ($method === '카드') { + // 카드 + $app_no = $od_app_no = isset($toss->responseData['card']['approveNo']) ? $toss->responseData['card']['approveNo'] : '00000000'; + $card_name = isset($toss->cardCode[$toss->responseData['card']['issuerCode']]) ? $toss->cardCode[$toss->responseData['card']['issuerCode']] : ''; + } else if ($method === '가상계좌') { + // 가상계좌 + $bank_name = $bankname = isset($toss->bankCode[$toss->responseData['virtualAccount']['bankCode']]) ? $toss->bankCode[$toss->responseData['virtualAccount']['bankCode']] : ''; + $depositor = isset($toss->responseData['virtualAccount']['customerName']) ? $toss->responseData['virtualAccount']['customerName'] : ''; + $account = isset($toss->responseData['virtualAccount']['accountNumber']) ? $toss->responseData['virtualAccount']['accountNumber'] : ''; + } else if ($method === '계좌이체') { + // 계좌이체 + $bank_name = isset($toss->bankCode[$toss->responseData['transfer']['bankCode']]) ? $toss->bankCode[$toss->responseData['transfer']['bankCode']] : ''; + + // 현금영수증 데이터 처리 + $cashReceiptType = isset($toss->responseData['cashReceipt']['type']) ? $toss->responseData['cashReceipt']['type'] : ''; + $RcptType = $cashReceiptType === '소득공제' ? '1' : ($cashReceiptType === '지출증빙' ? '2' : '0'); + $RcptTID = isset($toss->responseData['cashReceipt']['receiptKey']) ? $toss->responseData['cashReceipt']['receiptKey'] : ''; // 현금영수증 TID, 현금영수증 거래인 경우 리턴 + $RcptAuthCode = isset($toss->responseData['cashReceipt']['issueNumber']) ? $toss->responseData['cashReceipt']['issueNumber'] : ''; // 현금영수증 승인번호, 현금영수증 거래인 경우 리턴 + $RcptReceiptUrl = isset($toss->responseData['cashReceipt']['receiptUrl']) ? $toss->responseData['cashReceipt']['receiptUrl'] : ''; // 현금영수증 URL + + // 현금영수증 발급시 1 또는 2 이면 + if ($RcptType) { + $pg_receipt_infos['od_cash'] = 1; // 현금영수증 발급인것으로 처리 + $pg_receipt_infos['od_cash_no'] = $RcptAuthCode; // 현금영수증 승인번호 + $pg_receipt_infos['od_cash_info'] = serialize(array('TID'=>$RcptTID, 'ApplNum'=>$RcptAuthCode, 'receiptUrl'=>$RcptReceiptUrl)); + } + } else if ($method === '휴대폰') { + // 휴대폰 + $mobile_no = isset($toss->responseData['mobilePhone']['customerMobilePhone']) ? $toss->responseData['mobilePhone']['customerMobilePhone'] : ''; + } else if ($method === '간편결제') { + // 간편결제 + $provider = isset($toss->responseData['easyPay']['provider']) ? $toss->responseData['easyPay']['provider'] : ''; + $card_name = isset($toss->easyPayCode[$provider]) ? $toss->easyPayCode[$provider] : $provider; + } + } else { + + if(G5_IS_MOBILE) { + if(isset($_POST['pp_id']) && $_POST['pp_id']) { + $page_return_url = G5_SHOP_URL.'/personalpayform.php?pp_id='.get_session('ss_personalpay_id'); + } else { + $page_return_url = G5_SHOP_URL.'/orderform.php'; + if(get_session('ss_direct')) + $page_return_url .= '?sw_direct=1'; + } + + alert($toss->responseData['message'].' 코드 : '.$toss->responseData['code'], $page_return_url); + } else { + alert($toss->responseData['message'].' 코드 : '.$toss->responseData['code'], G5_SHOP_URL.'/orderform.php'); + } + } +} else { + alert($toss->responseData['message'].' 코드 : '.$toss->responseData['code'], G5_SHOP_URL); +} \ No newline at end of file diff --git a/skin/member/basic/consent_modal.inc.php b/skin/member/basic/consent_modal.inc.php new file mode 100644 index 000000000..2d9d63a5c --- /dev/null +++ b/skin/member/basic/consent_modal.inc.php @@ -0,0 +1,85 @@ + + + +
    +
    +

    안내

    +
    +
    +
    + + +
    +
    +
    + + + + + + \ No newline at end of file diff --git a/skin/member/basic/register.skin.php b/skin/member/basic/register.skin.php index 662c8da40..f337fe9ce 100644 --- a/skin/member/basic/register.skin.php +++ b/skin/member/basic/register.skin.php @@ -17,7 +17,7 @@ add_stylesheet('', @include_once(get_social_skin_path().'/social_register.skin.php'); ?>
    -

    회원가입약관

    +

    (필수) 회원가입약관

    @@ -25,8 +25,8 @@ add_stylesheet('',
    -
    -

    개인정보 수집 및 이용

    +
    +

    (필수) 개인정보 수집 및 이용

    diff --git a/skin/member/basic/register_form.skin.php b/skin/member/basic/register_form.skin.php index f8f73b6d3..c4bf8363b 100644 --- a/skin/member/basic/register_form.skin.php +++ b/skin/member/basic/register_form.skin.php @@ -51,8 +51,7 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi

    개인정보 입력

      -
    • - +
    • + 간편인증'.PHP_EOL; } @@ -72,12 +73,11 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi echo ''.PHP_EOL; echo '(필수)'; - echo ''.PHP_EOL; - } - ?> - 본인확인을 위해서는 자바스크립트 사용이 가능해야합니다.'.PHP_EOL; + ?> + 본인확인성인인증 완료
    - + +
  • class="frm_input full_input " size="10" placeholder="이름"> @@ -135,13 +136,12 @@ if ($config['cf_cert_use'] && ($config['cf_cert_simple'] || $config['cf_cert_ipi
  • +
  • - - class="frm_input full_input " maxlength="20" placeholder="전화번호"> -
  • +
  • @@ -227,26 +227,6 @@ gif, jpg, png파일만 가능하며 용량 - -
  • - class="selec_chk"> - - 정보 메일을 받겠습니다. -
  • - - -
  • - class="selec_chk"> - - 휴대폰 문자메세지를 받겠습니다. -
  • -
  • @@ -288,13 +268,120 @@ gif, jpg, png파일만 가능하며 용량
  • - -
  • - 자동등록방지 - -
  • + + + +
    +

    수신설정

    + +
      + +
    • + + +
      마케팅 목적의 개인정보 수집·이용에 대한 안내입니다. 자세히보기를 눌러 전문을 확인할 수 있습니다.
      + + + +
    • + + + + + + + '아이코드']; + + $usedCompanies = []; + foreach ($configKeys as $key) { + if (!empty($config[$key]) && isset($companies[$config[$key]])) { + $usedCompanies[] = $companies[$config[$key]]; + } + } + ?> + +
    • + + +
      개인정보 제3자 제공 동의에 대한 안내입니다. 자세히보기를 눌러 전문을 확인할 수 있습니다.
      + + + +
    • + +
    +
    + + +
    +

    자동등록방지

    +
      +
    • + 자동등록방지 + +
    • +
    +
    취소 @@ -302,6 +389,9 @@ gif, jpg, png파일만 가능하며 용량
    + + + \ No newline at end of file diff --git a/skin/member/basic/style.css b/skin/member/basic/style.css index 7ceba47e5..80cab2ea2 100644 --- a/skin/member/basic/style.css +++ b/skin/member/basic/style.css @@ -13,7 +13,6 @@ .mbskin .frm_input {width:100%} .mbskin .btn_submit {width:100%;margin:10px 0 0;height:45px;font-weight:bold;font-size:1.25em} .mbskin h1 {margin:60px 0 30px;font-size:2em} -.mbskin .tbl_frm01 th {width:85px} /* ### 기본 스타일 커스터마이징 끝 ### */ /* 회원가입 약관 */ @@ -31,12 +30,11 @@ #fregister_chkall {position:relative;text-align:center;background:#f5f7fa;line-height:50px;border:1px solid #e5e9f0;border-radius:3px;margin-bottom:15px} #fregister h2 {text-align:left;padding:20px;border-bottom:1px solid #dde7e9;font-size:1.2em} #fregister textarea {display:block;padding:20px;width:100%;height:150px;background:#fff;border:0;line-height:1.6em} -#fregister_private {position:relative} -#fregister_private div {padding:20px;background:#fff} -#fregister_private table {width:100%;border-collapse:collapse;font-size:1em;} -#fregister_private table caption {position:absolute;font-size:0;line-height:0;overflow:hidden} -#fregister_private table th {background:#f7f7f9;width:33.33%;color:#000;padding:10px;border:1px solid #d8dbdf} -#fregister_private table td {border:1px solid #e7e9ec;padding:10px;border-top:0} +.fregister_terms div {padding:20px;background:#fff} +.fregister_terms table {width:100%;border-collapse:collapse;font-size:1em;} +.fregister_terms table caption {position:absolute;font-size:0;line-height:0;overflow:hidden} +.fregister_terms table th {background:#f7f7f9;width:33.33%;color:#000;padding:10px;border:1px solid #d8dbdf} +.fregister_terms table td {border:1px solid #e7e9ec;padding:10px;border-top:0} .fregister_agree {position:absolute;top:0;right:0} .fregister_agree input[type="checkbox"] + label {color:#676e70} @@ -70,6 +68,11 @@ #fregisterform .captcha {display:block;margin:5px 0 0} #fregisterform .reg_mb_img_file img {max-width:100%;height:auto} #reg_mb_icon, #reg_mb_img {float:right} +#fregisterform .consent-line {display: flex; margin: 0 !important;} +#fregisterform .consent-line .chk_li {padding-left: 0;} +#fregisterform .consent-date { margin: 5px 0 0 20px !important; } +#fregisterform .consent-group .sub-consents {padding: 0 20px 0px} +#fregisterform .js-open-consent {display: block; margin-left: 10px; font-size: 12px; color: #3f51b5; background: none; border: none; cursor: pointer; text-decoration: underline; } /* 회원가입 완료 */ #reg_result {padding:40px 30px;text-align:center;background:#edf3fc;border:1px solid #d6e2f4;border-radius:5px} @@ -93,7 +96,7 @@ .tooltip_icon {display:inline-block;vertical-align:baseline;color:#b3b5b8;border:0;font-size:1.4em;background:transparent;cursor:pointer} .tooltip_icon:hover {color:#448bf5} -.tooltip {position:relative;width:auto;color:#fff;background:#000;padding:10px;font-size:small;line-height:18px;display:none;position:absolute;z-index:9;font-weight:normal;margin-left:15px;margin-top:10px} +.tooltip {position:absolute;width:auto;color:#fff;background:#000;padding:10px;font-size:small;line-height:18px;display:none;z-index:9;font-weight:normal;margin-left:15px;margin-top:10px} .tooltip:before {content:"";position:absolute;top:0;left:-10px;width:0;height:0;border-style:solid;border-top:0px solid transparent;border-bottom:10px solid transparent;border-left:0;border-right:10px solid #000} /* 아이디/비밀번호 찾기 */ @@ -152,12 +155,12 @@ #login_info .login_if_lpl {float:right} #login_password_lost {display:inline-block;border:1px solid #d5d9dd;color:#3a8afd;border-radius:2px;padding:2px 5px;line-height:20px} -#mb_login_notmb {margin:30px auto;padding:20px 30px} +#mb_login_notmb {margin:30px auto;padding:20px 30px;border: 1px solid #dde7e9} #mb_login_notmb h2 {font-size:1.25em;margin:20px 0 10px} #guest_privacy {border:1px solid #ccc;text-align:left;line-height:1.6em;color:#666;background:#fafafa;padding:10px;height:150px;margin:10px 0;overflow-y:auto} #mb_login_notmb .btn_submit {display:block;text-align:center;line-height:45px} -#mb_login_od_wr {margin:30px auto;padding:20px 30px} +#mb_login_od_wr {margin:30px auto;padding:20px 30px;border: 1px solid #dde7e9} #mb_login_od_wr h2 {font-size:1.25em;margin:20px 0 10px} #mb_login_od_wr .frm_input {margin:10px 0 0} #mb_login_od_wr p {background:#f3f3f3;margin:20px 0 0;padding:15px 20px;line-height:1.5em} diff --git a/skin/outlogin/basic/style.css b/skin/outlogin/basic/style.css index f233abd23..453770ccd 100644 --- a/skin/outlogin/basic/style.css +++ b/skin/outlogin/basic/style.css @@ -59,6 +59,6 @@ .chk_box {position:relative} .chk_box input[type="checkbox"] + label {padding-left:20px;color:#676e70} .chk_box input[type="checkbox"] + label:hover{color:#2172f8} -.chk_box input[type="checkbox"] + label span {position:absolute;top:2px;left:0;width:15px;height:15px;display:block;margin:0;background:#fff;border:1px solid #d0d4df;border-radius:3px} +.chk_box input[type="checkbox"] + label span {position:absolute;top:3px;left:0;width:15px;height:15px;display:block;margin:0;background:#fff;border:1px solid #d0d4df;border-radius:3px} .chk_box input[type="checkbox"]:checked + label {color:#000} .chk_box input[type="checkbox"]:checked + label span {background:url(./img/chk.png) no-repeat 50% 50% #3a8afd;border-color:#1471f6;border-radius:3px} diff --git a/skin/social/consent_modal.inc.php b/skin/social/consent_modal.inc.php new file mode 100644 index 000000000..2d9d63a5c --- /dev/null +++ b/skin/social/consent_modal.inc.php @@ -0,0 +1,85 @@ + + + +
    +
    +

    안내

    +
    +
    +
    + + +
    + +
    + + + + + + \ No newline at end of file diff --git a/skin/social/social_register_member.skin.php b/skin/social/social_register_member.skin.php index 80537b71a..6b72bac16 100644 --- a/skin/social/social_register_member.skin.php +++ b/skin/social/social_register_member.skin.php @@ -44,44 +44,60 @@ add_stylesheet('',
  • 안녕하세요! 에 오신것을 진심으로 환영해요!
    다양한 이벤트와 풍성한 혜택 받아가세요 :D
  • - -
  • - 회원가입약관 - -
    - - -
    -
  • -
  • - 개인정보 수집 및 이용정책 - -
    - - -
    -
  • - -
  • -
    - - -
    -
  • - - - - - - - - - - - - - - +
    +

    개인정보 수집 및 이용

    +
    +
    개인정보 수집 및 이용
    + + + + + + + + + + + + + + + + + + + + +
    개인정보 수집 및 이용
    목적항목보유기간
    이용자 식별 및 본인여부 확인아이디, 이름, 비밀번호회원 탈퇴 시까지
    고객서비스 이용에 관한 통지,
    CS대응을 위한 이용자 식별
    연락처 (이메일, 휴대전화번호)회원 탈퇴 시까지
    +
    + +
    + + +
    +
    + +
    + + +
    + + + + + + + + + + + + + + + + + @@ -138,9 +154,118 @@ add_stylesheet('',
    +<<<<<<< HEAD +======= + + + +
    +

    수신설정

    + +
      + +
    • + + +
      마케팅 목적의 개인정보 수집·이용에 대한 안내입니다. 자세히보기를 눌러 전문을 확인할 수 있습니다.
      + + +
    • + + + + + + + '아이코드']; + + $usedCompanies = []; + foreach ($configKeys as $key) { + if (!empty($config[$key]) && isset($companies[$config[$key]])) { + $usedCompanies[] = $companies[$config[$key]]; + } + } + ?> + +
    • + + +
      개인정보 제3자 제공 동의에 대한 안내입니다. 자세히보기를 눌러 전문을 확인할 수 있습니다.
      + + +
    • + +
    +
    + + + +
    + 취소 + +
    + + +>>>>>>> 그누보드/master