etax 서버환경으로 수정

This commit is contained in:
2025-12-16 16:22:30 +09:00
parent 5e786c26a1
commit 1d79a2989b
11 changed files with 223 additions and 212 deletions

View File

@@ -143,7 +143,8 @@ try {
'error' => $result['error'], 'error' => $result['error'],
'error_code' => $result['error_code'] ?? null 'error_code' => $result['error_code'] ?? null
], JSON_UNESCAPED_UNICODE); ], JSON_UNESCAPED_UNICODE);
} catch (Throwable $e) { }
} catch (Exception $e) {
echo json_encode([ echo json_encode([
'success' => false, 'success' => false,
'error' => '서버 오류: ' . $e->getMessage() 'error' => '서버 오류: ' . $e->getMessage()
@@ -183,4 +184,4 @@ function getBankName($code) {
]; ];
return $banks[$code] ?? $code; return $banks[$code] ?? $code;
} }
?>

View File

@@ -183,7 +183,7 @@ if (!empty($barobillCertKey) || $isTestMode) {
'stream_context' => $context, 'stream_context' => $context,
'cache_wsdl' => WSDL_CACHE_NONE // WSDL 캐시 비활성화 'cache_wsdl' => WSDL_CACHE_NONE // WSDL 캐시 비활성화
]); ]);
} catch (Throwable $e) { } catch (Exception $e) {
$barobillInitError = $e->getMessage(); $barobillInitError = $e->getMessage();
error_log('바로빌 계좌 SOAP 클라이언트 생성 실패: ' . $e->getMessage()); error_log('바로빌 계좌 SOAP 클라이언트 생성 실패: ' . $e->getMessage());
} }
@@ -200,79 +200,18 @@ function callBarobillAccountSOAP($method, $params = []) {
global $barobillAccountSoapClient, $barobillCertKey, $barobillCorpNum, $isTestMode, $barobillInitError, $barobillAccountSoapUrl; global $barobillAccountSoapClient, $barobillCertKey, $barobillCorpNum, $isTestMode, $barobillInitError, $barobillAccountSoapUrl;
if (!$barobillAccountSoapClient) { if (!$barobillAccountSoapClient) {
// SOAP 클라이언트가 없으면 시뮬레이션 모드로 동작 $errorMsg = $isTestMode
error_log("바로빌 SOAP 클라이언트 없음 - 시뮬레이션 모드 동작: $method"); ? '바로빌 계좌 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 [ return [
'success' => false, 'success' => false,
'error' => '시뮬레이션 모드 지원하지 않는 메서드입니다: ' . $method, 'error' => $errorMsg,
'error_detail' => [ 'error_detail' => [
'cert_key_file' => $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_cert_key.txt',
'soap_url' => $barobillAccountSoapUrl,
'init_error' => $barobillInitError, 'init_error' => $barobillInitError,
'mode' => 'simulation_fallback' 'test_mode' => $isTestMode
] ]
]; ];
} }
@@ -405,11 +344,17 @@ function callBarobillAccountSOAP($method, $params = []) {
] ]
]; ];
} catch (Throwable $e) { } catch (SoapFault $e) {
return [ return [
'success' => false, 'success' => false,
'error' => 'SOAP 오류: ' . $e->getMessage(), 'error' => 'SOAP 오류: ' . $e->getMessage(),
'error_code' => $e->getCode() 'error_code' => $e->getCode()
]; ];
} catch (Exception $e) {
return [
'success' => false,
'error' => 'API 호출 오류: ' . $e->getMessage()
];
} }
} }
?>

View File

@@ -483,9 +483,10 @@ try {
echo json_encode($response, JSON_UNESCAPED_UNICODE); echo json_encode($response, JSON_UNESCAPED_UNICODE);
} }
} catch (Throwable $e) { } catch (Exception $e) {
echo json_encode([ echo json_encode([
'success' => false, 'success' => false,
'error' => '서버 오류: ' . $e->getMessage() 'error' => '서버 오류: ' . $e->getMessage()
], JSON_UNESCAPED_UNICODE); ], JSON_UNESCAPED_UNICODE);
} }
?>

View File

