초기 커밋: 5130 레거시 시스템

- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경
- DB 연결 하드코딩 → .env 기반으로 변경
- MySQL strict mode DATE 오류 수정
This commit is contained in:
2025-12-10 20:14:31 +09:00
commit aca1767eb9
6728 changed files with 1863265 additions and 0 deletions

48
opendart/api/detail.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
/**
* Open DART 기업개황 조회 API (프록시 방식)
*
* 멀티테넌시 환경 지원:
* - 클라이언트의 IP가 아닌 서버의 IP로 Open DART API 호출
* - Open DART에 등록된 서버 IP만 사용하므로 여러 클라이언트 지원 가능
*
* 동작 흐름:
* 클라이언트 → 회사 서버 (이 파일) → Open DART API → 회사 서버 → 클라이언트
*/
header('Content-Type: application/json; charset=utf-8');
// 프록시 헬퍼 함수 로드
require_once __DIR__ . '/proxy_helper.php';
$corp_code = isset($_GET['corp_code']) ? trim($_GET['corp_code']) : '';
if (empty($corp_code)) {
echo json_encode(['status' => 'error', 'message' => 'Corp Code is required.']);
exit;
}
// 프록시를 통해 Open DART API 호출
$result = callOpenDartAPI('company.json', [
'corp_code' => $corp_code
], null, [
'timeout' => 30,
'return_type' => 'raw' // Open DART의 JSON 응답을 그대로 반환
]);
if (!$result['success']) {
// Open DART의 원본 응답 형식 유지
if ($result['raw_response']) {
echo $result['raw_response'];
} else {
echo json_encode([
'status' => 'error',
'message' => $result['error']
]);
}
exit;
}
// Open DART의 원본 JSON 응답을 그대로 반환
echo $result['raw_response'];
?>

View File

@@ -0,0 +1,82 @@
<?php
/**
* Open DART 재무제표 조회 API (프록시 방식)
*
* 특정 기업의 재무제표 정보를 조회합니다.
*
* 파라미터:
* - corp_code: 기업코드 (필수)
* - bsns_year: 사업연도 (YYYY 형식, 필수)
* - reprt_code: 보고서 코드 (11013: 1분기, 11012: 반기, 11014: 3분기, 11011: 사업보고서)
* - fs_div: 재무제표 구분 (CFS: 연결, OFS: 별도)
*
* 사용 예시:
* /api/financial_statement.php?corp_code=00126380&bsns_year=2023&reprt_code=11011&fs_div=CFS
*/
header('Content-Type: application/json; charset=utf-8');
// 프록시 헬퍼 함수 로드
require_once __DIR__ . '/proxy_helper.php';
$corp_code = isset($_GET['corp_code']) ? trim($_GET['corp_code']) : '';
$bsns_year = isset($_GET['bsns_year']) ? trim($_GET['bsns_year']) : '';
$reprt_code = isset($_GET['reprt_code']) ? trim($_GET['reprt_code']) : '11011'; // 기본값: 사업보고서
$fs_div = isset($_GET['fs_div']) ? trim($_GET['fs_div']) : 'CFS'; // 기본값: 연결
if (empty($corp_code)) {
echo json_encode(['status' => 'error', 'message' => 'Corp Code is required.']);
exit;
}
if (empty($bsns_year)) {
echo json_encode(['status' => 'error', 'message' => 'Business Year (bsns_year) is required.']);
exit;
}
// 파라미터 구성
$params = [
'corp_code' => $corp_code,
'bsns_year' => $bsns_year,
'reprt_code' => $reprt_code,
'fs_div' => $fs_div
];
// 프록시를 통해 Open DART API 호출
$result = callOpenDartAPI('fnlttSinglAcnt.json', $params, null, [
'timeout' => 30,
'return_type' => 'raw' // Open DART의 JSON 응답을 그대로 반환
]);
if (!$result['success']) {
// Open DART의 원본 응답 형식 유지
if (isset($result['raw_response']) && !empty($result['raw_response'])) {
echo $result['raw_response'];
} else {
// 에러 응답 형식을 Open DART 형식에 맞춤
echo json_encode([
'status' => '013',
'message' => $result['error'] || '재무제표 조회 중 오류가 발생했습니다.',
'status_nm' => 'ERROR'
], JSON_UNESCAPED_UNICODE);
}
exit;
}
// Open DART의 원본 JSON 응답을 그대로 반환
if (isset($result['raw_response']) && !empty($result['raw_response'])) {
echo $result['raw_response'];
} else {
// raw_response가 없는 경우 data 사용
if (isset($result['data'])) {
echo json_encode($result['data'], JSON_UNESCAPED_UNICODE);
} else {
echo json_encode([
'status' => '013',
'message' => '재무제표 데이터를 가져올 수 없습니다.',
'status_nm' => 'ERROR'
], JSON_UNESCAPED_UNICODE);
}
}
?>

