load(); require_once('barobill_account_config.php'); require_once(getenv('DOCUMENT_ROOT') . '/session.php'); require_once(getenv('DOCUMENT_ROOT') . '/lib/mydb.php'); try { // 1. 로컬 DB의 company_accounts 테이블에서 계좌 정보 가져오기 $localAccounts = []; $selectedTenantId = $_SESSION['eaccount_tenant_id'] ?? null; if ($selectedTenantId) { try { $pdo = db_connect(); if ($pdo) { $sql = "SELECT id, company_id, bank_code, account_num, account_pwd FROM {$DB}.company_accounts WHERE company_id = ? ORDER BY id DESC"; $stmt = $pdo->prepare($sql); $stmt->execute([$selectedTenantId]); $localAccounts = $stmt->fetchAll(PDO::FETCH_ASSOC); } } catch (Exception $e) { error_log('로컬 계좌 정보 로드 실패: ' . $e->getMessage()); } } // 2. 바로빌 API에서 계좌 정보 가져오기 (시도) $barobillAccounts = []; $barobillError = null; $barobillErrorCode = null; $debugInfo = null; $result = callBarobillAccountSOAP('GetBankAccountEx', [ 'AvailOnly' => 0 // 전체 계좌 조회 (0: 전체, 1: 사용가능, 2: 해지) ]); if ($result['success']) { $data = $result['data']; $accountList = []; // 디버그: 응답 구조 확인 $debugInfo = [ 'data_type' => gettype($data), 'data_keys' => is_object($data) ? array_keys(get_object_vars($data)) : [], 'has_BankAccountEx' => isset($data->BankAccountEx), 'has_BankAccount' => isset($data->BankAccount), 'BankAccountEx_type' => isset($data->BankAccountEx) ? gettype($data->BankAccountEx) : 'N/A', 'BankAccount_type' => isset($data->BankAccount) ? gettype($data->BankAccount) : 'N/A', 'BankAccountEx_is_array' => isset($data->BankAccountEx) ? is_array($data->BankAccountEx) : false, 'BankAccount_is_array' => isset($data->BankAccount) ? is_array($data->BankAccount) : false ]; // 실제 SOAP 응답 구조 확인: // GetBankAccountExResult -> BankAccount (단일 객체 또는 배열) // 또는 BankAccountEx (배열) - 다른 API 버전일 수 있음 // 우선순위 1: BankAccount 확인 (실제 응답 구조 - SOAP XML에서 확인됨) if (isset($data->BankAccount)) { if (is_array($data->BankAccount)) { $accountList = $data->BankAccount; } else if (is_object($data->BankAccount)) { // 단일 객체인 경우 배열로 변환 $accountList = [$data->BankAccount]; } } // 우선순위 2: BankAccountEx 배열 확인 (다른 API 버전) else if (isset($data->BankAccountEx)) { // 단일 객체가 에러 코드인 경우 (예: -10002, -25001) if (is_numeric($data->BankAccountEx) && $data->BankAccountEx < 0) { $errorCode = $data->BankAccountEx; $barobillError = '바로빌 API 오류: ' . $errorCode; $barobillErrorCode = $errorCode; // 상세 에러 메시지 매핑 if ($errorCode == -10002) { $barobillError = '인증 실패 (-10002). CERTKEY 또는 사업자번호를 확인해주세요.'; } else if ($errorCode == -25001) { $barobillError = '등록된 계좌가 없습니다 (-25001). 바로빌 사이트에서 계좌를 등록해주세요.'; } else if ($errorCode == -50214) { $barobillError = '은행 로그인 실패 (-50214). 바로빌 사이트에서 계좌 비밀번호/인증서를 점검해주세요.'; } } // 배열 또는 객체인 경우 else if (is_array($data->BankAccountEx)) { $accountList = $data->BankAccountEx; } else if (is_object($data->BankAccountEx)) { // 단일 객체인 경우 배열로 변환 $accountList = [$data->BankAccountEx]; } } // 방법 3: 직접 BankAccount 속성 확인 (다른 구조일 수 있음) else { // 객체의 모든 속성을 확인하여 BankAccount 관련 속성 찾기 if (is_object($data)) { $vars = get_object_vars($data); foreach ($vars as $key => $value) { // BankAccount로 시작하는 속성 찾기 if (stripos($key, 'BankAccount') !== false) { if (is_array($value)) { $accountList = $value; break; } else if (is_object($value)) { $accountList = [$value]; break; } } } } } // 계좌 정보 파싱 foreach ($accountList as $acc) { // 객체가 아닌 경우 스킵 if (!is_object($acc)) { continue; } // 에러 코드 체크 (개별 계좌 레벨) if (isset($acc->BankAccountNum)) { // BankAccountNum이 음수인 경우 에러 코드 if (is_numeric($acc->BankAccountNum) && $acc->BankAccountNum < 0) { $errorCode = $acc->BankAccountNum; if (!$barobillError) { $barobillError = '바로빌 API 오류: ' . $errorCode; $barobillErrorCode = $errorCode; } continue; } // BankAccountNum이 비어있는 경우도 스킵 if (empty($acc->BankAccountNum)) { continue; } } else { // BankAccountNum이 없는 경우도 스킵 continue; } // BankName으로 BankCode 추론 (응답에 BankCode가 없는 경우) $bankCode = $acc->BankCode ?? ''; if (empty($bankCode) && isset($acc->BankName)) { // BankName으로 BankCode 찾기 $bankName = $acc->BankName; $bankCodeMap = [ '기업은행' => '003', 'IBK기업은행' => '003', 'KB국민은행' => '004', '국민은행' => '004', '우리은행' => '020', '신한은행' => '088', '하나은행' => '081', 'NH농협은행' => '011', '농협은행' => '011' ]; $bankCode = $bankCodeMap[$bankName] ?? ''; } // UseState 처리: 없으면 기본값 1 (사용중)으로 설정 // UseState: 1=사용중, 0=중지, 2=해지 $useState = isset($acc->UseState) ? intval($acc->UseState) : 1; // 기본값: 사용중 $barobillAccounts[] = [ 'bankAccountNum' => $acc->BankAccountNum ?? '', 'bankCode' => $bankCode, 'bankName' => getBankName($bankCode) ?: ($acc->BankName ?? ''), 'accountName' => $acc->AccountName ?? '', 'accountType' => $acc->AccountType ?? '', 'currency' => $acc->Currency ?? 'KRW', 'issueDate' => $acc->IssueDate ?? '', 'balance' => $acc->Balance ?? 0, 'status' => $useState, 'statusText' => $useState == 1 ? '사용중' : ($useState == 0 ? '중지' : ($useState == 2 ? '해지' : '알 수 없음')), 'source' => 'barobill_api' // 바로빌 API에서 가져온 정보 ]; } // 디버그 정보 추가 $debugInfo['account_count'] = count($barobillAccounts); $debugInfo['account_list'] = array_map(function($acc) { return [ 'bankAccountNum' => $acc['bankAccountNum'], 'bankCode' => $acc['bankCode'], 'accountName' => $acc['accountName'] ]; }, $barobillAccounts); } else { $barobillError = $result['error']; $barobillErrorCode = $result['error_code'] ?? null; } // 3. 로컬 DB 계좌 정보를 바로빌 계좌 정보와 매칭하여 통합 $allAccounts = []; // 먼저 바로빌 API 계좌 정보를 기준으로 추가 (실제 사용 가능한 계좌) foreach ($barobillAccounts as $barobillAcc) { $allAccounts[] = $barobillAcc; } // 로컬 DB 계좌 정보를 바로빌 API 계좌와 매칭 foreach ($localAccounts as $localAcc) { $matched = false; // 바로빌 API에 같은 계좌번호가 있는지 확인 foreach ($allAccounts as &$existingAcc) { // 계좌번호 매칭 (하이픈 제거 후 비교) $localAccountNum = str_replace('-', '', $localAcc['account_num']); $barobillAccountNum = str_replace('-', '', $existingAcc['bankAccountNum']); if ($localAccountNum === $barobillAccountNum) { // 바로빌 API 계좌 정보에 로컬 DB 정보 병합 $existingAcc['id'] = $localAcc['id']; $existingAcc['hasPassword'] = !empty($localAcc['account_pwd']); $existingAcc['source'] = 'both'; // 양쪽 모두에 있음 (실제 사용 가능) $matched = true; break; } } // 바로빌 API에 없는 로컬 계좌는 경고와 함께 추가 if (!$matched) { $isApiError = !empty($barobillError); $statusText = $isApiError ? '상태 확인 불가' : '바로빌 미등록'; $sourceText = $isApiError ? 'barobill_api_error' : 'local_db_only'; $allAccounts[] = [ 'id' => $localAcc['id'], 'bankAccountNum' => $localAcc['account_num'], 'bankCode' => $localAcc['bank_code'], 'bankName' => getBankName($localAcc['bank_code']), 'accountName' => '', // 로컬 DB에는 별칭 정보 없음 'accountType' => '', 'currency' => 'KRW', 'issueDate' => '', 'balance' => 0, 'status' => '', 'statusText' => $statusText, 'source' => $sourceText, // 상태 확인 필요 'hasPassword' => !empty($localAcc['account_pwd']), 'warning' => true, // 경고 표시용 'api_error' => $isApiError // 프론트엔드에서 구분하기 위함 ]; } } // 사용 가능한 계좌 수 계산 (바로빌 API에서 확인된 계좌) $availableAccounts = array_filter($allAccounts, function($acc) { return $acc['source'] === 'barobill_api' || $acc['source'] === 'both'; }); $availableCount = count($availableAccounts); // 경고가 필요한 계좌 수 (로컬에만 있는 계좌) $warningAccounts = array_filter($allAccounts, function($acc) { return isset($acc['warning']) && $acc['warning'] === true; }); $warningCount = count($warningAccounts); $response = [ 'success' => true, 'accounts' => $allAccounts, 'count' => count($allAccounts), 'available_count' => $availableCount, // 바로빌 API에서 확인된 사용 가능한 계좌 수 'warning_count' => $warningCount, // 로컬에만 있는 계좌 수 'local_count' => count($localAccounts), 'barobill_count' => count($barobillAccounts), 'message' => $availableCount > 0 ? '사용 가능한 계좌가 ' . $availableCount . '개 있습니다.' . ($warningCount > 0 ? ' (바로빌 미등록 계좌 ' . $warningCount . '개)' : '') : '사용 가능한 계좌가 없습니다.' . ($warningCount > 0 ? ' (로컬에만 등록된 계좌 ' . $warningCount . '개는 바로빌 API에 등록이 필요합니다)' : '') ]; // 바로빌 API 오류 정보 추가 if ($barobillError) { $response['barobill_error'] = $barobillError; $response['barobill_error_code'] = $barobillErrorCode; } // 디버그 정보 추가 if (isset($result['debug'])) { $response['debug'] = $result['debug']; } // API 응답 구조 디버그 정보 추가 if (isset($debugInfo)) { $response['api_debug'] = $debugInfo; } echo json_encode($response, JSON_UNESCAPED_UNICODE); } catch (Exception $e) { echo json_encode([ 'success' => false, 'error' => '서버 오류: ' . $e->getMessage(), 'accounts' => [], 'count' => 0 ], JSON_UNESCAPED_UNICODE); } /** * 은행 코드 -> 은행명 변환 */ function getBankName($code) { $banks = [ '002' => 'KDB산업은행', '003' => 'IBK기업은행', '004' => 'KB국민은행', '007' => '수협은행', '011' => 'NH농협은행', '012' => '지역농축협', '020' => '우리은행', '023' => 'SC제일은행', '027' => '한국씨티은행', '031' => '대구은행', '032' => '부산은행', '034' => '광주은행', '035' => '제주은행', '037' => '전북은행', '039' => '경남은행', '045' => '새마을금고', '048' => '신협', '050' => '저축은행', '064' => '산림조합', '071' => '우체국', '081' => '하나은행', '088' => '신한은행', '089' => 'K뱅크', '090' => '카카오뱅크', '092' => '토스뱅크' ]; return $banks[$code] ?? $code; } ?>