@@ -14,11 +14,17 @@
* 3. 테스트 환경인 경우 apikey/barobill_test_mode.txt 파일에 "test" 또는 "true"를 저장하세요 * 3. 테스트 환경인 경우 apikey/barobill_test_mode.txt 파일에 "test" 또는 "true"를 저장하세요
*/ */
// load .env file
require_once __DIR__ . '/../../lib/DotEnv.php';
(new DotEnv(__DIR__ . '/../../.env'))->load();
// 인증서 키(CERTKEY) 파일 경로 // 인증서 키(CERTKEY) 파일 경로
$certKeyFile = $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_cert_key.txt'; $documentRoot = getenv('DOCUMENT_ROOT');
$legacyApiKeyFile = $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_api_key.txt'; // 기존 호환성 $certKeyFile = $documentRoot . '/apikey/barobill_cert_key.txt';
$corpNumFile = $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_corp_num.txt'; $legacyApiKeyFile = $documentRoot . '/apikey/barobill_api_key.txt'; // 기존 호환성
$testModeFile = $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_test_mode.txt'; $corpNumFile = $documentRoot . '/apikey/barobill_corp_num.txt';
$testModeFile = $documentRoot . '/apikey/barobill_test_mode.txt';
// CERTKEY 읽기 (인증서 키) // CERTKEY 읽기 (인증서 키)
// 우선순위: barobill_cert_key.txt > barobill_api_key.txt (기존 호환성) // 우선순위: barobill_cert_key.txt > barobill_api_key.txt (기존 호환성)
@@ -72,7 +78,7 @@ if (!empty($barobillCertKey) || $isTestMode) {
'connection_timeout' => 30 'connection_timeout' => 30
]); ]);
} catch (Throwable $e) { } catch (Throwable $e) {
// SOAP 클라이언트 생성 실패 시 null 유지 (Class not found 등 포함) // SOAP 클라이언트 생성 실패 시 null 유지 (Class not found 등 Fatal Error 포함)
error_log('바로빌 SOAP 클라이언트 생성 실패: ' . $e->getMessage()); error_log('바로빌 SOAP 클라이언트 생성 실패: ' . $e->getMessage());
} }
} }
@@ -92,7 +98,7 @@ function callBarobillSOAP($method, $params = []) {
'success' => false, 'success' => false,
'error' => '바로빌 SOAP 클라이언트가 초기화되지 않았습니다. CERTKEY를 확인하세요.', 'error' => '바로빌 SOAP 클라이언트가 초기화되지 않았습니다. CERTKEY를 확인하세요.',
'error_detail' => [ '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' '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 'soap_response' => $barobillSoapClient ? $barobillSoapClient->__getLastResponse() : null
] ]
]; ];
} catch (Exception $e) { } catch (Throwable $e) {
return [ return [
'success' => false, 'success' => false,
'error' => 'API 호출 오류: ' . $e->getMessage(), 'error' => 'API 호출 오류 (치명적): ' . $e->getMessage(),
'error_detail' => [ 'error_detail' => [
'exception_type' => get_class($e), 'exception_type' => get_class($e),
'soap_request' => $barobillSoapClient ? $barobillSoapClient->__getLastRequest() : null, 'soap_request' => $barobillSoapClient ? $barobillSoapClient->__getLastRequest() : null,
@@ -408,5 +414,5 @@ function sendToNTS($mgtKey) {
return callBarobillSOAP('SendToNTS', $params); return callBarobillSOAP('SendToNTS', $params);
} }
?>

34
etax/api/debug_test.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
header('Content-Type: text/plain');
echo "Current Dir: " . __DIR__ . "\n";
echo "DotEnv Path: " . __DIR__ . '/../../lib/DotEnv.php' . "\n";
echo "Env File Path: " . __DIR__ . '/../../.env' . "\n";
if (file_exists(__DIR__ . '/../../lib/DotEnv.php')) {
echo "DotEnv file exists.\n";
require_once __DIR__ . '/../../lib/DotEnv.php';
echo "DotEnv loaded.\n";
} else {
echo "DotEnv file NOT found.\n";
}
if (file_exists(__DIR__ . '/../../.env')) {
echo ".env file exists.\n";
try {
(new DotEnv(__DIR__ . '/../../.env'))->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";

View File

@@ -165,15 +165,6 @@ $response = [
"count" => count($invoices) "count" => count($invoices)
]; ];
$jsonOutput = json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); echo 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;
}

View File

@@ -315,112 +315,85 @@
"barobillInvoiceId": "1" "barobillInvoiceId": "1"
}, },
{ {
"id": "inv_1765865468", "id": "inv_1765869643",
"issueKey": "BARO-2025-4062", "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", "supplierBizno": "664-86-03713",
"supplierName": "(주)코드브릿지엑스", "supplierName": "(주)코드브릿지엑스",
"recipientBizno": "107-81-78114", "recipientBizno": "107-81-78114",
"recipientName": "(주)이상네트웍스", "recipientName": "(주)이상네트웍스",
"supplyDate": "2025-12-14", "supplyDate": "2025-12-10",
"items": [ "items": [
{ {
"name": "콘센트", "name": "배관자재",
"qty": 45, "qty": 52,
"unitPrice": 98238, "unitPrice": 64100,
"vatType": "vat", "vatType": "vat",
"supplyAmt": 4420710, "supplyAmt": 3333200,
"vat": 442071, "vat": 333320,
"total": 4862781 "total": 3666520
}, },
{ {
"name": "시멘트 50kg", "name": "수도꼭지",
"qty": 61, "qty": 100,
"unitPrice": 86282, "unitPrice": 487879,
"vatType": "vat", "vatType": "vat",
"supplyAmt": 5263202, "supplyAmt": 48787900,
"vat": 526320, "vat": 4878790,
"total": 5789522 "total": 53666690
} }
], ],
"totalSupplyAmt": 9683912, "totalSupplyAmt": 52121100,
"totalVat": 968391, "totalVat": 5212110,
"total": 10652303, "total": 57333210,
"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,
"status": "issued", "status": "issued",
"memo": "보수 납품", "memo": "보수 납품",
"createdAt": "2025-12-16T15:11:37", "createdAt": "2025-12-16T16:20:48",
"barobillInvoiceId": "BB-6940f819ddf22" "barobillInvoiceId": "BB-69410850c94ef"
},
{
"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"
} }
] ]
} }