View File

@@ -0,0 +1,70 @@
<?php
/**
* Open DART 공시목록 조회 API (프록시 방식)
*
* 특정 기업의 공시 목록을 조회합니다.
*
* 파라미터:
* - corp_code: 기업코드 (필수)
* - bgn_de: 시작일자 (YYYYMMDD 형식, 선택)
* - end_de: 종료일자 (YYYYMMDD 형식, 선택)
* - page_no: 페이지 번호 (기본값: 1)
* - page_count: 페이지당 건수 (기본값: 100)
*
* 사용 예시:
* /api/list_disclosures.php?corp_code=00126380&bgn_de=20240101&end_de=20241231
*/
header('Content-Type: application/json; charset=utf-8');
// 프록시 헬퍼 함수 로드
require_once __DIR__ . '/proxy_helper.php';
$corp_code = isset($_GET['corp_code']) ? trim($_GET['corp_code']) : '';
$bgn_de = isset($_GET['bgn_de']) ? trim($_GET['bgn_de']) : '';
$end_de = isset($_GET['end_de']) ? trim($_GET['end_de']) : '';
$page_no = isset($_GET['page_no']) ? intval($_GET['page_no']) : 1;
$page_count = isset($_GET['page_count']) ? intval($_GET['page_count']) : 100;
if (empty($corp_code)) {
echo json_encode(['status' => 'error', 'message' => 'Corp Code is required.']);
exit;
}
// 파라미터 구성
$params = [
'corp_code' => $corp_code,
'page_no' => $page_no,
'page_count' => $page_count
];
if (!empty($bgn_de)) {
$params['bgn_de'] = $bgn_de;
}
if (!empty($end_de)) {
$params['end_de'] = $end_de;
}
// 프록시를 통해 Open DART API 호출
$result = callOpenDartAPI('list.json', $params, null, [
'timeout' => 30,
'return_type' => 'raw' // Open DART의 JSON 응답을 그대로 반환
]);
if (!$result['success']) {
// Open DART의 원본 응답 형식 유지
if ($result['raw_response']) {
echo $result['raw_response'];
} else {
echo json_encode([
'status' => 'error',
'message' => $result['error']
]);
}
exit;
}
// Open DART의 원본 JSON 응답을 그대로 반환
echo $result['raw_response'];
?>

View File

