diff --git a/.gitattributes b/.gitattributes index 720b28de0..4e694d1d9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,6 @@ .gitattributes export-ignore .gitignore export-ignore *.php whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol + +/tests export-ignore +/bin export-ignore diff --git a/.gitignore b/.gitignore index e5ef42a54..2a5e5886e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ /.htaccess data/ test/ +/tests/ +/bin/ sirgle/ test.php *.key diff --git a/README.md b/README.md index ba0467ded..f1ba3ef30 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,15 @@ cd gnuboard5 > 기존 사이트에 재설치하면 데이터가 삭제될 수 있습니다. 진행하기 전에 파일과 데이터베이스를 백업하십시오. +### 기존 설치 업데이트 + +소스 코드를 업데이트한 뒤 데이터베이스 변경이 포함된 버전은 관리자 메뉴의 **환경설정 → DB업그레이드**에서 변경 내용을 확인하고 명시적으로 실행합니다. + +운영 절차와 마이그레이션 작성 규칙은 [데이터베이스 마이그레이션 문서](docs/database-migrations.md)를 확인하십시오. + ## 문서 및 지원 +- [5.6.37 SIRK 전용 카카오페이 연동 종료 및 기존 거래 지원](docs/sirk-kakaopay-retirement.md) - [그누보드5 공식 페이지](https://sir.kr/main/g5/) - [그누보드5 공식 매뉴얼](https://sir.kr/manuals/g5/1) - [그누보드5 Q&A](https://sir.kr/questions?s_tag=%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C5) diff --git a/adm/admin.lib.php b/adm/admin.lib.php index 1d2d70a97..6ebc6181a 100644 --- a/adm/admin.lib.php +++ b/adm/admin.lib.php @@ -478,6 +478,30 @@ function check_log_folder($log_path, $is_delete = true) } } +// 회원 본인확인 식별값과 인증 이력만 정리한다. 호출부에서 관리자 권한을 검증한다. +function admin_clear_member_certification($mb_id) +{ + global $g5; + + $esc_mb_id = sql_real_escape_string($mb_id); + $history_table = isset($g5['member_cert_history_table']) ? $g5['member_cert_history_table'] : G5_TABLE_PREFIX.'member_cert_history'; + + // 일반 회원정보(이름·연락처)와 이메일 인증 상태는 유지한다. + if (!sql_query(" update {$g5['member_table']} + set mb_certify = '', mb_adult = 0, mb_dupinfo = '', mb_birth = '', mb_sex = '' + where mb_id = '{$esc_mb_id}' ", false)) { + return false; + } + if (!sql_query(" delete from {$history_table} where mb_id = '{$esc_mb_id}' ", false)) { + return false; + } + if (!sql_query(" delete from {$g5['cert_history_table']} where mb_id = '{$esc_mb_id}' ", false)) { + return false; + } + + return true; +} + // POST로 넘어온 토큰과 세션에 저장된 토큰 비교 function check_admin_token() { diff --git a/adm/board_form.php b/adm/board_form.php index 640fffd55..7a4a723cd 100644 --- a/adm/board_form.php +++ b/adm/board_form.php @@ -13,81 +13,20 @@ if (!$row['cnt']) { $html_title = '게시판'; -if (!isset($board['bo_device'])) { - // 게시판 사용 필드 추가 - // both : pc, mobile 둘다 사용 - // pc : pc 전용 사용 - // mobile : mobile 전용 사용 - // none : 사용 안함 - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_device` ENUM( 'both', 'pc', 'mobile' ) NOT NULL DEFAULT 'both' AFTER `bo_subject` ", false); -} -if (!isset($board['bo_mobile_skin'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_mobile_skin` VARCHAR(255) NOT NULL DEFAULT '' AFTER `bo_skin` ", false); -} -if (!isset($board['bo_gallery_width'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_gallery_width` INT NOT NULL AFTER `bo_gallery_cols`, ADD `bo_gallery_height` INT NOT NULL DEFAULT '0' AFTER `bo_gallery_width`, ADD `bo_mobile_gallery_width` INT NOT NULL DEFAULT '0' AFTER `bo_gallery_height`, ADD `bo_mobile_gallery_height` INT NOT NULL DEFAULT '0' AFTER `bo_mobile_gallery_width` ", false); -} -if (!isset($board['bo_mobile_subject_len'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_mobile_subject_len` INT(11) NOT NULL DEFAULT '0' AFTER `bo_subject_len` ", false); -} -if (!isset($board['bo_mobile_page_rows'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_mobile_page_rows` INT(11) NOT NULL DEFAULT '0' AFTER `bo_page_rows` ", false); -} -if (!isset($board['bo_mobile_content_head'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_mobile_content_head` TEXT NOT NULL AFTER `bo_content_head`, ADD `bo_mobile_content_tail` TEXT NOT NULL AFTER `bo_content_tail`", false); -} -if (!isset($board['bo_use_cert'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_use_cert` ENUM('','cert','adult') NOT NULL DEFAULT '' AFTER `bo_use_email` ", false); -} -if (!isset($board['bo_use_sns'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_use_sns` TINYINT NOT NULL DEFAULT '0' AFTER `bo_use_cert` ", false); - - $result = sql_query(" select bo_table from `{$g5['board_table']}` "); - for ($i=0; $row=sql_fetch_array($result); $i++) { - sql_query( - " ALTER TABLE `{$g5['write_prefix']}{$row['bo_table']}` - ADD `wr_facebook_user` VARCHAR(255) NOT NULL DEFAULT '' AFTER `wr_ip`, - ADD `wr_twitter_user` VARCHAR(255) NOT NULL DEFAULT '' AFTER `wr_facebook_user` ", false - ); - } -} $sql = " SHOW COLUMNS FROM `{$g5['board_table']}` LIKE 'bo_use_cert' "; $row = sql_fetch($sql); -if (strpos($row['Type'], 'hp-') === false) { - sql_query(" ALTER TABLE `{$g5['board_table']}` CHANGE `bo_use_cert` `bo_use_cert` ENUM('','cert','adult','hp-cert','hp-adult') NOT NULL DEFAULT '' ", false); -} -if (!isset($board['bo_use_list_file'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_use_list_file` TINYINT NOT NULL DEFAULT '0' AFTER `bo_use_list_view` ", false); - $result = sql_query(" select bo_table from `{$g5['board_table']}` "); - for ($i=0; $row=sql_fetch_array($result); $i++) { - sql_query( - " ALTER TABLE `{$g5['write_prefix']}{$row['bo_table']}` - ADD `wr_file` TINYINT NOT NULL DEFAULT '0' AFTER `wr_datetime` ", false - ); - } -} -if (!isset($board['bo_mobile_subject'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_mobile_subject` VARCHAR(255) NOT NULL DEFAULT '' AFTER `bo_subject` ", false); -} -if (!isset($board['bo_use_captcha'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_use_captcha` TINYINT NOT NULL DEFAULT '0' AFTER `bo_use_sns` ", false); -} - -if (!isset($board['bo_select_editor'])) { - sql_query(" ALTER TABLE `{$g5['board_table']}` ADD `bo_select_editor` VARCHAR(50) NOT NULL DEFAULT '' AFTER `bo_use_dhtml_editor` ", false); -} $board_default = array( 'bo_mobile_subject'=>'', @@ -1500,4 +1439,4 @@ function fboardform_submit(f) > 사용 + + + + 만료된 미인증 회원은 최고관리자 접속 시 하루 한 번 실행되는 정리에서 탈퇴 처리하며, 본인확인 정보와 소셜 연결을 해제합니다. 나머지 회원자료는 회원탈퇴후 삭제일 설정에 따라 정리합니다.') ?> + 분 + + diff --git a/adm/config_form_update.php b/adm/config_form_update.php index 7ba01db8e..519f38d4a 100644 --- a/adm/config_form_update.php +++ b/adm/config_form_update.php @@ -56,6 +56,7 @@ if (isset($_POST['cf_intercept_ip']) && $_POST['cf_intercept_ip']) { $check_keys = array( 'cf_use_email_certify' => 'int', + 'cf_email_certify_minutes' => 'int', 'cf_use_homepage' => 'int', 'cf_req_homepage' => 'int', 'cf_use_tel' => 'int', @@ -178,6 +179,8 @@ foreach ($check_keys as $k => $v) { } } +$_POST['cf_email_certify_minutes'] = max(0, $_POST['cf_email_certify_minutes']); + // 본인확인을 사용할 경우 아이핀, 휴대폰인증 중 하나는 선택되어야 함 if ($_POST['cf_cert_use'] && !$_POST['cf_cert_ipin'] && !$_POST['cf_cert_hp'] && !$_POST['cf_cert_simple']) { alert('본인확인을 위해 아이핀, 휴대폰 본인확인, KG이니시스 간편인증 서비스 중 하나 이상 선택해 주십시오.'); @@ -226,6 +229,7 @@ $sql = " update {$g5['config_table']} cf_point_term = '{$_POST['cf_point_term']}', cf_use_copy_log = '{$_POST['cf_use_copy_log']}', cf_use_email_certify = '{$_POST['cf_use_email_certify']}', + cf_email_certify_minutes = '{$_POST['cf_email_certify_minutes']}', cf_login_point = '{$_POST['cf_login_point']}', cf_cut_name = '{$_POST['cf_cut_name']}', cf_nick_modify = '{$_POST['cf_nick_modify']}', diff --git a/adm/contentform.php b/adm/contentform.php index 5789a0de4..cdb95cfcf 100644 --- a/adm/contentform.php +++ b/adm/contentform.php @@ -8,41 +8,12 @@ auth_check_menu($auth, $sub_menu, "w"); $co_id = isset($_REQUEST['co_id']) ? preg_replace('/[^a-z0-9_]/i', '', $_REQUEST['co_id']) : ''; // 상단, 하단 파일경로 필드 추가 -if (!sql_query(" select co_include_head from {$g5['content_table']} limit 1 ", false)) { - $sql = " ALTER TABLE `{$g5['content_table']}` ADD `co_include_head` VARCHAR( 255 ) NOT NULL , - ADD `co_include_tail` VARCHAR( 255 ) NOT NULL "; - sql_query($sql, false); -} // html purifier 사용여부 필드 -if (!sql_query(" select co_tag_filter_use from {$g5['content_table']} limit 1 ", false)) { - sql_query( - " ALTER TABLE `{$g5['content_table']}` - ADD `co_tag_filter_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `co_content` ", - true - ); - sql_query(" update {$g5['content_table']} set co_tag_filter_use = '1' "); -} // 모바일 내용 추가 -if (!sql_query(" select co_mobile_content from {$g5['content_table']} limit 1", false)) { - sql_query( - " ALTER TABLE `{$g5['content_table']}` - ADD `co_mobile_content` longtext NOT NULL AFTER `co_content` ", - true - ); -} // 스킨 설정 추가 -if (!sql_query(" select co_skin from {$g5['content_table']} limit 1 ", false)) { - sql_query( - " ALTER TABLE `{$g5['content_table']}` - ADD `co_skin` varchar(255) NOT NULL DEFAULT '' AFTER `co_mobile_content`, - ADD `co_mobile_skin` varchar(255) NOT NULL DEFAULT '' AFTER `co_skin` ", - true - ); - sql_query(" update {$g5['content_table']} set co_skin = 'basic', co_mobile_skin = 'basic' "); -} $html_title = "내용"; $g5['title'] = $html_title . ' 관리'; diff --git a/adm/contentlist.php b/adm/contentlist.php index b8eebc3a6..de67d074b 100644 --- a/adm/contentlist.php +++ b/adm/contentlist.php @@ -8,30 +8,6 @@ if (!isset($g5['content_table'])) { die('/data/dbconfig.php 파일에 $g5[\'content_table\'] = G5_TABLE_PREFIX.\'content\'; 를 추가해 주세요.'); } //내용(컨텐츠)정보 테이블이 있는지 검사한다. -if (!sql_query(" DESCRIBE {$g5['content_table']} ", false)) { - if (sql_query(" DESCRIBE {$g5['g5_shop_content_table']} ", false)) { - sql_query(" ALTER TABLE {$g5['g5_shop_content_table']} RENAME TO `{$g5['content_table']}` ;", false); - } else { - $query_cp = sql_query( - " CREATE TABLE IF NOT EXISTS `{$g5['content_table']}` ( - `co_id` varchar(20) NOT NULL DEFAULT '', - `co_html` tinyint(4) NOT NULL DEFAULT '0', - `co_subject` varchar(255) NOT NULL DEFAULT '', - `co_content` longtext NOT NULL, - `co_hit` int(11) NOT NULL DEFAULT '0', - `co_include_head` varchar(255) NOT NULL, - `co_include_tail` varchar(255) NOT NULL, - PRIMARY KEY (`co_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ", - true - ); - - // 내용관리 생성 - sql_query(" insert into `{$g5['content_table']}` set co_id = 'company', co_html = '1', co_subject = '회사소개', co_content= '

회사소개에 대한 내용을 입력하십시오.

' ", false); - sql_query(" insert into `{$g5['content_table']}` set co_id = 'privacy', co_html = '1', co_subject = '개인정보 처리방침', co_content= '

개인정보 처리방침에 대한 내용을 입력하십시오.

' ", false); - sql_query(" insert into `{$g5['content_table']}` set co_id = 'provision', co_html = '1', co_subject = '서비스 이용약관', co_content= '

서비스 이용약관에 대한 내용을 입력하십시오.