View File

@@ -3,12 +3,10 @@ header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Origin: *');
// 바로빌 API 설정 로드 // 바로빌 API 설정 로드
try { require_once(__DIR__ . '/barobill_config.php');
require_once(__DIR__ . '/barobill_config.php');
// POST 데이터 읽기
$input = json_decode(file_get_contents('php://input'), true);
// POST 데이터 읽기
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) { if (!$input) {
http_response_code(400); http_response_code(400);
@@ -145,7 +143,6 @@ if ($useRealAPI) {
} }
} else { } else {
// 시뮬레이션 모드 (API 키가 없을 때) // 시뮬레이션 모드 (API 키가 없을 때)
// 시뮬레이션 모드 코드 (변경 없음)
$issueKey = "BARO-" . date('Y') . "-" . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT); $issueKey = "BARO-" . date('Y') . "-" . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT);
$newInvoice = [ $newInvoice = [
@@ -224,24 +221,6 @@ if ($useRealAPI) {
usleep(500000); // 0.5초 지연 시뮬레이션 usleep(500000); // 0.5초 지연 시뮬레이션
} }
$jsonOutput = json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); echo 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);
}

View File

@@ -1,5 +1,7 @@
<?php <?php
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php"); require_once __DIR__ . '/../lib/DotEnv.php';
(new DotEnv(__DIR__ . '/../.env'))->load();
require_once(getenv('DOCUMENT_ROOT') . "/session.php");
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ko"> <html lang="ko">

43
lib/DotEnv.php Normal file
View File

@@ -0,0 +1,43 @@
<?php
class DotEnv
{
/**
* The directory where the .env file is located.
*
* @var string
*/
protected $path;
public function __construct(string $path)
{
if (!file_exists($path)) {
throw new \InvalidArgumentException(sprintf('%s does not exist', $path));
}
$this->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;
}
}
}
}

36
test_soap_account.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
$_SERVER['DOCUMENT_ROOT'] = 'c:/Users/light/sam/5130';
require_once 'c:/Users/light/sam/5130/eaccount/api/barobill_account_config.php';
echo "1. SoapClient Check:\n";
if (class_exists('SoapClient')) {
echo "SoaptClient is available.\n";
} else {
echo "SoapClient is NOT available.\n";
}
echo "\n2. Global Client Check:\n";
global $barobillAccountSoapClient;
if ($barobillAccountSoapClient) {
echo "Global \$barobillAccountSoapClient is initialized.\n";
} else {
echo "Global \$barobillAccountSoapClient is NULL.\n";
global $barobillInitError;
echo "Init Error: $barobillInitError\n";
}
echo "\n3. Call GetBankAccountEx:\n";
$result = callBarobillAccountSOAP('GetBankAccountEx', ['AvailOnly' => 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']);
}
?>