@@ -0,0 +1,184 @@
<?php
/**
* Open DART API Proxy Helper
*
* 멀티테넌시 환경을 위한 프록시 함수
* 클라이언트의 IP 대신 서버의 IP로 Open DART API를 호출하여
* IP 화이트리스트 제한을 우회합니다.
*
* 동작 방식:
* 1. 클라이언트 요청 → 회사 서버 (이 파일)
* 2. 회사 서버 → Open DART API (등록된 IP로 호출)
* 3. Open DART 응답 → 회사 서버
* 4. 회사 서버 → 클라이언트
*/
/**
* Open DART API를 프록시를 통해 호출
*
* @param string $endpoint Open DART API 엔드포인트 (예: 'company.json', 'corpCode.xml')
* @param array $params API 파라미터 배열
* @param string $apiKey Open DART API 키 (null이면 기본 파일에서 로드)
* @param array $options 추가 옵션 (timeout, method 등)
* @return array ['success' => bool, 'data' => mixed, 'error' => string]
*/
function callOpenDartAPI($endpoint, $params = [], $apiKey = null, $options = []) {
// API Key 로드
if ($apiKey === null) {
$apiKeyPath = $_SERVER['DOCUMENT_ROOT'] . '/apikey/opendart.txt';
if (!file_exists($apiKeyPath)) {
return [
'success' => false,
'data' => null,
'error' => 'API Key file not found.'
];
}
$apiKey = trim(file_get_contents($apiKeyPath));
}
if (empty($apiKey)) {
return [
'success' => false,
'data' => null,
'error' => 'API Key is empty.'
];
}
// 기본 옵션
$defaultOptions = [
'timeout' => 30,
'method' => 'GET',
'return_type' => 'json', // 'json' or 'xml' or 'raw'
'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
];
$options = array_merge($defaultOptions, $options);
// 파라미터에 API 키 추가
$params['crtfc_key'] = $apiKey;
// URL 구성
$baseUrl = 'https://opendart.fss.or.kr/api/';
$url = $baseUrl . $endpoint;
if ($options['method'] === 'GET' && !empty($params)) {
$url .= '?' . http_build_query($params);
}
// cURL 설정
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, $options['timeout']);
curl_setopt($ch, CURLOPT_USERAGENT, $options['user_agent']);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
// POST 요청 처리 (필요한 경우)
if ($options['method'] === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
}
// 실행
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
$effectiveUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close($ch);
// 에러 처리
if ($httpCode !== 200 || !$response) {
$errorMsg = 'Failed to fetch data from Open DART.';
if ($curlError) {
$errorMsg .= ' cURL Error: ' . $curlError;
}
if ($httpCode) {
$errorMsg .= ' HTTP Code: ' . $httpCode;
}
// IP 접근 오류 체크
if ($response && (strpos($response, '접근할 수 없는 IP') !== false || strpos($response, 'Inaccessible IP') !== false)) {
$xml = @simplexml_load_string($response);
if ($xml && isset($xml->message)) {
$errorMsg = 'IP 접근 오류: ' . (string)$xml->message;
}
}
return [
'success' => false,
'data' => null,
'error' => $errorMsg,
'http_code' => $httpCode,
'raw_response' => $response
];
}
// 응답 처리
$data = $response;
if ($options['return_type'] === 'json') {
$decoded = json_decode($response, true);
if ($decoded !== null) {
$data = $decoded;
}
} elseif ($options['return_type'] === 'xml') {
$xml = @simplexml_load_string($response);
if ($xml !== false) {
$data = $xml;
}
}
return [
'success' => true,
'data' => $data,
'error' => null,
'http_code' => $httpCode,
'raw_response' => $response
];
}
/**
* 서버의 공인 IP 확인
*
* @return string 공인 IP 주소
*/
function getServerPublicIP() {
// Try multiple methods to get public IP
$ipServices = [
'https://api.ipify.org',
'https://checkip.amazonaws.com',
'https://icanhazip.com',
'https://ifconfig.me/ip'
];
foreach ($ipServices as $service) {
$ch = curl_init($service);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$ip = trim(curl_exec($ch));
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
// Fallback: try to get from $_SERVER
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[0]);
if (filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
if (!empty($_SERVER['REMOTE_ADDR'])) {
return $_SERVER['REMOTE_ADDR'];
}
return 'Unknown';
}
?>

51
opendart/api/search.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
header('Content-Type: application/json; charset=utf-8');
$query = isset($_GET['query']) ? trim($_GET['query']) : '';
if (empty($query)) {
echo json_encode(['status' => 'error', 'message' => 'Query is required.']);
exit;
}
$jsonFile = $_SERVER['DOCUMENT_ROOT'] . '/opendart/data/corp_codes.json';
if (!file_exists($jsonFile)) {
echo json_encode(['status' => 'error', 'message' => 'Data not synced. Please click "Sync Data" first.']);
exit;
}
$jsonData = @file_get_contents($jsonFile);
if ($jsonData === false) {
echo json_encode(['status' => 'error', 'message' => 'Failed to read data file. Check file permissions.']);
exit;
}
$corpList = json_decode($jsonData, true);
if ($corpList === null) {
$jsonError = json_last_error_msg();
echo json_encode(['status' => 'error', 'message' => 'Invalid data file. JSON Error: ' . $jsonError]);
exit;
}
if (!is_array($corpList)) {
echo json_encode(['status' => 'error', 'message' => 'Invalid data format. Expected array.']);
exit;
}
$results = [];
$count = 0;
$limit = 50; // Limit results
foreach ($corpList as $corp) {
// Simple case-insensitive search
if (stripos($corp['corp_name'], $query) !== false) {
$results[] = $corp;
$count++;
if ($count >= $limit) break;
}
}
echo json_encode(['status' => 'success', 'results' => $results]);
?>

View File

@@ -0,0 +1,290 @@
<?php
/**
* Open DART 기업코드 동기화 API (프록시 방식)
*
* 멀티테넌시 환경 지원:
* - 클라이언트의 IP가 아닌 서버의 IP로 Open DART API 호출
* - Open DART에 등록된 서버 IP만 사용하므로 여러 클라이언트 지원 가능
*
* 동작 흐름:
* 클라이언트 → 회사 서버 (이 파일) → Open DART API (ZIP 다운로드) → 회사 서버 (압축 해제 및 JSON 변환) → 클라이언트
*/
header('Content-Type: application/json; charset=utf-8');
// 프록시 헬퍼 함수 로드
require_once __DIR__ . '/proxy_helper.php';
// API Key Load
$apiKeyPath = $_SERVER['DOCUMENT_ROOT'] . '/apikey/opendart.txt';
if (!file_exists($apiKeyPath)) {
echo json_encode(['status' => 'error', 'message' => 'API Key file not found.']);
exit;
}
$apiKey = trim(file_get_contents($apiKeyPath));
if (empty($apiKey)) {
echo json_encode(['status' => 'error', 'message' => 'API Key is empty.']);
exit;
}
// Data Directory
$dataDir = $_SERVER['DOCUMENT_ROOT'] . '/opendart/data';
if (!is_dir($dataDir)) {
if (!mkdir($dataDir, 0777, true)) {
echo json_encode(['status' => 'error', 'message' => 'Failed to create data directory.']);
exit;
}
}
// Check if ZipArchive extension is available
if (!class_exists('ZipArchive')) {
echo json_encode(['status' => 'error', 'message' => 'ZipArchive extension is not available. Please enable php_zip extension.']);
exit;
}
// Open DART URL
$url = "https://opendart.fss.or.kr/api/corpCode.xml?crtfc_key=" . $apiKey;
// Download Zip
$zipFile = $dataDir . '/corpCode.zip';
// Remove old zip file if exists
if (file_exists($zipFile)) {
@unlink($zipFile);
}
$fp = @fopen($zipFile, 'w+');
if (!$fp) {
echo json_encode(['status' => 'error', 'message' => 'Failed to create zip file. Check directory permissions.']);
exit;
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 300); // 5 minutes timeout
curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
$effectiveUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close($ch);
fclose($fp);
if ($httpCode !== 200) {
$errorContent = '';
if (file_exists($zipFile)) {
$errorContent = file_get_contents($zipFile);
@unlink($zipFile);
}
// Check if it's an IP access error from Open DART
if ($errorContent && strpos($errorContent, '접근할 수 없는 IP') !== false || strpos($errorContent, 'Inaccessible IP') !== false) {
// Parse XML error response
$xml = @simplexml_load_string($errorContent);
$errorMessage = '';
$reportedIP = '';
if ($xml && isset($xml->message)) {
$errorMessage = (string)$xml->message;
// Extract IP from message if present
if (preg_match('/\(([0-9\.]+)\)/', $errorMessage, $matches)) {
$reportedIP = $matches[1];
}
} else {
$errorMessage = 'IP 접근이 거부되었습니다.';
}
// Get actual server IP
$actualIP = getServerPublicIP();
$ipErrorMsg = "Open DART IP 접근 오류: $errorMessage";
if ($reportedIP) {
$ipErrorMsg .= "\n\nOpen DART에서 감지한 IP: $reportedIP";
}
$ipErrorMsg .= "\n현재 서버의 공인 IP: $actualIP";
$ipErrorMsg .= "\n\n해결 방법:";
$ipErrorMsg .= "\n1. Open DART 홈페이지(https://opendart.fss.or.kr)에 로그인";
$ipErrorMsg .= "\n2. '회원정보 > API 인증키 관리' 메뉴로 이동";
$ipErrorMsg .= "\n3. '사용IP' 항목에 위의 '현재 서버의 공인 IP'를 등록하거나 수정";
$ipErrorMsg .= "\n4. 변경 사항 저장 후 몇 분 대기 후 다시 시도";
echo json_encode([
'status' => 'error',
'message' => $ipErrorMsg,
'error_type' => 'ip_access_denied',
'reported_ip' => $reportedIP,
'actual_ip' => $actualIP
]);
exit;
}
$debugMsg = "HTTP Code: $httpCode";
if ($curlError) {
$debugMsg .= ", cURL Error: $curlError";
}
if ($effectiveUrl) {
$debugMsg .= ", Effective URL: $effectiveUrl";
}
if ($errorContent) {
$debugMsg .= ", Content Preview: " . substr($errorContent, 0, 500);
}
echo json_encode(['status' => 'error', 'message' => 'Failed to download data. ' . $debugMsg]);
exit;
}
// Verify downloaded file
if (!file_exists($zipFile)) {
echo json_encode(['status' => 'error', 'message' => 'Downloaded file does not exist.']);
exit;
}
$fileSize = filesize($zipFile);
if ($fileSize === false || $fileSize < 100) {
// File too small, likely an error message
$errorContent = file_get_contents($zipFile);
@unlink($zipFile);
echo json_encode(['status' => 'error', 'message' => 'Downloaded file is too small or invalid. Content: ' . substr($errorContent, 0, 500)]);
exit;
}
// Check if file is actually a ZIP file (check magic bytes)
$handle = fopen($zipFile, 'rb');
$magicBytes = fread($handle, 4);
fclose($handle);
// ZIP file magic bytes: PK\x03\x04 or PK\x05\x06 (empty zip) or PK\x07\x08
if (substr($magicBytes, 0, 2) !== 'PK') {
$errorContent = file_get_contents($zipFile);
@unlink($zipFile);
// Check if it's an XML error response from Open DART (IP access error)
if (strpos($errorContent, '<?xml') !== false && (strpos($errorContent, '접근할 수 없는 IP') !== false || strpos($errorContent, 'Inaccessible IP') !== false)) {
$xml = @simplexml_load_string($errorContent);
$errorMessage = '';
$reportedIP = '';
if ($xml && isset($xml->message)) {
$errorMessage = (string)$xml->message;
if (preg_match('/\(([0-9\.]+)\)/', $errorMessage, $matches)) {
$reportedIP = $matches[1];
}
} else {
$errorMessage = 'IP 접근이 거부되었습니다.';
}
// Get actual server IP
$actualIP = getServerPublicIP();
$ipErrorMsg = "Open DART IP 접근 오류: $errorMessage";
if ($reportedIP) {
$ipErrorMsg .= "\n\nOpen DART에서 감지한 IP: $reportedIP";
}
$ipErrorMsg .= "\n현재 서버의 공인 IP: $actualIP";
$ipErrorMsg .= "\n\n해결 방법:";
$ipErrorMsg .= "\n1. Open DART 홈페이지(https://opendart.fss.or.kr)에 로그인";
$ipErrorMsg .= "\n2. '회원정보 > API 인증키 관리' 메뉴로 이동";
$ipErrorMsg .= "\n3. '사용IP' 항목에 위의 '현재 서버의 공인 IP'를 등록하거나 수정";
$ipErrorMsg .= "\n4. 변경 사항 저장 후 몇 분 대기 후 다시 시도";
echo json_encode([
'status' => 'error',
'message' => $ipErrorMsg,
'error_type' => 'ip_access_denied',
'reported_ip' => $reportedIP,
'actual_ip' => $actualIP
]);
exit;
}
echo json_encode(['status' => 'error', 'message' => 'Downloaded file is not a valid ZIP file. Content: ' . substr($errorContent, 0, 500)]);
exit;
}
// Unzip
$zip = new ZipArchive;
$zipResult = $zip->open($zipFile);
if ($zipResult !== TRUE) {
$errorMessages = [
ZipArchive::ER_OK => 'No error',
ZipArchive::ER_MULTIDISK => 'Multi-disk zip archives not supported',
ZipArchive::ER_RENAME => 'Renaming temporary file failed',
ZipArchive::ER_CLOSE => 'Closing zip archive failed',
ZipArchive::ER_SEEK => 'Seek error',
ZipArchive::ER_READ => 'Read error',
ZipArchive::ER_WRITE => 'Write error',
ZipArchive::ER_CRC => 'CRC error',
ZipArchive::ER_ZIPCLOSED => 'Containing zip archive was closed',
ZipArchive::ER_NOENT => 'No such file',
ZipArchive::ER_EXISTS => 'File already exists',
ZipArchive::ER_OPEN => 'Can\'t open file',
ZipArchive::ER_TMPOPEN => 'Failure to create temporary file',
ZipArchive::ER_ZLIB => 'Zlib error',
ZipArchive::ER_MEMORY => 'Memory allocation failure',
ZipArchive::ER_CHANGED => 'Entry has been changed',
ZipArchive::ER_COMPNOTSUPP => 'Compression method not supported',
ZipArchive::ER_EOF => 'Premature EOF',
ZipArchive::ER_INVAL => 'Invalid argument',
ZipArchive::ER_NOZIP => 'Not a zip archive',
ZipArchive::ER_INTERNAL => 'Internal error',
ZipArchive::ER_INCONS => 'Zip archive inconsistent',
ZipArchive::ER_REMOVE => 'Can\'t remove file',
ZipArchive::ER_DELETED => 'Entry has been deleted',
];
$errorMsg = isset($errorMessages[$zipResult]) ? $errorMessages[$zipResult] : "Unknown error (Code: $zipResult)";
echo json_encode(['status' => 'error', 'message' => 'Failed to unzip file. ' . $errorMsg . ' (Error Code: ' . $zipResult . ')']);
exit;
}
// Extract to data directory
if (!$zip->extractTo($dataDir)) {
$zip->close();
echo json_encode(['status' => 'error', 'message' => 'Failed to extract files from zip. Check directory permissions.']);
exit;
}
$zip->close();
// Parse XML
$xmlFile = $dataDir . '/CORPCODE.xml';
if (!file_exists($xmlFile)) {
echo json_encode(['status' => 'error', 'message' => 'XML file not found in zip.']);
exit;
}
$xml = simplexml_load_file($xmlFile);
$jsonArray = [];
foreach ($xml->list as $item) {
$corp_code = (string)$item->corp_code;
$corp_name = (string)$item->corp_name;
$stock_code = (string)$item->stock_code; // optional
$modify_date = (string)$item->modify_date;
$jsonArray[] = [
'corp_code' => $corp_code,
'corp_name' => $corp_name,
'stock_code' => $stock_code,
'modify_date' => $modify_date
];
}
// Save to JSON
$jsonFile = $dataDir . '/corp_codes.json';
if (file_put_contents($jsonFile, json_encode($jsonArray, JSON_UNESCAPED_UNICODE))) {
echo json_encode([
'status' => 'success',
'message' => 'Data synced successfully.',
'count' => count($jsonArray),
'timestamp' => date('Y-m-d H:i:s')
]);
} else {
echo json_encode(['status' => 'error', 'message' => 'Failed to save JSON data.']);
}
?>