' ", false); - } -} $g5['title'] = '내용관리'; require_once G5_ADMIN_PATH . '/admin.head.php'; diff --git a/adm/css/admin.css b/adm/css/admin.css index 9877286db..7431fc089 100644 --- a/adm/css/admin.css +++ b/adm/css/admin.css @@ -696,7 +696,6 @@ a.scf_pgreg {display:inline-block;margin:5px 0 0;padding:5px 10px;background:#22 a.kcp_btn {display:inline-block;margin:5px 0 0;padding:5px 10px;background:#226C8B;color:#fff;font-weight:normal;text-decoration:none} a.lg_btn{display:inline-block;margin:5px 0 0;padding:5px 10px;background:#ED008C;color:#fff;font-weight:normal;text-decoration:none} a.kg_btn{display:inline-block;margin:5px 0 0;padding:5px 10px;background:#4A2C7C;color:#fff;font-weight:normal;text-decoration:none} -a.kakao_btn{display:inline-block;margin:5px 0 0;padding:5px 10px;background:#FDDC2F;color:#3B1E1E;font-weight:normal;text-decoration:none} a.naver_btn {display:inline-block;margin:5px 0 0;padding:5px 10px;background:#00C73C;color:#fff;font-weight:normal;text-decoration:none} a.nicepay_btn{display:inline-block;margin:5px 0 0;padding:5px 10px;background:#0057bf;color:#fff;font-weight:normal;text-decoration:none} @@ -740,7 +739,6 @@ ul.de_pg_tab li.tab-current a{background:#2CC185;color:#fff} .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} .nicepay_info_fld th{background-color:#d1e6ff} diff --git a/adm/dbupgrade.php b/adm/dbupgrade.php index 5d6a80289..f9dadf600 100644 --- a/adm/dbupgrade.php +++ b/adm/dbupgrade.php @@ -1,646 +1,213 @@ true, 'applied' => 0, 'skipped' => 0, 'errors' => array()); +$shop_install_result = null; +$action = ''; + +if ($is_execute) { + check_demo(); + check_admin_token(); + $action = isset($_POST['action']) ? trim($_POST['action']) : 'migrate'; + if ($action === 'install_shop') { + $shop_install_result = g5_shop_install_run(); + } elseif ($action === 'record_existing') { + $migration_result = g5_migration_run('', true); + } else { + $migration_id = isset($_POST['migration_id']) ? trim($_POST['migration_id']) : ''; + $migration_result = g5_migration_run($migration_id); + $migration_result = run_replace('admin_dbupgrade_result', $migration_result); + } +} + +$migration_statuses = g5_migration_status(); +$pending_count = 0; +$unrecorded_count = 0; +foreach ($migration_statuses as $migration_status) { + if (isset($migration_status['status']) && $migration_status['status'] === 'unrecorded') { + $unrecorded_count++; + } elseif (isset($migration_status['error']) || $migration_status['status'] !== 'success' || $migration_status['checksum_changed']) { + $pending_count++; + } +} + +if ($shop_install_result !== null && $shop_install_result['success']) { + alert('쇼핑몰 설치가 완료되었습니다.', G5_ADMIN_URL . '/dbupgrade.php'); +} elseif ($shop_install_result !== null) { + $db_upgrade_msg = '쇼핑몰 설치에 실패했습니다. 오류 내용을 확인해 주십시오.'; +} elseif (!$is_execute) { + $db_upgrade_msg = $pending_count ? '확인·실행이 필요한 DB 마이그레이션이 있습니다. 아래 내용을 확인해 주십시오.' : ($unrecorded_count ? '현재 실행할 변경은 없지만 기존 상태 확인 이력이 등록되지 않았습니다.' : 'DB 마이그레이션이 모두 적용되어 있습니다.'); +} elseif (!$migration_result['success']) { + $db_upgrade_msg = 'DB 마이그레이션에 실패했습니다. 오류 내용을 확인해 주십시오.'; +} elseif ($action === 'record_existing') { + $db_upgrade_msg = '기존 상태 확인 이력 ' . (int) $migration_result['skipped'] . '건을 등록했습니다. 선행 항목에 실행이 필요하거나 실패 이력이 있으면 등록을 중단합니다.'; +} elseif ($migration_result['applied'] || $migration_result['skipped']) { + $db_upgrade_msg = 'DB 마이그레이션이 완료되었습니다.'; +} else { + $db_upgrade_msg = '적용할 DB 마이그레이션이 없습니다.'; +} + $g5['title'] = 'DB 업그레이드'; include_once('./admin.head.php'); - -$is_check = false; - -//소셜 로그인 관련 필드 및 구글 리챕챠 필드 추가 -if(!isset($config['cf_social_login_use'])) { - sql_query("ALTER TABLE `{$g5['config_table']}` - ADD `cf_social_login_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `cf_googl_shorturl_apikey`, - ADD `cf_google_clientid` varchar(100) NOT NULL DEFAULT '' AFTER `cf_twitter_secret`, - ADD `cf_google_secret` varchar(100) NOT NULL DEFAULT '' AFTER `cf_google_clientid`, - ADD `cf_naver_clientid` varchar(100) NOT NULL DEFAULT '' AFTER `cf_google_secret`, - ADD `cf_naver_secret` varchar(100) NOT NULL DEFAULT '' AFTER `cf_naver_clientid`, - ADD `cf_kakao_rest_key` varchar(100) NOT NULL DEFAULT '' AFTER `cf_naver_secret`, - ADD `cf_social_servicelist` varchar(255) NOT NULL DEFAULT '' AFTER `cf_social_login_use`, - ADD `cf_payco_clientid` varchar(100) NOT NULL DEFAULT '' AFTER `cf_social_servicelist`, - ADD `cf_payco_secret` varchar(100) NOT NULL DEFAULT '' AFTER `cf_payco_clientid`, - ADD `cf_captcha` varchar(100) NOT NULL DEFAULT '' AFTER `cf_kakao_js_apikey`, - ADD `cf_recaptcha_site_key` varchar(100) NOT NULL DEFAULT '' AFTER `cf_captcha`, - ADD `cf_recaptcha_secret_key` varchar(100) NOT NULL DEFAULT '' AFTER `cf_recaptcha_site_key` - ", true); - - $is_check = true; -} - -//소셜 로그인 관련 필드 카카오 클라이언트 시크릿 추가 -if(!isset($config['cf_kakao_client_secret'])) { - sql_query("ALTER TABLE `{$g5['config_table']}` - ADD `cf_kakao_client_secret` varchar(100) NOT NULL DEFAULT '' AFTER `cf_kakao_rest_key` - ", true); - - $is_check = true; -} - -// 회원 이미지 관련 필드 추가 -if(!isset($config['cf_member_img_size'])) { - sql_query("ALTER TABLE `{$g5['config_table']}` - ADD `cf_member_img_size` int(11) NOT NULL DEFAULT '0' AFTER `cf_member_icon_height`, - ADD `cf_member_img_width` int(11) NOT NULL DEFAULT '0' AFTER `cf_member_img_size`, - ADD `cf_member_img_height` int(11) NOT NULL DEFAULT '0' AFTER `cf_member_img_width` - ", true); - - $sql = " update {$g5['config_table']} set cf_member_img_size = 50000, cf_member_img_width = 60, cf_member_img_height = 60 "; - sql_query($sql, false); - - $is_check = true; -} - -// 소셜 로그인 관리 테이블 없을 경우 생성 -if( isset($g5['social_profile_table']) && !sql_query(" DESC {$g5['social_profile_table']} ", false)) { - sql_query(" CREATE TABLE IF NOT EXISTS `{$g5['social_profile_table']}` ( - `mp_no` int(11) NOT NULL AUTO_INCREMENT, - `mb_id` varchar(255) NOT NULL DEFAULT '', - `provider` varchar(50) NOT NULL DEFAULT '', - `object_sha` varchar(45) NOT NULL DEFAULT '', - `identifier` varchar(255) NOT NULL DEFAULT '', - `profileurl` varchar(255) NOT NULL DEFAULT '', - `photourl` varchar(255) NOT NULL DEFAULT '', - `displayname` varchar(150) NOT NULL DEFAULT '', - `description` varchar(255) NOT NULL DEFAULT '', - `mp_register_day` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `mp_latest_day` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - UNIQUE KEY `mp_no` (`mp_no`), - KEY `mb_id` (`mb_id`), - KEY `provider` (`provider`) - ) ", true); - - $is_check = true; -} - -// 게시판 짧은 주소 -$sql = " select bo_table from {$g5['board_table']} "; -$result = sql_query($sql); - -while ($row = sql_fetch_array($result)) { - $write_table = $g5['write_prefix'] . $row['bo_table']; // 게시판 테이블 전체이름 - - $sql = " SHOW COLUMNS FROM {$write_table} LIKE 'wr_seo_title' "; - $row = sql_fetch($sql); - - if( !$row ){ - sql_query("ALTER TABLE `{$write_table}` - ADD `wr_seo_title` varchar(200) NOT NULL DEFAULT '' AFTER `wr_content`, - ADD INDEX `wr_seo_title` (`wr_seo_title`); - ", false); - - $is_check = true; - } -} - -// 내용 관리 짧은 주소 -$sql = " SHOW COLUMNS FROM `{$g5['content_table']}` LIKE 'co_seo_title' "; -$row = sql_fetch($sql); - -if( !$row ){ - sql_query("ALTER TABLE `{$g5['content_table']}` - ADD `co_seo_title` varchar(200) NOT NULL DEFAULT '' AFTER `co_content`, - ADD INDEX `co_seo_title` (`co_seo_title`); - ", false); - - $is_check = true; -} - -$sql = "select * from {$g5['content_table']} limit 100 "; -$result = sql_query($sql); - -while ($row = sql_fetch_array($result)) { - - if( ! $row['co_seo_title']){ - - $co_seo_title = exist_seo_title_recursive('content', generate_seo_title($row['co_subject']), $g5['content_table'], $row['co_id']); - - $sql = " update {$g5['content_table']} - set co_seo_title = '$co_seo_title' - where co_id = '{$row['co_id']}' "; - sql_query($sql); - - } -} - -// 메모 테이블 -$sql = " SHOW COLUMNS FROM `{$g5['memo_table']}` LIKE 'me_send_id' "; -$row = sql_fetch($sql); - -if( !$row ){ - sql_query("ALTER TABLE `{$g5['memo_table']}` - ADD `me_send_id` INT(11) NOT NULL DEFAULT '0', - ADD `me_type` ENUM('send','recv') NOT NULL DEFAULT 'recv', - ADD `me_send_ip` VARCHAR(100) NOT NULL DEFAULT '', - CHANGE COLUMN `me_id` `me_id` INT(11) NOT NULL AUTO_INCREMENT; - ", false); - - $is_check = true; -} - -// 읽지 않은 메모 수 칼럼 -if(!isset($member['mb_memo_cnt'])) { - sql_query(" ALTER TABLE `{$g5['member_table']}` - ADD `mb_memo_cnt` int(11) NOT NULL DEFAULT '0' AFTER `mb_memo_call`", true); - - $is_check = true; -} - -// 스크랩 읽은 수 추가 -if(!isset($member['mb_scrap_cnt'])) { - sql_query(" ALTER TABLE `{$g5['member_table']}` - ADD `mb_scrap_cnt` int(11) NOT NULL DEFAULT '0' AFTER `mb_memo_cnt`", true); - - $is_check = true; -} - -// 짧은 URL 주소를 사용 여부 필드 추가 -if (!isset($config['cf_bbs_rewrite'])) { - sql_query(" ALTER TABLE `{$g5['config_table']}` - ADD `cf_bbs_rewrite` tinyint(4) NOT NULL DEFAULT '0' AFTER `cf_link_target` ", true); - - $is_check = true; -} - -// 파일테이블에 추가 칼럼 - -$sql = " SHOW COLUMNS FROM `{$g5['board_file_table']}` LIKE 'bf_fileurl' "; -$row = sql_fetch($sql); - -if( !$row ) { - sql_query(" ALTER TABLE `{$g5['board_file_table']}` - ADD COLUMN `bf_fileurl` VARCHAR(255) NOT NULL DEFAULT '' AFTER `bf_content`, - ADD COLUMN `bf_thumburl` VARCHAR(255) NOT NULL DEFAULT '' AFTER `bf_fileurl`, - ADD COLUMN `bf_storage` VARCHAR(50) NOT NULL DEFAULT '' AFTER `bf_thumburl`", true); - - $is_check = true; -} - -if (defined('G5_USE_SHOP') && G5_USE_SHOP) { - // 임시저장 테이블이 없을 경우 생성 - if(!sql_query(" DESC {$g5['g5_shop_post_log_table']} ", false)) { - sql_query(" CREATE TABLE IF NOT EXISTS `{$g5['g5_shop_post_log_table']}` ( - `log_id` int(11) NOT NULL AUTO_INCREMENT, - `oid` bigint(20) unsigned NOT NULL, - `mb_id` varchar(255) NOT NULL DEFAULT '', - `post_data` text NOT NULL, - `ol_code` varchar(255) NOT NULL DEFAULT '', - `ol_msg` text NOT NULL, - `ol_datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `ol_ip` varchar(25) NOT NULL DEFAULT '', - PRIMARY KEY (`log_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8; ", true); - - $is_check = true; - } - - $result = sql_query("describe `{$g5['g5_shop_post_log_table']}`"); - while ($row = sql_fetch_array($result)){ - if( isset($row['Field']) && $row['Field'] === 'ol_msg' && $row['Type'] === 'varchar(255)' ){ - sql_query("ALTER TABLE `{$g5['g5_shop_post_log_table']}` MODIFY ol_msg TEXT NOT NULL;", false); - sql_query("ALTER TABLE `{$g5['g5_shop_post_log_table']}` DROP PRIMARY KEY;", false); - sql_query("ALTER TABLE `{$g5['g5_shop_post_log_table']}` ADD `log_id` int(11) NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY (`log_id`);", false); - $is_check = true; - break; - } - } - - if (!isset($default['de_id'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD COLUMN `de_id` INT(11) NOT NULL AUTO_INCREMENT FIRST, - ADD PRIMARY KEY (`de_id`); ", true); - - $is_check = true; - } -} - -// auth.au_menu 컬럼 크기 조정 -$sql = " SHOW COLUMNS FROM `{$g5['auth_table']}` LIKE 'au_menu' "; -$row = sql_fetch($sql); -if ( - stripos($row['Type'], 'varchar') !== false - && (int) preg_replace('/[^0-9]/', '', $row['Type']) < 50 -) { - sql_query(" ALTER TABLE `{$g5['auth_table']}` CHANGE `au_menu` `au_menu` VARCHAR(50) NOT NULL; ", true); - - $is_check = true; -} - -// qa config 테이블 auto id key 추가 -$row = sql_fetch("select * from `{$g5['qa_config_table']}` limit 1"); -if (!isset($row['qa_id'])) { - sql_query(" ALTER TABLE `{$g5['qa_config_table']}` ADD COLUMN `qa_id` INT(11) NOT NULL AUTO_INCREMENT FIRST, - ADD PRIMARY KEY (`qa_id`); ", true); - - $is_check = true; -} - -// config 기본 테이블 auto id key 추가 -if (!isset($config['cf_id'])) { - sql_query(" ALTER TABLE `{$g5['config_table']}` - ADD COLUMN `cf_id` INT(11) NOT NULL AUTO_INCREMENT FIRST, - ADD PRIMARY KEY (`cf_id`); ", true); - - $is_check = true; -} - -// login 테이블 auto id key 추가 -$row = sql_fetch("select * from `{$g5['login_table']}` limit 1"); -if (!isset($row['lo_id'])) { - sql_query(" ALTER TABLE `{$g5['login_table']}` - ADD COLUMN `lo_id` INT(11) NOT NULL AUTO_INCREMENT FIRST, - DROP PRIMARY KEY, - ADD PRIMARY KEY (`lo_id`), - ADD UNIQUE KEY `lo_ip_unique` (`lo_ip`) ", true); - - $is_check = true; -} - -// visit 테이블 auto id key 로 변경 -$result = sql_query("describe `{$g5['visit_table']}`"); -while ($row = sql_fetch_array($result)){ - if (isset($row['Field']) && $row['Field'] === 'vi_id' && (isset($row['Default']) && $row['Default'] == 0)){ - sql_query("ALTER TABLE `{$g5['visit_table']}` - CHANGE COLUMN `vi_id` `vi_id` INT(11) NOT NULL AUTO_INCREMENT; - ", false); - - $is_check = true; - } -} - -// 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; -} - -// 쿠폰 로그 테이블에 UNIQUE 인덱스 추가 (쿠폰 이중사용 방지) -if (defined('G5_USE_SHOP') && G5_USE_SHOP) { - $result = sql_query("SHOW INDEX FROM `{$g5['g5_shop_coupon_log_table']}` WHERE Key_name = 'idx_coupon_use'", false); - if (!$result || !sql_num_rows($result)) { - // 기존에 동일 쿠폰이 중복 사용된 데이터가 있으면 UNIQUE 인덱스 생성 실패하므로 중복 데이터 정리 - $dup_sql = " SELECT cp_id, mb_id, MIN(cl_id) as keep_id - FROM `{$g5['g5_shop_coupon_log_table']}` - GROUP BY cp_id, mb_id - HAVING COUNT(*) > 1 "; - - $dup_result = sql_query($dup_sql, false); - if ($dup_result && sql_num_rows($dup_result)) { - while ($dup_row = sql_fetch_array($dup_result)) { - - echo $dup_row['cp_id']." 의 동일 쿠폰이 중복 사용된 데이터가 있으므로 인덱스 생성이 불가합니다.
"; - - $sql = " DELETE FROM `{$g5['g5_shop_coupon_log_table']}` - WHERE cp_id = '{$dup_row['cp_id']}' - AND mb_id = '{$dup_row['mb_id']}' - AND cl_id != '{$dup_row['keep_id']}' "; - if ($is_admin === 'super') { - echo "데이터베이스에서 검토후에 이 쿼리문을 실행해 주세요.
$sql
"; - } - // sql_query($sql); - } - } - - // MyISAM + utf8mb4 환경에서 키 길이 초과 방지: cp_id varchar(100), mb_id varchar(100)으로 조정 - sql_query("ALTER TABLE `{$g5['g5_shop_coupon_log_table']}` MODIFY `cp_id` varchar(100) NOT NULL DEFAULT '', MODIFY `mb_id` varchar(100) NOT NULL DEFAULT ''", false); - sql_query("ALTER TABLE `{$g5['g5_shop_coupon_log_table']}` ADD UNIQUE KEY `idx_coupon_use` (`cp_id`, `mb_id`)", false); - $is_check = true; - } -} - -// 자동 로그인 토큰 테이블 생성 (KVE-2026-0610: 추측 가능한 자동 로그인 쿠키 위조 방지) -// 다중 디바이스 지원을 위해 회원당 여러 토큰을 별도 테이블로 관리 -if (!isset($g5['member_auto_login_table'])) { - $g5['member_auto_login_table'] = G5_TABLE_PREFIX.'member_auto_login'; -} -if (!sql_query(" DESC `{$g5['member_auto_login_table']}` ", false)) { - sql_query(" CREATE TABLE IF NOT EXISTS `{$g5['member_auto_login_table']}` ( - `al_id` int(11) NOT NULL auto_increment, - `mb_id` varchar(20) NOT NULL default '', - `al_token` varchar(64) NOT NULL default '', - `al_user_agent` varchar(255) NOT NULL default '', - `al_ip` varchar(45) NOT NULL default '', - `al_created` datetime DEFAULT NULL, - `al_last_used` datetime DEFAULT NULL, - `al_expire` datetime DEFAULT NULL, - PRIMARY KEY (`al_id`), - UNIQUE KEY `al_token` (`al_token`), - KEY `mb_id` (`mb_id`), - KEY `al_expire` (`al_expire`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ", true); - $is_check = true; -} - -// KG이니시스 결제 처리 현황 및 단계별 이력 테이블 -if (defined('G5_USE_SHOP') && G5_USE_SHOP) { - $inicis_pro_config_columns = array( - 'de_inicis_pro_alert_use' => "ADD COLUMN `de_inicis_pro_alert_use` tinyint(4) NOT NULL DEFAULT '1'", - 'de_inicis_pro_reconcile_use' => "ADD COLUMN `de_inicis_pro_reconcile_use` tinyint(4) NOT NULL DEFAULT '0'", - 'de_inicis_pro_log_days' => "ADD COLUMN `de_inicis_pro_log_days` int(11) NOT NULL DEFAULT '365'", - 'de_inicis_pro_summary_days' => "ADD COLUMN `de_inicis_pro_summary_days` int(11) NOT NULL DEFAULT '1825'", - 'de_inicis_pro_monitor_at' => "ADD COLUMN `de_inicis_pro_monitor_at` datetime DEFAULT NULL", - 'de_inicis_pro_monitor_message' => "ADD COLUMN `de_inicis_pro_monitor_message` varchar(255) NOT NULL DEFAULT ''" - ); - $inicis_pro_config_alter = array(); - foreach ($inicis_pro_config_columns as $column => $alter) { - $column_result = sql_query(" SHOW COLUMNS FROM `{$g5['g5_shop_default_table']}` LIKE '$column' ", false); - if (!$column_result || sql_num_rows($column_result) === 0) - $inicis_pro_config_alter[] = $alter; - } - if (count($inicis_pro_config_alter)) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` ".implode(', ', $inicis_pro_config_alter), true); - $is_check = true; - } - - if (!isset($g5['g5_shop_inicis_pay_table'])) - $g5['g5_shop_inicis_pay_table'] = G5_SHOP_TABLE_PREFIX.'inicis_pay'; - if (!isset($g5['g5_shop_inicis_pay_event_table'])) - $g5['g5_shop_inicis_pay_event_table'] = G5_SHOP_TABLE_PREFIX.'inicis_pay_event'; - - if (!sql_query(" DESC `{$g5['g5_shop_inicis_pay_table']}` ", false)) { - sql_query(" CREATE TABLE IF NOT EXISTS `{$g5['g5_shop_inicis_pay_table']}` ( - `ip_id` int(11) NOT NULL AUTO_INCREMENT, - `ip_oid` varchar(64) NOT NULL DEFAULT '', - `ip_tid` varchar(80) NOT NULL DEFAULT '', - `ip_auth_tid` varchar(80) NOT NULL DEFAULT '', - `ip_mid` varchar(80) NOT NULL DEFAULT '', - `ip_environment` varchar(10) NOT NULL DEFAULT '', - `mb_id` varchar(20) NOT NULL DEFAULT '', - `ip_amount` int(11) NOT NULL DEFAULT '0', - `ip_pay_type` varchar(20) NOT NULL DEFAULT '', - `ip_easy_pay` varchar(20) NOT NULL DEFAULT '', - `ip_device` varchar(10) NOT NULL DEFAULT '', - `ip_order_type` varchar(10) NOT NULL DEFAULT '', - `ip_status` varchar(30) NOT NULL DEFAULT '', - `ip_result_code` varchar(30) NOT NULL DEFAULT '', - `ip_result_message` varchar(255) NOT NULL DEFAULT '', - `ip_noti_status` varchar(30) NOT NULL DEFAULT '', - `ip_noti_code` varchar(30) NOT NULL DEFAULT '', - `ip_noti_message` varchar(255) NOT NULL DEFAULT '', - `ip_noti_failed_count` int(11) NOT NULL DEFAULT '0', - `ip_noti_at` datetime DEFAULT NULL, - `ip_cancel_status` varchar(30) NOT NULL DEFAULT '', - `ip_cancel_code` varchar(30) NOT NULL DEFAULT '', - `ip_cancel_message` varchar(255) NOT NULL DEFAULT '', - `ip_cancel_checked_at` datetime DEFAULT NULL, - `ip_refund_required` tinyint(4) NOT NULL DEFAULT '0', - `ip_vbank_due_at` datetime DEFAULT NULL, - `ip_expired_at` datetime DEFAULT NULL, - `ip_order_exists` tinyint(4) NOT NULL DEFAULT '0', - `ip_approved_at` datetime DEFAULT NULL, - `ip_ordered_at` datetime DEFAULT NULL, - `ip_notified_at` datetime DEFAULT NULL, - `ip_canceled_at` datetime DEFAULT NULL, - `ip_created_at` datetime DEFAULT NULL, - `ip_updated_at` datetime DEFAULT NULL, - `ip_ip` varchar(45) NOT NULL DEFAULT '', - `ip_event_count` int(11) NOT NULL DEFAULT '0', - `ip_audit_error` tinyint(4) NOT NULL DEFAULT '0', - `ip_alerted_at` datetime DEFAULT NULL, - `ip_alert_key` varchar(64) NOT NULL DEFAULT '', - `ip_pg_status` varchar(30) NOT NULL DEFAULT '', - `ip_pg_amount` int(11) NOT NULL DEFAULT '0', - `ip_pg_tid` varchar(80) NOT NULL DEFAULT '', - `ip_pg_result_code` varchar(30) NOT NULL DEFAULT '', - `ip_pg_message` varchar(255) NOT NULL DEFAULT '', - `ip_pg_checked_at` datetime DEFAULT NULL, - PRIMARY KEY (`ip_id`), - UNIQUE KEY `ip_oid` (`ip_oid`), - KEY `ip_tid` (`ip_tid`), - KEY `ip_auth_tid` (`ip_auth_tid`), - KEY `ip_status` (`ip_status`), - KEY `ip_noti_status` (`ip_noti_status`), - KEY `ip_cancel_status` (`ip_cancel_status`), - KEY `ip_refund_required` (`ip_refund_required`), - KEY `ip_updated_at` (`ip_updated_at`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ", true); - $is_check = true; - } - - if (sql_query(" DESC `{$g5['g5_shop_inicis_pay_table']}` ", false)) { - $inicis_pay_columns = array( - 'ip_environment' => "ADD COLUMN `ip_environment` varchar(10) NOT NULL DEFAULT '' AFTER `ip_mid`", - 'ip_easy_pay' => "ADD COLUMN `ip_easy_pay` varchar(20) NOT NULL DEFAULT '' AFTER `ip_pay_type`", - 'ip_noti_status' => "ADD COLUMN `ip_noti_status` varchar(30) NOT NULL DEFAULT '' AFTER `ip_result_message`", - 'ip_noti_code' => "ADD COLUMN `ip_noti_code` varchar(30) NOT NULL DEFAULT '' AFTER `ip_noti_status`", - 'ip_noti_message' => "ADD COLUMN `ip_noti_message` varchar(255) NOT NULL DEFAULT '' AFTER `ip_noti_code`", - 'ip_noti_failed_count' => "ADD COLUMN `ip_noti_failed_count` int(11) NOT NULL DEFAULT '0' AFTER `ip_noti_message`", - 'ip_noti_at' => "ADD COLUMN `ip_noti_at` datetime DEFAULT NULL AFTER `ip_noti_failed_count`", - 'ip_cancel_status' => "ADD COLUMN `ip_cancel_status` varchar(30) NOT NULL DEFAULT '' AFTER `ip_noti_at`", - 'ip_cancel_code' => "ADD COLUMN `ip_cancel_code` varchar(30) NOT NULL DEFAULT '' AFTER `ip_cancel_status`", - 'ip_cancel_message' => "ADD COLUMN `ip_cancel_message` varchar(255) NOT NULL DEFAULT '' AFTER `ip_cancel_code`", - 'ip_cancel_checked_at' => "ADD COLUMN `ip_cancel_checked_at` datetime DEFAULT NULL AFTER `ip_cancel_message`", - 'ip_refund_required' => "ADD COLUMN `ip_refund_required` tinyint(4) NOT NULL DEFAULT '0' AFTER `ip_cancel_checked_at`", - 'ip_vbank_due_at' => "ADD COLUMN `ip_vbank_due_at` datetime DEFAULT NULL AFTER `ip_refund_required`", - 'ip_expired_at' => "ADD COLUMN `ip_expired_at` datetime DEFAULT NULL AFTER `ip_vbank_due_at`", - 'ip_audit_error' => "ADD COLUMN `ip_audit_error` tinyint(4) NOT NULL DEFAULT '0'", - 'ip_alerted_at' => "ADD COLUMN `ip_alerted_at` datetime DEFAULT NULL", - 'ip_alert_key' => "ADD COLUMN `ip_alert_key` varchar(64) NOT NULL DEFAULT ''", - 'ip_pg_status' => "ADD COLUMN `ip_pg_status` varchar(30) NOT NULL DEFAULT ''", - 'ip_pg_amount' => "ADD COLUMN `ip_pg_amount` int(11) NOT NULL DEFAULT '0'", - 'ip_pg_tid' => "ADD COLUMN `ip_pg_tid` varchar(80) NOT NULL DEFAULT ''", - 'ip_pg_result_code' => "ADD COLUMN `ip_pg_result_code` varchar(30) NOT NULL DEFAULT ''", - 'ip_pg_message' => "ADD COLUMN `ip_pg_message` varchar(255) NOT NULL DEFAULT ''", - 'ip_pg_checked_at' => "ADD COLUMN `ip_pg_checked_at` datetime DEFAULT NULL" - ); - $inicis_pay_alter = array(); - foreach ($inicis_pay_columns as $column => $alter) { - $column_result = sql_query(" SHOW COLUMNS FROM `{$g5['g5_shop_inicis_pay_table']}` LIKE '$column' ", false); - if (!$column_result || sql_num_rows($column_result) === 0) - $inicis_pay_alter[] = $alter; - } - if (count($inicis_pay_alter)) { - sql_query(" ALTER TABLE `{$g5['g5_shop_inicis_pay_table']}` ".implode(', ', $inicis_pay_alter), true); - $is_check = true; - } - - if (count($inicis_pay_alter)) { - $environment = !empty($default['de_card_test']) ? 'test' : 'live'; - sql_query(" insert ignore into `{$g5['g5_shop_inicis_pay_table']}` - (ip_oid, ip_environment, ip_status, ip_noti_status, ip_noti_code, ip_noti_message, - ip_noti_failed_count, ip_noti_at, ip_created_at, ip_updated_at, ip_event_count) - select e.ip_oid, '$environment', e.pe_status, e.pe_status, e.pe_code, e.pe_message, - sum(if(e.pe_status = 'notification_failed', 1, 0)), max(e.pe_created_at), - min(e.pe_created_at), max(e.pe_created_at), count(*) - from `{$g5['g5_shop_inicis_pay_event_table']}` e - left join `{$g5['g5_shop_inicis_pay_table']}` p on p.ip_oid = e.ip_oid - where p.ip_id is null - and e.pe_stage = 'notification' - group by e.ip_oid ", false); - sql_query(" update `{$g5['g5_shop_inicis_pay_table']}` - set ip_environment = case - when lower(ip_mid) in ('inipaytest','iniescrow0') then 'test' - when ip_mid <> '' then 'live' - else '$environment' - end - where ip_environment = '' ", false); - sql_query(" update `{$g5['g5_shop_inicis_pay_table']}` p - inner join ( - select ip_oid, max(pe_id) as pe_id, - sum(if(pe_status = 'notification_failed', 1, 0)) as fail_count - from `{$g5['g5_shop_inicis_pay_event_table']}` - where pe_stage = 'notification' - group by ip_oid - ) x on x.ip_oid = p.ip_oid - inner join `{$g5['g5_shop_inicis_pay_event_table']}` e on e.pe_id = x.pe_id - set p.ip_noti_status = e.pe_status, - p.ip_noti_code = e.pe_code, - p.ip_noti_message = e.pe_message, - p.ip_noti_failed_count = x.fail_count, - p.ip_noti_at = e.pe_created_at ", false); - sql_query(" update `{$g5['g5_shop_inicis_pay_table']}` p - inner join ( - select ip_oid, max(pe_id) as pe_id - from `{$g5['g5_shop_inicis_pay_event_table']}` - where pe_stage = 'cancel' - group by ip_oid - ) x on x.ip_oid = p.ip_oid - inner join `{$g5['g5_shop_inicis_pay_event_table']}` e on e.pe_id = x.pe_id - set p.ip_cancel_status = e.pe_status, - p.ip_cancel_code = e.pe_code, - p.ip_cancel_message = e.pe_message, - p.ip_cancel_checked_at = e.pe_created_at ", false); - sql_query(" update `{$g5['g5_shop_inicis_pay_table']}` p - inner join `{$g5['g5_shop_inicis_pay_event_table']}` e on e.ip_oid = p.ip_oid and e.pe_stage = 'request' - set p.ip_easy_pay = case - when e.pe_message like '삼성페이%' then 'SAMSUNGPAY' - when e.pe_message like 'lpay%' then 'LPAY' - when e.pe_message like 'inicis_kakaopay%' then 'KAKAOPAY' - when e.pe_message like '간편결제%' then 'EASYPAY' - else p.ip_easy_pay - end - where p.ip_easy_pay = '' ", false); - sql_query(" update `{$g5['g5_shop_inicis_pay_table']}` - set ip_noti_status = case - when ip_status = 'paid' then 'paid' - when ip_status = 'vbank_issued' then 'vbank_issued' - when ip_status = 'notification_received' then 'notification_received' - else ip_noti_status - end, - ip_cancel_status = case - when ip_status in ('canceled','cancel_failed','partial_canceled','partial_cancel_failed') then ip_status - else ip_cancel_status - end ", false); - sql_query(" update `{$g5['g5_shop_inicis_pay_table']}` p - inner join {$g5['g5_shop_order_table']} o on o.od_id = p.ip_oid - set p.ip_status = 'paid_after_cancel', - p.ip_refund_required = '1', - p.ip_noti_status = 'paid_after_cancel', - p.ip_noti_message = '취소 주문에 가상계좌 입금 확인' - where p.ip_pay_type = 'VBANK' - and p.ip_status = 'paid' - and o.od_status = '취소' - and o.od_receipt_price > 0 ", false); - $inicis_pro_migrated_at = G5_TIME_YMDHIS; - $inicis_pro_migrated_message = '기존 결제·주문 이력 대조에서 취소 후 입금 확인'; - sql_query(" insert into `{$g5['g5_shop_inicis_pay_event_table']}` - (ip_oid, ip_tid, pe_stage, pe_status, pe_code, pe_message, pe_source, pe_ip, pe_created_at) - select p.ip_oid, p.ip_tid, 'reconcile', 'paid_after_cancel', '', - '".sql_escape_string($inicis_pro_migrated_message)."', 'system', '', '$inicis_pro_migrated_at' - from `{$g5['g5_shop_inicis_pay_table']}` p - left join `{$g5['g5_shop_inicis_pay_event_table']}` e - on e.ip_oid = p.ip_oid and e.pe_status = 'paid_after_cancel' - where p.ip_status = 'paid_after_cancel' - and p.ip_refund_required = '1' - and e.pe_id is null ", false); - sql_query(" update `{$g5['g5_shop_inicis_pay_table']}` p - inner join `{$g5['g5_shop_inicis_pay_event_table']}` e - on e.ip_oid = p.ip_oid - and e.pe_status = 'paid_after_cancel' - and e.pe_message = '".sql_escape_string($inicis_pro_migrated_message)."' - and e.pe_created_at = '$inicis_pro_migrated_at' - set p.ip_event_count = p.ip_event_count + 1 ", false); - } - - $inicis_pay_indexes = array( - 'ip_noti_status' => "ADD KEY `ip_noti_status` (`ip_noti_status`)", - 'ip_cancel_status' => "ADD KEY `ip_cancel_status` (`ip_cancel_status`)", - 'ip_refund_required' => "ADD KEY `ip_refund_required` (`ip_refund_required`)" - ); - foreach ($inicis_pay_indexes as $index_name => $index_sql) { - $index_result = sql_query(" SHOW INDEX FROM `{$g5['g5_shop_inicis_pay_table']}` WHERE Key_name = '$index_name' ", false); - if (!$index_result || sql_num_rows($index_result) === 0) { - sql_query(" ALTER TABLE `{$g5['g5_shop_inicis_pay_table']}` $index_sql ", true); - $is_check = true; - } - } - } - - if (!sql_query(" DESC `{$g5['g5_shop_inicis_pay_event_table']}` ", false)) { - sql_query(" CREATE TABLE IF NOT EXISTS `{$g5['g5_shop_inicis_pay_event_table']}` ( - `pe_id` int(11) NOT NULL AUTO_INCREMENT, - `ip_oid` varchar(64) NOT NULL DEFAULT '', - `ip_tid` varchar(80) NOT NULL DEFAULT '', - `pe_stage` varchar(30) NOT NULL DEFAULT '', - `pe_status` varchar(30) NOT NULL DEFAULT '', - `pe_code` varchar(30) NOT NULL DEFAULT '', - `pe_message` varchar(255) NOT NULL DEFAULT '', - `pe_source` varchar(10) NOT NULL DEFAULT '', - `pe_ip` varchar(45) NOT NULL DEFAULT '', - `pe_created_at` datetime DEFAULT NULL, - PRIMARY KEY (`pe_id`), - KEY `ip_oid` (`ip_oid`), - KEY `ip_tid` (`ip_tid`), - KEY `pe_status` (`pe_status`), - KEY `pe_created_at` (`pe_created_at`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ", true); - $is_check = true; - } -} - -$is_check = run_replace('admin_dbupgrade', $is_check); - -$db_upgrade_msg = $is_check ? 'DB 업그레이드가 완료되었습니다.' : '더 이상 업그레이드 할 내용이 없습니다.
현재 DB 업그레이드가 완료된 상태입니다.'; +$dbupgrade_token = get_admin_token(); ?>
-

