diff --git a/eaccount/api/accounts.php b/eaccount/api/accounts.php index cf172e00..880ce18a 100644 --- a/eaccount/api/accounts.php +++ b/eaccount/api/accounts.php @@ -143,7 +143,8 @@ try { 'error' => $result['error'], 'error_code' => $result['error_code'] ?? null ], JSON_UNESCAPED_UNICODE); -} catch (Throwable $e) { + } +} catch (Exception $e) { echo json_encode([ 'success' => false, 'error' => '서버 오류: ' . $e->getMessage() @@ -183,4 +184,4 @@ function getBankName($code) { ]; return $banks[$code] ?? $code; } - +?> diff --git a/eaccount/api/barobill_account_config.php b/eaccount/api/barobill_account_config.php index 7af77cfd..0c99d436 100644 --- a/eaccount/api/barobill_account_config.php +++ b/eaccount/api/barobill_account_config.php @@ -183,7 +183,7 @@ if (!empty($barobillCertKey) || $isTestMode) { 'stream_context' => $context, 'cache_wsdl' => WSDL_CACHE_NONE // WSDL 캐시 비활성화 ]); - } catch (Throwable $e) { + } catch (Exception $e) { $barobillInitError = $e->getMessage(); error_log('바로빌 계좌 SOAP 클라이언트 생성 실패: ' . $e->getMessage()); } @@ -200,79 +200,18 @@ function callBarobillAccountSOAP($method, $params = []) { global $barobillAccountSoapClient, $barobillCertKey, $barobillCorpNum, $isTestMode, $barobillInitError, $barobillAccountSoapUrl; if (!$barobillAccountSoapClient) { - // SOAP 클라이언트가 없으면 시뮬레이션 모드로 동작 - error_log("바로빌 SOAP 클라이언트 없음 - 시뮬레이션 모드 동작: $method"); + $errorMsg = $isTestMode + ? '바로빌 계좌 SOAP 클라이언트가 초기화되지 않았습니다. (' . ($barobillInitError ?: '알 수 없는 오류') . ')' + : '바로빌 계좌 SOAP 클라이언트가 초기화되지 않았습니다. CERTKEY를 확인하세요. (' . ($barobillInitError ?: '알 수 없는 오류') . ')'; - $mockData = new stdClass(); - - if ($method === 'GetBankAccountEx') { - // 계좌 목록 모의 데이터 - $account = new stdClass(); - $account->BankAccountNum = '123-45-67890'; - $account->BankCode = '003'; - $account->BankName = '기업은행'; - $account->AccountName = '모의계좌(시뮬레이션)'; - $account->AccountType = '1'; - $account->Currency = 'KRW'; - $account->IssueDate = date('Ymd'); - $account->Balance = 15000000; - $account->UseState = 1; - - $mockData->BankAccountEx = [$account]; // 배열 형태 - // 일부 API 버전 호환성 - $mockData->BankAccount = [$account]; - - return [ - 'success' => true, - 'data' => $mockData, - 'debug' => ['mode' => 'simulation'] - ]; - } - elseif ($method === 'GetPeriodBankAccountTransLog') { - // 거래 내역 모의 데이터 - $logs = []; - for ($i = 0; $i < 5; $i++) { - $log = new stdClass(); - $log->TransDT = date('YmdHis', strtotime("-$i hours")); // 최근 시간 - $log->TransDate = date('Ymd', strtotime("-$i hours")); - $log->TransTime = date('His', strtotime("-$i hours")); - $log->BankAccountNum = $params['BankAccountNum'] ?? '123-45-67890'; - $log->BankName = '기업은행'; - $log->Deposit = ($i % 2 == 0) ? 100000 * ($i + 1) : 0; - $log->Withdraw = ($i % 2 != 0) ? 50000 * ($i + 1) : 0; - $log->Balance = 15000000 + ($i * 10000); - $log->TransRemark1 = "시뮬레이션 거래 " . ($i + 1); - $log->Cast = "테스터"; - $log->Identity = (string)$i; - $log->TransType = "IT"; // 인터넷 - $log->TransOffice = "영업점"; - - $logs[] = $log; - } - - $list = new stdClass(); - $list->BankAccountTransLog = $logs; - - $mockData->CurrentPage = 1; - $mockData->MaxPageNum = 1; - $mockData->CountPerPage = 10; - $mockData->MaxIndex = 5; - $mockData->BankAccountLogList = $list; - - return [ - 'success' => true, - 'data' => $mockData, - 'debug' => ['mode' => 'simulation'] - ]; - } - - // 그 외 메서드는 에러 반환하되 시뮬레이션 알림 return [ 'success' => false, - 'error' => '시뮬레이션 모드 지원하지 않는 메서드입니다: ' . $method, + 'error' => $errorMsg, 'error_detail' => [ + 'cert_key_file' => $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_cert_key.txt', + 'soap_url' => $barobillAccountSoapUrl, 'init_error' => $barobillInitError, - 'mode' => 'simulation_fallback' + 'test_mode' => $isTestMode ] ]; } @@ -405,11 +344,17 @@ function callBarobillAccountSOAP($method, $params = []) { ] ]; - } catch (Throwable $e) { + } catch (SoapFault $e) { return [ 'success' => false, 'error' => 'SOAP 오류: ' . $e->getMessage(), 'error_code' => $e->getCode() ]; + } catch (Exception $e) { + return [ + 'success' => false, + 'error' => 'API 호출 오류: ' . $e->getMessage() + ]; } } +?> diff --git a/eaccount/api/transactions.php b/eaccount/api/transactions.php index 53cf177a..14dbab7f 100644 --- a/eaccount/api/transactions.php +++ b/eaccount/api/transactions.php @@ -483,9 +483,10 @@ try { echo json_encode($response, JSON_UNESCAPED_UNICODE); } -} catch (Throwable $e) { +} catch (Exception $e) { echo json_encode([ 'success' => false, 'error' => '서버 오류: ' . $e->getMessage() ], JSON_UNESCAPED_UNICODE); } +?> diff --git a/etax/api/barobill_config.php b/etax/api/barobill_config.php index 9b3a3bb9..c52547f7 100644 --- a/etax/api/barobill_config.php +++ b/etax/api/barobill_config.php @@ -14,11 +14,17 @@ * 3. 테스트 환경인 경우 apikey/barobill_test_mode.txt 파일에 "test" 또는 "true"를 저장하세요 */ + +// load .env file +require_once __DIR__ . '/../../lib/DotEnv.php'; +(new DotEnv(__DIR__ . '/../../.env'))->load(); + // 인증서 키(CERTKEY) 파일 경로 -$certKeyFile = $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_cert_key.txt'; -$legacyApiKeyFile = $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_api_key.txt'; // 기존 호환성 -$corpNumFile = $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_corp_num.txt'; -$testModeFile = $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_test_mode.txt'; +$documentRoot = getenv('DOCUMENT_ROOT'); +$certKeyFile = $documentRoot . '/apikey/barobill_cert_key.txt'; +$legacyApiKeyFile = $documentRoot . '/apikey/barobill_api_key.txt'; // 기존 호환성 +$corpNumFile = $documentRoot . '/apikey/barobill_corp_num.txt'; +$testModeFile = $documentRoot . '/apikey/barobill_test_mode.txt'; // CERTKEY 읽기 (인증서 키) // 우선순위: barobill_cert_key.txt > barobill_api_key.txt (기존 호환성) @@ -72,7 +78,7 @@ if (!empty($barobillCertKey) || $isTestMode) { 'connection_timeout' => 30 ]); } catch (Throwable $e) { - // SOAP 클라이언트 생성 실패 시 null 유지 (Class not found 등 포함) + // SOAP 클라이언트 생성 실패 시 null 유지 (Class not found 등 Fatal Error 포함) error_log('바로빌 SOAP 클라이언트 생성 실패: ' . $e->getMessage()); } } @@ -92,7 +98,7 @@ function callBarobillSOAP($method, $params = []) { 'success' => false, 'error' => '바로빌 SOAP 클라이언트가 초기화되지 않았습니다. CERTKEY를 확인하세요.', 'error_detail' => [ - 'cert_key_file' => $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_cert_key.txt', + 'cert_key_file' => getenv('DOCUMENT_ROOT') . '/apikey/barobill_cert_key.txt', 'soap_url' => $isTestMode ? 'https://testws.baroservice.com/TI.asmx?WSDL' : 'https://ws.baroservice.com/TI.asmx?WSDL' ] ]; @@ -220,10 +226,10 @@ function callBarobillSOAP($method, $params = []) { 'soap_response' => $barobillSoapClient ? $barobillSoapClient->__getLastResponse() : null ] ]; - } catch (Exception $e) { + } catch (Throwable $e) { return [ 'success' => false, - 'error' => 'API 호출 오류: ' . $e->getMessage(), + 'error' => 'API 호출 오류 (치명적): ' . $e->getMessage(), 'error_detail' => [ 'exception_type' => get_class($e), 'soap_request' => $barobillSoapClient ? $barobillSoapClient->__getLastRequest() : null, @@ -408,5 +414,5 @@ function sendToNTS($mgtKey) { return callBarobillSOAP('SendToNTS', $params); } - +?> diff --git a/etax/api/debug_test.php b/etax/api/debug_test.php new file mode 100644 index 00000000..5c7efc39 --- /dev/null +++ b/etax/api/debug_test.php @@ -0,0 +1,34 @@ +load(); + echo ".env loaded.\n"; + } catch (Exception $e) { + echo "Error loading .env: " . $e->getMessage() . "\n"; + } +} else { + echo ".env file NOT found.\n"; +} + +$root = getenv('DOCUMENT_ROOT'); +echo "DOCUMENT_ROOT from getenv: " . var_export($root, true) . "\n"; +echo "DOCUMENT_ROOT from \$_ENV: " . var_export($_ENV['DOCUMENT_ROOT'] ?? 'unset', true) . "\n"; +echo "DOCUMENT_ROOT from \$_SERVER: " . var_export($_SERVER['DOCUMENT_ROOT'] ?? 'unset', true) . "\n"; diff --git a/etax/api/invoices.php b/etax/api/invoices.php index 13868139..89eeabe4 100644 --- a/etax/api/invoices.php +++ b/etax/api/invoices.php @@ -165,15 +165,6 @@ $response = [ "count" => count($invoices) ]; -$jsonOutput = json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); - -if ($jsonOutput === false) { - // JSON 인코딩 실패 시 에러 반환 - echo json_encode([ - "success" => false, - "error" => "JSON Encoding Error: " . json_last_error_msg() - ]); -} else { - echo $jsonOutput; -} +echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +?> diff --git a/etax/api/invoices_data.json b/etax/api/invoices_data.json index d8219b71..7afa988f 100644 --- a/etax/api/invoices_data.json +++ b/etax/api/invoices_data.json @@ -315,112 +315,85 @@ "barobillInvoiceId": "1" }, { - "id": "inv_1765865468", - "issueKey": "BARO-2025-4062", + "id": "inv_1765869643", + "issueKey": "BARO-2025-8437", + "supplierBizno": "664-86-03713", + "supplierName": "(주)코드브릿지엑스", + "recipientBizno": "843-22-01859", + "recipientName": "조은지게차", + "supplyDate": "2025-11-24", + "items": [ + { + "name": "샤워기", + "qty": 68, + "unitPrice": 82775, + "vatType": "vat", + "supplyAmt": 5628700, + "vat": 562870, + "total": 6191570 + }, + { + "name": "수도꼭지", + "qty": 67, + "unitPrice": 188668, + "vatType": "vat", + "supplyAmt": 12640756, + "vat": 1264075, + "total": 13904831 + }, + { + "name": "방수재", + "qty": 16, + "unitPrice": 470138, + "vatType": "vat", + "supplyAmt": 7522208, + "vat": 752220, + "total": 8274428 + } + ], + "totalSupplyAmt": 25791664, + "totalVat": 2579165, + "total": 28370829, + "status": "issued", + "memo": "시공 납품", + "createdAt": "2025-12-16T16:20:43", + "barobillInvoiceId": "BB-6941084b4185e" + }, + { + "id": "inv_1765869648", + "issueKey": "BARO-2025-0676", "supplierBizno": "664-86-03713", "supplierName": "(주)코드브릿지엑스", "recipientBizno": "107-81-78114", "recipientName": "(주)이상네트웍스", - "supplyDate": "2025-12-14", + "supplyDate": "2025-12-10", "items": [ { - "name": "콘센트", - "qty": 45, - "unitPrice": 98238, + "name": "배관자재", + "qty": 52, + "unitPrice": 64100, "vatType": "vat", - "supplyAmt": 4420710, - "vat": 442071, - "total": 4862781 + "supplyAmt": 3333200, + "vat": 333320, + "total": 3666520 }, { - "name": "시멘트 50kg", - "qty": 61, - "unitPrice": 86282, + "name": "수도꼭지", + "qty": 100, + "unitPrice": 487879, "vatType": "vat", - "supplyAmt": 5263202, - "vat": 526320, - "total": 5789522 + "supplyAmt": 48787900, + "vat": 4878790, + "total": 53666690 } ], - "totalSupplyAmt": 9683912, - "totalVat": 968391, - "total": 10652303, - "status": "issued", - "memo": "정기 납품", - "createdAt": "2025-12-16T15:11:08", - "barobillInvoiceId": "BB-6940f7fcadeae" - }, - { - "id": "inv_1765865497", - "issueKey": "BARO-2025-7108", - "supplierBizno": "664-86-03713", - "supplierName": "(주)코드브릿지엑스", - "recipientBizno": "311-46-00378", - "recipientName": "김인태", - "supplyDate": "2025-12-16", - "items": [ - { - "name": "스위치", - "qty": 7, - "unitPrice": 306056, - "vatType": "vat", - "supplyAmt": 2142392, - "vat": 214239, - "total": 2356631 - }, - { - "name": "욕조", - "qty": 5, - "unitPrice": 498181, - "vatType": "vat", - "supplyAmt": 2490905, - "vat": 249090, - "total": 2739995 - } - ], - "totalSupplyAmt": 4633297, - "totalVat": 463329, - "total": 5096626, + "totalSupplyAmt": 52121100, + "totalVat": 5212110, + "total": 57333210, "status": "issued", "memo": "보수 납품", - "createdAt": "2025-12-16T15:11:37", - "barobillInvoiceId": "BB-6940f819ddf22" - }, - { - "id": "inv_1765866226", - "issueKey": "BARO-2025-4774", - "supplierBizno": "664-86-03713", - "supplierName": "(주)코드브릿지엑스", - "recipientBizno": "311-46-00378", - "recipientName": "김인태", - "supplyDate": "2025-12-16", - "items": [ - { - "name": "욕조", - "qty": 68, - "unitPrice": 360769, - "vatType": "vat", - "supplyAmt": 24532292, - "vat": 2453229, - "total": 26985521 - }, - { - "name": "샤워기", - "qty": 62, - "unitPrice": 410116, - "vatType": "vat", - "supplyAmt": 25427192, - "vat": 2542719, - "total": 27969911 - } - ], - "totalSupplyAmt": 49959484, - "totalVat": 4995948, - "total": 54955432, - "status": "issued", - "memo": "추가 납품", - "createdAt": "2025-12-16T15:23:46", - "barobillInvoiceId": "BB-6940faf28199d" + "createdAt": "2025-12-16T16:20:48", + "barobillInvoiceId": "BB-69410850c94ef" } ] } \ No newline at end of file diff --git a/etax/api/issue.php b/etax/api/issue.php index 13bd4319..e576dc70 100644 --- a/etax/api/issue.php +++ b/etax/api/issue.php @@ -3,12 +3,10 @@ header('Content-Type: application/json'); header('Access-Control-Allow-Origin: *'); // 바로빌 API 설정 로드 -try { - require_once(__DIR__ . '/barobill_config.php'); - - // POST 데이터 읽기 - $input = json_decode(file_get_contents('php://input'), true); +require_once(__DIR__ . '/barobill_config.php'); +// POST 데이터 읽기 +$input = json_decode(file_get_contents('php://input'), true); if (!$input) { http_response_code(400); @@ -145,7 +143,6 @@ if ($useRealAPI) { } } else { // 시뮬레이션 모드 (API 키가 없을 때) -// 시뮬레이션 모드 코드 (변경 없음) $issueKey = "BARO-" . date('Y') . "-" . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT); $newInvoice = [ @@ -224,24 +221,6 @@ if ($useRealAPI) { usleep(500000); // 0.5초 지연 시뮬레이션 } -$jsonOutput = json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); - -if ($jsonOutput === false) { - throw new Exception("JSON Encoding Error: " . json_last_error_msg()); -} - -echo $jsonOutput; - -} catch (Throwable $e) { - error_log("API Error: " . $e->getMessage() . "\n" . $e->getTraceAsString()); - http_response_code(500); - echo json_encode([ - "success" => false, - "error" => "Internal Server Error: " . $e->getMessage(), - "debug" => [ - "file" => $e->getFile(), - "line" => $e->getLine() - ] - ], JSON_UNESCAPED_UNICODE); -} +echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +?> diff --git a/etax/barobill_api_info.php b/etax/barobill_api_info.php index 21149a91..762f2ad6 100644 --- a/etax/barobill_api_info.php +++ b/etax/barobill_api_info.php @@ -1,5 +1,7 @@ load(); +require_once(getenv('DOCUMENT_ROOT') . "/session.php"); ?> diff --git a/lib/DotEnv.php b/lib/DotEnv.php new file mode 100644 index 00000000..06e377d9 --- /dev/null +++ b/lib/DotEnv.php @@ -0,0 +1,43 @@ +path = $path; + } + + public function load(): void + { + if (!is_readable($this->path)) { + throw new \RuntimeException(sprintf('%s file is not readable', $this->path)); + } + + $lines = file($this->path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach ($lines as $line) { + if (strpos(trim($line), '#') === 0) { + continue; + } + + list($name, $value) = explode('=', $line, 2); + $name = trim($name); + $value = trim($value); + + if (!array_key_exists($name, $_SERVER) && !array_key_exists($name, $_ENV)) { + putenv(sprintf('%s=%s', $name, $value)); + $_ENV[$name] = $value; + $_SERVER[$name] = $value; + } + } + } +} diff --git a/test_soap_account.php b/test_soap_account.php new file mode 100644 index 00000000..5e46d2e7 --- /dev/null +++ b/test_soap_account.php @@ -0,0 +1,36 @@ + 0]); + +echo "Result Success: " . ($result['success'] ? 'Yes' : 'No') . "\n"; +if (!$result['success']) { + echo "Error: " . $result['error'] . "\n"; +} else { + echo "Data Type: " . gettype($result['data']) . "\n"; + print_r($result['data']); +} +?>