- -

+

+ +

실행 불필요 건: 현재 실행 조건상 건너뛰는 항목입니다. 과거 실행 성공을 의미하지 않으며, 선행 작업 후에는 결과가 달라질 수 있습니다. 기존 상태 등록은 처음부터 연속해서 실행 불필요한 항목만 기록합니다.

+ +

대기 항목에는 데이터 보정 등 조회만으로 완료를 판단할 수 없는 작업도 포함됩니다. 조회 시 DB 변경이나 이력 등록은 수행하지 않습니다.

+ +
+

+
+ +
+ +

+ +
+ + +
+ +
+ + + +
+ + +
+ + + +
+ +
+ + + +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
버전형 DB 마이그레이션 목록
+ +
+
+
+ + + + diff --git a/adm/faqmasterformupdate.php b/adm/faqmasterformupdate.php index 92e6415b7..ba20c8b94 100644 --- a/adm/faqmasterformupdate.php +++ b/adm/faqmasterformupdate.php @@ -42,9 +42,6 @@ $sql_common = " set fm_subject = '$fm_subject', fm_order = '$fm_order' "; if ($w == "") { - $sql = " alter table {$g5['faq_master_table']} auto_increment=1 "; - sql_query($sql); - $sql = " insert {$g5['faq_master_table']} $sql_common "; sql_query($sql); diff --git a/adm/faqmasterlist.php b/adm/faqmasterlist.php index d2ac55d0e..20da5dbc2 100644 --- a/adm/faqmasterlist.php +++ b/adm/faqmasterlist.php @@ -10,45 +10,8 @@ if (!isset($g5['faq_table']) || !isset($g5['faq_master_table'])) { } //자주하시는 질문 마스터 테이블이 있는지 검사한다. -if (!sql_query(" DESCRIBE {$g5['faq_master_table']} ", false)) { - if (sql_query(" DESCRIBE {$g5['g5_shop_faq_master_table']} ", false)) { - sql_query(" ALTER TABLE {$g5['g5_shop_faq_master_table']} RENAME TO `{$g5['faq_master_table']}` ;", false); - } else { - $query_cp = sql_query( - " CREATE TABLE IF NOT EXISTS `{$g5['faq_master_table']}` ( - `fm_id` int(11) NOT NULL AUTO_INCREMENT, - `fm_subject` varchar(255) NOT NULL DEFAULT '', - `fm_head_html` text NOT NULL, - `fm_tail_html` text NOT NULL, - `fm_order` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`fm_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ", - true - ); - } - // FAQ Master - sql_query(" insert into `{$g5['faq_master_table']}` set fm_id = '1', fm_subject = '자주하시는 질문' ", false); -} //자주하시는 질문 테이블이 있는지 검사한다. -if (!sql_query(" DESCRIBE {$g5['faq_table']} ", false)) { - if (sql_query(" DESCRIBE {$g5['g5_shop_faq_table']} ", false)) { - sql_query(" ALTER TABLE {$g5['g5_shop_faq_table']} RENAME TO `{$g5['faq_table']}` ;", false); - } else { - $query_cp = sql_query( - " CREATE TABLE IF NOT EXISTS `{$g5['faq_table']}` ( - `fa_id` int(11) NOT NULL AUTO_INCREMENT, - `fm_id` int(11) NOT NULL DEFAULT '0', - `fa_subject` text NOT NULL, - `fa_content` text NOT NULL, - `fa_order` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`fa_id`), - KEY `fm_id` (`fm_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ", - true - ); - } -} $g5['title'] = 'FAQ관리'; require_once G5_ADMIN_PATH . '/admin.head.php'; diff --git a/adm/mail_select_update.php b/adm/mail_select_update.php index c0d7c7400..c6083d90d 100644 --- a/adm/mail_select_update.php +++ b/adm/mail_select_update.php @@ -8,6 +8,8 @@ $html_title = '회원메일 발송'; check_demo(); +$security_mail_url = g5_require_security_mail_url(); + check_admin_token(); require_once './admin.head.php'; @@ -59,7 +61,7 @@ for ($i = 0; $i < count($member_list); $i++) { $content = preg_replace("/{회원아이디}/", $mb_id, (string)$content); $content = preg_replace("/{이메일}/", $to_email, (string)$content); - $content = $content . "

▶ 더 이상 정보 수신을 원치 않으시면 [수신거부] 해 주십시오.

"; + $content = $content . "

▶ 더 이상 정보 수신을 원치 않으시면 [수신거부] 해 주십시오.

"; mailer($config['cf_admin_email_name'], $config['cf_admin_email'], $to_email, $subject, $content, 1); diff --git a/adm/mail_test.php b/adm/mail_test.php index 13d74aeca..afb8a8fd8 100644 --- a/adm/mail_test.php +++ b/adm/mail_test.php @@ -12,6 +12,8 @@ auth_check_menu($auth, $sub_menu, 'w'); check_demo(); +$security_mail_url = g5_require_security_mail_url(); + $g5['title'] = '회원메일 테스트'; $name = get_text($member['mb_name']); @@ -33,7 +35,7 @@ $content = preg_replace("/{이메일}/", $email, (string)$content); $mb_md5 = md5($member['mb_id'] . $member['mb_email'] . $member['mb_datetime']); -$content = $content . '

더 이상 정보 수신을 원치 않으시면 [수신거부] 해 주십시오.

'; +$content = $content . '

더 이상 정보 수신을 원치 않으시면 [수신거부] 해 주십시오.

'; mailer($config['cf_title'], $member['mb_email'], $member['mb_email'], $subject, $content, 1); diff --git a/adm/member_cert_cleanup.php b/adm/member_cert_cleanup.php new file mode 100644 index 000000000..fce93fb42 --- /dev/null +++ b/adm/member_cert_cleanup.php @@ -0,0 +1,30 @@ += $member['mb_level'] || is_admin($mb['mb_id']) === 'super')) { + alert('자신보다 권한이 높거나 같은 회원의 본인확인 정보는 삭제할 수 없습니다.'); +} + +if (!admin_clear_member_certification($mb['mb_id'])) { + alert('본인확인 정보를 모두 삭제하지 못했습니다. DB 상태를 확인한 뒤 다시 시도해 주십시오.'); +} + +alert('본인확인 정보와 인증 내역을 삭제했습니다.', './member_form.php?w=u&mb_id='.urlencode($mb['mb_id'])); diff --git a/adm/member_form.php b/adm/member_form.php index 501d6aa2c..77e6a302b 100644 --- a/adm/member_form.php +++ b/adm/member_form.php @@ -150,62 +150,21 @@ $mb_marketing_agree_no = !$mb['mb_marketing_agree'] ? 'checked="checked"' : $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'])) { - sql_query(" ALTER TABLE `{$g5['member_table']}` DROP `mb_certify` ", false); - } -} else { - sql_query(" ALTER TABLE `{$g5['member_table']}` ADD `mb_certify` TINYINT(4) NOT NULL DEFAULT '0' AFTER `mb_hp` ", false); -} -if (isset($mb['mb_adult'])) { - sql_query(" ALTER TABLE `{$g5['member_table']}` CHANGE `mb_adult` `mb_adult` TINYINT(4) NOT NULL DEFAULT '0' ", false); -} else { - sql_query(" ALTER TABLE `{$g5['member_table']}` ADD `mb_adult` TINYINT NOT NULL DEFAULT '0' AFTER `mb_certify` ", false); -} // 지번주소 필드추가 -if (!isset($mb['mb_addr_jibeon'])) { - sql_query(" ALTER TABLE {$g5['member_table']} ADD `mb_addr_jibeon` varchar(255) NOT NULL DEFAULT '' AFTER `mb_addr2` ", false); -} // 건물명필드추가 -if (!isset($mb['mb_addr3'])) { - sql_query(" ALTER TABLE {$g5['member_table']} ADD `mb_addr3` varchar(255) NOT NULL DEFAULT '' AFTER `mb_addr2` ", false); -} // 중복가입 확인필드 추가 -if (!isset($mb['mb_dupinfo'])) { - sql_query(" ALTER TABLE {$g5['member_table']} ADD `mb_dupinfo` varchar(255) NOT NULL DEFAULT '' AFTER `mb_adult` ", false); -} // 이메일인증 체크 필드추가 -if (!isset($mb['mb_email_certify2'])) { - sql_query(" ALTER TABLE {$g5['member_table']} ADD `mb_email_certify2` varchar(255) NOT NULL DEFAULT '' AFTER `mb_email_certify` ", false); -} // 본인인증 내역 테이블 정보가 dbconfig에 없으면 소셜 테이블 정의 if (!isset($g5['member_cert_history'])) { $g5['member_cert_history_table'] = G5_TABLE_PREFIX . 'member_cert_history'; } // 멤버 본인인증 정보 변경 내역 테이블 없을 경우 생성 -if (isset($g5['member_cert_history_table']) && !sql_query(" DESC {$g5['member_cert_history_table']} ", false)) { - sql_query( - " CREATE TABLE IF NOT EXISTS `{$g5['member_cert_history_table']}` ( - `ch_id` int(11) NOT NULL auto_increment, - `mb_id` varchar(20) NOT NULL DEFAULT '', - `ch_name` varchar(255) NOT NULL DEFAULT '', - `ch_hp` varchar(255) NOT NULL DEFAULT '', - `ch_birth` varchar(255) NOT NULL DEFAULT '', - `ch_type` varchar(20) NOT NULL DEFAULT '', - `ch_datetime` datetime NOT NULL default '0000-00-00 00:00:00', - PRIMARY KEY (`ch_id`), - KEY `mb_id` (`mb_id`) - ) ", - true - ); -} $mb_cert_history = ''; if (isset($mb_id) && $mb_id) { @@ -479,6 +438,20 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js 본인인증 내역이 없습니다. + 0 || !empty($mb['mb_dupinfo']) || !empty($mb['mb_certify']) + || !empty($mb['mb_adult']) || !empty($mb['mb_birth']) || !empty($mb['mb_sex']); + if ($w === 'u' && !$has_certification_data) { + $cert_request = sql_fetch("select count(*) as cnt from {$g5['cert_history_table']} where mb_id = '".sql_real_escape_string($mb['mb_id'])."'"); + $has_certification_data = !empty($cert_request['cnt']); + } + $can_cleanup_certification = $w === 'u' && $has_certification_data + && ($is_admin === 'super' || (isset($auth[$sub_menu]) && strpos($auth[$sub_menu], 'd') !== false)); + ?> + +

본인확인 ‘아니오’는 인증 상태만 변경합니다. 정보 삭제는 CI/DI 관련 식별값, 본인확인·성인인증 상태, 생년월일·성별 및 본인인증 내역을 삭제합니다. 회원 이름과 연락처는 유지합니다.

+ + @@ -639,6 +612,13 @@ add_javascript(G5_POSTCODE_JS, 0); //다음 주소 js + +
+ + +
+ +
  • SMS설정
  • '; -// 무이자 할부 사용설정 필드 추가 -if(!isset($default['de_card_noint_use'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_card_noint_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_card_use` ", true); -} - -// 모바일 관련상품 설정 필드추가 -if(!isset($default['de_mobile_rel_list_use'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_mobile_rel_list_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_rel_img_height`, - ADD `de_mobile_rel_list_skin` varchar(255) NOT NULL DEFAULT '' AFTER `de_mobile_rel_list_use`, - ADD `de_mobile_rel_img_width` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_rel_list_skin`, - ADD `de_mobile_rel_img_height` int(11) NOT NULL DEFAULT ' 0' AFTER `de_mobile_rel_img_width`", true); -} - -// 신규회원 쿠폰 설정 필드 추가 -if(!isset($default['de_member_reg_coupon_use'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_member_reg_coupon_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_tax_flag_use`, - ADD `de_member_reg_coupon_term` int(11) NOT NULL DEFAULT '0' AFTER `de_member_reg_coupon_use`, - ADD `de_member_reg_coupon_price` int(11) NOT NULL DEFAULT '0' AFTER `de_member_reg_coupon_term` ", true); -} - -// 신규회원 쿠폰 주문 최소금액 필드추가 -if(!isset($default['de_member_reg_coupon_minimum'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_member_reg_coupon_minimum` int(11) NOT NULL DEFAULT '0' AFTER `de_member_reg_coupon_price` ", true); -} - -// lg 결제관련 필드 추가 -if(!isset($default['de_pg_service'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_pg_service` varchar(255) NOT NULL DEFAULT '' AFTER `de_sms_hp` ", true); -} - - -// inicis 필드 추가 -if(!isset($default['de_inicis_mid'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_inicis_mid` varchar(255) NOT NULL DEFAULT '' AFTER `de_kcp_site_key` ", true); -} - -// 모바일 초기화면 이미지 줄 수 필드 추가 -if(!isset($default['de_mobile_type1_list_row'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_mobile_type1_list_row` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_type1_list_mod`, - ADD `de_mobile_type2_list_row` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_type2_list_mod`, - ADD `de_mobile_type3_list_row` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_type3_list_mod`, - ADD `de_mobile_type4_list_row` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_type4_list_mod`, - ADD `de_mobile_type5_list_row` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_type5_list_mod` ", true); -} - -// 모바일 관련상품 이미지 줄 수 필드 추가 -if(!isset($default['de_mobile_rel_list_mod'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_mobile_rel_list_mod` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_rel_list_skin` ", true); -} - -// 모바일 검색상품 이미지 줄 수 필드 추가 -if(!isset($default['de_mobile_search_list_row'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_mobile_search_list_row` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_search_list_mod` ", true); -} - -// PG 간펼결제 사용여부 필드 추가 -if(!isset($default['de_easy_pay_use'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_easy_pay_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_iche_use` ", true); -} - -// 이니시스 삼성페이 사용여부 필드 추가 -if(!isset($default['de_samsung_pay_use'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_samsung_pay_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_easy_pay_use` ", true); -} - -// 이니시스 -if(!isset($default['de_inicis_cartpoint_use'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_inicis_cartpoint_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_samsung_pay_use` ", true); -} - -// 이니시스 lpay 사용여부 필드 추가 -if(!isset($default['de_inicis_lpay_use'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_inicis_lpay_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_samsung_pay_use` ", true); -} - -// 이니시스 kakaopay 사용여부 필드 추가 -if(!isset($default['de_inicis_kakaopay_use'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_inicis_kakaopay_use` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_inicis_lpay_use` ", true); -} - -// 카카오페이 필드 추가 -if(!isset($default['de_kakaopay_mid'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_kakaopay_mid` varchar(255) NOT NULL DEFAULT '' AFTER `de_tax_flag_use`, - ADD `de_kakaopay_key` varchar(255) NOT NULL DEFAULT '' AFTER `de_kakaopay_mid`, - ADD `de_kakaopay_enckey` varchar(255) NOT NULL DEFAULT '' AFTER `de_kakaopay_key`, - ADD `de_kakaopay_hashkey` varchar(255) NOT NULL DEFAULT '' AFTER `de_kakaopay_enckey`, - ADD `de_kakaopay_cancelpwd` varchar(255) NOT NULL DEFAULT '' AFTER `de_kakaopay_hashkey` ", true); -} - -// 이니시스 웹결제 사인키 필드 추가 -if(!isset($default['de_inicis_sign_key'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_inicis_sign_key` varchar(255) NOT NULL DEFAULT '' ", true); -} - -// 네이버페이 필드추가 -if(!isset($default['de_naverpay_mid'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_naverpay_mid` varchar(255) NOT NULL DEFAULT '' AFTER `de_kakaopay_cancelpwd`, - ADD `de_naverpay_cert_key` varchar(255) NOT NULL DEFAULT '' AFTER `de_naverpay_mid`, - ADD `de_naverpay_button_key` varchar(255) NOT NULL DEFAULT '' AFTER `de_naverpay_cert_key`, - ADD `de_naverpay_test` tinyint(4) NOT NULL DEFAULT '0' AFTER `de_naverpay_button_key`, - ADD `de_naverpay_mb_id` varchar(255) NOT NULL DEFAULT '' AFTER `de_naverpay_test`, - ADD `de_naverpay_sendcost` varchar(255) NOT NULL DEFAULT '' AFTER `de_naverpay_mb_id`", true); -} - -// 유형별상품리스트 설정필드 추가 -if(!isset($default['de_listtype_list_skin'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_listtype_list_skin` varchar(255) NOT NULL DEFAULT '' AFTER `de_mobile_search_img_height`, - ADD `de_listtype_list_mod` int(11) NOT NULL DEFAULT '0' AFTER `de_listtype_list_skin`, - ADD `de_listtype_list_row` int(11) NOT NULL DEFAULT '0' AFTER `de_listtype_list_mod`, - ADD `de_listtype_img_width` int(11) NOT NULL DEFAULT '0' AFTER `de_listtype_list_row`, - ADD `de_listtype_img_height` int(11) NOT NULL DEFAULT '0' AFTER `de_listtype_img_width`, - ADD `de_mobile_listtype_list_skin` varchar(255) NOT NULL DEFAULT '' AFTER `de_listtype_img_height`, - ADD `de_mobile_listtype_list_mod` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_listtype_list_skin`, - ADD `de_mobile_listtype_list_row` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_listtype_list_mod`, - ADD `de_mobile_listtype_img_width` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_listtype_list_row`, - ADD `de_mobile_listtype_img_height` int(11) NOT NULL DEFAULT '0' AFTER `de_mobile_listtype_img_width` ", true); -} - -// 임시저장 테이블이 없을 경우 생성 -if(!sql_query(" DESC {$g5['g5_shop_post_log_table']} ", false)) { - sql_query(" CREATE TABLE IF NOT EXISTS `{$g5['g5_shop_post_log_table']}` ( - `log_id` int(11) NOT NULL AUTO_INCREMENT, - `oid` bigint(20) unsigned NOT NULL, - `mb_id` varchar(255) NOT NULL DEFAULT '', - `post_data` text NOT NULL, - `ol_code` varchar(255) NOT NULL DEFAULT '', - `ol_msg` text NOT NULL, - `ol_datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', - `ol_ip` varchar(25) NOT NULL DEFAULT '', - PRIMARY KEY (`log_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8; ", false); -} - - -// 현금영수증 발급 조건 추가 -if(!isset($default['de_taxsave_types'])) { - sql_query(" ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD `de_taxsave_types` set('account','vbank','transfer') NOT NULL DEFAULT 'account' AFTER `de_taxsave_use` ", true); -} - -// 아이코드 토큰키 추가 -if( ! isset($config['cf_icode_token_key']) ){ - $sql = "ALTER TABLE `{$g5['config_table']}` - ADD COLUMN `cf_icode_token_key` VARCHAR(100) NOT NULL DEFAULT '' AFTER `cf_icode_server_port`; "; - sql_query($sql, false); -} - -// PG 간편결제 추가 ( NHN_KCP 네이버페이, 카카오페이 ) -if( ! isset($default['de_easy_pay_services']) ){ - $sql = "ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD COLUMN `de_easy_pay_services` VARCHAR(255) NOT NULL DEFAULT '' AFTER `de_easy_pay_use`; "; - sql_query($sql, false); -} - -// KG 이니시스 iniapi_key 추가 -if( ! isset($default['de_inicis_iniapi_key']) ){ - $sql = "ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD COLUMN `de_inicis_iniapi_key` VARCHAR(30) NOT NULL DEFAULT '' AFTER `de_inicis_sign_key`, - ADD COLUMN `de_inicis_iniapi_iv` VARCHAR(30) NOT NULL DEFAULT '' AFTER `de_inicis_iniapi_key`; "; - sql_query($sql, false); -} - -// KG이니시스 INIpay PRO 설정 추가 -if (!isset($default['de_inicis_pro_use'])) { - $sql = "ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD COLUMN `de_inicis_pro_use` TINYINT(4) NOT NULL DEFAULT '0' AFTER `de_inicis_sign_key`, - ADD COLUMN `de_inicis_hash_key` VARCHAR(255) NOT NULL DEFAULT '' AFTER `de_inicis_pro_use`; "; - sql_query($sql, false); -} - -if (!isset($default['de_inicis_pro_alert_use'])) { - sql_query("ALTER TABLE `{$g5['g5_shop_default_table']}` ADD COLUMN `de_inicis_pro_alert_use` TINYINT(4) NOT NULL DEFAULT '1'", false); - $default['de_inicis_pro_alert_use'] = 1; -} -if (!isset($default['de_inicis_pro_reconcile_use'])) { - sql_query("ALTER TABLE `{$g5['g5_shop_default_table']}` ADD COLUMN `de_inicis_pro_reconcile_use` TINYINT(4) NOT NULL DEFAULT '0'", false); - $default['de_inicis_pro_reconcile_use'] = 0; -} -if (!isset($default['de_inicis_pro_log_days'])) { - sql_query("ALTER TABLE `{$g5['g5_shop_default_table']}` ADD COLUMN `de_inicis_pro_log_days` INT(11) NOT NULL DEFAULT '365'", false); - $default['de_inicis_pro_log_days'] = 365; -} -if (!isset($default['de_inicis_pro_summary_days'])) { - sql_query("ALTER TABLE `{$g5['g5_shop_default_table']}` ADD COLUMN `de_inicis_pro_summary_days` INT(11) NOT NULL DEFAULT '1825'", false); - $default['de_inicis_pro_summary_days'] = 1825; -} -if (!array_key_exists('de_inicis_pro_monitor_at', $default)) { - sql_query("ALTER TABLE `{$g5['g5_shop_default_table']}` ADD COLUMN `de_inicis_pro_monitor_at` DATETIME DEFAULT NULL", false); - $default['de_inicis_pro_monitor_at'] = ''; -} -if (!isset($default['de_inicis_pro_monitor_message'])) { - sql_query("ALTER TABLE `{$g5['g5_shop_default_table']}` ADD COLUMN `de_inicis_pro_monitor_message` VARCHAR(255) NOT NULL DEFAULT ''", false); - $default['de_inicis_pro_monitor_message'] = ''; -} - -// KG이니시스 INIpay PRO 결제 감사 테이블이 없으면 생성한다. -include_once(G5_SHOP_PATH.'/inicis/pro/inicis_pro.lib.php'); -if (function_exists('inicis_pro_audit_ensure_tables')) - inicis_pro_audit_ensure_tables(); - -// NICEPAY mid, key 추가 -if (! isset($default['de_nicepay_mid'])) { - $sql = "ALTER TABLE `{$g5['g5_shop_default_table']}` - ADD COLUMN `de_nicepay_mid` VARCHAR(20) NOT NULL DEFAULT '' AFTER `de_inicis_cartpoint_use`, - ADD COLUMN `de_nicepay_key` VARCHAR(150) NOT NULL DEFAULT '' AFTER `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); } -if(!$default['de_kakaopay_cancelpwd']){ - $default['de_kakaopay_cancelpwd'] = '1111'; -} ?> + +
    +

    5.6.37부터 SIRK 전용 카카오페이 연동을 지원하지 않습니다. 기존 거래는 이니시스 상점관리자에서 승인·취소 내역을 확인해 주십시오.

    +

    기존 이용 고객 지원: 김민섭 minsup@sir.kr

    +
    + +
    @@ -732,7 +502,7 @@ if(!$default['de_kakaopay_cancelpwd']){ - + 일 이후에 포인트를 지급 + + 배송 완료 일 이후에 포인트를 지급 @@ -856,16 +626,16 @@ if(!$default['de_kakaopay_cancelpwd']){ 네이버페이, 카카오페이는 테스트결제가 되지 않습니다.\n애플페이는 IOS 기기에 모바일결제만 가능합니다."); ?> - >
    - >
    - >
    - > + $easy_provider) { ?> + > +
    + - + >
    @@ -889,7 +659,7 @@ if(!$default['de_kakaopay_cancelpwd']){ - 개발자센터 -> API키 -> 머트 키에서 확인하실 수 있습니다.\n예) 95160cce09854ef44d2edb2bfb05f9f3"); ?> + 개발자센터 -> API키 -> 머트 키에서 확인하실 수 있습니다. 예) 95160cce09854ef44d2edb2bfb05f9f3\n실결제용 [라이브] 키와 테스트용 [테스트] 키는 서로 다르므로, 테스트로 결제시에는 [테스트] 키로 변경하여 사용해주시기 바랍니다."); ?> @@ -977,34 +747,18 @@ if(!$default['de_kakaopay_cancelpwd']){ 일 - - - - 삼성페이 서비스신청하기 - + 'KG이니시스', 'toss' => '토스페이먼츠 API') as $easy_pg => $easy_title) { ?> + + 간편결제 - 삼성페이 사용 계약을 하신 경우에만 체크해주세요. INIpay PRO 사용 시 PC와 모바일 주문서에 삼성페이가 노출되며 삼성페이 결제창을 직접 호출합니다. 구버전 결제에서는 모바일 주문서에만 노출됩니다.
    실결제 시 상점 아이디와 사용 중인 결제모듈의 인증키(PRO: HashKey, 구버전: 웹결제 사인키)를 입력해 주세요.", 50); ?> - > - - - - - - - - 실결제 시 상점 아이디와 사용 중인 결제모듈의 인증키(PRO: HashKey, 구버전: 웹결제 사인키)를 입력해 주세요.", 50); ?> - > - - - - - - - - 실결제 시 상점 아이디와 사용 중인 결제모듈의 인증키(PRO: HashKey, 구버전: 웹결제 사인키)를 입력해 주세요.", 50); ?> - > + + $easy_provider) { ?> + > +
    + + @@ -1014,46 +768,6 @@ if(!$default['de_kakaopay_cancelpwd']){ > - - - - 카카오페이 서비스신청하기 - - - - SIRK - - - - - - 상점정보 > 계약정보 > 부가정보의 웹결제 signkey생성 조회 버튼 클릭, 팝업창에서 생성 버튼 클릭 후 해당 값을 입력합니다."); ?> - - - - - - - - - - - - - - - - KG 이니시스의 SIRK****** 아이디를 받은 상점만 해당됩니다.", 50); ?> - > - - - - - - - - -
    NICEPAY 신청하기 @@ -1075,14 +789,10 @@ if(!$default['de_kakaopay_cancelpwd']){ 간편결제는 테스트결제가 되지 않습니다. 실결제에만 정상작동 합니다.\n애플페이는 IOS 기기에 모바일결제만 가능합니다."); ?> - >
    - >
    - >
    - >
    - >
    - >
    - >
    - > + $easy_provider) { ?> + > +
    + @@ -1924,7 +1634,7 @@ 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 = "토스페이먼츠(구버전)"; + msg += "(주의!) 토스페이먼츠(구버전) 결제의 결제 설정이 현재 테스트결제로 되어 있습니다.\nMERT KEY를 [테스트]키로 설정한 후 테스트결제를 진행해주세요.\n쇼핑몰 운영중이면 반드시 실결제 전환 및 [라이브]키로 설정하여 운영하셔야 합니다.\n실결제로 변경하려면 결제설정 탭 -> 결제 테스트에서 실결제를 선택해 주세요.\n정말로 테스트결제로 설정하시겠습니까?"; } } 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 ){ @@ -2239,26 +1949,7 @@ if($default['de_iche_use'] || $default['de_vbank_use'] || $default['de_hp_use'] } } - // 카카오페이의 경우 log 디렉토리 체크 - if($default['de_kakaopay_mid'] && $default['de_kakaopay_key'] && $default['de_kakaopay_enckey'] && $default['de_kakaopay_hashkey'] && $default['de_kakaopay_cancelpwd']) { - $log_path = G5_SHOP_PATH.'/kakaopay/log'; - if(!is_dir($log_path)) { - echo ''.PHP_EOL; - } else { - if(!is_writable($log_path)) { - echo ''.PHP_EOL; - } else { - if( function_exists('check_log_folder') && is_writable($log_path) ){ - check_log_folder($log_path); - } - } - } - } } diff --git a/adm/shop_admin/configformupdate.php b/adm/shop_admin/configformupdate.php index f3f263cad..3b0b71986 100644 --- a/adm/shop_admin/configformupdate.php +++ b/adm/shop_admin/configformupdate.php @@ -19,8 +19,8 @@ $logo_img_fields = array('logo_img', 'logo_img2', 'mobile_logo_img', 'mobile_log foreach ($logo_img_fields as $logo_img_field) { if (isset($_FILES[$logo_img_field]['name']) && $_FILES[$logo_img_field]['name']) { $filename = get_safe_filename($_FILES[$logo_img_field]['name']); - if (is_disallowed_svg_filename($filename)) { - alert('허용되지 않는 파일 확장자입니다. (svg, svgz)'); + if (is_disallowed_active_filename($filename)) { + alert('허용되지 않는 파일 확장자입니다.'); } } } @@ -88,15 +88,16 @@ if(isset($_POST['de_taxsave_types_transfer']) && $_POST['de_taxsave_types_transf $de_taxsave_types .= ',transfer'; } -// NHN_KCP 간편결제 체크 -$de_easy_pay_services = ''; -if(isset($_POST['de_easy_pays'])){ - $tmps = array(); - foreach( (array) $_POST['de_easy_pays'] as $v ){ - $tmps[] = preg_replace('/[^0-9a-z_\-]/i', '', $v); - } - $de_easy_pay_services = implode(",", $tmps); +// 알려진 PG별 간편결제 설정만 저장한다. 선택 해제도 명시적으로 보존한다. +$easy_allowed = array('global_nhnkcp_naverpay', 'used_nhnkcp_naverpay_point'); +foreach (array('kcp', 'inicis', 'toss', 'nicepay') as $easy_pg) { + $easy_allowed = array_merge($easy_allowed, array_keys(shop_easypay_catalog($easy_pg))); } +$easy_selected = array(); +foreach (isset($_POST['de_easy_pays']) ? (array) $_POST['de_easy_pays'] : array() as $easy_key) { + if (is_string($easy_key) && in_array($easy_key, $easy_allowed, true)) $easy_selected[] = $easy_key; +} +$de_easy_pay_services = implode(',', array_unique(array_merge($easy_selected, array('inicis_configured', 'toss_configured')))); //KVE-2019-0689, KVE-2019-0691, KVE-2019-0694 $check_sanitize_keys = array( @@ -189,11 +190,6 @@ $check_sanitize_keys = array( 'de_inicis_cartpoint_use', //KG이니시스 신용카드 포인트 결제 'de_nicepay_mid', //NICEPAY 상점아이디 'de_nicepay_key', //NICEPAY 상점키 -'de_kakaopay_mid', //카카오페이 상점MID -'de_kakaopay_key', //카카오페이 상점키 -'de_kakaopay_enckey', //카카오페이 상점 EncKey -'de_kakaopay_hashkey', //카카오페이 상점 HashKey -'de_kakaopay_cancelpwd', //카카오페이 결제취소 비밀번호 'de_naverpay_mid', //네이버페이 가맹점 아이디 'de_naverpay_cert_key', //네이버페이 가맹점 인증키 'de_naverpay_button_key', //네이버페이 버튼 인증키 @@ -269,6 +265,11 @@ foreach( $check_sanitize_keys as $key ){ } } +// 구버전 결제 코드 및 기존 스킨과의 호환을 위해 개별 컬럼도 동기화한다. +foreach (shop_easypay_legacy_keys() as $easy_key => $legacy_key) { + $$legacy_key = (int) in_array($easy_key, $easy_selected, true); +} + $de_inicis_pro_use = !empty($de_inicis_pro_use) ? 1 : 0; $de_inicis_hash_key = preg_replace('/[^A-Za-z0-9+\/=_-]/', '', $de_inicis_hash_key); @@ -300,11 +301,6 @@ if($de_pg_service == 'kcp' && ! $de_card_test && ($de_iche_use || $de_vbank_use alert('NHN KCP SITE KEY를 입력해 주십시오.'); } -if( $de_kakaopay_enckey && ($de_pg_service === 'inicis' || $de_inicis_lpay_use || $de_inicis_kakaopay_use) ){ - - $warning_msg = 'KG 이니시스 결제 또는 L.pay 또는 KG이니시스 카카오페이를 사용시 결제모듈 중복문제로 카카오페이를 활성화 할수 없습니다. \\n\\n카카오페이 사용을 비활성화 합니다.'; - $de_kakaopay_enckey = ''; -} // // 영카트 default @@ -481,11 +477,6 @@ $sql = " update {$g5['g5_shop_default_table']} de_hp_use = '{$de_hp_use}', de_escrow_use = '{$de_escrow_use}', de_tax_flag_use = '{$de_tax_flag_use}', - de_kakaopay_mid = '{$de_kakaopay_mid}', - de_kakaopay_key = '{$de_kakaopay_key}', - de_kakaopay_enckey = '{$de_kakaopay_enckey}', - de_kakaopay_hashkey = '{$de_kakaopay_hashkey}', - de_kakaopay_cancelpwd = '{$de_kakaopay_cancelpwd}', de_member_reg_coupon_use = '{$de_member_reg_coupon_use}', de_member_reg_coupon_term = '{$de_member_reg_coupon_term}', de_member_reg_coupon_price = '{$de_member_reg_coupon_price}', diff --git a/adm/shop_admin/date_filter.lib.php b/adm/shop_admin/date_filter.lib.php new file mode 100644 index 000000000..d7dc3f966 --- /dev/null +++ b/adm/shop_admin/date_filter.lib.php @@ -0,0 +1,26 @@ + $params['to_date']) { + return false; + } + + return array($params['fr_date'], $params['to_date']); +} diff --git a/adm/shop_admin/inorderformupdate.php b/adm/shop_admin/inorderformupdate.php index 06504776c..02b611cfc 100644 --- a/adm/shop_admin/inorderformupdate.php +++ b/adm/shop_admin/inorderformupdate.php @@ -30,6 +30,9 @@ if($w == 'd') { // 주문정보 $data = unserialize(base64_decode($od['dt_data'])); +if (isset($data['od_settle_case']) && $data['od_settle_case'] === 'KAKAOPAY') { + alert('SIRK 전용 카카오페이 미완료 주문은 결제 상태를 이니시스에서 확인한 뒤 사후지원 담당자에게 문의해 주십시오.'); +} $data_od_cp_id = isset($data['od_cp_id']) ? safe_replace_regex($data['od_cp_id'], 'cp_id') : ''; $data_sc_cp_id = isset($data['sc_cp_id']) ? safe_replace_regex($data['sc_cp_id'], 'cp_id') : ''; @@ -210,8 +213,6 @@ if($default['de_tax_flag_use']) { } $od_pg = $default['de_pg_service']; -if($data['od_settle_case'] == 'KAKAOPAY') - $od_pg = 'KAKAOPAY'; $od_email = get_email_address($data['od_email']); $od_name = addslashes(clean_xss_tags($data['od_name'])); diff --git a/adm/shop_admin/itemeventform.php b/adm/shop_admin/itemeventform.php index a12967713..898a97796 100644 --- a/adm/shop_admin/itemeventform.php +++ b/adm/shop_admin/itemeventform.php @@ -73,10 +73,6 @@ for ($i=0; $row=sql_fetch_array($result); $i++) } // 모바일 1줄당 이미지수 필드 추가 -if(!sql_query(" select ev_mobile_list_row from {$g5['g5_shop_event_table']} limit 1 ", false)) { - sql_query(" ALTER TABLE `{$g5['g5_shop_event_table']}` - ADD `ev_mobile_list_row` int(11) NOT NULL DEFAULT '0' AFTER `ev_mobile_list_mod` ", true); -} include_once (G5_ADMIN_PATH.'/admin.head.php'); ?> @@ -455,4 +451,4 @@ function feventform_check(f)
  • 상품분류
  • @@ -199,17 +183,8 @@ $pg_anchor =' diff --git a/tests/admin_date_filter.js b/tests/admin_date_filter.js new file mode 100644 index 000000000..694fe6512 --- /dev/null +++ b/tests/admin_date_filter.js @@ -0,0 +1,48 @@ +// 실행: node tests/admin_date_filter.js (playwright 필요, 실제 서버·DB 연결 없음) +const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright'); +const { execFileSync } = require('node:child_process'); +const path = require('node:path'); +const assert = require('node:assert/strict'); +(async () => { + const results = JSON.parse(execFileSync('php', [path.join(__dirname, 'admin_date_filter.php'), '--json'], {encoding: 'utf8'})); + const browser = await chromium.launch({headless: true, ...(process.env.CHROME_EXECUTABLE ? {executablePath: process.env.CHROME_EXECUTABLE} : {})}); + try { + for (const [name, result] of Object.entries(results)) { + const page = await browser.newPage(); + await page.route('**/*', route => route.abort()); + await page.setContent('' + result.html + ''); + assert.equal(await page.locator('[autofocus], [onfocus]').count(), 0, name); + assert.equal(await page.evaluate(() => document.documentElement.dataset.g5xss), undefined, name); + if (name.endsWith('-blocked')) { + assert.equal(result.status, 400); + assert.equal(await page.locator('input').count(), 0); + } else { + assert.equal(await page.locator('#fr_date').count(), 1); + assert.equal(await page.locator('#to_date').count(), 1); + if (name.endsWith('-valid')) { + assert.equal(await page.locator('#fr_date').inputValue(), '20240229'); + assert.equal(await page.locator('#to_date').inputValue(), '20240301'); + } + if (name.endsWith('-encoded-output')) { + assert.equal(await page.locator('#fr_date').inputValue(), '1" autofocus onfocus=document.documentElement.dataset.g5xss=1 x="'); + await page.locator('#fr_date').focus(); + await page.locator('#to_date').focus(); + assert.equal(await page.evaluate(() => document.documentElement.dataset.g5xss), undefined); + } + for (const url of await page.locator('a[href*="page="]').evaluateAll(links => links.map(a => a.getAttribute('href')))) { + const query = new URL(url, 'https://example.invalid').searchParams; + assert.equal(query.has('amp;fr_date'), false); + if (name.endsWith('-initial')) assert.equal(query.has('fr_date') || query.has('to_date'), false); + if (name.endsWith('-valid')) { + assert.equal(query.get('fr_date'), '20240229'); + assert.equal(query.get('to_date'), '20240301'); + } + } + } + await page.close(); + } + console.log('보관함·판매순위 Chromium 속성 주입 차단·날짜 출력·링크 검증 통과'); + } finally { + await browser.close(); + } +})().catch(error => {console.error(error); process.exitCode = 1;}); diff --git a/tests/admin_date_filter.php b/tests/admin_date_filter.php new file mode 100644 index 000000000..d4fe88b7f --- /dev/null +++ b/tests/admin_date_filter.php @@ -0,0 +1,124 @@ +";'); +file_put_contents($fixture.'/admin.tail.php', ' 'wish', 'g5_shop_item_table' => 'item', 'g5_shop_category_table' => 'category', 'g5_shop_cart_table' => 'cart'); + $config = array('cf_page_rows' => 10, 'cf_mobile_pages' => 5, 'cf_write_pages' => 5); + $auth = array(); $page = isset($params['page']) ? (int) $params['page'] : 1; + $_GET = array(); + foreach ($params as $key => $value) $_GET[$key] = is_string($value) ? sql_escape_string($value) : $value; + $_SERVER['SCRIPT_NAME'] = '/adm/shop_admin/'.$name.'.php'; + $GLOBALS['date_test_queries'] = array(); + $GLOBALS['date_test_auth'] = null; + http_response_code(200); + $cwd = getcwd(); chdir($fixture); ob_start(); + try { include $root.'/adm/shop_admin/'.$name.'.php'; } + catch (InvalidArgumentException $e) { echo '조회 기간 오류'; } + finally { $html = ob_get_clean(); chdir($cwd); } + return array('html' => $html, 'status' => http_response_code(), 'queries' => $GLOBALS['date_test_queries'], 'auth' => $GLOBALS['date_test_auth']); +} + +$bad_dates = array( + '1" autofocus onfocus=document.documentElement.dataset.g5xss=1 x="', + "1' onfocus=alert(1)", '20260909" onfocus="alert(1)', '20260909\\', '1', + '', '20260229', '20260431', '20261301', '20260001', '20260900', '00000101', '2026099', '202609090', + "20260909\n", "20260909\r\n", ' 20260909', '20260909 ', '20260909', '2026-09-09', + array('20260909'), array(array('x')), null, 20260909, true +); +$results = array(); +foreach (array('wishlist' => '500140', 'itemsellrank' => '500100') as $name => $menu) { + foreach (array('fr_date', 'to_date') as $field) { + foreach ($bad_dates as $i => $bad) { + $params = array('fr_date' => '20260101', 'to_date' => '20261231'); $params[$field] = $bad; + $result = render_date_report($name, $params); + expect_date($result['status'] === 400 && !$result['queries'], $name.' '.$field.' 잘못된 입력 '.$i); + expect_date(strpos($result['html'], ' '20260909'), array('to_date' => '20260909'), array('fr_date' => '', 'to_date' => ''), array('fr_date' => '20260910', 'to_date' => '20260909')) as $params) { + $result = render_date_report($name, $params); + expect_date($result['status'] === 400 && !$result['queries'], '누락·빈값·역전 범위 거부'); + } + $initial = render_date_report($name, array()); + expect_date($initial['status'] === 200 && count($initial['queries']) === 3, '최초 전체 조회 유지'); + expect_date(strpos(implode('', $initial['queries']), 'between') === false, '최초 조회 기간 조건 없음'); + $results[$name.'-initial'] = $initial; + $sort = $name === 'wishlist' ? 'wi_time' : 'ct_status_1'; + $valid = render_date_report($name, array('fr_date' => '20240229', 'to_date' => '20240301', 'sort1' => $sort, 'sort2' => 'asc', 'sel_ca_id' => '10')); + expect_date($valid['status'] === 200, '윤년 정상 범위'); + expect_date(strpos($valid['queries'][0], "between '2024-02-29 00:00:00' and '2024-03-01 23:59:59'") !== false, '정상 SQL 기간'); + foreach (array('initial' => $initial, 'valid' => $valid) as $kind => $result) { + preg_match_all('/href="([^"]+)"/', $result['html'], $links); + $paging_count = 0; + foreach ($links[1] as $link) { + $url = html_entity_decode($link, ENT_QUOTES, 'UTF-8'); + parse_str((string) parse_url($url, PHP_URL_QUERY), $params); + if (!isset($params['page'])) continue; + $paging_count++; + expect_date(!isset($params['amp;fr_date']), 'URL 중복 인코딩 없음'); + if ($kind === 'initial') expect_date(!isset($params['fr_date']) && !isset($params['to_date']), '최초 조회 링크에 빈 날짜 없음'); + else expect_date($params['fr_date'] === '20240229' && $params['to_date'] === '20240301' && $params['sel_ca_id'] === '10', '검색·분류 유지'); + $next = render_date_report($name, $params); + expect_date($next['status'] === 200, '정렬·페이지 이동 재조회 성공'); + } + expect_date($paging_count >= 2, '실제 페이지 링크 검증'); + } + $results[$name.'-valid'] = $valid; + // 검증 단계가 우회되더라도 실제 input 출력의 속성 인코딩이 동작하는지 확인한다. + $fr_date = $to_date = $bad_dates[0]; + preg_match_all('/
  • ') === 0) === $mobile, 'PC/모바일 마크업'); + check(strpos($html, 'data-pay="'.shop_easypay_catalog($pg)[$key][1].'"') !== false, '요청 provider'); + } + check(strpos(implode('', $buttons), 'KPAY') === false, '범용 KPAY 중복 제거'); + } + $default['de_easy_pay_use'] = 0; + check(!shop_easypay_buttons(), '간편결제 전체 비활성'); +} +$default = settings('kcp', 'global_nhnkcp_naverpay'); +check(!shop_easypay_buttons(), '병용 설정이 KCP 기본 네이버페이로 오인되지 않음'); +$default = settings('lg', 'global_nhnkcp_naverpay,used_nhnkcp_naverpay_point', 0); +check(count(shop_easypay_buttons(true)) === 2, '병용 카드/머니 독립 노출'); +$default = settings('inicis', 'inicis_samsungpay'); +$default['de_inicis_pro_use'] = 0; +check(!shop_easypay_buttons(false) && count(shop_easypay_buttons(true)) === 1, '구 INIpay 삼성페이 모바일 제한'); +$default = settings('toss', 'toss_configured,toss_applepay'); +check(!shop_easypay_buttons(false) && count(shop_easypay_buttons(true)) === 1, '애플페이 iOS 모바일'); +$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Linux; Android 14)'; +check(!shop_easypay_buttons(true), 'Android 애플페이 숨김'); +$old = array('de_pg_service' => 'inicis', 'de_easy_pay_use' => 0, 'de_inicis_lpay_use' => 1); +$new = shop_easypay_normalize($old); +check($new['de_easy_pay_use'] && strpos($new['de_easy_pay_services'], 'inicis_lpay') !== false, '기존 이니시스 설정 승계'); +$old['de_easy_pay_services'] = 'inicis_configured'; +check(!shop_easypay_normalize($old)['de_inicis_lpay_use'], '명시적 선택 해제 유지'); +$default = settings('toss', ''); +check(isset(shop_easypay_buttons()['toss_payco']), '기존 토스 PAYCO 승계'); +$default = settings('toss', 'toss_configured'); +check(!shop_easypay_buttons(), '토스 전체 선택 해제 유지'); + +// 실제 승인 성공 처리 블록에 카드 없는 머니 결제와 복합결제 응답을 투입한다. +$source = file_get_contents(dirname(__DIR__).'/shop/toss/toss_result.php'); +$start = strpos($source, ' // 공통 DB처리 변수 설정'); +$end = strpos($source, "\n } else {", $start); +$code = substr($source, $start, $end - $start); +foreach (array(false, true) as $with_card) { + $method = '간편결제'; + $toss = (object) array('easyPayCode' => array('NAVERPAY' => '네이버페이'), 'responseData' => array( + 'paymentKey' => 'fixture-key', 'totalAmount' => 10000, 'useEscrow' => false, 'approvedAt' => '2026-09-09T12:00:00+09:00', + 'easyPay' => array('provider' => 'NAVERPAY', 'amount' => 4000, 'discountAmount' => 1000), + 'cashReceipt' => array('type' => '소득공제', 'receiptKey' => 'receipt', 'issueNumber' => '123', 'receiptUrl' => 'https://example.test/receipt'))); + if ($with_card) $toss->responseData['card'] = array('approveNo' => '456', 'amount' => 5000); + $pg_receipt_infos = array(); + eval($code); + check($amount === 10000 && $card_name === '네이버페이', '총 승인금액과 provider 유지'); + check($app_no === ($with_card ? '456' : ''), '전액 머니/복합결제 승인번호'); + check($pg_receipt_infos['od_cash'] === 1 && $pg_receipt_infos['od_cash_no'] === '123', '간편결제 현금영수증 보존'); +} +echo "PG 간편결제 회귀 테스트 통과\n"; diff --git a/theme/basic/css/default_shop.css b/theme/basic/css/default_shop.css index 76ddaf037..8454f3e50 100644 --- a/theme/basic/css/default_shop.css +++ b/theme/basic/css/default_shop.css @@ -806,11 +806,17 @@ box-shadow: 1px 2px 2px #eee;} #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} -#sod_frm_paysel .bank_icon{background:url('../../../img/pay_icon1.png') no-repeat 15px 50% #fff} -#sod_frm_paysel .vbank_icon{background:url('../../../img/pay_icon2.png') no-repeat 15px 50% #fff} -#sod_frm_paysel .iche_icon{background:url('../../../img/pay_icon2.png') no-repeat 15px 50% #fff} -#sod_frm_paysel .hp_icon{background:url('../../../img/pay_icon3.png') no-repeat 24px 50% #fff} -#sod_frm_paysel .card_icon{background:url('../../../img/pay_icon4.png') no-repeat 17px 50% #fff} +/* 일반 결제수단은 아이콘 없이 텍스트를 표시한다. */ +#sod_frm_paysel .lb_icon.bank_icon, +#sod_frm_paysel .lb_icon.vbank_icon, +#sod_frm_paysel .lb_icon.iche_icon, +#sod_frm_paysel .lb_icon.hp_icon, +#sod_frm_paysel .lb_icon.card_icon{background-image:none;padding:0 12px;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;line-height:18px} +#m_sod_frm_paysel .lb_icon.bank_icon, +#m_sod_frm_paysel .lb_icon.vbank_icon, +#m_sod_frm_paysel .lb_icon.iche_icon, +#m_sod_frm_paysel .lb_icon.hp_icon, +#m_sod_frm_paysel .lb_icon.card_icon{background-image:none;display:inline-block;padding:0;min-height:24px;line-height:24px;vertical-align:middle} #forderform .sod_right #sod_bsk_tot {border:1px solid #e3e5e8} #forderform .od_pay_buttons_el{margin-top:20px;border:1px solid #e3e5e8;background:#fff;padding:10px} #forderform .od_pay_buttons_el h3{font-size:1.167em;margin:0px 0 5px} @@ -1297,3 +1303,51 @@ html.no-overflowscrolling #sc_coupon_frm, html.no-overflowscrolling #od_coupon_f .chk_box input[type="radio"]:checked + label {color:#305af9} .chk_box input[type="radio"]:checked + label span:before {width:7px;height:7px;background:#305af9;content:'';position:absolute;top:3px;left:3px;border-radius:50%} + +/* 간편결제 로고: 작은 원본은 확대하지 않고 큰 로고만 축소한다. */ +#sod_frm_paysel .lb_icon.PAYCO:not(.nhnkcp_icon), +#sod_frm_paysel .lb_icon.paycopay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.PAYCO:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.paycopay_icon:not(.nhnkcp_icon){background-image:url('../../../img/payco.png');background-size:59px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.PAYNOW:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.PAYNOW:not(.nhnkcp_icon){background-image:url('../../../img/paynow.png');background-size:48px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.lpay_icon:not(.nhnkcp_icon), +#sod_frm_paysel .lb_icon.inicis_lpay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.lpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.inicis_lpay:not(.nhnkcp_icon){background-image:url('../../../img/lpay_logo.png');background-size:35px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.kakaopay_icon:not(.nhnkcp_icon), +#sod_frm_paysel .lb_icon.inicis_kakaopay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.kakaopay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.inicis_kakaopay:not(.nhnkcp_icon){background-image:url('../../../img/kakao.png');background-size:43px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.naverpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.naverpay_icon:not(.nhnkcp_icon){background-image:url('../../../img/ico-default-naverpay.png');background-size:42px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.samsungpay_icon:not(.nhnkcp_icon), +#sod_frm_paysel .lb_icon.samsung_pay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.samsungpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.samsung_pay:not(.nhnkcp_icon){background-image:url('../../../img/samsungpay.png');background-size:72px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.ssgpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.ssgpay_icon:not(.nhnkcp_icon){background-image:url('../../../img/ssgpay_icon.png');background-size:64px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.skpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.skpay_icon:not(.nhnkcp_icon){background-image:url('../../../img/skpay11_icon.png');background-size:46px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.applepay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.applepay_icon:not(.nhnkcp_icon){background-image:url('../../../img/ico-mobile-applepay.png');background-size:32px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.tosspay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.tosspay_icon:not(.nhnkcp_icon){background-image:url('../../../img/tosspay-logo.svg');background-size:72px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.pinpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.pinpay_icon:not(.nhnkcp_icon){background-image:url('../../../img/pinpay-logo.png');background-size:60px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#m_sod_frm_paysel .lb_icon.PAYCO:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.paycopay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.PAYNOW:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.lpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.inicis_lpay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.kakaopay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.inicis_kakaopay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.naverpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.samsungpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.samsung_pay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.ssgpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.skpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.applepay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.tosspay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.pinpay_icon:not(.nhnkcp_icon){width:96px;height:28px;min-height:28px;margin:0;padding:0;border-radius:0;display:inline-block;vertical-align:middle} +#sod_frm_paysel .lb_icon.inicis_kakaopay em{display:none} diff --git a/theme/basic/css/mobile_shop.css b/theme/basic/css/mobile_shop.css index 471d8853b..b1e82507e 100644 --- a/theme/basic/css/mobile_shop.css +++ b/theme/basic/css/mobile_shop.css @@ -918,11 +918,17 @@ box-shadow:0 0 8px rgba(65,98,255,0.8)} #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} -#sod_frm_paysel .bank_icon{background:url('../../../img/pay_icon1.png') no-repeat 15px 50% #fff} -#sod_frm_paysel .vbank_icon{background:url('../../../img/pay_icon2.png') no-repeat 15px 50% #fff} -#sod_frm_paysel .iche_icon{background:url('../../../img/pay_icon2.png') no-repeat 15px 50% #fff} -#sod_frm_paysel .hp_icon{background:url('../../../img/pay_icon3.png') no-repeat 24px 50% #fff} -#sod_frm_paysel .card_icon{background:url('../../../img/pay_icon4.png') no-repeat 17px 50% #fff} +/* 일반 결제수단은 아이콘 없이 텍스트를 표시한다. */ +#sod_frm_paysel .lb_icon.bank_icon, +#sod_frm_paysel .lb_icon.vbank_icon, +#sod_frm_paysel .lb_icon.iche_icon, +#sod_frm_paysel .lb_icon.hp_icon, +#sod_frm_paysel .lb_icon.card_icon{background-image:none;padding:0 12px;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;line-height:18px} +#m_sod_frm_paysel .lb_icon.bank_icon, +#m_sod_frm_paysel .lb_icon.vbank_icon, +#m_sod_frm_paysel .lb_icon.iche_icon, +#m_sod_frm_paysel .lb_icon.hp_icon, +#m_sod_frm_paysel .lb_icon.card_icon{background-image:none;display:inline-block;padding:0;min-height:24px;line-height:24px;vertical-align:middle} #forderform .sod_right #sod_bsk_tot {border:1px solid #e3e5e8} #forderform .od_pay_buttons_el{margin-top:20px;border:1px solid #e3e5e8;background:#fff;padding:10px} #forderform .od_pay_buttons_el h3{font-size:1.167em;margin:0px 0 5px} @@ -1037,3 +1043,51 @@ box-shadow:0 0 8px rgba(65,98,255,0.8)} .chk_box input[type="radio"]:checked + label {color:#305af9} .chk_box input[type="radio"]:checked + label span:before {width:7px;height:7px;background:#305af9;content:'';position:absolute;top:3px;left:3px;border-radius:50%} + +/* 간편결제 로고: 작은 원본은 확대하지 않고 큰 로고만 축소한다. */ +#sod_frm_paysel .lb_icon.PAYCO:not(.nhnkcp_icon), +#sod_frm_paysel .lb_icon.paycopay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.PAYCO:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.paycopay_icon:not(.nhnkcp_icon){background-image:url('../../../img/payco.png');background-size:59px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.PAYNOW:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.PAYNOW:not(.nhnkcp_icon){background-image:url('../../../img/paynow.png');background-size:48px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.lpay_icon:not(.nhnkcp_icon), +#sod_frm_paysel .lb_icon.inicis_lpay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.lpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.inicis_lpay:not(.nhnkcp_icon){background-image:url('../../../img/lpay_logo.png');background-size:35px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.kakaopay_icon:not(.nhnkcp_icon), +#sod_frm_paysel .lb_icon.inicis_kakaopay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.kakaopay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.inicis_kakaopay:not(.nhnkcp_icon){background-image:url('../../../img/kakao.png');background-size:43px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.naverpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.naverpay_icon:not(.nhnkcp_icon){background-image:url('../../../img/ico-default-naverpay.png');background-size:42px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.samsungpay_icon:not(.nhnkcp_icon), +#sod_frm_paysel .lb_icon.samsung_pay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.samsungpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.samsung_pay:not(.nhnkcp_icon){background-image:url('../../../img/samsungpay.png');background-size:72px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.ssgpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.ssgpay_icon:not(.nhnkcp_icon){background-image:url('../../../img/ssgpay_icon.png');background-size:64px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.skpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.skpay_icon:not(.nhnkcp_icon){background-image:url('../../../img/skpay11_icon.png');background-size:46px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.applepay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.applepay_icon:not(.nhnkcp_icon){background-image:url('../../../img/ico-mobile-applepay.png');background-size:32px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.tosspay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.tosspay_icon:not(.nhnkcp_icon){background-image:url('../../../img/tosspay-logo.svg');background-size:72px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#sod_frm_paysel .lb_icon.pinpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.pinpay_icon:not(.nhnkcp_icon){background-image:url('../../../img/pinpay-logo.png');background-size:60px auto;background-repeat:no-repeat;background-position:50% 50%;background-color:#fff;overflow:hidden;text-indent:-999px} +#m_sod_frm_paysel .lb_icon.PAYCO:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.paycopay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.PAYNOW:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.lpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.inicis_lpay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.kakaopay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.inicis_kakaopay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.naverpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.samsungpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.samsung_pay:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.ssgpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.skpay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.applepay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.tosspay_icon:not(.nhnkcp_icon), +#m_sod_frm_paysel .lb_icon.pinpay_icon:not(.nhnkcp_icon){width:96px;height:28px;min-height:28px;margin:0;padding:0;border-radius:0;display:inline-block;vertical-align:middle} +#sod_frm_paysel .lb_icon.inicis_kakaopay em{display:none} diff --git a/theme/basic/mobile/skin/shop/basic/listcategory.skin.php b/theme/basic/mobile/skin/shop/basic/listcategory.skin.php index 7f0213773..ddd995594 100644 --- a/theme/basic/mobile/skin/shop/basic/listcategory.skin.php +++ b/theme/basic/mobile/skin/shop/basic/listcategory.skin.php @@ -6,15 +6,23 @@ $exists = false; $ca_id_len = strlen($ca_id); $len2 = $ca_id_len + 2; -$len4 = $ca_id_len + 4; $sql = " select ca_id, ca_name from {$g5['g5_shop_category_table']} where ca_id like '$ca_id%' and length(ca_id) = $len2 and ca_use = '1' order by ca_order, ca_id "; $result = sql_query($sql); + +// 하위 분류가 없으면 현재 분류를 포함한 같은 단계의 사용 중인 분류를 표시한다. +if (!sql_num_rows($result)) { + $parent_ca_id = substr($ca_id, 0, -2); + $sql = " select ca_id, ca_name from {$g5['g5_shop_category_table']} where ca_id like '$parent_ca_id%' and length(ca_id) = $ca_id_len and ca_use = '1' order by ca_order, ca_id "; + $result = sql_query($sql); +} + while ($row=sql_fetch_array($result)) { $row2 = sql_fetch(" select count(*) as cnt from {$g5['g5_shop_item_table']} where (ca_id like '{$row['ca_id']}%' or ca_id2 like '{$row['ca_id']}%' or ca_id3 like '{$row['ca_id']}%') and it_use = '1' "); - $str .= '
  • '.$row['ca_name'].' '.$row2['cnt'].'
  • '; + $current_attr = ($row['ca_id'] === $ca_id) ? ' class="sct_ct_here" aria-current="page"' : ''; + $str .= '
  • '.$row['ca_name'].' '.$row2['cnt'].'
  • '; $exists = true; } diff --git a/theme/basic/shop/orderinquiryview.php b/theme/basic/shop/orderinquiryview.php index b081888bd..bee39d2f1 100644 --- a/theme/basic/shop/orderinquiryview.php +++ b/theme/basic/shop/orderinquiryview.php @@ -594,7 +594,9 @@ if($od['od_pg'] == 'lg') { 이 주문의 취소·환불은 쇼핑몰 고객센터에 문의해 주십시오.

    '; + } elseif ($custom_cancel) { ?>
    diff --git a/theme/basic/skin/shop/basic/listcategory.skin.php b/theme/basic/skin/shop/basic/listcategory.skin.php index a7a3b4208..6f1ad0d40 100644 --- a/theme/basic/skin/shop/basic/listcategory.skin.php +++ b/theme/basic/skin/shop/basic/listcategory.skin.php @@ -6,15 +6,23 @@ $exists = false; $ca_id_len = strlen($ca_id); $len2 = $ca_id_len + 2; -$len4 = $ca_id_len + 4; $sql = " select ca_id, ca_name from {$g5['g5_shop_category_table']} where ca_id like '$ca_id%' and length(ca_id) = $len2 and ca_use = '1' order by ca_order, ca_id "; $result = sql_query($sql); + +// 하위 분류가 없으면 현재 분류를 포함한 같은 단계의 사용 중인 분류를 표시한다. +if (!sql_num_rows($result)) { + $parent_ca_id = substr($ca_id, 0, -2); + $sql = " select ca_id, ca_name from {$g5['g5_shop_category_table']} where ca_id like '$parent_ca_id%' and length(ca_id) = $ca_id_len and ca_use = '1' order by ca_order, ca_id "; + $result = sql_query($sql); +} + while ($row=sql_fetch_array($result)) { $row2 = sql_fetch(" select count(*) as cnt from {$g5['g5_shop_item_table']} where (ca_id like '{$row['ca_id']}%' or ca_id2 like '{$row['ca_id']}%' or ca_id3 like '{$row['ca_id']}%') and it_use = '1' "); - $str .= '
  • '.$row['ca_name'].' ('.$row2['cnt'].')
  • '; + $current_attr = ($row['ca_id'] === $ca_id) ? ' class="sct_ct_here" aria-current="page"' : ''; + $str .= '
  • '.$row['ca_name'].' ('.$row2['cnt'].')
  • '; $exists = true; } diff --git a/version.php b/version.php index 678a3a8a0..59f29c5fc 100644 --- a/version.php +++ b/version.php @@ -2,7 +2,7 @@ if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가 define('G5_VERSION', '그누보드5'); -define('G5_GNUBOARD_VER', '5.6.36'); +define('G5_GNUBOARD_VER', '5.6.37'); // 그누보드5.4.5.5 버전과 영카트5.4.5.5.1 버전을 합쳐서 그누보드5.4.6 버전에서 시작함 (kagla-210617) // G5_YOUNGCART_VER 이 상수를 사용하는 곳이 있으므로 주석 처리 해제함 // 그누보드5.4.6 이상 버전 부터는 영카트를 그누보드에 포함하여 배포하므로 영카트5의 버전은 의미가 없습니다.