From 50308dd340a128b0b70cd5244a6d7a85ac2a638d Mon Sep 17 00:00:00 2001 From: aweso Date: Wed, 14 Jan 2026 09:33:23 +0900 Subject: [PATCH] =?UTF-8?q?=ED=94=BC=ED=94=8C=EB=9D=BC=EC=9D=B4=ED=94=84?= =?UTF-8?q?=20=EA=B8=B0=EC=97=85=EB=B6=84=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- barobill/index.php | 26 +- barobill_registration/index.php | 26 +- company/peoplelife/index.php | 520 ++++++++ eaccount/README.md | 138 +++ eaccount/api/account_status.php | 340 ++++++ eaccount/api/accounts.php | 245 ++++ eaccount/api/barobill_account_config.php | 366 ++++++ eaccount/api/barobill_card_config.php | 404 ++++++ eaccount/api/cards.php | 225 ++++ eaccount/api/check_api_config.php | 138 +++ eaccount/api/debug_accounts.php | 273 +++++ eaccount/api/get_tenants.php | 97 ++ eaccount/api/set_tenant.php | 61 + eaccount/api/transactions.php | 515 ++++++++ eaccount/api/usage.php | 397 ++++++ eaccount/index.php | 1421 ++++++++++++++++++++++ ecard/README.md | 138 +++ ecard/api/barobill_card_config.php | 510 ++++++++ ecard/api/cards.php | 252 ++++ ecard/api/debug_raw.php | 65 + ecard/api/usage.php | 402 ++++++ ecard/index.php | 920 ++++++++++++++ ecard/์นด๋“œ์‚ฌ์šฉ๋‚ด์—ญ์กฐํšŒ.md | 957 +++++++++++++++ tenant/api.php | 225 ++++ tenant/index.php | 506 ++++++++ 25 files changed, 9162 insertions(+), 5 deletions(-) create mode 100644 company/peoplelife/index.php create mode 100644 eaccount/README.md create mode 100644 eaccount/api/account_status.php create mode 100644 eaccount/api/accounts.php create mode 100644 eaccount/api/barobill_account_config.php create mode 100644 eaccount/api/barobill_card_config.php create mode 100644 eaccount/api/cards.php create mode 100644 eaccount/api/check_api_config.php create mode 100644 eaccount/api/debug_accounts.php create mode 100644 eaccount/api/get_tenants.php create mode 100644 eaccount/api/set_tenant.php create mode 100644 eaccount/api/transactions.php create mode 100644 eaccount/api/usage.php create mode 100644 eaccount/index.php create mode 100644 ecard/README.md create mode 100644 ecard/api/barobill_card_config.php create mode 100644 ecard/api/cards.php create mode 100644 ecard/api/debug_raw.php create mode 100644 ecard/api/usage.php create mode 100644 ecard/index.php create mode 100644 ecard/์นด๋“œ์‚ฌ์šฉ๋‚ด์—ญ์กฐํšŒ.md create mode 100644 tenant/api.php create mode 100644 tenant/index.php diff --git a/barobill/index.php b/barobill/index.php index 6f2e83c..089f05f 100644 --- a/barobill/index.php +++ b/barobill/index.php @@ -61,7 +61,31 @@

๋ฐ”๋กœ๋นŒ API ํšŒ๊ณ„ ์†”๋ฃจ์…˜

- + + diff --git a/barobill_registration/index.php b/barobill_registration/index.php index 439dbf6..9c94105 100644 --- a/barobill_registration/index.php +++ b/barobill_registration/index.php @@ -56,14 +56,32 @@

๋ฐ”๋กœ๋นŒ ํšŒ์›๊ด€๋ฆฌ ์†”๋ฃจ์…˜

-
- +
+ + ๊ณ„์ขŒ์กฐํšŒ + + + ์นด๋“œ๋‚ด์—ญ + + + ํ…Œ๋„ŒํŠธ๊ด€๋ฆฌ + + + ํšŒ์›๊ด€๋ฆฌ + + + API์ •๋ณด + + +
+ + ํ˜„ํ™ฉ - + ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ - + ํ™ˆ
diff --git a/company/peoplelife/index.php b/company/peoplelife/index.php new file mode 100644 index 0000000..ebac30d --- /dev/null +++ b/company/peoplelife/index.php @@ -0,0 +1,520 @@ + + + + + + ํ”ผํ”Œ๋ผ์ดํ”„(PeopleLife) ๊ธฐ์—… ๋ถ„์„ ๋ฆฌํฌํŠธ + + + + + + + + + + + + + +
+
+
+
+
P
+ ํ”ผํ”Œ๋ผ์ดํ”„ ๊ธฐ์—…๋ถ„์„ +
+ +
+
+ +
+ + + + +
+
+ +
+ + +
+ +
+ +
+ +
+
+

ยฉ 2024 PeopleLife Analysis Dashboard. ๋ณธ ์ž๋ฃŒ๋Š” ๊ณต๊ฐœ๋œ ๊ธฐ์—… ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ตฌ์„ฑ๋œ ๋ถ„์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ž…๋‹ˆ๋‹ค.

+
+
+ + + + \ No newline at end of file diff --git a/eaccount/README.md b/eaccount/README.md new file mode 100644 index 0000000..946f3b9 --- /dev/null +++ b/eaccount/README.md @@ -0,0 +1,138 @@ +# ๋ฒ•์ธ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ ๋ชจ๋“ˆ + +๋ฐ”๋กœ๋นŒ API๋ฅผ ์ด์šฉํ•œ ๋ฒ•์ธ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ ๋ชจ๋“ˆ์ž…๋‹ˆ๋‹ค. + +## ๐Ÿ“‹ ๊ธฐ๋Šฅ + +- ๋“ฑ๋ก๋œ ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ +- ๊ธฐ๊ฐ„๋ณ„/์ผ๋ณ„/์›”๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ +- ์‚ฌ์šฉ๊ธˆ์•ก ํ†ต๊ณ„ (์ด ์‚ฌ์šฉ๊ธˆ์•ก, ์‚ฌ์šฉ๊ฑด์ˆ˜, ์ทจ์†Œ๊ฑด์ˆ˜) +- ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ง€์› + +## ๐Ÿ”ง ์„ค์ • + +### 1. API ํ‚ค ์„ค์ • (๊ธฐ์กด etax ๋ชจ๋“ˆ๊ณผ ๊ณต์œ ) + +๋‹ค์Œ ํŒŒ์ผ๋“ค์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค (`/apikey/` ํด๋”): + +| ํŒŒ์ผ๋ช… | ์„ค๋ช… | ์˜ˆ์‹œ | +|--------|------|------| +| `barobill_cert_key.txt` | ๋ฐ”๋กœ๋นŒ CERTKEY (์ธ์ฆ์„œ ํ‚ค) | `ABC123...` | +| `barobill_corp_num.txt` | ์‚ฌ์—…์ž๋ฒˆํ˜ธ (ํ•˜์ดํ”ˆ ์ œ์™ธ) | `6648603713` | +| `barobill_test_mode.txt` | ํ…Œ์ŠคํŠธ ๋ชจ๋“œ (์„ ํƒ) | `test` ๋˜๋Š” `true` | + +### 2. ๋ฐ”๋กœ๋นŒ ์นด๋“œ ๋“ฑ๋ก + +์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ์„ ์กฐํšŒํ•˜๋ ค๋ฉด **๋ฐ”๋กœ๋นŒ ์›น์‚ฌ์ดํŠธ**์—์„œ ์นด๋“œ๋ฅผ ๋จผ์ € ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +1. [๋ฐ”๋กœ๋นŒ](https://www.barobill.co.kr) ๋กœ๊ทธ์ธ +2. ์นด๋“œ์กฐํšŒ ์„œ๋น„์Šค ์‹ ์ฒญ +3. ์นด๋“œ ๋“ฑ๋ก (์นด๋“œ์‚ฌ ์›น ID/๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„์š”) + +## ๐Ÿ“ ํŒŒ์ผ ๊ตฌ์กฐ + +``` +ecard/ +โ”œโ”€โ”€ index.php # ๋ฉ”์ธ UI (React ๊ธฐ๋ฐ˜) +โ”œโ”€โ”€ api/ +โ”‚ โ”œโ”€โ”€ barobill_card_config.php # ๋ฐ”๋กœ๋นŒ ์นด๋“œ API ์„ค์ • +โ”‚ โ”œโ”€โ”€ cards.php # ๋“ฑ๋ก๋œ ์นด๋“œ ๋ชฉ๋ก API +โ”‚ โ””โ”€โ”€ usage.php # ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ API +โ””โ”€โ”€ README.md # ์ด ๋ฌธ์„œ +``` + +## ๐Ÿ”Œ API ์—”๋“œํฌ์ธํŠธ + +### ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ +``` +GET /ecard/api/cards.php +``` + +**์‘๋‹ต ์˜ˆ์‹œ:** +```json +{ + "success": true, + "cards": [ + { + "cardNum": "1234-****-****-5678", + "cardCompany": "02", + "cardCompanyName": "KB๊ตญ๋ฏผ", + "alias": "๋ฒ•์ธ์นด๋“œ1", + "status": "1", + "statusName": "์ •์ƒ" + } + ], + "count": 1 +} +``` + +### ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ +``` +GET /ecard/api/usage.php?type=period&startDate=20241101&endDate=20241130 +``` + +**ํŒŒ๋ผ๋ฏธํ„ฐ:** +| ํŒŒ๋ผ๋ฏธํ„ฐ | ์„ค๋ช… | ๊ธฐ๋ณธ๊ฐ’ | +|---------|------|--------| +| `type` | ์กฐํšŒ ํƒ€์ž… (period/daily/monthly) | `period` | +| `cardNum` | ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’=์ „์ฒด) | - | +| `startDate` | ์‹œ์ž‘์ผ (YYYYMMDD) - period์šฉ | 30์ผ ์ „ | +| `endDate` | ์ข…๋ฃŒ์ผ (YYYYMMDD) - period์šฉ | ์˜ค๋Š˜ | +| `baseDate` | ๊ธฐ์ค€์ผ (YYYYMMDD) - daily์šฉ | ์˜ค๋Š˜ | +| `baseMonth` | ๊ธฐ์ค€์›” (YYYYMM) - monthly์šฉ | ์ด๋ฒˆ๋‹ฌ | +| `page` | ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ | `1` | +| `limit` | ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ | `50` | + +**์‘๋‹ต ์˜ˆ์‹œ:** +```json +{ + "success": true, + "data": { + "logs": [ + { + "cardNum": "1234-****-****-5678", + "approvalNum": "12345678", + "approvalDate": "2024-11-15", + "approvalTime": "14:30:25", + "merchantName": "์Šคํƒ€๋ฒ…์Šค ๊ฐ•๋‚จ์ ", + "amount": 5000, + "totalAmountFormatted": "5,000", + "approvalTypeName": "์Šน์ธ", + "installmentName": "์ผ์‹œ๋ถˆ" + } + ], + "pagination": { + "currentPage": 1, + "countPerPage": 50, + "maxPageNum": 1, + "totalCount": 15 + }, + "summary": { + "totalAmount": 150000, + "count": 15, + "approvalCount": 14, + "cancelCount": 1 + } + } +} +``` + +## ๐ŸŽจ UI ๊ธฐ๋Šฅ + +- **์นด๋“œ ์„ ํƒ**: ํŠน์ • ์นด๋“œ ๋˜๋Š” ์ „์ฒด ์นด๋“œ ์กฐํšŒ +- **๊ธฐ๊ฐ„ ์„ค์ •**: ๋‚ ์งœ ๋ฒ”์œ„ ์ง์ ‘ ์„ ํƒ ๋˜๋Š” ๋น ๋ฅธ ์„ ํƒ (์˜ค๋Š˜, 7์ผ, 30์ผ, 3๊ฐœ์›”, 6๊ฐœ์›”) +- **ํ†ต๊ณ„ ๋Œ€์‹œ๋ณด๋“œ**: ์ด ์‚ฌ์šฉ๊ธˆ์•ก, ์‚ฌ์šฉ๊ฑด์ˆ˜, ์ทจ์†Œ๊ฑด์ˆ˜ ํ‘œ์‹œ +- **์‚ฌ์šฉ๋‚ด์—ญ ํ…Œ์ด๋ธ”**: ์Šน์ธ์ผ์‹œ, ๊ฐ€๋งน์ ๋ช…, ๊ธˆ์•ก, ํ• ๋ถ€, ์Šน์ธ/์ทจ์†Œ ๊ตฌ๋ถ„ + +## โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ + +1. ๋ฐ”๋กœ๋นŒ ์นด๋“œ์กฐํšŒ ์„œ๋น„์Šค๋Š” **์œ ๋ฃŒ ์„œ๋น„์Šค**์ž…๋‹ˆ๋‹ค. +2. ์นด๋“œ ๋“ฑ๋ก ์‹œ **์นด๋“œ์‚ฌ ์›น ID/๋น„๋ฐ€๋ฒˆํ˜ธ**๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. +3. ์นด๋“œ์‚ฌ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๋ฏ€๋กœ **์‹ค์‹œ๊ฐ„ ์กฐํšŒ๊ฐ€ ์•„๋‹ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค** (๋ณดํ†ต 1์ผ 1ํšŒ ์ˆ˜์ง‘). +4. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ๋Š” ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹Œ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๊ฐ€ ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค. + +## ๐Ÿ”— ์ฐธ๊ณ  ๋ฌธ์„œ + +- [๋ฐ”๋กœ๋นŒ ์นด๋“œ์กฐํšŒ API ๋ ˆํผ๋Ÿฐ์Šค](https://dev.barobill.co.kr/docs/references/์นด๋“œ์กฐํšŒ-API) +- [๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ](https://dev.barobill.co.kr) + diff --git a/eaccount/api/account_status.php b/eaccount/api/account_status.php new file mode 100644 index 0000000..79fa3d6 --- /dev/null +++ b/eaccount/api/account_status.php @@ -0,0 +1,340 @@ +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; +} +?> + diff --git a/eaccount/api/accounts.php b/eaccount/api/accounts.php new file mode 100644 index 0000000..505dd71 --- /dev/null +++ b/eaccount/api/accounts.php @@ -0,0 +1,245 @@ + $availOnly + ]); + + if ($result['success']) { + $accounts = []; + $data = $result['data']; + + // ์—๋Ÿฌ ์ฝ”๋“œ ์ฒดํฌ (์ „์ฒด ์‘๋‹ต ๋ ˆ๋ฒจ) + if (isset($data->BankAccountEx)) { + // ๋‹จ์ผ ๊ฐ์ฒด๊ฐ€ ์—๋Ÿฌ ์ฝ”๋“œ์ธ ๊ฒฝ์šฐ + if (is_numeric($data->BankAccountEx) && $data->BankAccountEx < 0) { + $errorCode = $data->BankAccountEx; + $errorMsg = '๊ณ„์ขŒ ๋ชฉ๋ก ์กฐํšŒ ์‹คํŒจ: ' . $errorCode; + + // ์ƒ์„ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋งคํ•‘ + if ($errorCode == -50214) { + $errorMsg = '์€ํ–‰ ๋กœ๊ทธ์ธ ์‹คํŒจ (-50214). ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ์—์„œ ๊ณ„์ขŒ ๋น„๋ฐ€๋ฒˆํ˜ธ/์ธ์ฆ์„œ๋ฅผ ์ ๊ฒ€ํ•ด์ฃผ์„ธ์š”.'; + } else if ($errorCode == -24005) { + $errorMsg = '์‚ฌ์šฉ์ž ์ •๋ณด ๋ถˆ์ผ์น˜ (-24005). ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.'; + } else if ($errorCode == -25001) { + $errorMsg = '๋“ฑ๋ก๋œ ๊ณ„์ขŒ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค (-25001). ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ์—์„œ ๊ณ„์ขŒ๋ฅผ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”.'; + } + + echo json_encode([ + 'success' => false, + 'error' => $errorMsg, + 'error_code' => $errorCode + ], JSON_UNESCAPED_UNICODE); + return; + } + } + + // ์‹ค์ œ SOAP ์‘๋‹ต ๊ตฌ์กฐ ํ™•์ธ: + // GetBankAccountExResult -> BankAccount (๋‹จ์ผ ๊ฐ์ฒด ๋˜๋Š” ๋ฐฐ์—ด) + // ๋˜๋Š” BankAccountEx (๋ฐฐ์—ด) - ๋‹ค๋ฅธ API ๋ฒ„์ „์ผ ์ˆ˜ ์žˆ์Œ + + $accountList = []; + + // ์šฐ์„ ์ˆœ์œ„ 1: BankAccount ํ™•์ธ (์‹ค์ œ ์‘๋‹ต ๊ตฌ์กฐ) + 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)) { + if (is_array($data->BankAccountEx)) { + $accountList = $data->BankAccountEx; + } else if (is_object($data->BankAccountEx)) { + // ๋‹จ์ผ ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ + $accountList = [$data->BankAccountEx]; + } + } + + foreach ($accountList as $acc) { + // ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์Šคํ‚ต + if (!is_object($acc)) { + continue; + } + + // ์—๋Ÿฌ ์ฝ”๋“œ ์ฒดํฌ (๊ฐœ๋ณ„ ๊ณ„์ขŒ ๋ ˆ๋ฒจ) + if (isset($acc->BankAccountNum)) { + // BankAccountNum์ด ์Œ์ˆ˜์ธ ๊ฒฝ์šฐ ์—๋Ÿฌ ์ฝ”๋“œ + if (is_numeric($acc->BankAccountNum) && $acc->BankAccountNum < 0) { + 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 = isset($acc->UseState) ? intval($acc->UseState) : 1; + + $accounts[] = [ + 'bankAccountNum' => $acc->BankAccountNum ?? '', + 'bankCode' => $bankCode, + 'bankName' => getBankName($bankCode) ?: ($acc->BankName ?? ''), + 'accountName' => $acc->AccountName ?? '', // ๊ณ„์ขŒ ๋ณ„์นญ/์ด๋ฆ„ + 'accountType' => $acc->AccountType ?? '', // 1:์ž…์ถœ๊ธˆ, 2:์˜ˆ์ ๊ธˆ + 'currency' => $acc->Currency ?? 'KRW', + 'issueDate' => $acc->IssueDate ?? '', + 'balance' => $acc->Balance ?? 0, + 'status' => $useState // 1:์‚ฌ์šฉ, 0:์ค‘์ง€, 2:ํ•ด์ง€ + ]; + } + + $response = [ + 'success' => true, + 'accounts' => $accounts, + 'count' => count($accounts) + ]; + + // ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถ”๊ฐ€ + if (isset($result['debug'])) { + $response['debug'] = $result['debug']; + } + + echo json_encode($response, JSON_UNESCAPED_UNICODE); + } else { + // API ํ˜ธ์ถœ ์‹คํŒจ ์‹œ (์˜ˆ: SoapClient ๋ฏธ์„ค์น˜, ํ†ต์‹  ๋“ฑ) ๋กœ์ปฌ DB์—์„œ ์กฐํšŒ + error_log('๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ์‹คํŒจ, ๋กœ์ปฌ DB ์กฐํšŒ ์‹œ๋„: ' . $result['error']); + + require_once(getenv('DOCUMENT_ROOT') . '/session.php'); + require_once(getenv('DOCUMENT_ROOT') . '/lib/mydb.php'); + + $accounts = []; + $selectedTenantId = $_SESSION['eaccount_tenant_id'] ?? null; + + if ($selectedTenantId) { + try { + $pdo = db_connect(); + if ($pdo) { + // ๋กœ์ปฌ DB์—์„œ ๊ณ„์ขŒ ์ •๋ณด ์กฐํšŒ + $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); + + foreach ($localAccounts as $acc) { + // ์€ํ–‰๋ช… ๋ณ€ํ™˜ + $bankName = getBankName($acc['bank_code']); + + $accounts[] = [ + 'bankAccountNum' => $acc['account_num'], + 'bankCode' => $acc['bank_code'], + 'bankName' => $bankName, + 'accountName' => $bankName . ' ' . $acc['account_num'], + 'accountType' => '', // ๋กœ์ปฌ ์ •๋ณด ์—†์Œ + 'currency' => 'KRW', + 'issueDate' => '', + 'balance' => 0, // ์ž”์•ก ์ •๋ณด ์—†์Œ + 'status' => 1, // ๊ธฐ๋ณธ๊ฐ’: ์‚ฌ์šฉ์ค‘ + 'source' => 'local_db_fallback', + 'error_message' => 'API ์—ฐ๋™ ์‹คํŒจ๋กœ ๋กœ์ปฌ ๋ฐ์ดํ„ฐ ํ‘œ์‹œ' + ]; + } + } + } catch (Exception $dbEx) { + error_log('๋กœ์ปฌ DB ์กฐํšŒ ์‹คํŒจ: ' . $dbEx->getMessage()); + } + } + + // ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด ์„ฑ๊ณต์œผ๋กœ masquerade + if (!empty($accounts)) { + echo json_encode([ + 'success' => true, + 'accounts' => $accounts, + 'count' => count($accounts), + 'message' => '๋ฐ”๋กœ๋นŒ API ์—ฐ๋™์— ์‹คํŒจํ•˜์—ฌ ๋กœ์ปฌ ์ €์žฅ๋œ ๊ณ„์ขŒ ๋ชฉ๋ก์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.', + 'api_error' => $result['error'] + ], JSON_UNESCAPED_UNICODE); + } else { + // ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋„ ์—†์œผ๋ฉด ์—๋Ÿฌ ๋ฆฌํ„ด + echo json_encode([ + 'success' => false, + 'error' => $result['error'], + 'error_code' => $result['error_code'] ?? null + ], JSON_UNESCAPED_UNICODE); + } + } +} catch (Exception $e) { + echo json_encode([ + 'success' => false, + 'error' => '์„œ๋ฒ„ ์˜ค๋ฅ˜: ' . $e->getMessage() + ], 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; +} +?> diff --git a/eaccount/api/barobill_account_config.php b/eaccount/api/barobill_account_config.php new file mode 100644 index 0000000..a1053c7 --- /dev/null +++ b/eaccount/api/barobill_account_config.php @@ -0,0 +1,366 @@ +load(); + +// ์ธ์ฆ์„œ ํ‚ค(CERTKEY) ํŒŒ์ผ ๊ฒฝ๋กœ +$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 ์ฝ๊ธฐ +$barobillCertKey = ''; +if (file_exists($certKeyFile)) { + $content = trim(file_get_contents($certKeyFile)); + + // ์„ค๋ช… ํ…์ŠคํŠธ ํ•„ํ„ฐ๋ง: ์‹ค์ œ CERTKEY๋งŒ ์ถ”์ถœ + // ์„ค๋ช… ํ…์ŠคํŠธ ํŒจํ„ด ์ฒดํฌ + $isPlaceholder = false; + $placeholderPatterns = [ + '/^\[์—ฌ๊ธฐ์—/', // [์—ฌ๊ธฐ์—๋กœ ์‹œ์ž‘ + '/^=/', // =๋กœ ์‹œ์ž‘ + '/๋ฐ”๋กœ๋นŒ CERTKEY/', // '๋ฐ”๋กœ๋นŒ CERTKEY' ๋ฌธ์ž์—ด ํฌํ•จ + '/================================/', // ๊ตฌ๋ถ„์„  ํฌํ•จ + '/์„ค์ • ๋ฐฉ๋ฒ•:/', // '์„ค์ • ๋ฐฉ๋ฒ•:' ํฌํ•จ + '/์ธ์ฆ์„œ ๊ด€๋ฆฌ/', // '์ธ์ฆ์„œ ๊ด€๋ฆฌ' ํฌํ•จ + '/๊ฐœ๋ฐœ์ž์„ผํ„ฐ/', // '๊ฐœ๋ฐœ์ž์„ผํ„ฐ' ํฌํ•จ + '/โš ๏ธ/', // ๊ฒฝ๊ณ  ์ด๋ชจ์ง€ ํฌํ•จ + '/์ฐธ๊ณ :/', // '์ฐธ๊ณ :' ํฌํ•จ + ]; + + foreach ($placeholderPatterns as $pattern) { + if (preg_match($pattern, $content)) { + $isPlaceholder = true; + break; + } + } + + // ์‹ค์ œ CERTKEY๋Š” ๋ณดํ†ต 20์ž ์ด์ƒ์˜ ์˜๋ฌธ/์ˆซ์ž ์กฐํ•ฉ + // ์„ค๋ช… ํ…์ŠคํŠธ๊ฐ€ ์•„๋‹ˆ๊ณ , ์ถฉ๋ถ„ํžˆ ๊ธด ๊ฒฝ์šฐ์—๋งŒ CERTKEY๋กœ ์ธ์‹ + if (!empty($content) && !$isPlaceholder && strlen($content) >= 10) { + // ์ถ”๊ฐ€ ๊ฒ€์ฆ: ์‹ค์ œ CERTKEY๋Š” ๋ณดํ†ต ์˜๋ฌธ/์ˆซ์ž/ํ•˜์ดํ”ˆ ์กฐํ•ฉ + // ์„ค๋ช… ํ…์ŠคํŠธ๋Š” ํ•œ๊ธ€์ด๋‚˜ ํŠน์ˆ˜๋ฌธ์ž๊ฐ€ ๋งŽ์Œ + $koreanCharCount = preg_match_all('/[๊ฐ€-ํžฃ]/u', $content); + $totalCharCount = mb_strlen($content, 'UTF-8'); + + // ํ•œ๊ธ€ ๋น„์œจ์ด 10% ๋ฏธ๋งŒ์ด๊ณ , ๊ธธ์ด๊ฐ€ ์ ์ ˆํ•˜๋ฉด CERTKEY๋กœ ์ธ์‹ + if ($koreanCharCount / max($totalCharCount, 1) < 0.1) { + $barobillCertKey = $content; + } + } +} +if (empty($barobillCertKey) && file_exists($legacyApiKeyFile)) { + $barobillCertKey = trim(file_get_contents($legacyApiKeyFile)); +} + +// ์‚ฌ์—…์ž๋ฒˆํ˜ธ ์ฝ๊ธฐ +$barobillCorpNum = ''; +if (file_exists($corpNumFile)) { + $content = trim(file_get_contents($corpNumFile)); + if (!empty($content) && !preg_match('/^\[์—ฌ๊ธฐ์—/', $content)) { + $barobillCorpNum = str_replace('-', '', $content); + } +} + +// ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ํ™•์ธ +$isTestMode = false; +if (file_exists($testModeFile)) { + $testMode = trim(file_get_contents($testModeFile)); + $isTestMode = (strtolower($testMode) === 'test' || strtolower($testMode) === 'true'); +} + +// ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (๊ณ„์ขŒ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ์— ํ•„์š”) +// ๋นˆ ๊ฐ’์ด๋ฉด ์ „์ฒด ๊ณ„์ขŒ ์กฐํšŒ, ํŠน์ • ์‚ฌ์šฉ์ž๋งŒ ์กฐํšŒํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž ID ์ž…๋ ฅ +$barobillUserIdFile = getenv('DOCUMENT_ROOT') . '/apikey/barobill_user_id.txt'; +$barobillUserId = ''; +if (file_exists($barobillUserIdFile)) { + $content = trim(file_get_contents($barobillUserIdFile)); + if (!empty($content) && !preg_match('/^\[์—ฌ๊ธฐ์—/', $content)) { + $barobillUserId = $content; + } +} + +// ํ…Œ๋„ŒํŠธ๋ณ„ ์„ค์ • (DB์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ) +require_once(getenv('DOCUMENT_ROOT') . '/session.php'); +require_once(getenv('DOCUMENT_ROOT') . '/lib/mydb.php'); + +$selectedTenantId = $_SESSION['eaccount_tenant_id'] ?? null; + +// DB์—์„œ ํ…Œ๋„ŒํŠธ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ +if ($selectedTenantId) { + try { + $pdo = db_connect(); + if ($pdo) { + $sql = "SELECT id, company_name, corp_num, barobill_user_id + FROM {$DB}.barobill_companies + WHERE id = ?"; + $stmt = $pdo->prepare($sql); + $stmt->execute([$selectedTenantId]); + $tenant = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($tenant) { + $barobillUserId = $tenant['barobill_user_id']; + $barobillCorpNum = $tenant['corp_num']; + } + } + } catch (Exception $e) { + error_log('ํ…Œ๋„ŒํŠธ ์ •๋ณด ๋กœ๋“œ ์‹คํŒจ: ' . $e->getMessage()); + } +} else { + // ์„ธ์…˜์— ํ…Œ๋„ŒํŠธ ID๊ฐ€ ์—†์œผ๋ฉด '(์ฃผ)์ฃผ์ผ๊ธฐ์—…'์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฐพ๊ธฐ + try { + $pdo = db_connect(); + if ($pdo) { + // '(์ฃผ)์ฃผ์ผ๊ธฐ์—…' ๋˜๋Š” barobill_user_id๊ฐ€ 'juil5130'์ธ ํšŒ์‚ฌ ์ฐพ๊ธฐ + $sql = "SELECT id, company_name, corp_num, barobill_user_id + FROM {$DB}.barobill_companies + WHERE company_name LIKE '%์ฃผ์ผ๊ธฐ์—…%' + OR company_name LIKE '%์ฃผ์ผ%' + OR barobill_user_id = 'juil5130' + ORDER BY id ASC + LIMIT 1"; + $stmt = $pdo->query($sql); + $tenant = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($tenant) { + $barobillUserId = $tenant['barobill_user_id']; + $barobillCorpNum = $tenant['corp_num']; + $selectedTenantId = $tenant['id']; + // ์„ธ์…˜์— ์ €์žฅ + $_SESSION['eaccount_tenant_id'] = $selectedTenantId; + } + } + } catch (Exception $e) { + error_log('๊ธฐ๋ณธ ํ…Œ๋„ŒํŠธ ์ •๋ณด ๋กœ๋“œ ์‹คํŒจ: ' . $e->getMessage()); + } +} + +/** + * ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID ๋ฐ˜ํ™˜ + */ +function getBarobillUserId() { + global $barobillUserId; + return $barobillUserId; +} + +// ๋ฐ”๋กœ๋นŒ ๊ณ„์ขŒ SOAP ์›น์„œ๋น„์Šค URL (BANK.asmx) +// ๋ฐ”๋กœ๋นŒ ๊ณ„์ขŒ SOAP ์›น์„œ๋น„์Šค URL (BANKACCOUNT.asmx) +$barobillAccountSoapUrl = $isTestMode + ? 'https://testws.baroservice.com/BANKACCOUNT.asmx?WSDL' // ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ + : 'https://ws.baroservice.com/BANKACCOUNT.asmx?WSDL'; // ์šด์˜ ํ™˜๊ฒฝ + +// SOAP ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” +$barobillAccountSoapClient = null; +$barobillInitError = ''; + +if (!empty($barobillCertKey) || $isTestMode) { + try { + // SSL ๊ฒ€์ฆ ๋น„ํ™œ์„ฑํ™” ๋ฐ ํƒ€์ž„์•„์›ƒ ์„ค์ • + $context = stream_context_create([ + 'ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'allow_self_signed' => true + ] + ]); + + $barobillAccountSoapClient = new SoapClient($barobillAccountSoapUrl, [ + 'trace' => true, + 'encoding' => 'UTF-8', + 'exceptions' => true, + 'connection_timeout' => 30, + 'stream_context' => $context, + 'cache_wsdl' => WSDL_CACHE_NONE // WSDL ์บ์‹œ ๋น„ํ™œ์„ฑํ™” + ]); + } catch (Throwable $e) { + $barobillInitError = $e->getMessage(); + error_log('๋ฐ”๋กœ๋นŒ ๊ณ„์ขŒ SOAP ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ ์‹คํŒจ: ' . $e->getMessage()); + } +} + +/** + * ๋ฐ”๋กœ๋นŒ ๊ณ„์ขŒ SOAP ์›น์„œ๋น„์Šค ํ˜ธ์ถœ ํ•จ์ˆ˜ + * + * @param string $method SOAP ๋ฉ”์„œ๋“œ๋ช… + * @param array $params SOAP ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function callBarobillAccountSOAP($method, $params = []) { + global $barobillAccountSoapClient, $barobillCertKey, $barobillCorpNum, $isTestMode, $barobillInitError, $barobillAccountSoapUrl; + + if (!$barobillAccountSoapClient) { + $errorMsg = $isTestMode + ? '๋ฐ”๋กœ๋นŒ ๊ณ„์ขŒ SOAP ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. (' . ($barobillInitError ?: '์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜') . ')' + : '๋ฐ”๋กœ๋นŒ ๊ณ„์ขŒ SOAP ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. CERTKEY๋ฅผ ํ™•์ธํ•˜์„ธ์š”. (' . ($barobillInitError ?: '์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜') . ')'; + + return [ + 'success' => false, + 'error' => $errorMsg, + 'error_detail' => [ + 'cert_key_file' => getenv('DOCUMENT_ROOT') . '/apikey/barobill_cert_key.txt', + 'soap_url' => $barobillAccountSoapUrl, + 'init_error' => $barobillInitError, + 'test_mode' => $isTestMode + ] + ]; + } + + if (empty($barobillCertKey) && !$isTestMode) { + return [ + 'success' => false, + 'error' => 'CERTKEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. apikey/barobill_cert_key.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜์„ธ์š”.' + ]; + } + + if (empty($barobillCorpNum)) { + return [ + 'success' => false, + 'error' => '์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. apikey/barobill_corp_num.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜์„ธ์š”.' + ]; + } + + // CERTKEY์™€ CorpNum ์ž๋™ ์ถ”๊ฐ€ + // ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ๋„ CERTKEY๊ฐ€ ์žˆ์œผ๋ฉด ์‚ฌ์šฉ (์ผ๋ถ€ API๋Š” ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ๋„ CERTKEY ํ•„์š”) + if (!isset($params['CERTKEY'])) { + if ($isTestMode) { + // ํ…Œ์ŠคํŠธ ๋ชจ๋“œ: CERTKEY๊ฐ€ ์žˆ์œผ๋ฉด ์‚ฌ์šฉ, ์—†์œผ๋ฉด ๋นˆ ๊ฐ’ + // ์ฃผ์˜: ์ผ๋ถ€ API๋Š” ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ๋„ CERTKEY๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Œ + $params['CERTKEY'] = !empty($barobillCertKey) ? $barobillCertKey : ''; + } else { + // ์šด์˜ ๋ชจ๋“œ: CERTKEY ํ•„์ˆ˜ + $params['CERTKEY'] = $barobillCertKey; + } + } + if (!isset($params['CorpNum'])) { + $params['CorpNum'] = $barobillCorpNum; + } + + try { + error_log('๋ฐ”๋กœ๋นŒ ๊ณ„์ขŒ API ํ˜ธ์ถœ - Method: ' . $method . ', CorpNum: ' . $barobillCorpNum); + + // SOAP ์š”์ฒญ ๋กœ๊ทธ ์ˆ˜์ง‘ (CERTKEY๋Š” ๋งˆ์Šคํ‚น) + $logParams = $params; + if (isset($logParams['CERTKEY'])) { + $logParams['CERTKEY'] = substr($logParams['CERTKEY'], 0, 8) . '...' . substr($logParams['CERTKEY'], -4); + } + + $soapRequest = [ + 'method' => $method, + 'url' => $barobillAccountSoapUrl, + 'params' => $logParams, + 'timestamp' => date('Y-m-d H:i:s') + ]; + + $result = $barobillAccountSoapClient->$method($params); + + // SOAP ์š”์ฒญ/์‘๋‹ต XML ๋กœ๊ทธ ์ˆ˜์ง‘ + $soapRequestXml = $barobillAccountSoapClient->__getLastRequest(); + $soapResponseXml = $barobillAccountSoapClient->__getLastResponse(); + + $resultProperty = $method . 'Result'; + if (isset($result->$resultProperty)) { + $resultData = $result->$resultProperty; + + // ์—๋Ÿฌ ์ฝ”๋“œ ์ฒดํฌ (์Œ์ˆ˜ ๊ฐ’ ๋˜๋Š” ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ์Œ์ˆ˜ ๊ฐ’) + $errorCode = null; + + // ์ง์ ‘ ์ˆซ์ž๋กœ ๋ฐ˜ํ™˜๋œ ๊ฒฝ์šฐ + if (is_numeric($resultData) && $resultData < 0) { + $errorCode = $resultData; + } + // ๊ฐ์ฒด ๋‚ด๋ถ€์— BankAccountNum์ด ์Œ์ˆ˜์ธ ๊ฒฝ์šฐ (์˜ˆ: -10002) + elseif (is_object($resultData)) { + if (isset($resultData->BankAccountNum) && is_numeric($resultData->BankAccountNum) && $resultData->BankAccountNum < 0) { + $errorCode = $resultData->BankAccountNum; + } + // ๋‹ค๋ฅธ ํ•„๋“œ์—์„œ๋„ ์Œ์ˆ˜ ๊ฐ’ ์ฒดํฌ + foreach (get_object_vars($resultData) as $key => $value) { + if (is_numeric($value) && $value < 0 && ($key == 'CurrentPage' || $key == 'ErrorCode' || $key == 'ResultCode')) { + $errorCode = $value; + break; + } + } + } + + if ($errorCode !== null) { + $errorMsg = '๋ฐ”๋กœ๋นŒ ๊ณ„์ขŒ API ์˜ค๋ฅ˜ ์ฝ”๋“œ: ' . $errorCode; + + // ์ƒ์„ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋งคํ•‘ + $errorMessages = [ + -10002 => '์ธ์ฆ ์‹คํŒจ (-10002). CERTKEY๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๊ฑฐ๋‚˜ ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ CERTKEY๋ฅผ ํ™•์ธํ•˜์„ธ์š”.', + -50214 => '์€ํ–‰ ๋กœ๊ทธ์ธ ์‹คํŒจ (-50214). ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ์—์„œ ๊ณ„์ขŒ ๋น„๋ฐ€๋ฒˆํ˜ธ/์ธ์ฆ์„œ๋ฅผ ์ ๊ฒ€ํ•ด์ฃผ์„ธ์š”.', + -24005 => '์‚ฌ์šฉ์ž ์ •๋ณด ๋ถˆ์ผ์น˜ (-24005). ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.', + -25001 => '๋“ฑ๋ก๋œ ๊ณ„์ขŒ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค (-25001). ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ์—์„œ ๊ณ„์ขŒ๋ฅผ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”.', + -25005 => '์กฐํšŒ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค (-25005).', + -25006 => '๊ณ„์ขŒ๋ฒˆํ˜ธ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค (-25006).', + -25007 => '์กฐํšŒ ๊ธฐ๊ฐ„์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค (-25007).', + ]; + + if (isset($errorMessages[$errorCode])) { + $errorMsg = $errorMessages[$errorCode]; + } + + return [ + 'success' => false, + 'error' => $errorMsg, + 'error_code' => $errorCode, + 'debug' => [ + 'request' => $soapRequest, + 'request_xml' => $soapRequestXml, + 'response_xml' => $soapResponseXml + ] + ]; + } + + return [ + 'success' => true, + 'data' => $resultData, + 'debug' => [ + 'request' => $soapRequest, + 'request_xml' => $soapRequestXml, + 'response_xml' => $soapResponseXml + ] + ]; + } + + return [ + 'success' => true, + 'data' => $result, + 'debug' => [ + 'request' => $soapRequest, + 'request_xml' => $soapRequestXml, + 'response_xml' => $soapResponseXml + ] + ]; + + } catch (SoapFault $e) { + return [ + 'success' => false, + 'error' => 'SOAP ์˜ค๋ฅ˜: ' . $e->getMessage(), + 'error_code' => $e->getCode() + ]; + } catch (Throwable $e) { + return [ + 'success' => false, + 'error' => 'API ํ˜ธ์ถœ ์˜ค๋ฅ˜ (์น˜๋ช…์ ): ' . $e->getMessage() + ]; + } +} +?> diff --git a/eaccount/api/barobill_card_config.php b/eaccount/api/barobill_card_config.php new file mode 100644 index 0000000..f6801bc --- /dev/null +++ b/eaccount/api/barobill_card_config.php @@ -0,0 +1,404 @@ +load(); + +// ์ธ์ฆ์„œ ํ‚ค(CERTKEY) ํŒŒ์ผ ๊ฒฝ๋กœ +$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 ์ฝ๊ธฐ +$barobillCertKey = ''; +if (file_exists($certKeyFile)) { + $content = trim(file_get_contents($certKeyFile)); + // ์„ค๋ช… ํ…์ŠคํŠธ๊ฐ€ ์•„๋‹Œ ์‹ค์ œ ํ‚ค๋งŒ ์ถ”์ถœ (๋Œ€๊ด„ํ˜ธ ์•ˆ์˜ ๋‚ด์šฉ ์ œ์™ธ, =๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ์ œ์™ธ) + if (!empty($content) && !preg_match('/^\[์—ฌ๊ธฐ์—/', $content) && !preg_match('/^=/', $content) && strpos($content, '๋ฐ”๋กœ๋นŒ CERTKEY') === false) { + $barobillCertKey = $content; + } +} +if (empty($barobillCertKey) && file_exists($legacyApiKeyFile)) { + $barobillCertKey = trim(file_get_contents($legacyApiKeyFile)); +} + +// ์‚ฌ์—…์ž๋ฒˆํ˜ธ ์ฝ๊ธฐ +$barobillCorpNum = ''; +if (file_exists($corpNumFile)) { + $content = trim(file_get_contents($corpNumFile)); + if (!empty($content) && !preg_match('/^\[์—ฌ๊ธฐ์—/', $content)) { + $barobillCorpNum = str_replace('-', '', $content); + } +} + +// ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ํ™•์ธ +$isTestMode = false; +if (file_exists($testModeFile)) { + $testMode = trim(file_get_contents($testModeFile)); + $isTestMode = (strtolower($testMode) === 'test' || strtolower($testMode) === 'true'); +} + +// ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ์— ํ•„์š”) +// ๋นˆ ๊ฐ’์ด๋ฉด ์ „์ฒด ์นด๋“œ ์กฐํšŒ, ํŠน์ • ์‚ฌ์šฉ์ž๋งŒ ์กฐํšŒํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž ID ์ž…๋ ฅ +$barobillUserIdFile = getenv('DOCUMENT_ROOT') . '/apikey/barobill_user_id.txt'; +$barobillUserId = ''; +if (file_exists($barobillUserIdFile)) { + $content = trim(file_get_contents($barobillUserIdFile)); + if (!empty($content) && !preg_match('/^\[์—ฌ๊ธฐ์—/', $content)) { + $barobillUserId = $content; + } +} + +/** + * ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID ๋ฐ˜ํ™˜ + */ +function getBarobillUserId() { + global $barobillUserId; + return $barobillUserId; +} + +// ๋ฐ”๋กœ๋นŒ ์นด๋“œ SOAP ์›น์„œ๋น„์Šค URL +$barobillCardSoapUrl = $isTestMode + ? 'https://testws.baroservice.com/CARD.asmx?WSDL' // ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ + : 'https://ws.baroservice.com/CARD.asmx?WSDL'; // ์šด์˜ ํ™˜๊ฒฝ + +// SOAP ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” +$barobillCardSoapClient = null; +if (!empty($barobillCertKey) || $isTestMode) { + try { + $barobillCardSoapClient = new SoapClient($barobillCardSoapUrl, [ + 'trace' => true, + 'encoding' => 'UTF-8', + 'exceptions' => true, + 'connection_timeout' => 30 + ]); + } catch (Throwable $e) { + error_log('๋ฐ”๋กœ๋นŒ ์นด๋“œ SOAP ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ ์‹คํŒจ: ' . $e->getMessage()); + } +} + +/** + * ๋ฐ”๋กœ๋นŒ ์นด๋“œ SOAP ์›น์„œ๋น„์Šค ํ˜ธ์ถœ ํ•จ์ˆ˜ + * + * @param string $method SOAP ๋ฉ”์„œ๋“œ๋ช… + * @param array $params SOAP ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function callBarobillCardSOAP($method, $params = []) { + global $barobillCardSoapClient, $barobillCertKey, $barobillCorpNum, $isTestMode; + + if (!$barobillCardSoapClient) { + return [ + 'success' => false, + 'error' => '๋ฐ”๋กœ๋นŒ ์นด๋“œ SOAP ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. CERTKEY๋ฅผ ํ™•์ธํ•˜์„ธ์š”.', + 'error_detail' => [ + 'cert_key_file' => getenv('DOCUMENT_ROOT') . '/apikey/barobill_cert_key.txt', + 'soap_url' => $isTestMode ? 'https://testws.baroservice.com/CARD.asmx?WSDL' : 'https://ws.baroservice.com/CARD.asmx?WSDL' + ] + ]; + } + + if (empty($barobillCertKey) && !$isTestMode) { + return [ + 'success' => false, + 'error' => 'CERTKEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. apikey/barobill_cert_key.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜์„ธ์š”.' + ]; + } + + if (empty($barobillCorpNum)) { + return [ + 'success' => false, + 'error' => '์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. apikey/barobill_corp_num.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜์„ธ์š”.' + ]; + } + + // CERTKEY์™€ CorpNum ์ž๋™ ์ถ”๊ฐ€ + if (!isset($params['CERTKEY'])) { + $params['CERTKEY'] = $barobillCertKey; + } + if (!isset($params['CorpNum'])) { + $params['CorpNum'] = $barobillCorpNum; + } + + try { + error_log('๋ฐ”๋กœ๋นŒ ์นด๋“œ API ํ˜ธ์ถœ - Method: ' . $method . ', CorpNum: ' . $barobillCorpNum); + + $result = $barobillCardSoapClient->$method($params); + + $resultProperty = $method . 'Result'; + if (isset($result->$resultProperty)) { + $resultData = $result->$resultProperty; + + // ์—๋Ÿฌ ์ฝ”๋“œ ์ฒดํฌ (์Œ์ˆ˜ ๊ฐ’) + if (is_numeric($resultData) && $resultData < 0) { + return [ + 'success' => false, + 'error' => '๋ฐ”๋กœ๋นŒ ์นด๋“œ API ์˜ค๋ฅ˜ ์ฝ”๋“œ: ' . $resultData, + 'error_code' => $resultData + ]; + } + + return [ + 'success' => true, + 'data' => $resultData + ]; + } + + return [ + 'success' => true, + 'data' => $result + ]; + + } catch (SoapFault $e) { + return [ + 'success' => false, + 'error' => 'SOAP ์˜ค๋ฅ˜: ' . $e->getMessage(), + 'error_code' => $e->getCode() + ]; + } catch (Throwable $e) { + return [ + 'success' => false, + 'error' => 'API ํ˜ธ์ถœ ์˜ค๋ฅ˜ (์น˜๋ช…์ ): ' . $e->getMessage() + ]; + } +} + +/** + * ๋“ฑ๋ก๋œ ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ (GetCardEx2 API ์‚ฌ์šฉ) + * API ๋ ˆํผ๋Ÿฐ์Šค: https://dev.barobill.co.kr/docs/references/์นด๋“œ์กฐํšŒ-API#GetCardEx2 + * + * @param int $availOnly 0: ์ „์ฒด, 1: ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ์นด๋“œ๋งŒ + * @return array ์นด๋“œ ๋ชฉ๋ก + */ +function getCardList($availOnly = 0) { + $result = callBarobillCardSOAP('GetCardEx2', [ + 'AvailOnly' => $availOnly + ]); + + if (!$result['success']) { + return $result; + } + + $cards = []; + $data = $result['data']; + + // GetCardEx2๋Š” CardEx ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ + if (!isset($data->CardEx)) { + return ['success' => true, 'data' => []]; + } + + if (!is_array($data->CardEx)) { + $cards = [$data->CardEx]; + } else { + $cards = $data->CardEx; + } + + // ์—๋Ÿฌ ์ฒดํฌ: CardNum์ด ์Œ์ˆ˜๋ฉด ์—๋Ÿฌ ์ฝ”๋“œ + if (count($cards) == 1 && isset($cards[0]->CardNum) && $cards[0]->CardNum < 0) { + return [ + 'success' => false, + 'error' => '์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ ์‹คํŒจ', + 'error_code' => $cards[0]->CardNum + ]; + } + + return ['success' => true, 'data' => $cards]; +} + +/** + * ๊ธฐ๊ฐ„๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ + * + * @param string $cardNum ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @param string $startDate ์‹œ์ž‘์ผ (YYYYMMDD) + * @param string $endDate ์ข…๋ฃŒ์ผ (YYYYMMDD) + * @param int $countPerPage ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ + * @param int $currentPage ํ˜„์žฌ ํŽ˜์ด์ง€ + * @param int $orderDirection ์ •๋ ฌ (1: ์˜ค๋ฆ„์ฐจ์ˆœ, 2: ๋‚ด๋ฆผ์ฐจ์ˆœ) + * @param string $userId ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @return array ์‚ฌ์šฉ๋‚ด์—ญ + */ +function getPeriodCardUsage($cardNum = '', $startDate = '', $endDate = '', $countPerPage = 50, $currentPage = 1, $orderDirection = 2, $userId = '') { + global $barobillCorpNum; + + // ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID ํŒŒ์ผ์—์„œ ์ฝ๊ธฐ (์—†์œผ๋ฉด ๋นˆ๊ฐ’) + $barobillUserId = getBarobillUserId(); + if (!empty($userId)) { + $barobillUserId = $userId; + } + + $result = callBarobillCardSOAP('GetPeriodCardApprovalLog', [ + 'ID' => $barobillUserId, + 'CardNum' => $cardNum, + 'StartDate' => $startDate, + 'EndDate' => $endDate, + 'CountPerPage' => $countPerPage, + 'CurrentPage' => $currentPage, + 'OrderDirection' => $orderDirection + ]); + + if (!$result['success']) { + return $result; + } + + return parseCardUsageResult($result['data']); +} + +/** + * ์ผ๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ + * + * @param string $cardNum ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @param string $baseDate ๊ธฐ์ค€์ผ (YYYYMMDD) + * @param int $countPerPage ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ + * @param int $currentPage ํ˜„์žฌ ํŽ˜์ด์ง€ + * @param int $orderDirection ์ •๋ ฌ (1: ์˜ค๋ฆ„์ฐจ์ˆœ, 2: ๋‚ด๋ฆผ์ฐจ์ˆœ) + * @param string $userId ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @return array ์‚ฌ์šฉ๋‚ด์—ญ + */ +function getDailyCardUsage($cardNum = '', $baseDate = '', $countPerPage = 50, $currentPage = 1, $orderDirection = 2, $userId = '') { + $barobillUserId = getBarobillUserId(); + if (!empty($userId)) { + $barobillUserId = $userId; + } + + $result = callBarobillCardSOAP('GetDailyCardApprovalLog', [ + 'ID' => $barobillUserId, + 'CardNum' => $cardNum, + 'BaseDate' => $baseDate, + 'CountPerPage' => $countPerPage, + 'CurrentPage' => $currentPage, + 'OrderDirection' => $orderDirection + ]); + + if (!$result['success']) { + return $result; + } + + return parseCardUsageResult($result['data']); +} + +/** + * ์›”๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ + * + * @param string $cardNum ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @param string $baseMonth ๊ธฐ์ค€์›” (YYYYMM) + * @param int $countPerPage ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ + * @param int $currentPage ํ˜„์žฌ ํŽ˜์ด์ง€ + * @param int $orderDirection ์ •๋ ฌ (1: ์˜ค๋ฆ„์ฐจ์ˆœ, 2: ๋‚ด๋ฆผ์ฐจ์ˆœ) + * @param string $userId ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @return array ์‚ฌ์šฉ๋‚ด์—ญ + */ +function getMonthlyCardUsage($cardNum = '', $baseMonth = '', $countPerPage = 50, $currentPage = 1, $orderDirection = 2, $userId = '') { + $barobillUserId = getBarobillUserId(); + if (!empty($userId)) { + $barobillUserId = $userId; + } + + $result = callBarobillCardSOAP('GetMonthlyCardApprovalLog', [ + 'ID' => $barobillUserId, + 'CardNum' => $cardNum, + 'BaseMonth' => $baseMonth, + 'CountPerPage' => $countPerPage, + 'CurrentPage' => $currentPage, + 'OrderDirection' => $orderDirection + ]); + + if (!$result['success']) { + return $result; + } + + return parseCardUsageResult($result['data']); +} + +/** + * ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ๊ฒฐ๊ณผ ํŒŒ์‹ฑ + * + * @param object $data SOAP ์‘๋‹ต ๋ฐ์ดํ„ฐ + * @return array ํŒŒ์‹ฑ๋œ ๊ฒฐ๊ณผ + */ +function parseCardUsageResult($data) { + // ์—๋Ÿฌ ์ฒดํฌ + if (isset($data->CurrentPage) && $data->CurrentPage < 0) { + $errorCode = $data->CurrentPage; + + // -24005: ์กฐํšŒ ๋ฐ์ดํ„ฐ ์—†์Œ (์ •์ƒ ์ผ€์ด์Šค๋กœ ์ฒ˜๋ฆฌ) + // -24001: ๋“ฑ๋ก๋œ ์นด๋“œ ์—†์Œ + // -24002: ์กฐํšŒ ๊ธฐ๊ฐ„ ์˜ค๋ฅ˜ + if ($errorCode == -24005 || $errorCode == -24001) { + // ๋ฐ์ดํ„ฐ ์—†์Œ - ๋นˆ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ (์—๋Ÿฌ๊ฐ€ ์•„๋‹˜) + return [ + 'success' => true, + 'data' => [ + 'currentPage' => 1, + 'countPerPage' => 50, + 'maxPageNum' => 1, + 'maxIndex' => 0, + 'logs' => [] + ] + ]; + } + + return [ + 'success' => false, + 'error' => '์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ ์‹คํŒจ', + 'error_code' => $errorCode + ]; + } + + $logs = []; + if (isset($data->CardLogList) && isset($data->CardLogList->CardApprovalLog)) { + if (!is_array($data->CardLogList->CardApprovalLog)) { + $logs = [$data->CardLogList->CardApprovalLog]; + } else { + $logs = $data->CardLogList->CardApprovalLog; + } + } + + return [ + 'success' => true, + 'data' => [ + 'currentPage' => $data->CurrentPage ?? 1, + 'countPerPage' => $data->CountPerPage ?? 50, + 'maxPageNum' => $data->MaxPageNum ?? 1, + 'maxIndex' => $data->MaxIndex ?? 0, + 'logs' => $logs + ] + ]; +} + +/** + * ์นด๋“œ ๋“ฑ๋ก + * + * @param array $cardData ์นด๋“œ ๋ฐ์ดํ„ฐ + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function registerCard($cardData) { + return callBarobillCardSOAP('RegistCardEx', [ + 'CollectCycle' => $cardData['collectCycle'] ?? '1', // ์ˆ˜์ง‘์ฃผ๊ธฐ (1: 1์ผ 1ํšŒ) + 'CardCompany' => $cardData['cardCompany'] ?? '', // ์นด๋“œ์‚ฌ ์ฝ”๋“œ + 'CardType' => $cardData['cardType'] ?? '1', // ์นด๋“œ ์ข…๋ฅ˜ (1: ๊ฐœ์ธ, 2: ๋ฒ•์ธ) + 'CardNum' => $cardData['cardNum'] ?? '', // ์นด๋“œ๋ฒˆํ˜ธ + 'WebId' => $cardData['webId'] ?? '', // ์นด๋“œ์‚ฌ ์›น ID + 'WebPwd' => $cardData['webPwd'] ?? '', // ์นด๋“œ์‚ฌ ์›น ๋น„๋ฐ€๋ฒˆํ˜ธ + 'Alias' => $cardData['alias'] ?? '', // ์นด๋“œ ๋ณ„์นญ + 'Usage' => $cardData['usage'] ?? '1' // ์šฉ๋„ (1: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ, 2: ๊ธฐํƒ€) + ]); +} + +?> + diff --git a/eaccount/api/cards.php b/eaccount/api/cards.php new file mode 100644 index 0000000..51dc538 --- /dev/null +++ b/eaccount/api/cards.php @@ -0,0 +1,225 @@ +CardCompanyCode ?? $card->CardCompany ?? ''; + + // ์นด๋“œ ๋ธŒ๋žœ๋“œ (๋น„์ž, ๋งˆ์Šคํ„ฐ์นด๋“œ ๋“ฑ) ์ถ”์ธก + $cardBrand = guessCardTypeFromNumber($card->CardNum ?? ''); + + // ์นด๋“œ ํšŒ์‚ฌ๋ช… (์‹ ํ•œ, KB ๋“ฑ) + $cardCompanyName = !empty($card->CardCompanyName) + ? $card->CardCompanyName + : getCardCompanyName($cardCompanyCode); + + $cards[] = [ + 'cardNum' => $card->CardNum ?? '', + 'cardNumMasked' => maskCardNumber($card->CardNum ?? ''), + 'cardCompany' => $cardCompanyCode, + 'cardCompanyName' => $cardCompanyName, + 'cardBrand' => $cardBrand, // ์นด๋“œ ๋ธŒ๋žœ๋“œ (๋น„์ž, ๋งˆ์Šคํ„ฐ์นด๋“œ ๋“ฑ) + 'alias' => $card->Alias ?? '', + 'cardType' => $card->CardType ?? '', + 'cardTypeName' => getCardTypeName($card->CardType ?? ''), + 'status' => $card->Status ?? '', + 'statusName' => getCardStatusName($card->Status ?? ''), + 'collectCycle' => $card->CollectCycle ?? '', + 'collectCycleName' => getCollectCycleName($card->CollectCycle ?? ''), + 'lastCollectDate' => formatDate($card->LastCollectDate ?? ''), + 'lastCollectResult' => $card->LastCollectResult ?? '', + 'lastCollectResultName' => getCollectResultName($card->LastCollectResult ?? ''), + 'nextExtendDate' => formatDate($card->NextExtendDate ?? ''), + 'registDate' => formatDate($card->RegistDate ?? ''), + 'webId' => $card->WebId ?? '' + ]; + } + + echo json_encode([ + 'success' => true, + 'cards' => $cards, + 'count' => count($cards) + ], JSON_UNESCAPED_UNICODE); + } else { + echo json_encode([ + 'success' => false, + 'error' => $result['error'], + 'error_code' => $result['error_code'] ?? null + ], JSON_UNESCAPED_UNICODE); + } +} catch (Exception $e) { + echo json_encode([ + 'success' => false, + 'error' => '์„œ๋ฒ„ ์˜ค๋ฅ˜: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} + +/** + * ์นด๋“œ๋ฒˆํ˜ธ ๋งˆ์Šคํ‚น + */ +function maskCardNumber($cardNum) { + if (strlen($cardNum) < 8) return $cardNum; + return substr($cardNum, 0, 4) . '-****-****-' . substr($cardNum, -4); +} + +/** + * ๋‚ ์งœ ํฌ๋งทํŒ… + */ +function formatDate($date) { + if (empty($date)) return ''; + if (strlen($date) === 8) { + return substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2); + } + return $date; +} + +/** + * ์นด๋“œ๋ฒˆํ˜ธ๋กœ ์นด๋“œ ์ข…๋ฅ˜ ์ถ”์ธก (BIN ์ฝ”๋“œ ๊ธฐ๋ฐ˜) + */ +function guessCardTypeFromNumber($cardNum) { + if (empty($cardNum) || strlen($cardNum) < 4) { + return '์นด๋“œ'; + } + + $bin = substr($cardNum, 0, 4); + + // ์ฃผ์š” ์นด๋“œ์‚ฌ BIN ์ฝ”๋“œ + $binMappings = [ + '4518' => '๋น„์ž', + '4092' => '๋น„์ž', + '4569' => '๋น„์ž', + '4563' => '๋น„์ž', + '5' => '๋งˆ์Šคํ„ฐ์นด๋“œ', // 5๋กœ ์‹œ์ž‘ + '3528' => 'JCB', + '3529' => 'JCB', + '3' => '์•„๋ฉ•์Šค/๋‹ค์ด๋„ˆ์Šค', // 34, 37๋กœ ์‹œ์ž‘ + '9' => '๊ตญ๋‚ด์ „์šฉ์นด๋“œ' + ]; + + // ์ •ํ™•ํ•œ ๋งค์นญ ์‹œ๋„ + if (isset($binMappings[$bin])) { + return $binMappings[$bin]; + } + + // ์ฒซ ๋ฒˆ์งธ ์ˆซ์ž๋กœ ๋งค์นญ ์‹œ๋„ + $firstDigit = substr($cardNum, 0, 1); + if (isset($binMappings[$firstDigit])) { + return $binMappings[$firstDigit]; + } + + return '์นด๋“œ'; +} + +/** + * ์นด๋“œ์‚ฌ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + * ๋ฐ”๋กœ๋นŒ ์นด๋“œ์‚ฌ ์ฝ”๋“œ ์ฐธ๊ณ  + */ +function getCardCompanyName($code) { + $companies = [ + '01' => '๋น„์”จ์นด๋“œ', + '02' => 'KB๊ตญ๋ฏผ์นด๋“œ', + '03' => 'ํ•˜๋‚˜์นด๋“œ(์™ธํ™˜)', + '04' => '์‚ผ์„ฑ์นด๋“œ', + '06' => '์‹ ํ•œ์นด๋“œ', + '07' => 'ํ˜„๋Œ€์นด๋“œ', + '08' => '๋กฏ๋ฐ์นด๋“œ', + '11' => 'NH๋†ํ˜‘์นด๋“œ', + '12' => '์ˆ˜ํ˜‘์นด๋“œ', + '13' => '์”จํ‹ฐ์นด๋“œ', + '14' => '์šฐ๋ฆฌ์นด๋“œ', + '15' => '๊ด‘์ฃผ์นด๋“œ', + '16' => '์ „๋ถ์นด๋“œ', + '21' => 'ํ•˜๋‚˜์นด๋“œ', + '22' => '์ œ์ฃผ์นด๋“œ', + '23' => 'SC์ œ์ผ์นด๋“œ', + '25' => 'KDB์‚ฐ์—…์นด๋“œ', + '26' => 'IBK๊ธฐ์—…์นด๋“œ', + '27' => '์ƒˆ๋งˆ์„๊ธˆ๊ณ ', + '28' => '์‹ ํ˜‘์นด๋“œ', + '29' => '์ €์ถ•์€ํ–‰', + '30' => '์šฐ์ฒด๊ตญ์นด๋“œ', + '31' => '์นด์นด์˜ค๋ฑ…ํฌ', + '32' => 'K๋ฑ…ํฌ', + '33' => 'ํ† ์Šค๋ฑ…ํฌ', + 'BC' => '๋น„์”จ์นด๋“œ', + 'KB' => 'KB๊ตญ๋ฏผ์นด๋“œ', + 'HANA' => 'ํ•˜๋‚˜์นด๋“œ', + 'SAMSUNG' => '์‚ผ์„ฑ์นด๋“œ', + 'SHINHAN' => '์‹ ํ•œ์นด๋“œ', + 'HYUNDAI' => 'ํ˜„๋Œ€์นด๋“œ', + 'LOTTE' => '๋กฏ๋ฐ์นด๋“œ', + 'NH' => 'NH๋†ํ˜‘์นด๋“œ', + 'SUHYUP' => '์ˆ˜ํ˜‘์นด๋“œ', + 'CITI' => '์”จํ‹ฐ์นด๋“œ', + 'WOORI' => '์šฐ๋ฆฌ์นด๋“œ', + 'KJBANK' => '๊ด‘์ฃผ์นด๋“œ', + 'JBBANK' => '์ „๋ถ์นด๋“œ' + ]; + return $companies[$code] ?? $code; +} + +/** + * ์นด๋“œ ์ข…๋ฅ˜ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + */ +function getCardTypeName($type) { + $types = [ + '1' => '๊ฐœ์ธ์นด๋“œ', + '2' => '๋ฒ•์ธ์นด๋“œ' + ]; + return $types[$type] ?? $type; +} + +/** + * ์นด๋“œ ์ƒํƒœ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + */ +function getCardStatusName($status) { + $statuses = [ + '0' => '๋Œ€๊ธฐ์ค‘', + '1' => '์ •์ƒ', + '2' => 'ํ•ด์ง€', + '3' => '์ˆ˜์ง‘์˜ค๋ฅ˜', + '4' => '์ผ์‹œ์ค‘์ง€' + ]; + return $statuses[$status] ?? $status; +} + +/** + * ์ˆ˜์ง‘์ฃผ๊ธฐ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + */ +function getCollectCycleName($cycle) { + $cycles = [ + '1' => '1์ผ 1ํšŒ', + '2' => '1์ผ 2ํšŒ', + '3' => '1์ผ 3ํšŒ' + ]; + return $cycles[$cycle] ?? $cycle; +} + +/** + * ์ˆ˜์ง‘๊ฒฐ๊ณผ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + */ +function getCollectResultName($result) { + $results = [ + '0' => '๋Œ€๊ธฐ', + '1' => '์„ฑ๊ณต', + '2' => '์‹คํŒจ', + '3' => '์ง„ํ–‰์ค‘' + ]; + return $results[$result] ?? $result; +} +?> + diff --git a/eaccount/api/check_api_config.php b/eaccount/api/check_api_config.php new file mode 100644 index 0000000..97f7071 --- /dev/null +++ b/eaccount/api/check_api_config.php @@ -0,0 +1,138 @@ + [ + 'file_exists' => file_exists($documentRoot . '/apikey/barobill_cert_key.txt'), + 'file_path' => $documentRoot . '/apikey/barobill_cert_key.txt', + 'is_set' => !empty($barobillCertKey), + 'length' => strlen($barobillCertKey), + 'preview' => !empty($barobillCertKey) ? substr($barobillCertKey, 0, 8) . '...' . substr($barobillCertKey, -4) : 'NOT SET', + 'raw_content' => file_exists($documentRoot . '/apikey/barobill_cert_key.txt') + ? file_get_contents($documentRoot . '/apikey/barobill_cert_key.txt') + : 'FILE NOT FOUND', + 'is_placeholder' => !empty($barobillCertKey) ? false : ( + file_exists($documentRoot . '/apikey/barobill_cert_key.txt') + ? (strpos(file_get_contents($documentRoot . '/apikey/barobill_cert_key.txt'), '[์—ฌ๊ธฐ์—') !== false + || strpos(file_get_contents($documentRoot . '/apikey/barobill_cert_key.txt'), '๋ฐ”๋กœ๋นŒ CERTKEY') !== false + || strpos(file_get_contents($documentRoot . '/apikey/barobill_cert_key.txt'), '================================') !== false) + : false + ) + ], + 'corp_num' => [ + 'file_exists' => file_exists($documentRoot . '/apikey/barobill_corp_num.txt'), + 'file_path' => $documentRoot . '/apikey/barobill_corp_num.txt', + 'is_set' => !empty($barobillCorpNum), + 'value' => $barobillCorpNum, + 'raw_content' => file_exists($documentRoot . '/apikey/barobill_corp_num.txt') + ? file_get_contents($documentRoot . '/apikey/barobill_corp_num.txt') + : 'FILE NOT FOUND' + ], + 'user_id' => [ + 'file_exists' => file_exists($documentRoot . '/apikey/barobill_user_id.txt'), + 'file_path' => $documentRoot . '/apikey/barobill_user_id.txt', + 'is_set' => !empty($barobillUserId), + 'value' => $barobillUserId, + 'raw_content' => file_exists($documentRoot . '/apikey/barobill_user_id.txt') + ? file_get_contents($documentRoot . '/apikey/barobill_user_id.txt') + : 'FILE NOT FOUND' + ], + 'test_mode' => [ + 'file_exists' => file_exists($documentRoot . '/apikey/barobill_test_mode.txt'), + 'is_active' => $isTestMode, + 'raw_content' => file_exists($documentRoot . '/apikey/barobill_test_mode.txt') + ? file_get_contents($documentRoot . '/apikey/barobill_test_mode.txt') + : 'FILE NOT FOUND' + ], + 'soap_client' => [ + 'url' => $barobillAccountSoapUrl, + 'initialized' => isset($barobillAccountSoapClient) && $barobillAccountSoapClient !== null + ], + 'hardcoded_values' => [ + 'note' => 'โš ๏ธ barobill_account_config.php์— ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ฐ’์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.', + 'check_file' => 'eaccount/api/barobill_account_config.php (62-68์ค„)' + ] +]; + +// ์‹ค์ œ API ํ˜ธ์ถœ ํ…Œ์ŠคํŠธ +// ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์ผ ๋•Œ๋Š” CERTKEY๊ฐ€ ์—†์–ด๋„ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ +$testResult = null; +$canTest = false; +if ($isTestMode) { + // ํ…Œ์ŠคํŠธ ๋ชจ๋“œ: CERTKEY ๋ถˆํ•„์š”, ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋งŒ ํ™•์ธ + $canTest = !empty($barobillCorpNum); +} else { + // ์šด์˜ ๋ชจ๋“œ: CERTKEY์™€ ์‚ฌ์—…์ž๋ฒˆํ˜ธ ๋ชจ๋‘ ํ•„์š” + $canTest = !empty($barobillCertKey) && !empty($barobillCorpNum); +} + +if ($canTest) { + try { + $testResult = callBarobillAccountSOAP('GetBankAccountEx', [ + 'AvailOnly' => 0 + ]); + + $diagnostics['api_test'] = [ + 'success' => $testResult['success'], + 'error' => $testResult['error'] ?? null, + 'error_code' => $testResult['error_code'] ?? null, + 'has_data' => isset($testResult['data']), + 'debug_available' => isset($testResult['debug']) + ]; + + if (isset($testResult['debug'])) { + $diagnostics['api_test']['request_preview'] = $testResult['debug']['request'] ?? null; + } + } catch (Exception $e) { + $diagnostics['api_test'] = [ + 'success' => false, + 'error' => 'Exception: ' . $e->getMessage() + ]; + } +} else { + if ($isTestMode) { + $diagnostics['api_test'] = [ + 'skipped' => true, + 'reason' => 'ํ…Œ์ŠคํŠธ ๋ชจ๋“œ: ์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. (CERTKEY๋Š” ๋ถˆํ•„์š”)' + ]; + } else { + $diagnostics['api_test'] = [ + 'skipped' => true, + 'reason' => '์šด์˜ ๋ชจ๋“œ: CERTKEY ๋˜๋Š” ์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.' + ]; + } +} + +echo json_encode([ + 'success' => true, + 'diagnostics' => $diagnostics, + 'recommendations' => array_filter([ + !$isTestMode && !$diagnostics['cert_key']['is_set'] ? 'CERTKEY๋ฅผ ์„ค์ •ํ•˜์„ธ์š”: apikey/barobill_cert_key.txt ํŒŒ์ผ์— ๋ฐ”๋กœ๋นŒ CERTKEY๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.' : null, + !$isTestMode && isset($diagnostics['cert_key']['is_placeholder']) && $diagnostics['cert_key']['is_placeholder'] ? 'โš ๏ธ CERTKEY ํŒŒ์ผ์— ์„ค๋ช… ํ…์ŠคํŠธ๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ์˜ ๋ชจ๋“  ์„ค๋ช…์„ ์‚ญ์ œํ•˜๊ณ  ์‹ค์ œ CERTKEY ๊ฐ’๋งŒ ์ž…๋ ฅํ•˜์„ธ์š”. (์˜ˆ: "2DD6C76C-1234-5678-ABCD-EF1234561826")' : null, + !$diagnostics['corp_num']['is_set'] ? '์‚ฌ์—…์ž๋ฒˆํ˜ธ๋ฅผ ์„ค์ •ํ•˜์„ธ์š”: apikey/barobill_corp_num.txt ํŒŒ์ผ์— ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.' : null, + !$isTestMode && $diagnostics['cert_key']['file_exists'] && empty(trim($diagnostics['cert_key']['raw_content'])) ? 'CERTKEY ํŒŒ์ผ์ด ๋น„์–ด์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ์—์„œ CERTKEY๋ฅผ ํ™•์ธํ•˜๊ณ  ์ž…๋ ฅํ•˜์„ธ์š”.' : null, + !$isTestMode && strpos($diagnostics['cert_key']['raw_content'], '[์—ฌ๊ธฐ์—') !== false ? 'CERTKEY ํŒŒ์ผ์— ์„ค๋ช… ํ…์ŠคํŠธ๊ฐ€ ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ CERTKEY ๊ฐ’๋งŒ ์ž…๋ ฅํ•˜์„ธ์š”.' : null, + isset($diagnostics['api_test']['error_code']) && $diagnostics['api_test']['error_code'] == -24005 ? '์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ์— ๋กœ๊ทธ์ธํ•˜์—ฌ ๋“ฑ๋ก๋œ ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.' : null, + isset($diagnostics['api_test']['error_code']) && $diagnostics['api_test']['error_code'] == -25001 ? '๋“ฑ๋ก๋œ ๊ณ„์ขŒ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ์—์„œ ๊ณ„์ขŒ๋ฅผ ๋จผ์ € ๋“ฑ๋กํ•˜์„ธ์š”.' : null, + $isTestMode ? 'ํ˜„์žฌ ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์ž…๋‹ˆ๋‹ค. CERTKEY๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.' : null, + ]), + 'next_steps' => [ + '1. ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ(https://www.barobill.co.kr)์— ๋กœ๊ทธ์ธ', + '2. ๋งˆ์ดํŽ˜์ด์ง€ > API ์„ค์ •์—์„œ CERTKEY ํ™•์ธ', + '3. apikey/barobill_cert_key.txt ํŒŒ์ผ์— CERTKEY ์ž…๋ ฅ (์„ค๋ช… ํ…์ŠคํŠธ ์ œ์™ธ)', + '4. apikey/barobill_corp_num.txt ํŒŒ์ผ์— ์‚ฌ์—…์ž๋ฒˆํ˜ธ ์ž…๋ ฅ (ํ•˜์ดํ”ˆ ์ œ์™ธ ๊ฐ€๋Šฅ)', + '5. (์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€ ์‚ฐํ•˜ ๊ธฐ์—…์ธ ๊ฒฝ์šฐ, barobill_account_config.php์˜ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ฐ’ ํ™•์ธ ํ•„์š”' + ] +], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); +?> + diff --git a/eaccount/api/debug_accounts.php b/eaccount/api/debug_accounts.php new file mode 100644 index 0000000..54719b0 --- /dev/null +++ b/eaccount/api/debug_accounts.php @@ -0,0 +1,273 @@ +load(); + +require_once('barobill_account_config.php'); +require_once(getenv('DOCUMENT_ROOT') . '/session.php'); +require_once(getenv('DOCUMENT_ROOT') . '/lib/mydb.php'); + +$debug = [ + 'step' => [], + 'tenant_info' => [], + 'local_db' => [], + 'barobill_api' => [], + 'final_result' => [] +]; + +try { + // Step 1: ์„ธ์…˜์—์„œ ํ…Œ๋„ŒํŠธ ID ํ™•์ธ + $selectedTenantId = $_SESSION['eaccount_tenant_id'] ?? null; + $debug['step'][] = '1. ์„ธ์…˜์—์„œ ํ…Œ๋„ŒํŠธ ID ํ™•์ธ'; + $debug['tenant_info']['session_tenant_id'] = $selectedTenantId; + + // Step 2: DB์—์„œ ํ…Œ๋„ŒํŠธ ์ •๋ณด ํ™•์ธ + $pdo = db_connect(); + if (!$pdo) { + throw new Exception("Database connection failed."); + } + + $debug['step'][] = '2. DB ์—ฐ๊ฒฐ ์„ฑ๊ณต'; + + // ํ…Œ๋„ŒํŠธ ์ •๋ณด ์กฐํšŒ + if ($selectedTenantId) { + $sql = "SELECT id, company_name, corp_num, barobill_user_id + FROM {$DB}.barobill_companies + WHERE id = ?"; + $stmt = $pdo->prepare($sql); + $stmt->execute([$selectedTenantId]); + $tenant = $stmt->fetch(PDO::FETCH_ASSOC); + + $debug['tenant_info']['db_query'] = $sql; + $debug['tenant_info']['db_params'] = [$selectedTenantId]; + $debug['tenant_info']['tenant_found'] = $tenant ? true : false; + $debug['tenant_info']['tenant_data'] = $tenant; + + if ($tenant) { + $debug['step'][] = '3. ํ…Œ๋„ŒํŠธ ์ •๋ณด ์กฐํšŒ ์„ฑ๊ณต: ' . $tenant['company_name']; + } else { + $debug['step'][] = '3. ํ…Œ๋„ŒํŠธ ์ •๋ณด ์กฐํšŒ ์‹คํŒจ: ID ' . $selectedTenantId . '๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ'; + } + } else { + // ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ฃผ์ผ๊ธฐ์—… ์ฐพ๊ธฐ + $sql = "SELECT id, company_name, corp_num, barobill_user_id + FROM {$DB}.barobill_companies + WHERE company_name LIKE '%์ฃผ์ผ๊ธฐ์—…%' + OR company_name LIKE '%์ฃผ์ผ%' + OR barobill_user_id = 'juil5130' + ORDER BY id ASC + LIMIT 1"; + $stmt = $pdo->query($sql); + $tenant = $stmt->fetch(PDO::FETCH_ASSOC); + + $debug['tenant_info']['default_search_query'] = $sql; + $debug['tenant_info']['tenant_found'] = $tenant ? true : false; + $debug['tenant_info']['tenant_data'] = $tenant; + + if ($tenant) { + $selectedTenantId = $tenant['id']; + $debug['step'][] = '3. ๊ธฐ๋ณธ ํ…Œ๋„ŒํŠธ(์ฃผ์ผ๊ธฐ์—…) ์ฐพ๊ธฐ ์„ฑ๊ณต: ' . $tenant['company_name']; + } else { + $debug['step'][] = '3. ๊ธฐ๋ณธ ํ…Œ๋„ŒํŠธ(์ฃผ์ผ๊ธฐ์—…) ์ฐพ๊ธฐ ์‹คํŒจ'; + } + } + + // Step 3: ๋กœ์ปฌ DB์—์„œ ๊ณ„์ขŒ ์ •๋ณด ์กฐํšŒ + if ($selectedTenantId) { + $debug['step'][] = '4. ๋กœ์ปฌ DB ๊ณ„์ขŒ ์ •๋ณด ์กฐํšŒ ์‹œ์ž‘'; + + $accountSql = "SELECT id, company_id, bank_code, account_num, account_pwd + FROM {$DB}.company_accounts + WHERE company_id = ? + ORDER BY id DESC"; + $accountStmt = $pdo->prepare($accountSql); + $accountStmt->execute([$selectedTenantId]); + $localAccounts = $accountStmt->fetchAll(PDO::FETCH_ASSOC); + + $debug['local_db']['query'] = $accountSql; + $debug['local_db']['params'] = [$selectedTenantId]; + $debug['local_db']['count'] = count($localAccounts); + $debug['local_db']['accounts'] = $localAccounts; + $debug['step'][] = '4. ๋กœ์ปฌ DB ๊ณ„์ขŒ ์ •๋ณด ์กฐํšŒ ์™„๋ฃŒ: ' . count($localAccounts) . '๊ฐœ'; + + // ๋ชจ๋“  ํšŒ์‚ฌ์˜ ๊ณ„์ขŒ ์ •๋ณด๋„ ํ™•์ธ (๋””๋ฒ„๊น…์šฉ) + $allAccountsSql = "SELECT ca.*, c.company_name, c.barobill_user_id + FROM {$DB}.company_accounts ca + LEFT JOIN {$DB}.barobill_companies c ON ca.company_id = c.id + ORDER BY ca.id DESC + LIMIT 20"; + $allAccountsStmt = $pdo->query($allAccountsSql); + $allAccounts = $allAccountsStmt->fetchAll(PDO::FETCH_ASSOC); + + $debug['local_db']['all_companies_accounts'] = $allAccounts; + $debug['local_db']['all_companies_accounts_count'] = count($allAccounts); + } else { + $debug['local_db']['error'] = 'ํ…Œ๋„ŒํŠธ ID๊ฐ€ ์—†์–ด์„œ ๋กœ์ปฌ DB ์กฐํšŒ ๋ถˆ๊ฐ€'; + } + + // Step 4: ๋ฐ”๋กœ๋นŒ API ์„ค์ • ํ™•์ธ + global $barobillUserId, $barobillCorpNum, $barobillCertKey, $isTestMode; + $debug['barobill_api']['config'] = [ + 'user_id' => $barobillUserId, + 'corp_num' => $barobillCorpNum, + 'cert_key_length' => strlen($barobillCertKey), + 'cert_key_preview' => !empty($barobillCertKey) ? substr($barobillCertKey, 0, 8) . '...' . substr($barobillCertKey, -4) : 'NOT SET', + 'test_mode' => $isTestMode + ]; + $debug['step'][] = '5. ๋ฐ”๋กœ๋นŒ API ์„ค์ • ํ™•์ธ ์™„๋ฃŒ'; + + // Step 5: ๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ์‹œ๋„ + $debug['step'][] = '6. ๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ์‹œ์ž‘'; + $result = callBarobillAccountSOAP('GetBankAccountEx', [ + 'AvailOnly' => 0 + ]); + + $debug['barobill_api']['success'] = $result['success']; + $debug['barobill_api']['error'] = $result['error'] ?? null; + $debug['barobill_api']['error_code'] = $result['error_code'] ?? null; + + if ($result['success']) { + $data = $result['data']; + $accountList = []; + + if (isset($data->BankAccountEx)) { + if (is_array($data->BankAccountEx)) { + $accountList = $data->BankAccountEx; + } else { + $accountList = [$data->BankAccountEx]; + } + } + + $barobillAccounts = []; + foreach ($accountList as $acc) { + if (isset($acc->BankAccountNum) && is_numeric($acc->BankAccountNum) && $acc->BankAccountNum < 0) { + continue; + } + + $barobillAccounts[] = [ + 'bankAccountNum' => $acc->BankAccountNum ?? '', + 'bankCode' => $acc->BankCode ?? '', + 'bankName' => getBankName($acc->BankCode ?? ''), + 'accountName' => $acc->AccountName ?? '', + ]; + } + + $debug['barobill_api']['accounts'] = $barobillAccounts; + $debug['barobill_api']['count'] = count($barobillAccounts); + $debug['step'][] = '6. ๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ์„ฑ๊ณต: ' . count($barobillAccounts) . '๊ฐœ ๊ณ„์ขŒ'; + } else { + $debug['barobill_api']['accounts'] = []; + $debug['barobill_api']['count'] = 0; + $debug['step'][] = '6. ๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ์‹คํŒจ: ' . ($result['error'] ?? '์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜'); + } + + // Step 6: ์ตœ์ข… ๊ฒฐ๊ณผ ํ†ตํ•ฉ + $allAccounts = []; + + // ๋กœ์ปฌ DB ๊ณ„์ขŒ ์ถ”๊ฐ€ + if (isset($localAccounts)) { + foreach ($localAccounts as $localAcc) { + $allAccounts[] = [ + 'source' => 'local_db', + 'bankAccountNum' => $localAcc['account_num'], + 'bankCode' => $localAcc['bank_code'], + 'bankName' => getBankName($localAcc['bank_code']), + ]; + } + } + + // ๋ฐ”๋กœ๋นŒ API ๊ณ„์ขŒ ์ถ”๊ฐ€ + if (isset($barobillAccounts)) { + foreach ($barobillAccounts as $barobillAcc) { + $exists = false; + foreach ($allAccounts as &$existingAcc) { + if ($existingAcc['bankAccountNum'] === $barobillAcc['bankAccountNum'] && + $existingAcc['source'] === 'local_db') { + $existingAcc['source'] = 'both'; + $exists = true; + break; + } + } + if (!$exists) { + $allAccounts[] = array_merge($barobillAcc, ['source' => 'barobill_api']); + } + } + } + + $debug['final_result']['total_count'] = count($allAccounts); + $debug['final_result']['accounts'] = $allAccounts; + $debug['step'][] = '7. ์ตœ์ข… ํ†ตํ•ฉ ์™„๋ฃŒ: ' . count($allAccounts) . '๊ฐœ ๊ณ„์ขŒ'; + + // ๋ชจ๋“  barobill_companies ๋ชฉ๋ก๋„ ํ™•์ธ + $allCompaniesSql = "SELECT id, company_name, corp_num, barobill_user_id, parent_id + FROM {$DB}.barobill_companies + ORDER BY id ASC"; + $allCompaniesStmt = $pdo->query($allCompaniesSql); + $allCompanies = $allCompaniesStmt->fetchAll(PDO::FETCH_ASSOC); + + $debug['tenant_info']['all_companies'] = $allCompanies; + $debug['tenant_info']['all_companies_count'] = count($allCompanies); + + echo json_encode([ + 'success' => true, + 'debug' => $debug, + 'summary' => [ + 'tenant_id' => $selectedTenantId, + 'tenant_name' => $tenant['company_name'] ?? '์•Œ ์ˆ˜ ์—†์Œ', + 'local_accounts_count' => count($localAccounts ?? []), + 'barobill_accounts_count' => count($barobillAccounts ?? []), + 'total_accounts_count' => count($allAccounts) + ] + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + +} catch (Exception $e) { + $debug['error'] = $e->getMessage(); + $debug['error_trace'] = $e->getTraceAsString(); + + echo json_encode([ + 'success' => false, + 'error' => $e->getMessage(), + 'debug' => $debug + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); +} + +/** + * ์€ํ–‰ ์ฝ”๋“œ -> ์€ํ–‰๋ช… ๋ณ€ํ™˜ + */ +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; +} +?> + diff --git a/eaccount/api/get_tenants.php b/eaccount/api/get_tenants.php new file mode 100644 index 0000000..1123c0f --- /dev/null +++ b/eaccount/api/get_tenants.php @@ -0,0 +1,97 @@ +load(); + +require_once(getenv('DOCUMENT_ROOT') . '/session.php'); +require_once(getenv('DOCUMENT_ROOT') . '/lib/mydb.php'); + +try { + $pdo = db_connect(); + + if (!$pdo) { + throw new Exception("Database connection failed."); + } + + // barobill_companies ํ…Œ์ด๋ธ”์—์„œ ๋ชจ๋“  ํšŒ์‚ฌ ๊ฐ€์ ธ์˜ค๊ธฐ + $sql = "SELECT c.*, p.company_name as parent_name, p.barobill_user_id as parent_user_id + FROM {$DB}.barobill_companies c + LEFT JOIN {$DB}.barobill_companies p ON c.parent_id = p.id + ORDER BY c.parent_id ASC, c.id ASC"; + $stmt = $pdo->query($sql); + $companies = $stmt->fetchAll(PDO::FETCH_ASSOC); + + // ๊ณ„์ขŒ ์ •๋ณด ํ™•์ธ (company_accounts ํ…Œ์ด๋ธ”์—์„œ) + $tenants = []; + foreach ($companies as $company) { + // ๊ณ„์ขŒ ์ •๋ณด ํ™•์ธ + $accountSql = "SELECT COUNT(*) as count FROM {$DB}.company_accounts WHERE company_id = ?"; + $accountStmt = $pdo->prepare($accountSql); + $accountStmt->execute([$company['id']]); + $accountResult = $accountStmt->fetch(PDO::FETCH_ASSOC); + $hasAccount = ($accountResult['count'] > 0); + + $tenants[] = [ + 'id' => $company['id'], + 'name' => $company['company_name'], + 'corp_num' => $company['corp_num'], + 'user_id' => $company['barobill_user_id'], + 'parent_id' => $company['parent_id'], + 'parent_name' => $company['parent_name'] ?? null, + 'has_account' => $hasAccount, + 'memo' => $company['memo'] ?? '' + ]; + } + + // ํ˜„์žฌ ์„ธ์…˜์˜ ํšŒ์‚ฌ ์ •๋ณด + $currentCompany = $mycompany ?? ''; + + // ํ˜„์žฌ ์„ ํƒ๋œ ํ…Œ๋„ŒํŠธ (์„ธ์…˜์—์„œ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ๊ธฐ๋ณธ๊ฐ’) + $selectedTenantId = $_SESSION['eaccount_tenant_id'] ?? null; + + // ์„ธ์…˜์— ์ €์žฅ๋œ tenant_id๊ฐ€ ์—†์œผ๋ฉด '(์ฃผ)์ฃผ์ผ๊ธฐ์—…'์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ • + if ($selectedTenantId === null) { + // '(์ฃผ)์ฃผ์ผ๊ธฐ์—…' ์ฐพ๊ธฐ + $defaultTenant = null; + foreach ($tenants as $tenant) { + if (strpos($tenant['name'], '์ฃผ์ผ๊ธฐ์—…') !== false || + strpos($tenant['name'], '์ฃผ์ผ') !== false || + $tenant['user_id'] === 'juil5130') { + $defaultTenant = $tenant; + break; + } + } + + // '(์ฃผ)์ฃผ์ผ๊ธฐ์—…'์„ ์ฐพ์ง€ ๋ชปํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ ํ…Œ๋„ŒํŠธ ์‚ฌ์šฉ + if ($defaultTenant) { + $selectedTenantId = $defaultTenant['id']; + } elseif (count($tenants) > 0) { + $selectedTenantId = $tenants[0]['id']; + } + + if ($selectedTenantId) { + $_SESSION['eaccount_tenant_id'] = $selectedTenantId; + } + } + + echo json_encode([ + 'success' => true, + 'tenants' => $tenants, + 'current_tenant_id' => $selectedTenantId, + 'current_company' => $currentCompany + ], JSON_UNESCAPED_UNICODE); + +} catch (Exception $e) { + echo json_encode([ + 'success' => false, + 'error' => 'ํ…Œ๋„ŒํŠธ ๋ชฉ๋ก ์กฐํšŒ ์‹คํŒจ: ' . $e->getMessage(), + 'tenants' => [], + 'current_tenant_id' => null + ], JSON_UNESCAPED_UNICODE); +} +?> \ No newline at end of file diff --git a/eaccount/api/set_tenant.php b/eaccount/api/set_tenant.php new file mode 100644 index 0000000..2fb49e5 --- /dev/null +++ b/eaccount/api/set_tenant.php @@ -0,0 +1,61 @@ +load(); + +require_once(getenv('DOCUMENT_ROOT') . '/session.php'); +require_once(getenv('DOCUMENT_ROOT') . '/lib/mydb.php'); + +$tenantId = $_POST['tenant_id'] ?? $_GET['tenant_id'] ?? ''; + +if (empty($tenantId)) { + echo json_encode([ + 'success' => false, + 'error' => 'ํ…Œ๋„ŒํŠธ ID๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.' + ], JSON_UNESCAPED_UNICODE); + exit; +} + +// DB์—์„œ ํ…Œ๋„ŒํŠธ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ +try { + $pdo = db_connect(); + if (!$pdo) { + throw new Exception("Database connection failed."); + } + + $sql = "SELECT id, company_name FROM {$DB}.barobill_companies WHERE id = ?"; + $stmt = $pdo->prepare($sql); + $stmt->execute([$tenantId]); + $tenant = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$tenant) { + echo json_encode([ + 'success' => false, + 'error' => '์œ ํšจํ•˜์ง€ ์•Š์€ ํ…Œ๋„ŒํŠธ ID์ž…๋‹ˆ๋‹ค.' + ], JSON_UNESCAPED_UNICODE); + exit; + } + + // ์„ธ์…˜์— ์ €์žฅ + $_SESSION['eaccount_tenant_id'] = $tenantId; + + echo json_encode([ + 'success' => true, + 'tenant_id' => $tenantId, + 'tenant_name' => $tenant['company_name'], + 'message' => 'ํ…Œ๋„ŒํŠธ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.' + ], JSON_UNESCAPED_UNICODE); + +} catch (Exception $e) { + echo json_encode([ + 'success' => false, + 'error' => 'ํ…Œ๋„ŒํŠธ ๋ณ€๊ฒฝ ์‹คํŒจ: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} +?> + diff --git a/eaccount/api/transactions.php b/eaccount/api/transactions.php new file mode 100644 index 0000000..2237409 --- /dev/null +++ b/eaccount/api/transactions.php @@ -0,0 +1,515 @@ + 0 // ์ „์ฒด ๊ณ„์ขŒ + ]); + + if ($accountResult['success']) { + $accountData = $accountResult['data']; + $accountList = []; + + // BankAccount ๋˜๋Š” BankAccountEx์—์„œ ๊ณ„์ขŒ ๋ชฉ๋ก ์ถ”์ถœ + if (isset($accountData->BankAccount)) { + if (is_array($accountData->BankAccount)) { + $accountList = $accountData->BankAccount; + } else if (is_object($accountData->BankAccount)) { + $accountList = [$accountData->BankAccount]; + } + } else if (isset($accountData->BankAccountEx)) { + if (is_array($accountData->BankAccountEx)) { + $accountList = $accountData->BankAccountEx; + } else if (is_object($accountData->BankAccountEx)) { + $accountList = [$accountData->BankAccountEx]; + } + } + + // ๊ฐ ๊ณ„์ขŒ๋ณ„๋กœ ๊ฑฐ๋ž˜ ๋‚ด์—ญ ์กฐํšŒ + $allLogs = []; + $allSummary = ['totalDeposit' => 0, 'totalWithdraw' => 0, 'count' => 0]; + $debugAllAccounts = []; + + foreach ($accountList as $accIndex => $acc) { + if (!is_object($acc)) continue; + + $accNum = $acc->BankAccountNum ?? ''; + if (empty($accNum) || (is_numeric($accNum) && $accNum < 0)) { + continue; // ์—๋Ÿฌ ์ฝ”๋“œ ์Šคํ‚ต + } + + // ๊ฐ ๊ณ„์ขŒ์˜ ๊ฑฐ๋ž˜ ๋‚ด์—ญ ์กฐํšŒ + $accResult = callBarobillAccountSOAP('GetPeriodBankAccountTransLog', [ + 'ID' => $userId, + 'BankAccountNum' => $accNum, + 'StartDate' => $startDate, + 'EndDate' => $endDate, + 'TransDirection' => 1, + 'CountPerPage' => 1000, // ์ „์ฒด ์กฐํšŒ๋ฅผ ์œ„ํ•ด ํฐ ๊ฐ’ ์‚ฌ์šฉ + 'CurrentPage' => 1, + 'OrderDirection' => 2 + ]); + + if ($accResult['success']) { + $accData = $accResult['data']; + + // ์—๋Ÿฌ ์ฝ”๋“œ ์ฒดํฌ + $errorCode = null; + if (isset($accData->CurrentPage) && is_numeric($accData->CurrentPage) && $accData->CurrentPage < 0) { + $errorCode = $accData->CurrentPage; + } elseif (isset($accData->BankAccountNum) && is_numeric($accData->BankAccountNum) && $accData->BankAccountNum < 0) { + $errorCode = $accData->BankAccountNum; + } + + // -25005, -25001์€ ๋ฐ์ดํ„ฐ ์—†์Œ (์ •์ƒ) + if (!$errorCode || ($errorCode == -25005 || $errorCode == -25001)) { + // ๊ฑฐ๋ž˜ ๋‚ด์—ญ ํŒŒ์‹ฑ + if (isset($accData->BankAccountLogList) && isset($accData->BankAccountLogList->BankAccountTransLog)) { + $rawLogs = is_array($accData->BankAccountLogList->BankAccountTransLog) + ? $accData->BankAccountLogList->BankAccountTransLog + : [$accData->BankAccountLogList->BankAccountTransLog]; + + foreach ($rawLogs as $log) { + $deposit = floatval($log->Deposit ?? 0); + $withdraw = floatval($log->Withdraw ?? 0); + + // ๊ฑฐ๋ž˜์ผ์‹œ ํŒŒ์‹ฑ: TransDT ํ•„๋“œ ์‚ฌ์šฉ (YYYYMMDDHHmmss ํ˜•์‹) + $transDT = $log->TransDT ?? ''; + $transDate = ''; + $transTime = ''; + $dateTime = ''; + + if (!empty($transDT) && strlen($transDT) >= 14) { + // TransDT: "20251203100719" -> "2025-12-03 10:07:19" + $transDate = substr($transDT, 0, 8); // YYYYMMDD + $transTime = substr($transDT, 8, 6); // HHmmss + $dateTime = substr($transDT, 0, 4) . '-' . substr($transDT, 4, 2) . '-' . substr($transDT, 6, 2) . ' ' . + substr($transDT, 8, 2) . ':' . substr($transDT, 10, 2) . ':' . substr($transDT, 12, 2); + } else { + // ๊ธฐ์กด ๋ฐฉ์‹๋„ ์ง€์› (๋‹ค์–‘ํ•œ ํ•„๋“œ๋ช… ํ™•์ธ) + $transDate = $log->TransDate ?? $log->TradeDate ?? $log->Date ?? ''; + $transTime = $log->TransTime ?? $log->TradeTime ?? $log->Time ?? ''; + + if (!empty($transDate) && !empty($transTime)) { + $dateStr = (string)$transDate; + $timeStr = (string)$transTime; + + if (strlen($dateStr) == 8 && strlen($timeStr) >= 4) { + $dateTime = substr($dateStr, 0, 4) . '-' . substr($dateStr, 4, 2) . '-' . substr($dateStr, 6, 2) . ' ' . + substr($timeStr, 0, 2) . ':' . substr($timeStr, 2, 2); + if (strlen($timeStr) >= 6) { + $dateTime .= ':' . substr($timeStr, 4, 2); + } + } elseif (strlen($dateStr) == 10 && strpos($dateStr, '-') !== false) { + $dateTime = $dateStr . ' ' . substr($timeStr, 0, 2) . ':' . substr($timeStr, 2, 2); + if (strlen($timeStr) >= 6) { + $dateTime .= ':' . substr($timeStr, 4, 2); + } + } + } + } + + // ์ ์š” ํŒŒ์‹ฑ: TransRemark1 ํ•„๋“œ ์‚ฌ์šฉ + $summary = $log->TransRemark1 ?? $log->Summary ?? $log->Content ?? $log->Description ?? $log->Remark ?? $log->Note ?? ''; + + // ์ถ”๊ฐ€ ์ ์š” ์ •๋ณด: TransRemark2 + $remark2 = $log->TransRemark2 ?? ''; + + // ๊ฑฐ๋ž˜ ์œ ํ˜•: TransType (์˜ˆ: CC) + $transType = $log->TransType ?? ''; + + // ๊ฑฐ๋ž˜ ๋ฐฉํ–ฅ: TransDirection (์˜ˆ: ์ž…๊ธˆ, ์ถœ๊ธˆ) + $transDirection = $log->TransDirection ?? ''; + + // ์ทจ๊ธ‰์ : TransOffice + $transOffice = $log->TransOffice ?? ''; + + // ์ ์š” ์ •๋ณด ๊ฒฐํ•ฉ + $fullSummary = $summary; + if (!empty($remark2)) { + $fullSummary = (!empty($fullSummary) ? $fullSummary . ' ' . $remark2 : $remark2); + } + if (!empty($transType)) { + $fullSummary = (!empty($fullSummary) ? $fullSummary . ' (' . $transType . ')' : '(' . $transType . ')'); + } + + // ๋ณด๋‚ธ๋ถ„/๋ฐ›๋Š”๋ถ„ ์ •๋ณด (๊ธฐ์กด ํ•„๋“œ๋ช…๋„ ์ง€์›) + $cast = $log->Cast ?? $log->Counterpart ?? $log->Opponent ?? $log->Name ?? ''; + + // ์ทจ๊ธ‰์ /์ˆ˜๋‹จ ์ •๋ณด + $branch = $transOffice ?: ($log->Branch ?? $log->HandlingBranch ?? $log->Method ?? ''); + + // ๋””๋ฒ„๊ทธ: ์ฒซ ๋ฒˆ์งธ ๊ณ„์ขŒ์˜ ์ฒซ ๋ฒˆ์งธ ๋กœ๊ทธ ์ •๋ณด ์ €์žฅ + if ($accIndex === 0 && empty($debugAllAccounts)) { + $debugAllAccounts['first_account_first_log'] = [ + 'account_num' => $accNum, + 'log_raw_fields' => [], + 'parsed' => [ + 'transDate' => $transDate, + 'transTime' => $transTime, + 'transDateTime' => $dateTime, + 'summary' => $summary, + 'fullSummary' => $fullSummary, + 'cast' => $cast, + 'branch' => $branch + ] + ]; + // ์›๋ณธ ๋กœ๊ทธ์˜ ๋ชจ๋“  ํ•„๋“œ ์ €์žฅ + foreach ($log as $key => $value) { + $debugAllAccounts['first_account_first_log']['log_raw_fields'][$key] = + is_string($value) ? substr($value, 0, 100) : (is_numeric($value) ? $value : gettype($value)); + } + } + + $allLogs[] = [ + 'transDate' => $transDate, + 'transTime' => $transTime, + 'transDateTime' => $dateTime, + 'bankAccountNum' => $log->BankAccountNum ?? $accNum, + 'bankName' => $log->BankName ?? ($acc->BankName ?? ''), + 'deposit' => $deposit, + 'withdraw' => $withdraw, + 'depositFormatted' => number_format($deposit), + 'withdrawFormatted' => number_format($withdraw), + 'balance' => floatval($log->Balance ?? 0), + 'balanceFormatted' => number_format(floatval($log->Balance ?? 0)), + 'summary' => $fullSummary ?: $summary, + 'cast' => $cast, + 'memo' => $log->Memo ?? '', + 'identity' => $log->Identity ?? '', + 'branch' => $branch + ]; + + $allSummary['totalDeposit'] += $deposit; + $allSummary['totalWithdraw'] += $withdraw; + $allSummary['count']++; + } + } + } + } + } + + // ๋‚ ์งœ/์‹œ๊ฐ„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ (์ตœ์‹ ์ˆœ) + usort($allLogs, function($a, $b) { + $dateA = $a['transDate'] . $a['transTime']; + $dateB = $b['transDate'] . $b['transTime']; + return strcmp($dateB, $dateA); // ๋‚ด๋ฆผ์ฐจ์ˆœ + }); + + // ํŽ˜์ด์ง€๋„ค์ด์…˜ ๊ณ„์‚ฐ + $maxPageNum = ceil($allSummary['count'] / $limit); + $startIndex = ($page - 1) * $limit; + $paginatedLogs = array_slice($allLogs, $startIndex, $limit); + + $response = [ + 'success' => true, + 'data' => [ + 'logs' => $paginatedLogs, + 'pagination' => [ + 'currentPage' => $page, + 'countPerPage' => $limit, + 'maxPageNum' => $maxPageNum, + 'maxIndex' => $allSummary['count'] + ], + 'summary' => $allSummary + ] + ]; + + // ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถ”๊ฐ€ + if (!empty($debugAllAccounts)) { + $response['debug_all_accounts'] = $debugAllAccounts; + } + + // ๋””๋ฒ„๊ทธ: ์ „์ฒด ๊ณ„์ขŒ ์กฐํšŒ ์‹œ ์ฒซ ๋ฒˆ์งธ ๋กœ๊ทธ ํ™•์ธ + if (!empty($paginatedLogs) && isset($paginatedLogs[0])) { + $response['debug_first_log_parsed'] = $paginatedLogs[0]; + } + + echo json_encode($response, JSON_UNESCAPED_UNICODE); + return; + } + } + + // ๋‹จ์ผ ๊ณ„์ขŒ ์กฐํšŒ (๊ธฐ์กด ๋กœ์ง) + $result = callBarobillAccountSOAP('GetPeriodBankAccountTransLog', [ + 'ID' => $userId, + 'BankAccountNum' => $bankAccountNum, + 'StartDate' => $startDate, + 'EndDate' => $endDate, + 'TransDirection' => 1, // 1:์ „์ฒด? (API ์˜ˆ์ œ ๊ฐ’), 2:์ž…๊ธˆ, 3:์ถœ๊ธˆ ์ถ”์ • (ํ™•์ธ ํ•„์š”) - ์šฐ์„  ์˜ˆ์ œ๊ฐ’ 1 ์‚ฌ์šฉ + 'CountPerPage' => $limit, + 'CurrentPage' => $page, + 'OrderDirection' => 2 // 1:์˜ค๋ฆ„์ฐจ์ˆœ, 2:๋‚ด๋ฆผ์ฐจ์ˆœ + ]); + + if ($result['success']) { + $resultData = $result['data']; + + // ์—๋Ÿฌ ์ฝ”๋“œ ์ฒดํฌ (๋‹ค์–‘ํ•œ ํ•„๋“œ์—์„œ ํ™•์ธ) + $errorCode = null; + + // CurrentPage๊ฐ€ ์Œ์ˆ˜์ธ ๊ฒฝ์šฐ + if (isset($resultData->CurrentPage) && is_numeric($resultData->CurrentPage) && $resultData->CurrentPage < 0) { + $errorCode = $resultData->CurrentPage; + } + // BankAccountNum์ด ์Œ์ˆ˜์ธ ๊ฒฝ์šฐ (์˜ˆ: -10002) + elseif (isset($resultData->BankAccountNum) && is_numeric($resultData->BankAccountNum) && $resultData->BankAccountNum < 0) { + $errorCode = $resultData->BankAccountNum; + } + + // -25005: ๋ฐ์ดํ„ฐ ์—†์Œ (์ •์ƒ), -25001: ๊ณ„์ขŒ ์—†์Œ (์ •์ƒ) + if ($errorCode && ($errorCode == -25005 || $errorCode == -25001)) { + echo json_encode([ + 'success' => true, + 'data' => [ + 'logs' => [], + 'summary' => ['totalDeposit' => 0, 'totalWithdraw' => 0, 'count' => 0], + 'pagination' => ['currentPage' => 1, 'maxPageNum' => 1] + ] + ], JSON_UNESCAPED_UNICODE); + return; + } + + // ๋‹ค๋ฅธ ์˜ค๋ฅ˜ ์ฝ”๋“œ์ธ ๊ฒฝ์šฐ + if ($errorCode) { + // ์ƒ์„ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋งคํ•‘ + $errorMsg = '๊ณ„์ขŒ ๋‚ด์—ญ ์กฐํšŒ ์‹คํŒจ: ' . $errorCode; + $errorMessages = [ + -10002 => '์ธ์ฆ ์‹คํŒจ (-10002). CERTKEY๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๊ฑฐ๋‚˜ ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ CERTKEY๋ฅผ ํ™•์ธํ•˜์„ธ์š”.', + -50214 => '์€ํ–‰ ๋กœ๊ทธ์ธ ์‹คํŒจ (-50214). ๋ฐ”๋กœ๋นŒ ์‚ฌ์ดํŠธ์—์„œ ๊ณ„์ขŒ ๋น„๋ฐ€๋ฒˆํ˜ธ/์ธ์ฆ์„œ๋ฅผ ์ ๊ฒ€ํ•ด์ฃผ์„ธ์š”.', + -24005 => '์‚ฌ์šฉ์ž ์ •๋ณด ๋ถˆ์ผ์น˜ (-24005). ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.', + ]; + + if (isset($errorMessages[$errorCode])) { + $errorMsg = $errorMessages[$errorCode]; + } + + throw new Exception($errorMsg); + } + + // ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ (BankAccountTransLog) + $logs = []; + $rawLogs = []; + if (isset($resultData->BankAccountLogList) && isset($resultData->BankAccountLogList->BankAccountTransLog)) { + if (is_array($resultData->BankAccountLogList->BankAccountTransLog)) { + $rawLogs = $resultData->BankAccountLogList->BankAccountTransLog; + } else { + $rawLogs = [$resultData->BankAccountLogList->BankAccountTransLog]; + } + } + + // ๋””๋ฒ„๊ทธ: ์ฒซ ๋ฒˆ์งธ ๋กœ๊ทธ์˜ ์ „์ฒด ๊ตฌ์กฐ ํ™•์ธ + $debugInfo = []; + if (!empty($rawLogs) && is_object($rawLogs[0])) { + $firstLog = $rawLogs[0]; + $debugInfo['first_log_structure'] = []; + $debugInfo['first_log_all_keys'] = []; + foreach ($firstLog as $key => $value) { + $debugInfo['first_log_all_keys'][] = $key; + $debugInfo['first_log_structure'][$key] = [ + 'type' => gettype($value), + 'value' => is_string($value) ? $value : (is_numeric($value) ? $value : gettype($value)), + 'length' => is_string($value) ? strlen($value) : null + ]; + } + } + + $totalDeposit = 0; + $totalWithdraw = 0; + + foreach ($rawLogs as $logIndex => $log) { + $deposit = floatval($log->Deposit ?? 0); + $withdraw = floatval($log->Withdraw ?? 0); + + $totalDeposit += $deposit; + $totalWithdraw += $withdraw; + + // ๊ฑฐ๋ž˜์ผ์‹œ ํŒŒ์‹ฑ: TransDT ํ•„๋“œ ์‚ฌ์šฉ (YYYYMMDDHHmmss ํ˜•์‹) + $transDT = $log->TransDT ?? ''; + $transDate = ''; + $transTime = ''; + $dateTime = ''; + + if (!empty($transDT) && strlen($transDT) >= 14) { + // TransDT: "20251203100719" -> "2025-12-03 10:07:19" + $transDate = substr($transDT, 0, 8); // YYYYMMDD + $transTime = substr($transDT, 8, 6); // HHmmss + $dateTime = substr($transDT, 0, 4) . '-' . substr($transDT, 4, 2) . '-' . substr($transDT, 6, 2) . ' ' . + substr($transDT, 8, 2) . ':' . substr($transDT, 10, 2) . ':' . substr($transDT, 12, 2); + } else { + // ๊ธฐ์กด ๋ฐฉ์‹๋„ ์ง€์› (๋‹ค์–‘ํ•œ ํ•„๋“œ๋ช… ํ™•์ธ) + $transDate = $log->TransDate ?? $log->TradeDate ?? $log->Date ?? ''; + $transTime = $log->TransTime ?? $log->TradeTime ?? $log->Time ?? ''; + + if (!empty($transDate) && !empty($transTime)) { + $dateStr = (string)$transDate; + $timeStr = (string)$transTime; + + if (strlen($dateStr) == 8 && strlen($timeStr) >= 4) { + $dateTime = substr($dateStr, 0, 4) . '-' . substr($dateStr, 4, 2) . '-' . substr($dateStr, 6, 2) . ' ' . + substr($timeStr, 0, 2) . ':' . substr($timeStr, 2, 2); + if (strlen($timeStr) >= 6) { + $dateTime .= ':' . substr($timeStr, 4, 2); + } + } elseif (strlen($dateStr) == 10 && strpos($dateStr, '-') !== false) { + $dateTime = $dateStr . ' ' . substr($timeStr, 0, 2) . ':' . substr($timeStr, 2, 2); + if (strlen($timeStr) >= 6) { + $dateTime .= ':' . substr($timeStr, 4, 2); + } + } + } + } + + // ์ ์š” ํŒŒ์‹ฑ: TransRemark1 ํ•„๋“œ ์‚ฌ์šฉ + $summary = $log->TransRemark1 ?? $log->Summary ?? $log->Content ?? $log->Description ?? $log->Remark ?? $log->Note ?? ''; + + // ์ถ”๊ฐ€ ์ ์š” ์ •๋ณด: TransRemark2 + $remark2 = $log->TransRemark2 ?? ''; + + // ๊ฑฐ๋ž˜ ์œ ํ˜•: TransType (์˜ˆ: CC) + $transType = $log->TransType ?? ''; + + // ๊ฑฐ๋ž˜ ๋ฐฉํ–ฅ: TransDirection (์˜ˆ: ์ž…๊ธˆ, ์ถœ๊ธˆ) + $transDirection = $log->TransDirection ?? ''; + + // ์ทจ๊ธ‰์ : TransOffice + $transOffice = $log->TransOffice ?? ''; + + // ์ ์š” ์ •๋ณด ๊ฒฐํ•ฉ + $fullSummary = $summary; + if (!empty($remark2)) { + $fullSummary = (!empty($fullSummary) ? $fullSummary . ' ' . $remark2 : $remark2); + } + if (!empty($transType)) { + $fullSummary = (!empty($fullSummary) ? $fullSummary . ' (' . $transType . ')' : '(' . $transType . ')'); + } + + // ๋ณด๋‚ธ๋ถ„/๋ฐ›๋Š”๋ถ„ ์ •๋ณด (๊ธฐ์กด ํ•„๋“œ๋ช…๋„ ์ง€์›) + $cast = $log->Cast ?? $log->Counterpart ?? $log->Opponent ?? $log->Name ?? ''; + + // ์ทจ๊ธ‰์ /์ˆ˜๋‹จ ์ •๋ณด + $branch = $transOffice ?: ($log->Branch ?? $log->HandlingBranch ?? $log->Method ?? ''); + + $logs[] = [ + 'transDate' => $transDate, + 'transTime' => $transTime, + 'transDateTime' => $dateTime, + 'bankAccountNum' => $log->BankAccountNum ?? '', + 'bankName' => $log->BankName ?? '', + 'deposit' => $deposit, + 'withdraw' => $withdraw, + 'depositFormatted' => number_format($deposit), + 'withdrawFormatted' => number_format($withdraw), + 'balance' => floatval($log->Balance ?? 0), + 'balanceFormatted' => number_format(floatval($log->Balance ?? 0)), + 'summary' => $fullSummary ?: $summary, // ์ ์š” (ํ†ตํ•ฉ ์ •๋ณด) + 'cast' => $cast, // ๋ณด๋‚ธ๋ถ„/๋ฐ›๋Š”๋ถ„ + 'memo' => $log->Memo ?? '', + 'identity' => $log->Identity ?? '', // ๊ณ ์œ ๋ฒˆํ˜ธ + 'branch' => $branch, // ์ทจ๊ธ‰์ /์ˆ˜๋‹จ + 'rawData' => json_encode($log, JSON_UNESCAPED_UNICODE) // ๋””๋ฒ„๊น…์šฉ ์›๋ณธ ๋ฐ์ดํ„ฐ + ]; + } + + $response = [ + 'success' => true, + 'data' => [ + 'logs' => $logs, + 'pagination' => [ + 'currentPage' => $resultData->CurrentPage ?? 1, + 'countPerPage' => $resultData->CountPerPage ?? 50, + 'maxPageNum' => $resultData->MaxPageNum ?? 1, + 'maxIndex' => $resultData->MaxIndex ?? 0 + ], + 'summary' => [ + 'totalDeposit' => $totalDeposit, + 'totalWithdraw' => $totalWithdraw, + 'count' => count($logs) + ] + ] + ]; + + // ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถ”๊ฐ€ + if (isset($result['debug'])) { + $response['debug'] = $result['debug']; + } + + // API ์‘๋‹ต ๊ตฌ์กฐ ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถ”๊ฐ€ + if (!empty($debugInfo)) { + $response['debug_api_structure'] = $debugInfo; + } + + // ์ฒซ ๋ฒˆ์งธ ๋กœ๊ทธ์˜ ์›๋ณธ ๋ฐ์ดํ„ฐ๋„ ํฌํ•จ (ํ•„๋“œ๋ช… ํ™•์ธ์šฉ) + if (!empty($rawLogs) && is_object($rawLogs[0])) { + $response['debug_first_log_raw'] = []; + foreach ($rawLogs[0] as $key => $value) { + $response['debug_first_log_raw'][$key] = is_string($value) ? $value : (is_numeric($value) ? $value : gettype($value)); + } + } + + echo json_encode($response, JSON_UNESCAPED_UNICODE); + + } else { + // API Error Handling (Graceful Fallback) + // If API fails (e.g., SoapClient missing), return empty list with warning + // so the UI doesn't break. + $response = [ + 'success' => true, // Masquerade as success to render empty table + 'data' => [ + 'logs' => [], + 'pagination' => [ + 'currentPage' => 1, + 'countPerPage' => $limit, + 'maxPageNum' => 1, + 'maxIndex' => 0 + ], + 'summary' => [ + 'totalDeposit' => 0, + 'totalWithdraw' => 0, + 'count' => 0 + ] + ], + 'warning' => 'API ์—ฐ๋™ ์‹คํŒจ: ' . $result['error'], // Custom warning field + 'api_error_code' => $result['error_code'] ?? null + ]; + + // Add debug info if available + if (isset($result['debug'])) { + $response['debug'] = $result['debug']; + } + + echo json_encode($response, JSON_UNESCAPED_UNICODE); + } +} catch (Throwable $e) { + // Global Exception/Error Handling + echo json_encode([ + 'success' => true, // Return true to avoid UI breakage + 'data' => [ + 'logs' => [], + 'pagination' => ['currentPage' => 1, 'maxPageNum' => 1], + 'summary' => ['totalDeposit' => 0, 'totalWithdraw' => 0, 'count' => 0] + ], + 'warning' => '์‹œ์Šคํ…œ ์˜ค๋ฅ˜: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} +?> diff --git a/eaccount/api/usage.php b/eaccount/api/usage.php new file mode 100644 index 0000000..17648bc --- /dev/null +++ b/eaccount/api/usage.php @@ -0,0 +1,397 @@ +load(); + +require_once('barobill_card_config.php'); + +// ๋””๋ฒ„๊ทธ ๋ชจ๋“œ +$debugMode = isset($_GET['debug']) && $_GET['debug'] == '1'; + +try { + $type = $_GET['type'] ?? 'period'; + $cardNum = $_GET['cardNum'] ?? ''; + $page = max(1, intval($_GET['page'] ?? 1)); + $limit = min(100, max(10, intval($_GET['limit'] ?? 50))); + $orderDirection = intval($_GET['order'] ?? 2); // 2: ๋‚ด๋ฆผ์ฐจ์ˆœ (์ตœ์‹ ์ˆœ) + + $result = null; + + // cardNum์ด ๋นˆ ๊ฐ’์ด๋ฉด ์ „์ฒด ์นด๋“œ ์กฐํšŒ (๊ฐ ์นด๋“œ๋ณ„๋กœ ์กฐํšŒ ํ›„ ๋ณ‘ํ•ฉ) + if (empty($cardNum)) { + // ๋“ฑ๋ก๋œ ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ + $cardsResult = getCardList(1); // ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์นด๋“œ๋งŒ + if (!$cardsResult['success'] || empty($cardsResult['data'])) { + $result = [ + 'success' => true, + 'data' => [ + 'currentPage' => 1, + 'countPerPage' => $limit, + 'maxPageNum' => 1, + 'maxIndex' => 0, + 'logs' => [] + ] + ]; + } else { + // ๊ฐ ์นด๋“œ๋ณ„๋กœ ์กฐํšŒ ํ›„ ๋ณ‘ํ•ฉ + $allLogs = []; + foreach ($cardsResult['data'] as $card) { + $cardNumToQuery = $card->CardNum ?? ''; + if (empty($cardNumToQuery)) continue; + + switch ($type) { + case 'daily': + $baseDate = $_GET['baseDate'] ?? date('Ymd'); + $tempResult = getDailyCardUsage($cardNumToQuery, $baseDate, 100, 1, $orderDirection); + break; + case 'monthly': + $baseMonth = $_GET['baseMonth'] ?? date('Ym'); + $tempResult = getMonthlyCardUsage($cardNumToQuery, $baseMonth, 100, 1, $orderDirection); + break; + case 'period': + default: + $startDate = $_GET['startDate'] ?? date('Ymd', strtotime('-30 days')); + $endDate = $_GET['endDate'] ?? date('Ymd'); + $tempResult = getPeriodCardUsage($cardNumToQuery, $startDate, $endDate, 100, 1, $orderDirection); + break; + } + + if ($tempResult['success'] && !empty($tempResult['data']['logs'])) { + $allLogs = array_merge($allLogs, $tempResult['data']['logs']); + } + } + + // UseDT ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ + usort($allLogs, function($a, $b) use ($orderDirection) { + $aTime = $a->UseDT ?? ''; + $bTime = $b->UseDT ?? ''; + return $orderDirection == 1 ? strcmp($aTime, $bTime) : strcmp($bTime, $aTime); + }); + + // ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ + $totalCount = count($allLogs); + $maxPageNum = ceil($totalCount / $limit); + $offset = ($page - 1) * $limit; + $pagedLogs = array_slice($allLogs, $offset, $limit); + + $result = [ + 'success' => true, + 'data' => [ + 'currentPage' => $page, + 'countPerPage' => $limit, + 'maxPageNum' => $maxPageNum, + 'maxIndex' => $totalCount, + 'logs' => $pagedLogs + ] + ]; + } + } else { + // ํŠน์ • ์นด๋“œ ์กฐํšŒ + switch ($type) { + case 'daily': + $baseDate = $_GET['baseDate'] ?? date('Ymd'); + $result = getDailyCardUsage($cardNum, $baseDate, $limit, $page, $orderDirection); + break; + + case 'monthly': + $baseMonth = $_GET['baseMonth'] ?? date('Ym'); + $result = getMonthlyCardUsage($cardNum, $baseMonth, $limit, $page, $orderDirection); + break; + + case 'period': + default: + $startDate = $_GET['startDate'] ?? date('Ymd', strtotime('-30 days')); + $endDate = $_GET['endDate'] ?? date('Ymd'); + $result = getPeriodCardUsage($cardNum, $startDate, $endDate, $limit, $page, $orderDirection); + break; + } + } + + if ($result['success']) { + $logs = []; + + // ๋””๋ฒ„๊ทธ: raw ๋กœ๊ทธ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ + if ($debugMode && !empty($result['data']['logs'])) { + $firstLog = $result['data']['logs'][0]; + error_log('CardApprovalLog raw data: ' . print_r($firstLog, true)); + // ๋””๋ฒ„๊ทธ: ๋ชจ๋“  ํ•„๋“œ๋ช… ํ™•์ธ + if (is_object($firstLog)) { + $fields = get_object_vars($firstLog); + error_log('CardApprovalLog fields: ' . implode(', ', array_keys($fields))); + error_log('ApprovalAmount value: ' . ($firstLog->ApprovalAmount ?? 'NOT SET')); + error_log('Amount value: ' . ($firstLog->Amount ?? 'NOT SET')); + error_log('TotalAmount value: ' . ($firstLog->TotalAmount ?? 'NOT SET')); + } + } + + foreach ($result['data']['logs'] as $log) { + // UseDT ํ˜•์‹: YYYYMMDDHHMMSS + $useDT = $log->UseDT ?? ''; + $approvalDate = ''; + $approvalTime = ''; + if (strlen($useDT) >= 8) { + $approvalDate = substr($useDT, 0, 4) . '-' . substr($useDT, 4, 2) . '-' . substr($useDT, 6, 2); + } + if (strlen($useDT) >= 14) { + $approvalTime = substr($useDT, 8, 2) . ':' . substr($useDT, 10, 2) . ':' . substr($useDT, 12, 2); + } elseif (strlen($useDT) >= 12) { + $approvalTime = substr($useDT, 8, 2) . ':' . substr($useDT, 10, 2); + } + + $logs[] = [ + 'cardNum' => maskCardNumber($log->CardNum ?? ''), + 'cardNumFull' => $log->CardNum ?? '', + 'approvalNum' => $log->ApprovalNum ?? '', + 'approvalDate' => $approvalDate, + 'approvalTime' => $approvalTime, + 'approvalDateTime' => $approvalDate . ' ' . $approvalTime, + 'merchantName' => $log->UseStoreName ?? '', + 'merchantBizNum' => $log->UseStoreCorpNum ?? '', + // ๊ธˆ์•ก ํ•„๋“œ: ์—ฌ๋Ÿฌ ๊ฐ€๋Šฅํ•œ ํ•„๋“œ๋ช… ์‹œ๋„ + // ApprovalAmount๊ฐ€ ์‹ค์ œ ์Šน์ธ๊ธˆ์•ก (ํ™”๋ฉด์— ํ‘œ์‹œํ•  ๊ธˆ์•ก) + 'amount' => intval($log->ApprovalAmount ?? 0), + 'amountFormatted' => number_format(intval($log->ApprovalAmount ?? 0)), + 'vat' => intval($log->Tax ?? 0), + 'vatFormatted' => number_format(intval($log->Tax ?? 0)), + 'serviceCharge' => intval($log->ServiceCharge ?? 0), + // totalAmount๋Š” ํ™”๋ฉด์—์„œ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ApprovalAmount๋ฅผ ์‚ฌ์šฉ + 'totalAmount' => intval($log->ApprovalAmount ?? 0), + 'totalAmountFormatted' => number_format(intval($log->ApprovalAmount ?? 0)), + 'approvalType' => $log->ApprovalType ?? '', + 'approvalTypeName' => getApprovalTypeName($log->ApprovalType ?? ''), + 'installment' => $log->PaymentPlan ?? '', + 'installmentName' => getInstallmentName($log->PaymentPlan ?? ''), + 'currencyCode' => $log->CurrencyCode ?? 'KRW', + 'memo' => $log->Memo ?? '', + 'cardCompany' => $log->CardCompany ?? '', + 'cardCompanyName' => getCardCompanyNameFromLog($log->CardCompany ?? ''), + // ์ถ”๊ฐ€ ํ•„๋“œ + 'useKey' => $log->UseKey ?? '', + 'storeAddress' => $log->UseStoreAddr ?? '', + 'storeCeo' => $log->UseStoreCeo ?? '', + 'storeBizType' => $log->UseStoreBizType ?? '', + 'storeTel' => $log->UseStoreTel ?? '' + ]; + } + + // ํ†ต๊ณ„ ๊ณ„์‚ฐ + $totalAmount = array_sum(array_column($logs, 'totalAmount')); + $approvalCount = count(array_filter($logs, function($l) { return $l['approvalType'] == '1'; })); + $cancelCount = count(array_filter($logs, function($l) { return $l['approvalType'] == '2'; })); + + $response = [ + 'success' => true, + 'data' => [ + 'logs' => $logs, + 'pagination' => [ + 'currentPage' => $result['data']['currentPage'], + 'countPerPage' => $result['data']['countPerPage'], + 'maxPageNum' => $result['data']['maxPageNum'], + 'totalCount' => $result['data']['maxIndex'] + ], + 'summary' => [ + 'totalAmount' => $totalAmount, + 'totalAmountFormatted' => number_format($totalAmount), + 'count' => count($logs), + 'approvalCount' => $approvalCount, + 'cancelCount' => $cancelCount + ] + ] + ]; + + // ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถ”๊ฐ€ (์„ฑ๊ณตํ•œ ๊ฒฝ์šฐ์—๋„ ํ•ญ์ƒ ์ฒซ ๋ฒˆ์งธ ๋กœ๊ทธ์˜ ํ•„๋“œ ์ •๋ณด ์ถœ๋ ฅ) + if (!empty($result['data']['logs'])) { + $firstLog = $result['data']['logs'][0]; + if (is_object($firstLog)) { + // ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ + $allFields = get_object_vars($firstLog); + $fieldNames = array_keys($allFields); + + // ๊ธˆ์•ก ๊ด€๋ จ ํ•„๋“œ ์ฐพ๊ธฐ (๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ ์—†์ด) + $amountFields = []; + foreach ($fieldNames as $fieldName) { + if (stripos($fieldName, 'amount') !== false || + stripos($fieldName, 'cost') !== false || + stripos($fieldName, 'price') !== false || + stripos($fieldName, '๊ธˆ์•ก') !== false) { + $amountFields[$fieldName] = (string)($firstLog->$fieldName ?? 'NULL'); + } + } + + // ๋””๋ฒ„๊ทธ ๋ชจ๋“œ์ผ ๋•Œ๋งŒ ์ƒ์„ธ ์ •๋ณด ์ถœ๋ ฅ + if ($debugMode) { + $response['debug'] = [ + 'userId' => getBarobillUserId(), + 'params' => $_GET, + 'firstLogFields' => $fieldNames, + 'firstLogAllValues' => array_map(function($v) { + return is_string($v) ? $v : (is_numeric($v) ? (string)$v : gettype($v)); + }, $allFields), + 'amountFields' => $amountFields + ]; + } else { + // ๋””๋ฒ„๊ทธ ๋ชจ๋“œ๊ฐ€ ์•„๋‹ˆ์–ด๋„ ๊ธˆ์•ก ํ•„๋“œ ์ •๋ณด๋Š” ํ•ญ์ƒ ํฌํ•จ (๋ฌธ์ œ ํ•ด๊ฒฐ์šฉ) + $response['debug'] = [ + 'amountFields' => $amountFields, + 'allFields' => $fieldNames + ]; + } + } + } elseif ($debugMode) { + $response['debug'] = [ + 'userId' => getBarobillUserId(), + 'params' => $_GET, + 'message' => 'No logs found' + ]; + } + + echo json_encode($response, JSON_UNESCAPED_UNICODE); + } else { + // API Error Handling (Graceful Fallback) + // If API fails (e.g., SoapClient missing), return empty list with warning + $response = [ + 'success' => true, // Masquerade as success to render empty table + 'data' => [ + 'logs' => [], + 'pagination' => [ + 'currentPage' => 1, + 'countPerPage' => $limit, + 'maxPageNum' => 1, + 'totalCount' => 0 + ], + 'summary' => [ + 'totalAmount' => 0, + 'totalAmountFormatted' => '0', + 'count' => 0, + 'approvalCount' => 0, + 'cancelCount' => 0 + ] + ], + 'warning' => 'API ์—ฐ๋™ ์‹คํŒจ: ' . $result['error'], + 'api_error_code' => $result['error_code'] ?? null + ]; + + // ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถ”๊ฐ€ + if ($debugMode) { + $response['debug'] = [ + 'userId' => getBarobillUserId(), + 'params' => $_GET + ]; + } + + echo json_encode($response, JSON_UNESCAPED_UNICODE); + } +} catch (Throwable $e) { + echo json_encode([ + 'success' => true, // Return true to avoid UI breakage + 'data' => [ + 'logs' => [], + 'pagination' => ['currentPage' => 1, 'maxPageNum' => 1, 'totalCount' => 0], + 'summary' => ['totalAmount' => 0, 'count' => 0] + ], + 'warning' => '์‹œ์Šคํ…œ ์˜ค๋ฅ˜: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} + +/** + * ์นด๋“œ๋ฒˆํ˜ธ ๋งˆ์Šคํ‚น + */ +function maskCardNumber($cardNum) { + if (strlen($cardNum) < 8) return $cardNum; + return substr($cardNum, 0, 4) . '-****-****-' . substr($cardNum, -4); +} + +/** + * ๋‚ ์งœ ํฌ๋งทํŒ… + */ +function formatDate($date) { + if (strlen($date) === 8) { + return substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2); + } + return $date; +} + +/** + * ์‹œ๊ฐ„ ํฌ๋งทํŒ… + */ +function formatTime($time) { + if (strlen($time) === 6) { + return substr($time, 0, 2) . ':' . substr($time, 2, 2) . ':' . substr($time, 4, 2); + } elseif (strlen($time) === 4) { + return substr($time, 0, 2) . ':' . substr($time, 2, 2); + } + return $time; +} + +/** + * ์Šน์ธ ์œ ํ˜• ์ด๋ฆ„ + */ +function getApprovalTypeName($type) { + $types = [ + '1' => '์Šน์ธ', + '2' => '์ทจ์†Œ' + ]; + return $types[$type] ?? $type; +} + +/** + * ํ• ๋ถ€ ์ด๋ฆ„ + */ +function getInstallmentName($installment) { + if (empty($installment) || $installment == '0' || $installment == '00') { + return '์ผ์‹œ๋ถˆ'; + } + return $installment . '๊ฐœ์›”'; +} + +/** + * ์นด๋“œ์‚ฌ ์ด๋ฆ„ (๋กœ๊ทธ์šฉ) + */ +function getCardCompanyNameFromLog($code) { + $companies = [ + '01' => '๋น„์”จ', + '02' => 'KB๊ตญ๋ฏผ', + '03' => 'ํ•˜๋‚˜(์™ธํ™˜)', + '04' => '์‚ผ์„ฑ', + '06' => '์‹ ํ•œ', + '07' => 'ํ˜„๋Œ€', + '08' => '๋กฏ๋ฐ', + '11' => 'NH๋†ํ˜‘', + '12' => '์ˆ˜ํ˜‘', + '13' => '์”จํ‹ฐ', + '14' => '์šฐ๋ฆฌ', + '15' => '๊ด‘์ฃผ', + '16' => '์ „๋ถ', + '21' => 'ํ•˜๋‚˜', + '22' => '์ œ์ฃผ', + '23' => 'SC์ œ์ผ', + '25' => 'KDB์‚ฐ์—…', + '26' => 'IBK๊ธฐ์—…', + '27' => '์ƒˆ๋งˆ์„๊ธˆ๊ณ ', + '28' => '์‹ ํ˜‘', + '29' => '์ €์ถ•์€ํ–‰', + '30' => '์šฐ์ฒด๊ตญ', + '31' => '์นด์นด์˜ค๋ฑ…ํฌ', + '32' => 'K๋ฑ…ํฌ', + '33' => 'ํ† ์Šค๋ฑ…ํฌ' + ]; + return $companies[$code] ?? $code; +} +?> + diff --git a/eaccount/index.php b/eaccount/index.php new file mode 100644 index 0000000..5ada23d --- /dev/null +++ b/eaccount/index.php @@ -0,0 +1,1421 @@ + + + + + + ๊ณ„์ขŒ ์ž…์ถœ๊ธˆ๋‚ด์—ญ ์กฐํšŒ - ๋ฐ”๋กœ๋นŒ ์—ฐ๋™ + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/ecard/README.md b/ecard/README.md new file mode 100644 index 0000000..946f3b9 --- /dev/null +++ b/ecard/README.md @@ -0,0 +1,138 @@ +# ๋ฒ•์ธ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ ๋ชจ๋“ˆ + +๋ฐ”๋กœ๋นŒ API๋ฅผ ์ด์šฉํ•œ ๋ฒ•์ธ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ ๋ชจ๋“ˆ์ž…๋‹ˆ๋‹ค. + +## ๐Ÿ“‹ ๊ธฐ๋Šฅ + +- ๋“ฑ๋ก๋œ ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ +- ๊ธฐ๊ฐ„๋ณ„/์ผ๋ณ„/์›”๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ +- ์‚ฌ์šฉ๊ธˆ์•ก ํ†ต๊ณ„ (์ด ์‚ฌ์šฉ๊ธˆ์•ก, ์‚ฌ์šฉ๊ฑด์ˆ˜, ์ทจ์†Œ๊ฑด์ˆ˜) +- ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ง€์› + +## ๐Ÿ”ง ์„ค์ • + +### 1. API ํ‚ค ์„ค์ • (๊ธฐ์กด etax ๋ชจ๋“ˆ๊ณผ ๊ณต์œ ) + +๋‹ค์Œ ํŒŒ์ผ๋“ค์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค (`/apikey/` ํด๋”): + +| ํŒŒ์ผ๋ช… | ์„ค๋ช… | ์˜ˆ์‹œ | +|--------|------|------| +| `barobill_cert_key.txt` | ๋ฐ”๋กœ๋นŒ CERTKEY (์ธ์ฆ์„œ ํ‚ค) | `ABC123...` | +| `barobill_corp_num.txt` | ์‚ฌ์—…์ž๋ฒˆํ˜ธ (ํ•˜์ดํ”ˆ ์ œ์™ธ) | `6648603713` | +| `barobill_test_mode.txt` | ํ…Œ์ŠคํŠธ ๋ชจ๋“œ (์„ ํƒ) | `test` ๋˜๋Š” `true` | + +### 2. ๋ฐ”๋กœ๋นŒ ์นด๋“œ ๋“ฑ๋ก + +์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ์„ ์กฐํšŒํ•˜๋ ค๋ฉด **๋ฐ”๋กœ๋นŒ ์›น์‚ฌ์ดํŠธ**์—์„œ ์นด๋“œ๋ฅผ ๋จผ์ € ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + +1. [๋ฐ”๋กœ๋นŒ](https://www.barobill.co.kr) ๋กœ๊ทธ์ธ +2. ์นด๋“œ์กฐํšŒ ์„œ๋น„์Šค ์‹ ์ฒญ +3. ์นด๋“œ ๋“ฑ๋ก (์นด๋“œ์‚ฌ ์›น ID/๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„์š”) + +## ๐Ÿ“ ํŒŒ์ผ ๊ตฌ์กฐ + +``` +ecard/ +โ”œโ”€โ”€ index.php # ๋ฉ”์ธ UI (React ๊ธฐ๋ฐ˜) +โ”œโ”€โ”€ api/ +โ”‚ โ”œโ”€โ”€ barobill_card_config.php # ๋ฐ”๋กœ๋นŒ ์นด๋“œ API ์„ค์ • +โ”‚ โ”œโ”€โ”€ cards.php # ๋“ฑ๋ก๋œ ์นด๋“œ ๋ชฉ๋ก API +โ”‚ โ””โ”€โ”€ usage.php # ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ API +โ””โ”€โ”€ README.md # ์ด ๋ฌธ์„œ +``` + +## ๐Ÿ”Œ API ์—”๋“œํฌ์ธํŠธ + +### ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ +``` +GET /ecard/api/cards.php +``` + +**์‘๋‹ต ์˜ˆ์‹œ:** +```json +{ + "success": true, + "cards": [ + { + "cardNum": "1234-****-****-5678", + "cardCompany": "02", + "cardCompanyName": "KB๊ตญ๋ฏผ", + "alias": "๋ฒ•์ธ์นด๋“œ1", + "status": "1", + "statusName": "์ •์ƒ" + } + ], + "count": 1 +} +``` + +### ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ +``` +GET /ecard/api/usage.php?type=period&startDate=20241101&endDate=20241130 +``` + +**ํŒŒ๋ผ๋ฏธํ„ฐ:** +| ํŒŒ๋ผ๋ฏธํ„ฐ | ์„ค๋ช… | ๊ธฐ๋ณธ๊ฐ’ | +|---------|------|--------| +| `type` | ์กฐํšŒ ํƒ€์ž… (period/daily/monthly) | `period` | +| `cardNum` | ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’=์ „์ฒด) | - | +| `startDate` | ์‹œ์ž‘์ผ (YYYYMMDD) - period์šฉ | 30์ผ ์ „ | +| `endDate` | ์ข…๋ฃŒ์ผ (YYYYMMDD) - period์šฉ | ์˜ค๋Š˜ | +| `baseDate` | ๊ธฐ์ค€์ผ (YYYYMMDD) - daily์šฉ | ์˜ค๋Š˜ | +| `baseMonth` | ๊ธฐ์ค€์›” (YYYYMM) - monthly์šฉ | ์ด๋ฒˆ๋‹ฌ | +| `page` | ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ | `1` | +| `limit` | ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ | `50` | + +**์‘๋‹ต ์˜ˆ์‹œ:** +```json +{ + "success": true, + "data": { + "logs": [ + { + "cardNum": "1234-****-****-5678", + "approvalNum": "12345678", + "approvalDate": "2024-11-15", + "approvalTime": "14:30:25", + "merchantName": "์Šคํƒ€๋ฒ…์Šค ๊ฐ•๋‚จ์ ", + "amount": 5000, + "totalAmountFormatted": "5,000", + "approvalTypeName": "์Šน์ธ", + "installmentName": "์ผ์‹œ๋ถˆ" + } + ], + "pagination": { + "currentPage": 1, + "countPerPage": 50, + "maxPageNum": 1, + "totalCount": 15 + }, + "summary": { + "totalAmount": 150000, + "count": 15, + "approvalCount": 14, + "cancelCount": 1 + } + } +} +``` + +## ๐ŸŽจ UI ๊ธฐ๋Šฅ + +- **์นด๋“œ ์„ ํƒ**: ํŠน์ • ์นด๋“œ ๋˜๋Š” ์ „์ฒด ์นด๋“œ ์กฐํšŒ +- **๊ธฐ๊ฐ„ ์„ค์ •**: ๋‚ ์งœ ๋ฒ”์œ„ ์ง์ ‘ ์„ ํƒ ๋˜๋Š” ๋น ๋ฅธ ์„ ํƒ (์˜ค๋Š˜, 7์ผ, 30์ผ, 3๊ฐœ์›”, 6๊ฐœ์›”) +- **ํ†ต๊ณ„ ๋Œ€์‹œ๋ณด๋“œ**: ์ด ์‚ฌ์šฉ๊ธˆ์•ก, ์‚ฌ์šฉ๊ฑด์ˆ˜, ์ทจ์†Œ๊ฑด์ˆ˜ ํ‘œ์‹œ +- **์‚ฌ์šฉ๋‚ด์—ญ ํ…Œ์ด๋ธ”**: ์Šน์ธ์ผ์‹œ, ๊ฐ€๋งน์ ๋ช…, ๊ธˆ์•ก, ํ• ๋ถ€, ์Šน์ธ/์ทจ์†Œ ๊ตฌ๋ถ„ + +## โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ + +1. ๋ฐ”๋กœ๋นŒ ์นด๋“œ์กฐํšŒ ์„œ๋น„์Šค๋Š” **์œ ๋ฃŒ ์„œ๋น„์Šค**์ž…๋‹ˆ๋‹ค. +2. ์นด๋“œ ๋“ฑ๋ก ์‹œ **์นด๋“œ์‚ฌ ์›น ID/๋น„๋ฐ€๋ฒˆํ˜ธ**๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. +3. ์นด๋“œ์‚ฌ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๋ฏ€๋กœ **์‹ค์‹œ๊ฐ„ ์กฐํšŒ๊ฐ€ ์•„๋‹ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค** (๋ณดํ†ต 1์ผ 1ํšŒ ์ˆ˜์ง‘). +4. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ๋Š” ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹Œ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๊ฐ€ ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค. + +## ๐Ÿ”— ์ฐธ๊ณ  ๋ฌธ์„œ + +- [๋ฐ”๋กœ๋นŒ ์นด๋“œ์กฐํšŒ API ๋ ˆํผ๋Ÿฐ์Šค](https://dev.barobill.co.kr/docs/references/์นด๋“œ์กฐํšŒ-API) +- [๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ](https://dev.barobill.co.kr) + diff --git a/ecard/api/barobill_card_config.php b/ecard/api/barobill_card_config.php new file mode 100644 index 0000000..cd95c78 --- /dev/null +++ b/ecard/api/barobill_card_config.php @@ -0,0 +1,510 @@ + true, + 'encoding' => 'UTF-8', + 'exceptions' => true, + 'connection_timeout' => 30 + ]); + } catch (Exception $e) { + error_log('๋ฐ”๋กœ๋นŒ ์นด๋“œ SOAP ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ ์‹คํŒจ: ' . $e->getMessage()); + } +} + +/** + * ๋ฐ”๋กœ๋นŒ ์นด๋“œ SOAP ์›น์„œ๋น„์Šค ํ˜ธ์ถœ ํ•จ์ˆ˜ + * + * @param string $method SOAP ๋ฉ”์„œ๋“œ๋ช… + * @param array $params SOAP ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function callBarobillCardSOAP($method, $params = []) { + global $barobillCardSoapClient, $barobillCertKey, $barobillCorpNum, $isTestMode; + + if (!$barobillCardSoapClient) { + return [ + 'success' => false, + 'error' => '๋ฐ”๋กœ๋นŒ ์นด๋“œ SOAP ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. CERTKEY๋ฅผ ํ™•์ธํ•˜์„ธ์š”.', + 'error_detail' => [ + 'cert_key_file' => $_SERVER['DOCUMENT_ROOT'] . '/apikey/barobill_cert_key.txt', + 'soap_url' => $isTestMode ? 'https://testws.baroservice.com/CARD.asmx?WSDL' : 'https://ws.baroservice.com/CARD.asmx?WSDL' + ] + ]; + } + + if (empty($barobillCertKey) && !$isTestMode) { + return [ + 'success' => false, + 'error' => 'CERTKEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. apikey/barobill_cert_key.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜์„ธ์š”.' + ]; + } + + if (empty($barobillCorpNum)) { + return [ + 'success' => false, + 'error' => '์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. apikey/barobill_corp_num.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜์„ธ์š”.' + ]; + } + + // CERTKEY์™€ CorpNum ์ž๋™ ์ถ”๊ฐ€ + if (!isset($params['CERTKEY'])) { + $params['CERTKEY'] = $barobillCertKey; + } + if (!isset($params['CorpNum'])) { + $params['CorpNum'] = $barobillCorpNum; + } + + try { + error_log('๋ฐ”๋กœ๋นŒ ์นด๋“œ API ํ˜ธ์ถœ - Method: ' . $method . ', CorpNum: ' . $barobillCorpNum); + + $result = $barobillCardSoapClient->$method($params); + + $resultProperty = $method . 'Result'; + if (isset($result->$resultProperty)) { + $resultData = $result->$resultProperty; + + // ์—๋Ÿฌ ์ฝ”๋“œ ์ฒดํฌ (์Œ์ˆ˜ ๊ฐ’) + if (is_numeric($resultData) && $resultData < 0) { + return [ + 'success' => false, + 'error' => '๋ฐ”๋กœ๋นŒ ์นด๋“œ API ์˜ค๋ฅ˜ ์ฝ”๋“œ: ' . $resultData, + 'error_code' => $resultData + ]; + } + + return [ + 'success' => true, + 'data' => $resultData + ]; + } + + return [ + 'success' => true, + 'data' => $result + ]; + + } catch (SoapFault $e) { + return [ + 'success' => false, + 'error' => 'SOAP ์˜ค๋ฅ˜: ' . $e->getMessage(), + 'error_code' => $e->getCode() + ]; + } catch (Exception $e) { + return [ + 'success' => false, + 'error' => 'API ํ˜ธ์ถœ ์˜ค๋ฅ˜: ' . $e->getMessage() + ]; + } +} + +/** + * ๋“ฑ๋ก๋œ ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ (GetCardEx2 API ์‚ฌ์šฉ) + * API ๋ ˆํผ๋Ÿฐ์Šค: https://dev.barobill.co.kr/docs/references/์นด๋“œ์กฐํšŒ-API#GetCardEx2 + * + * ๋ฐ์ดํ„ฐ ์ถœ์ฒ˜: ๋ฐ”๋กœ๋นŒ ์„œ๋ฒ„์— ๋“ฑ๋ก๋œ ์นด๋“œ ์ •๋ณด + * - ์นด๋“œ ๋“ฑ๋ก์€ ๋ฐ”๋กœ๋นŒ ์›น์‚ฌ์ดํŠธ(https://www.barobill.co.kr)์—์„œ ์ง์ ‘ ํ•ด์•ผ ํ•จ + * - ์ด ํ•จ์ˆ˜๋Š” ๋“ฑ๋ก๋œ ์นด๋“œ ์ •๋ณด๋ฅผ ์กฐํšŒ๋งŒ ์ˆ˜ํ–‰ + * + * ๋ฐ˜ํ™˜๋˜๋Š” ์นด๋“œ ์ •๋ณด: + * - CardNum: ์นด๋“œ๋ฒˆํ˜ธ (๋ฐ”๋กœ๋นŒ์— ๋“ฑ๋ก๋œ ์นด๋“œ๋ฒˆํ˜ธ) + * - CardCompanyCode: ์นด๋“œ์‚ฌ ์ฝ”๋“œ (01=BC, 02=KB, 04=์‚ผ์„ฑ, 06=์‹ ํ•œ ๋“ฑ) + * - CardCompanyName: ์นด๋“œ์‚ฌ ์ด๋ฆ„ + * - WebId: ์นด๋“œ์‚ฌ ์›น ID (์นด๋“œ์‚ฌ ํ™ˆํŽ˜์ด์ง€ ๋กœ๊ทธ์ธ ID) + * - Alias: ์นด๋“œ ๋ณ„์นญ + * - CardType: ์นด๋“œ ์ข…๋ฅ˜ (1=๊ฐœ์ธ, 2=๋ฒ•์ธ) + * - Status: ์นด๋“œ ์ƒํƒœ (0=๋Œ€๊ธฐ์ค‘, 1=์ •์ƒ, 2=ํ•ด์ง€, 3=์ˆ˜์ง‘์˜ค๋ฅ˜, 4=์ผ์‹œ์ค‘์ง€) + * - CollectCycle: ์ˆ˜์ง‘์ฃผ๊ธฐ (1=1์ผ1ํšŒ, 2=1์ผ2ํšŒ, 3=1์ผ3ํšŒ) + * + * @param int $availOnly 0: ์ „์ฒด, 1: ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ์นด๋“œ๋งŒ + * @return array ์นด๋“œ ๋ชฉ๋ก + */ +function getCardList($availOnly = 0) { + $result = callBarobillCardSOAP('GetCardEx2', [ + 'AvailOnly' => $availOnly + ]); + + if (!$result['success']) { + return $result; + } + + $cards = []; + $data = $result['data']; + + // GetCardEx2๋Š” CardEx ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ + if (!isset($data->CardEx)) { + return ['success' => true, 'data' => []]; + } + + if (!is_array($data->CardEx)) { + $cards = [$data->CardEx]; + } else { + $cards = $data->CardEx; + } + + // ์—๋Ÿฌ ์ฒดํฌ: CardNum์ด ์Œ์ˆ˜๋ฉด ์—๋Ÿฌ ์ฝ”๋“œ + if (count($cards) == 1 && isset($cards[0]->CardNum) && $cards[0]->CardNum < 0) { + return [ + 'success' => false, + 'error' => '์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ ์‹คํŒจ', + 'error_code' => $cards[0]->CardNum + ]; + } + + return ['success' => true, 'data' => $cards]; +} + +/** + * ๊ธฐ๊ฐ„๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ + * + * ๋ฐ์ดํ„ฐ ์ถœ์ฒ˜: ๋ฐ”๋กœ๋นŒ ์„œ๋ฒ„์—์„œ ์ˆ˜์ง‘๋œ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ + * - ๋ฐ”๋กœ๋นŒ์ด ์นด๋“œ์‚ฌ์—์„œ ์ž๋™์œผ๋กœ ์ˆ˜์ง‘ํ•œ ์‚ฌ์šฉ๋‚ด์—ญ์„ ์กฐํšŒ + * - ์ˆ˜์ง‘์ฃผ๊ธฐ(CollectCycle)์— ๋”ฐ๋ผ 1์ผ 1ํšŒ~3ํšŒ ์ž๋™ ์ˆ˜์ง‘ + * + * ๋ฐ˜ํ™˜๋˜๋Š” ์‚ฌ์šฉ๋‚ด์—ญ ์ •๋ณด: + * - CardNum: ์นด๋“œ๋ฒˆํ˜ธ + * - UseDT: ์‚ฌ์šฉ์ผ์‹œ (YYYYMMDDHHMMSS) + * - UseStoreName: ๊ฐ€๋งน์ ๋ช… + * - UseStoreCorpNum: ๊ฐ€๋งน์  ์‚ฌ์—…์ž๋ฒˆํ˜ธ + * - ApprovalAmount: ์Šน์ธ๊ธˆ์•ก + * - Tax: ๋ถ€๊ฐ€์„ธ + * - ServiceCharge: ๋ด‰์‚ฌ๋ฃŒ + * - ApprovalType: ์Šน์ธ์œ ํ˜• (1=์Šน์ธ, 2=์ทจ์†Œ) + * - PaymentPlan: ํ• ๋ถ€๊ฐœ์›” (0=์ผ์‹œ๋ถˆ) + * - ApprovalNum: ์Šน์ธ๋ฒˆํ˜ธ + * + * @param string $cardNum ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @param string $startDate ์‹œ์ž‘์ผ (YYYYMMDD) + * @param string $endDate ์ข…๋ฃŒ์ผ (YYYYMMDD) + * @param int $countPerPage ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ + * @param int $currentPage ํ˜„์žฌ ํŽ˜์ด์ง€ + * @param int $orderDirection ์ •๋ ฌ (1: ์˜ค๋ฆ„์ฐจ์ˆœ, 2: ๋‚ด๋ฆผ์ฐจ์ˆœ) + * @param string $userId ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @return array ์‚ฌ์šฉ๋‚ด์—ญ + */ +function getPeriodCardUsage($cardNum = '', $startDate = '', $endDate = '', $countPerPage = 50, $currentPage = 1, $orderDirection = 2, $userId = '') { + global $barobillCorpNum; + + // ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID ํŒŒ์ผ์—์„œ ์ฝ๊ธฐ (์—†์œผ๋ฉด ๋นˆ๊ฐ’) + $barobillUserId = getBarobillUserId(); + if (!empty($userId)) { + $barobillUserId = $userId; + } + + $result = callBarobillCardSOAP('GetPeriodCardApprovalLog', [ + 'ID' => $barobillUserId, + 'CardNum' => $cardNum, + 'StartDate' => $startDate, + 'EndDate' => $endDate, + 'CountPerPage' => $countPerPage, + 'CurrentPage' => $currentPage, + 'OrderDirection' => $orderDirection + ]); + + if (!$result['success']) { + return $result; + } + + return parseCardUsageResult($result['data']); +} + +/** + * ์ผ๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ + * + * @param string $cardNum ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @param string $baseDate ๊ธฐ์ค€์ผ (YYYYMMDD) + * @param int $countPerPage ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ + * @param int $currentPage ํ˜„์žฌ ํŽ˜์ด์ง€ + * @param int $orderDirection ์ •๋ ฌ (1: ์˜ค๋ฆ„์ฐจ์ˆœ, 2: ๋‚ด๋ฆผ์ฐจ์ˆœ) + * @param string $userId ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @return array ์‚ฌ์šฉ๋‚ด์—ญ + */ +function getDailyCardUsage($cardNum = '', $baseDate = '', $countPerPage = 50, $currentPage = 1, $orderDirection = 2, $userId = '') { + $barobillUserId = getBarobillUserId(); + if (!empty($userId)) { + $barobillUserId = $userId; + } + + $result = callBarobillCardSOAP('GetDailyCardApprovalLog', [ + 'ID' => $barobillUserId, + 'CardNum' => $cardNum, + 'BaseDate' => $baseDate, + 'CountPerPage' => $countPerPage, + 'CurrentPage' => $currentPage, + 'OrderDirection' => $orderDirection + ]); + + if (!$result['success']) { + return $result; + } + + return parseCardUsageResult($result['data']); +} + +/** + * ์›”๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ + * + * @param string $cardNum ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @param string $baseMonth ๊ธฐ์ค€์›” (YYYYMM) + * @param int $countPerPage ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ + * @param int $currentPage ํ˜„์žฌ ํŽ˜์ด์ง€ + * @param int $orderDirection ์ •๋ ฌ (1: ์˜ค๋ฆ„์ฐจ์ˆœ, 2: ๋‚ด๋ฆผ์ฐจ์ˆœ) + * @param string $userId ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + * @return array ์‚ฌ์šฉ๋‚ด์—ญ + */ +function getMonthlyCardUsage($cardNum = '', $baseMonth = '', $countPerPage = 50, $currentPage = 1, $orderDirection = 2, $userId = '') { + $barobillUserId = getBarobillUserId(); + if (!empty($userId)) { + $barobillUserId = $userId; + } + + $result = callBarobillCardSOAP('GetMonthlyCardApprovalLog', [ + 'ID' => $barobillUserId, + 'CardNum' => $cardNum, + 'BaseMonth' => $baseMonth, + 'CountPerPage' => $countPerPage, + 'CurrentPage' => $currentPage, + 'OrderDirection' => $orderDirection + ]); + + if (!$result['success']) { + return $result; + } + + return parseCardUsageResult($result['data']); +} + +/** + * ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ๊ฒฐ๊ณผ ํŒŒ์‹ฑ + * + * @param object $data SOAP ์‘๋‹ต ๋ฐ์ดํ„ฐ + * @return array ํŒŒ์‹ฑ๋œ ๊ฒฐ๊ณผ + */ +function parseCardUsageResult($data) { + // ์—๋Ÿฌ ์ฒดํฌ + if (isset($data->CurrentPage) && $data->CurrentPage < 0) { + $errorCode = $data->CurrentPage; + + // -24005: ์กฐํšŒ ๋ฐ์ดํ„ฐ ์—†์Œ (์ •์ƒ ์ผ€์ด์Šค๋กœ ์ฒ˜๋ฆฌ) + // -24001: ๋“ฑ๋ก๋œ ์นด๋“œ ์—†์Œ + // -24002: ์กฐํšŒ ๊ธฐ๊ฐ„ ์˜ค๋ฅ˜ + if ($errorCode == -24005 || $errorCode == -24001) { + // ๋ฐ์ดํ„ฐ ์—†์Œ - ๋นˆ ๋ฐฐ์—ด ๋ฐ˜ํ™˜ (์—๋Ÿฌ๊ฐ€ ์•„๋‹˜) + return [ + 'success' => true, + 'data' => [ + 'currentPage' => 1, + 'countPerPage' => 50, + 'maxPageNum' => 1, + 'maxIndex' => 0, + 'logs' => [] + ] + ]; + } + + return [ + 'success' => false, + 'error' => '์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ ์‹คํŒจ', + 'error_code' => $errorCode + ]; + } + + $logs = []; + if (isset($data->CardLogList) && isset($data->CardLogList->CardApprovalLog)) { + if (!is_array($data->CardLogList->CardApprovalLog)) { + $logs = [$data->CardLogList->CardApprovalLog]; + } else { + $logs = $data->CardLogList->CardApprovalLog; + } + } + + return [ + 'success' => true, + 'data' => [ + 'currentPage' => $data->CurrentPage ?? 1, + 'countPerPage' => $data->CountPerPage ?? 50, + 'maxPageNum' => $data->MaxPageNum ?? 1, + 'maxIndex' => $data->MaxIndex ?? 0, + 'logs' => $logs + ] + ]; +} + +/** + * ์นด๋“œ ๋“ฑ๋ก + * + * โš ๏ธ ์ฃผ์˜: ํ˜„์žฌ ์ด ํ•จ์ˆ˜๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + * ์นด๋“œ ๋“ฑ๋ก์€ ๋ฐ”๋กœ๋นŒ ์›น์‚ฌ์ดํŠธ(https://www.barobill.co.kr)์—์„œ ์ง์ ‘ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + * + * ์นด๋“œ ๋“ฑ๋ก ์‹œ ํ•„์š”ํ•œ ์ •๋ณด: + * - CardNum: ์นด๋“œ๋ฒˆํ˜ธ (์˜ˆ: "1234567890123456") + * - CardCompany: ์นด๋“œ์‚ฌ ์ฝ”๋“œ (์˜ˆ: "04"=์‚ผ์„ฑ, "06"=์‹ ํ•œ, "02"=KB) + * - CardType: ์นด๋“œ ์ข…๋ฅ˜ ("1"=๊ฐœ์ธ, "2"=๋ฒ•์ธ) + * - WebId: ์นด๋“œ์‚ฌ ์›น ID (์นด๋“œ์‚ฌ ํ™ˆํŽ˜์ด์ง€ ๋กœ๊ทธ์ธ ID) + * - WebPwd: ์นด๋“œ์‚ฌ ์›น ๋น„๋ฐ€๋ฒˆํ˜ธ (์นด๋“œ์‚ฌ ํ™ˆํŽ˜์ด์ง€ ๋กœ๊ทธ์ธ ๋น„๋ฐ€๋ฒˆํ˜ธ) + * - Alias: ์นด๋“œ ๋ณ„์นญ (์„ ํƒ์‚ฌํ•ญ, ์˜ˆ: "๋ฒ•์ธ์นด๋“œ1") + * - CollectCycle: ์ˆ˜์ง‘์ฃผ๊ธฐ ("1"=1์ผ1ํšŒ, "2"=1์ผ2ํšŒ, "3"=1์ผ3ํšŒ) + * - Usage: ์šฉ๋„ ("1"=์„ธ๊ธˆ๊ณ„์‚ฐ์„œ, "2"=๊ธฐํƒ€) + * + * ์นด๋“œ์‚ฌ ์ฝ”๋“œ ์ฐธ๊ณ : + * - 01: BC์นด๋“œ + * - 02: KB๊ตญ๋ฏผ์นด๋“œ + * - 04: ์‚ผ์„ฑ์นด๋“œ + * - 06: ์‹ ํ•œ์นด๋“œ + * - 07: ํ˜„๋Œ€์นด๋“œ + * - 08: ๋กฏ๋ฐ์นด๋“œ + * - 11: NH๋†ํ˜‘์นด๋“œ + * - 21: ํ•˜๋‚˜์นด๋“œ + * + * @param array $cardData ์นด๋“œ ๋ฐ์ดํ„ฐ + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function registerCard($cardData) { + return callBarobillCardSOAP('RegistCardEx', [ + 'CollectCycle' => $cardData['collectCycle'] ?? '1', // ์ˆ˜์ง‘์ฃผ๊ธฐ (1: 1์ผ 1ํšŒ) + 'CardCompany' => $cardData['cardCompany'] ?? '', // ์นด๋“œ์‚ฌ ์ฝ”๋“œ + 'CardType' => $cardData['cardType'] ?? '1', // ์นด๋“œ ์ข…๋ฅ˜ (1: ๊ฐœ์ธ, 2: ๋ฒ•์ธ) + 'CardNum' => $cardData['cardNum'] ?? '', // ์นด๋“œ๋ฒˆํ˜ธ + 'WebId' => $cardData['webId'] ?? '', // ์นด๋“œ์‚ฌ ์›น ID + 'WebPwd' => $cardData['webPwd'] ?? '', // ์นด๋“œ์‚ฌ ์›น ๋น„๋ฐ€๋ฒˆํ˜ธ + 'Alias' => $cardData['alias'] ?? '', // ์นด๋“œ ๋ณ„์นญ + 'Usage' => $cardData['usage'] ?? '1' // ์šฉ๋„ (1: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ, 2: ๊ธฐํƒ€) + ]); +} + +?> + diff --git a/ecard/api/cards.php b/ecard/api/cards.php new file mode 100644 index 0000000..b7192b0 --- /dev/null +++ b/ecard/api/cards.php @@ -0,0 +1,252 @@ +CardCompanyCode ?? $card->CardCompany ?? ''; + + // ์นด๋“œ ๋ธŒ๋žœ๋“œ (๋น„์ž, ๋งˆ์Šคํ„ฐ์นด๋“œ ๋“ฑ) ์ถ”์ธก + $cardBrand = guessCardTypeFromNumber($card->CardNum ?? ''); + + // ์นด๋“œ ํšŒ์‚ฌ๋ช… (์‹ ํ•œ, KB ๋“ฑ) + $cardCompanyName = !empty($card->CardCompanyName) + ? $card->CardCompanyName + : getCardCompanyName($cardCompanyCode); + + $cards[] = [ + 'cardNum' => $card->CardNum ?? '', + 'cardNumMasked' => maskCardNumber($card->CardNum ?? ''), + 'cardCompany' => $cardCompanyCode, + 'cardCompanyName' => $cardCompanyName, + 'cardBrand' => $cardBrand, // ์นด๋“œ ๋ธŒ๋žœ๋“œ (๋น„์ž, ๋งˆ์Šคํ„ฐ์นด๋“œ ๋“ฑ) + 'alias' => $card->Alias ?? '', + 'cardType' => $card->CardType ?? '', + 'cardTypeName' => getCardTypeName($card->CardType ?? ''), + 'status' => $card->Status ?? '', + 'statusName' => getCardStatusName($card->Status ?? ''), + 'collectCycle' => $card->CollectCycle ?? '', + 'collectCycleName' => getCollectCycleName($card->CollectCycle ?? ''), + 'lastCollectDate' => formatDate($card->LastCollectDate ?? ''), + 'lastCollectResult' => $card->LastCollectResult ?? '', + 'lastCollectResultName' => getCollectResultName($card->LastCollectResult ?? ''), + 'nextExtendDate' => formatDate($card->NextExtendDate ?? ''), + 'registDate' => formatDate($card->RegistDate ?? ''), + 'webId' => $card->WebId ?? '' + ]; + } + + echo json_encode([ + 'success' => true, + 'cards' => $cards, + 'count' => count($cards) + ], JSON_UNESCAPED_UNICODE); + } else { + echo json_encode([ + 'success' => false, + 'error' => $result['error'], + 'error_code' => $result['error_code'] ?? null + ], JSON_UNESCAPED_UNICODE); + } +} catch (Exception $e) { + echo json_encode([ + 'success' => false, + 'error' => '์„œ๋ฒ„ ์˜ค๋ฅ˜: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} + +/** + * ์นด๋“œ๋ฒˆํ˜ธ ๋งˆ์Šคํ‚น + */ +function maskCardNumber($cardNum) { + if (strlen($cardNum) < 8) return $cardNum; + return substr($cardNum, 0, 4) . '-****-****-' . substr($cardNum, -4); +} + +/** + * ๋‚ ์งœ ํฌ๋งทํŒ… + */ +function formatDate($date) { + if (empty($date)) return ''; + if (strlen($date) === 8) { + return substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2); + } + return $date; +} + +/** + * ์นด๋“œ๋ฒˆํ˜ธ๋กœ ์นด๋“œ ์ข…๋ฅ˜ ์ถ”์ธก (BIN ์ฝ”๋“œ ๊ธฐ๋ฐ˜) + */ +function guessCardTypeFromNumber($cardNum) { + if (empty($cardNum) || strlen($cardNum) < 4) { + return '์นด๋“œ'; + } + + $bin = substr($cardNum, 0, 4); + + // ์ฃผ์š” ์นด๋“œ์‚ฌ BIN ์ฝ”๋“œ + $binMappings = [ + '4518' => '๋น„์ž', + '4092' => '๋น„์ž', + '4569' => '๋น„์ž', + '4563' => '๋น„์ž', + '5' => '๋งˆ์Šคํ„ฐ์นด๋“œ', // 5๋กœ ์‹œ์ž‘ + '3528' => 'JCB', + '3529' => 'JCB', + '3' => '์•„๋ฉ•์Šค/๋‹ค์ด๋„ˆ์Šค', // 34, 37๋กœ ์‹œ์ž‘ + '9' => '๊ตญ๋‚ด์ „์šฉ์นด๋“œ' + ]; + + // ์ •ํ™•ํ•œ ๋งค์นญ ์‹œ๋„ + if (isset($binMappings[$bin])) { + return $binMappings[$bin]; + } + + // ์ฒซ ๋ฒˆ์งธ ์ˆซ์ž๋กœ ๋งค์นญ ์‹œ๋„ + $firstDigit = substr($cardNum, 0, 1); + if (isset($binMappings[$firstDigit])) { + return $binMappings[$firstDigit]; + } + + return '์นด๋“œ'; +} + +/** + * ์นด๋“œ์‚ฌ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + * ๋ฐ”๋กœ๋นŒ ์นด๋“œ์‚ฌ ์ฝ”๋“œ ์ฐธ๊ณ  + */ +function getCardCompanyName($code) { + $companies = [ + '01' => '๋น„์”จ์นด๋“œ', + '02' => 'KB๊ตญ๋ฏผ์นด๋“œ', + '03' => 'ํ•˜๋‚˜์นด๋“œ(์™ธํ™˜)', + '04' => '์‚ผ์„ฑ์นด๋“œ', + '06' => '์‹ ํ•œ์นด๋“œ', + '07' => 'ํ˜„๋Œ€์นด๋“œ', + '08' => '๋กฏ๋ฐ์นด๋“œ', + '11' => 'NH๋†ํ˜‘์นด๋“œ', + '12' => '์ˆ˜ํ˜‘์นด๋“œ', + '13' => '์”จํ‹ฐ์นด๋“œ', + '14' => '์šฐ๋ฆฌ์นด๋“œ', + '15' => '๊ด‘์ฃผ์นด๋“œ', + '16' => '์ „๋ถ์นด๋“œ', + '21' => 'ํ•˜๋‚˜์นด๋“œ', + '22' => '์ œ์ฃผ์นด๋“œ', + '23' => 'SC์ œ์ผ์นด๋“œ', + '25' => 'KDB์‚ฐ์—…์นด๋“œ', + '26' => 'IBK๊ธฐ์—…์นด๋“œ', + '27' => '์ƒˆ๋งˆ์„๊ธˆ๊ณ ', + '28' => '์‹ ํ˜‘์นด๋“œ', + '29' => '์ €์ถ•์€ํ–‰', + '30' => '์šฐ์ฒด๊ตญ์นด๋“œ', + '31' => '์นด์นด์˜ค๋ฑ…ํฌ', + '32' => 'K๋ฑ…ํฌ', + '33' => 'ํ† ์Šค๋ฑ…ํฌ', + 'BC' => '๋น„์”จ์นด๋“œ', + 'KB' => 'KB๊ตญ๋ฏผ์นด๋“œ', + 'HANA' => 'ํ•˜๋‚˜์นด๋“œ', + 'SAMSUNG' => '์‚ผ์„ฑ์นด๋“œ', + 'SHINHAN' => '์‹ ํ•œ์นด๋“œ', + 'HYUNDAI' => 'ํ˜„๋Œ€์นด๋“œ', + 'LOTTE' => '๋กฏ๋ฐ์นด๋“œ', + 'NH' => 'NH๋†ํ˜‘์นด๋“œ', + 'SUHYUP' => '์ˆ˜ํ˜‘์นด๋“œ', + 'CITI' => '์”จํ‹ฐ์นด๋“œ', + 'WOORI' => '์šฐ๋ฆฌ์นด๋“œ', + 'KJBANK' => '๊ด‘์ฃผ์นด๋“œ', + 'JBBANK' => '์ „๋ถ์นด๋“œ' + ]; + return $companies[$code] ?? $code; +} + +/** + * ์นด๋“œ ์ข…๋ฅ˜ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + */ +function getCardTypeName($type) { + $types = [ + '1' => '๊ฐœ์ธ์นด๋“œ', + '2' => '๋ฒ•์ธ์นด๋“œ' + ]; + return $types[$type] ?? $type; +} + +/** + * ์นด๋“œ ์ƒํƒœ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + */ +function getCardStatusName($status) { + $statuses = [ + '0' => '๋Œ€๊ธฐ์ค‘', + '1' => '์ •์ƒ', + '2' => 'ํ•ด์ง€', + '3' => '์ˆ˜์ง‘์˜ค๋ฅ˜', + '4' => '์ผ์‹œ์ค‘์ง€' + ]; + return $statuses[$status] ?? $status; +} + +/** + * ์ˆ˜์ง‘์ฃผ๊ธฐ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + */ +function getCollectCycleName($cycle) { + $cycles = [ + '1' => '1์ผ 1ํšŒ', + '2' => '1์ผ 2ํšŒ', + '3' => '1์ผ 3ํšŒ' + ]; + return $cycles[$cycle] ?? $cycle; +} + +/** + * ์ˆ˜์ง‘๊ฒฐ๊ณผ ์ฝ”๋“œ -> ์ด๋ฆ„ ๋ณ€ํ™˜ + */ +function getCollectResultName($result) { + $results = [ + '0' => '๋Œ€๊ธฐ', + '1' => '์„ฑ๊ณต', + '2' => '์‹คํŒจ', + '3' => '์ง„ํ–‰์ค‘' + ]; + return $results[$result] ?? $result; +} +?> + diff --git a/ecard/api/debug_raw.php b/ecard/api/debug_raw.php new file mode 100644 index 0000000..dff0dcd --- /dev/null +++ b/ecard/api/debug_raw.php @@ -0,0 +1,65 @@ + $barobillCertKey, + 'CorpNum' => $barobillCorpNum, + 'ID' => '', + 'CardNum' => '', + 'StartDate' => $startDate, + 'EndDate' => $endDate, + 'CountPerPage' => 10, + 'CurrentPage' => 1, + 'OrderDirection' => 2 + ]; + + $result = $barobillCardSoapClient->GetPeriodCardApprovalLog($params); + $resultData = $result->GetPeriodCardApprovalLogResult; + + // raw ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ + $output = [ + 'params' => $params, + 'resultKeys' => is_object($resultData) ? array_keys(get_object_vars($resultData)) : 'not object', + 'CurrentPage' => $resultData->CurrentPage ?? null, + 'MaxIndex' => $resultData->MaxIndex ?? null + ]; + + // CardLogList ํ™•์ธ + if (isset($resultData->CardLogList)) { + $output['CardLogListKeys'] = is_object($resultData->CardLogList) ? array_keys(get_object_vars($resultData->CardLogList)) : 'not object'; + + if (isset($resultData->CardLogList->CardApprovalLog)) { + $logs = $resultData->CardLogList->CardApprovalLog; + if (!is_array($logs)) { + $logs = [$logs]; + } + + if (!empty($logs)) { + $firstLog = $logs[0]; + $output['firstLogKeys'] = is_object($firstLog) ? array_keys(get_object_vars($firstLog)) : 'not object'; + $output['firstLogData'] = $firstLog; + } + } + } + + echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + +} catch (Exception $e) { + echo json_encode([ + 'error' => $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} +?> + diff --git a/ecard/api/usage.php b/ecard/api/usage.php new file mode 100644 index 0000000..e296800 --- /dev/null +++ b/ecard/api/usage.php @@ -0,0 +1,402 @@ + true, + 'data' => [ + 'currentPage' => 1, + 'countPerPage' => $limit, + 'maxPageNum' => 1, + 'maxIndex' => 0, + 'logs' => [] + ] + ]; + } else { + // ๊ฐ ์นด๋“œ๋ณ„๋กœ ์กฐํšŒ ํ›„ ๋ณ‘ํ•ฉ + $allLogs = []; + foreach ($cardsResult['data'] as $card) { + $cardNumToQuery = $card->CardNum ?? ''; + if (empty($cardNumToQuery)) continue; + + switch ($type) { + case 'daily': + $baseDate = $_GET['baseDate'] ?? date('Ymd'); + $tempResult = getDailyCardUsage($cardNumToQuery, $baseDate, 100, 1, $orderDirection); + break; + case 'monthly': + $baseMonth = $_GET['baseMonth'] ?? date('Ym'); + $tempResult = getMonthlyCardUsage($cardNumToQuery, $baseMonth, 100, 1, $orderDirection); + break; + case 'period': + default: + $startDate = $_GET['startDate'] ?? date('Ymd', strtotime('-30 days')); + $endDate = $_GET['endDate'] ?? date('Ymd'); + $tempResult = getPeriodCardUsage($cardNumToQuery, $startDate, $endDate, 100, 1, $orderDirection); + break; + } + + if ($tempResult['success'] && !empty($tempResult['data']['logs'])) { + $allLogs = array_merge($allLogs, $tempResult['data']['logs']); + } + } + + // UseDT ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ + usort($allLogs, function($a, $b) use ($orderDirection) { + $aTime = $a->UseDT ?? ''; + $bTime = $b->UseDT ?? ''; + return $orderDirection == 1 ? strcmp($aTime, $bTime) : strcmp($bTime, $aTime); + }); + + // ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ + $totalCount = count($allLogs); + $maxPageNum = ceil($totalCount / $limit); + $offset = ($page - 1) * $limit; + $pagedLogs = array_slice($allLogs, $offset, $limit); + + $result = [ + 'success' => true, + 'data' => [ + 'currentPage' => $page, + 'countPerPage' => $limit, + 'maxPageNum' => $maxPageNum, + 'maxIndex' => $totalCount, + 'logs' => $pagedLogs + ] + ]; + } + } else { + // ํŠน์ • ์นด๋“œ ์กฐํšŒ + switch ($type) { + case 'daily': + $baseDate = $_GET['baseDate'] ?? date('Ymd'); + $result = getDailyCardUsage($cardNum, $baseDate, $limit, $page, $orderDirection); + break; + + case 'monthly': + $baseMonth = $_GET['baseMonth'] ?? date('Ym'); + $result = getMonthlyCardUsage($cardNum, $baseMonth, $limit, $page, $orderDirection); + break; + + case 'period': + default: + $startDate = $_GET['startDate'] ?? date('Ymd', strtotime('-30 days')); + $endDate = $_GET['endDate'] ?? date('Ymd'); + $result = getPeriodCardUsage($cardNum, $startDate, $endDate, $limit, $page, $orderDirection); + break; + } + } + + if ($result['success']) { + $logs = []; + + // ๋””๋ฒ„๊ทธ: raw ๋กœ๊ทธ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ + if ($debugMode && !empty($result['data']['logs'])) { + $firstLog = $result['data']['logs'][0]; + error_log('CardApprovalLog raw data: ' . print_r($firstLog, true)); + // ๋””๋ฒ„๊ทธ: ๋ชจ๋“  ํ•„๋“œ๋ช… ํ™•์ธ + if (is_object($firstLog)) { + $fields = get_object_vars($firstLog); + error_log('CardApprovalLog fields: ' . implode(', ', array_keys($fields))); + error_log('ApprovalAmount value: ' . ($firstLog->ApprovalAmount ?? 'NOT SET')); + error_log('Amount value: ' . ($firstLog->Amount ?? 'NOT SET')); + error_log('TotalAmount value: ' . ($firstLog->TotalAmount ?? 'NOT SET')); + } + } + + foreach ($result['data']['logs'] as $log) { + // UseDT ํ˜•์‹: YYYYMMDDHHMMSS + $useDT = $log->UseDT ?? ''; + $approvalDate = ''; + $approvalTime = ''; + if (strlen($useDT) >= 8) { + $approvalDate = substr($useDT, 0, 4) . '-' . substr($useDT, 4, 2) . '-' . substr($useDT, 6, 2); + } + if (strlen($useDT) >= 14) { + $approvalTime = substr($useDT, 8, 2) . ':' . substr($useDT, 10, 2) . ':' . substr($useDT, 12, 2); + } elseif (strlen($useDT) >= 12) { + $approvalTime = substr($useDT, 8, 2) . ':' . substr($useDT, 10, 2); + } + + $logs[] = [ + 'cardNum' => maskCardNumber($log->CardNum ?? ''), + 'cardNumFull' => $log->CardNum ?? '', + 'approvalNum' => $log->ApprovalNum ?? '', + 'approvalDate' => $approvalDate, + 'approvalTime' => $approvalTime, + 'approvalDateTime' => $approvalDate . ' ' . $approvalTime, + 'merchantName' => $log->UseStoreName ?? '', + 'merchantBizNum' => $log->UseStoreCorpNum ?? '', + // ๊ธˆ์•ก ํ•„๋“œ: ์—ฌ๋Ÿฌ ๊ฐ€๋Šฅํ•œ ํ•„๋“œ๋ช… ์‹œ๋„ + // ApprovalAmount๊ฐ€ ์‹ค์ œ ์Šน์ธ๊ธˆ์•ก (ํ™”๋ฉด์— ํ‘œ์‹œํ•  ๊ธˆ์•ก) + 'amount' => intval($log->ApprovalAmount ?? 0), + 'amountFormatted' => number_format(intval($log->ApprovalAmount ?? 0)), + 'vat' => intval($log->Tax ?? 0), + 'vatFormatted' => number_format(intval($log->Tax ?? 0)), + 'serviceCharge' => intval($log->ServiceCharge ?? 0), + // totalAmount๋Š” ํ™”๋ฉด์—์„œ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ApprovalAmount๋ฅผ ์‚ฌ์šฉ + 'totalAmount' => intval($log->ApprovalAmount ?? 0), + 'totalAmountFormatted' => number_format(intval($log->ApprovalAmount ?? 0)), + 'approvalType' => $log->ApprovalType ?? '', + 'approvalTypeName' => getApprovalTypeName($log->ApprovalType ?? ''), + 'installment' => $log->PaymentPlan ?? '', + 'installmentName' => getInstallmentName($log->PaymentPlan ?? ''), + 'currencyCode' => $log->CurrencyCode ?? 'KRW', + 'memo' => $log->Memo ?? '', + 'cardCompany' => $log->CardCompany ?? '', + 'cardCompanyName' => getCardCompanyNameFromLog($log->CardCompany ?? ''), + // ์ถ”๊ฐ€ ํ•„๋“œ + 'useKey' => $log->UseKey ?? '', + 'storeAddress' => $log->UseStoreAddr ?? '', + 'storeCeo' => $log->UseStoreCeo ?? '', + 'storeBizType' => $log->UseStoreBizType ?? '', + 'storeTel' => $log->UseStoreTel ?? '' + ]; + } + + // ํ†ต๊ณ„ ๊ณ„์‚ฐ + $totalAmount = array_sum(array_column($logs, 'totalAmount')); + $approvalCount = count(array_filter($logs, function($l) { return $l['approvalType'] == '1'; })); + $cancelCount = count(array_filter($logs, function($l) { return $l['approvalType'] == '2'; })); + + $response = [ + 'success' => true, + 'data' => [ + 'logs' => $logs, + 'pagination' => [ + 'currentPage' => $result['data']['currentPage'], + 'countPerPage' => $result['data']['countPerPage'], + 'maxPageNum' => $result['data']['maxPageNum'], + 'totalCount' => $result['data']['maxIndex'] + ], + 'summary' => [ + 'totalAmount' => $totalAmount, + 'totalAmountFormatted' => number_format($totalAmount), + 'count' => count($logs), + 'approvalCount' => $approvalCount, + 'cancelCount' => $cancelCount + ] + ] + ]; + + // ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถ”๊ฐ€ (์„ฑ๊ณตํ•œ ๊ฒฝ์šฐ์—๋„ ํ•ญ์ƒ ์ฒซ ๋ฒˆ์งธ ๋กœ๊ทธ์˜ ํ•„๋“œ ์ •๋ณด ์ถœ๋ ฅ) + if (!empty($result['data']['logs'])) { + $firstLog = $result['data']['logs'][0]; + if (is_object($firstLog)) { + // ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ + $allFields = get_object_vars($firstLog); + $fieldNames = array_keys($allFields); + + // ๊ธˆ์•ก ๊ด€๋ จ ํ•„๋“œ ์ฐพ๊ธฐ (๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ ์—†์ด) + $amountFields = []; + foreach ($fieldNames as $fieldName) { + if (stripos($fieldName, 'amount') !== false || + stripos($fieldName, 'cost') !== false || + stripos($fieldName, 'price') !== false || + stripos($fieldName, '๊ธˆ์•ก') !== false) { + $amountFields[$fieldName] = (string)($firstLog->$fieldName ?? 'NULL'); + } + } + + // ๋””๋ฒ„๊ทธ ๋ชจ๋“œ์ผ ๋•Œ๋งŒ ์ƒ์„ธ ์ •๋ณด ์ถœ๋ ฅ + if ($debugMode) { + $response['debug'] = [ + 'userId' => getBarobillUserId(), + 'params' => $_GET, + 'firstLogFields' => $fieldNames, + 'firstLogAllValues' => array_map(function($v) { + return is_string($v) ? $v : (is_numeric($v) ? (string)$v : gettype($v)); + }, $allFields), + 'amountFields' => $amountFields + ]; + } else { + // ๋””๋ฒ„๊ทธ ๋ชจ๋“œ๊ฐ€ ์•„๋‹ˆ์–ด๋„ ๊ธˆ์•ก ํ•„๋“œ ์ •๋ณด๋Š” ํ•ญ์ƒ ํฌํ•จ (๋ฌธ์ œ ํ•ด๊ฒฐ์šฉ) + $response['debug'] = [ + 'amountFields' => $amountFields, + 'allFields' => $fieldNames + ]; + } + } + } elseif ($debugMode) { + $response['debug'] = [ + 'userId' => getBarobillUserId(), + 'params' => $_GET, + 'message' => 'No logs found' + ]; + } + + echo json_encode($response, JSON_UNESCAPED_UNICODE); + } else { + $response = [ + 'success' => false, + 'error' => $result['error'], + 'error_code' => $result['error_code'] ?? null + ]; + + // ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถ”๊ฐ€ + if ($debugMode) { + $response['debug'] = [ + 'userId' => getBarobillUserId(), + 'params' => $_GET + ]; + } + + echo json_encode($response, JSON_UNESCAPED_UNICODE); + } +} catch (Exception $e) { + echo json_encode([ + 'success' => false, + 'error' => '์„œ๋ฒ„ ์˜ค๋ฅ˜: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} + +/** + * ์นด๋“œ๋ฒˆํ˜ธ ๋งˆ์Šคํ‚น + */ +function maskCardNumber($cardNum) { + if (strlen($cardNum) < 8) return $cardNum; + return substr($cardNum, 0, 4) . '-****-****-' . substr($cardNum, -4); +} + +/** + * ๋‚ ์งœ ํฌ๋งทํŒ… + */ +function formatDate($date) { + if (strlen($date) === 8) { + return substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2); + } + return $date; +} + +/** + * ์‹œ๊ฐ„ ํฌ๋งทํŒ… + */ +function formatTime($time) { + if (strlen($time) === 6) { + return substr($time, 0, 2) . ':' . substr($time, 2, 2) . ':' . substr($time, 4, 2); + } elseif (strlen($time) === 4) { + return substr($time, 0, 2) . ':' . substr($time, 2, 2); + } + return $time; +} + +/** + * ์Šน์ธ ์œ ํ˜• ์ด๋ฆ„ + */ +function getApprovalTypeName($type) { + $types = [ + '1' => '์Šน์ธ', + '2' => '์ทจ์†Œ' + ]; + return $types[$type] ?? $type; +} + +/** + * ํ• ๋ถ€ ์ด๋ฆ„ + */ +function getInstallmentName($installment) { + if (empty($installment) || $installment == '0' || $installment == '00') { + return '์ผ์‹œ๋ถˆ'; + } + return $installment . '๊ฐœ์›”'; +} + +/** + * ์นด๋“œ์‚ฌ ์ด๋ฆ„ (๋กœ๊ทธ์šฉ) + */ +function getCardCompanyNameFromLog($code) { + $companies = [ + '01' => '๋น„์”จ', + '02' => 'KB๊ตญ๋ฏผ', + '03' => 'ํ•˜๋‚˜(์™ธํ™˜)', + '04' => '์‚ผ์„ฑ', + '06' => '์‹ ํ•œ', + '07' => 'ํ˜„๋Œ€', + '08' => '๋กฏ๋ฐ', + '11' => 'NH๋†ํ˜‘', + '12' => '์ˆ˜ํ˜‘', + '13' => '์”จํ‹ฐ', + '14' => '์šฐ๋ฆฌ', + '15' => '๊ด‘์ฃผ', + '16' => '์ „๋ถ', + '21' => 'ํ•˜๋‚˜', + '22' => '์ œ์ฃผ', + '23' => 'SC์ œ์ผ', + '25' => 'KDB์‚ฐ์—…', + '26' => 'IBK๊ธฐ์—…', + '27' => '์ƒˆ๋งˆ์„๊ธˆ๊ณ ', + '28' => '์‹ ํ˜‘', + '29' => '์ €์ถ•์€ํ–‰', + '30' => '์šฐ์ฒด๊ตญ', + '31' => '์นด์นด์˜ค๋ฑ…ํฌ', + '32' => 'K๋ฑ…ํฌ', + '33' => 'ํ† ์Šค๋ฑ…ํฌ' + ]; + return $companies[$code] ?? $code; +} +?> + diff --git a/ecard/index.php b/ecard/index.php new file mode 100644 index 0000000..f81c7af --- /dev/null +++ b/ecard/index.php @@ -0,0 +1,920 @@ + + + + + + ๋ฒ•์ธ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ - ๋ฐ”๋กœ๋นŒ ์—ฐ๋™ + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/ecard/์นด๋“œ์‚ฌ์šฉ๋‚ด์—ญ์กฐํšŒ.md b/ecard/์นด๋“œ์‚ฌ์šฉ๋‚ด์—ญ์กฐํšŒ.md new file mode 100644 index 0000000..b7cf466 --- /dev/null +++ b/ecard/์นด๋“œ์‚ฌ์šฉ๋‚ด์—ญ์กฐํšŒ.md @@ -0,0 +1,957 @@ +# ๋ฐ”๋กœ๋นŒ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ - ๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ ๊ฐœ๋ฐœ ๋ฌธ์„œ + +## ๋ชฉ์ฐจ +1. [๊ฐœ์š”](#๊ฐœ์š”) +2. [์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜](#์‹œ์Šคํ…œ-์•„ํ‚คํ…์ฒ˜) +3. [๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค๊ณ„](#๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค-์„ค๊ณ„) +4. [API ๊ตฌ์กฐ](#api-๊ตฌ์กฐ) +5. [๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ](#๋ณด์•ˆ-๊ณ ๋ ค์‚ฌํ•ญ) +6. [๊ตฌํ˜„ ๊ฐ€์ด๋“œ](#๊ตฌํ˜„-๊ฐ€์ด๋“œ) + +--- + +## ๊ฐœ์š” + +### ๋ชฉ์  +๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ ํ™˜๊ฒฝ์—์„œ ๊ฐ ์—…์ฒด(ํ…Œ๋„ŒํŠธ)๋ณ„๋กœ ๋…๋ฆฝ์ ์ธ ๋ฐ”๋กœ๋นŒ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•œ ๊ฐœ๋ฐœ ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค. + +### ์ฃผ์š” ๊ธฐ๋Šฅ +- ์—…์ฒด๋ณ„ ๋ฐ”๋กœ๋นŒ ์ธ์ฆ ์ •๋ณด ๊ด€๋ฆฌ +- ์—…์ฒด๋ณ„ ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ +- ์—…์ฒด๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ +- ๋ฐ์ดํ„ฐ ๊ฒฉ๋ฆฌ ๋ฐ ๋ณด์•ˆ ๊ด€๋ฆฌ + +### ๊ธฐ์ˆ  ์Šคํƒ +- **๋ฐฑ์—”๋“œ**: PHP 7.3+ +- **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค**: MySQL/MariaDB +- **์™ธ๋ถ€ API**: ๋ฐ”๋กœ๋นŒ SOAP ์›น์„œ๋น„์Šค +- **ํ”„๋ก ํŠธ์—”๋“œ**: React (ecard/index.php) + +--- + +## ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ + +### ๋ฐ์ดํ„ฐ ํ๋ฆ„๋„ + +``` +[์—…์ฒด ์‚ฌ์šฉ์ž] + โ†“ +[ecard/index.php] (ํ”„๋ก ํŠธ์—”๋“œ) + โ†“ (์—…์ฒด ID ์ „๋‹ฌ) +[API Layer] + โ”œโ”€ cards.php (์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ) + โ””โ”€ usage.php (์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ) + โ†“ (์—…์ฒด๋ณ„ ์ธ์ฆ ์ •๋ณด ์กฐํšŒ) +[Database] + โ”œโ”€ companies (์—…์ฒด ์ •๋ณด) + โ””โ”€ barobill_credentials (๋ฐ”๋กœ๋นŒ ์ธ์ฆ ์ •๋ณด) + โ†“ (๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ) +[๋ฐ”๋กœ๋นŒ SOAP API] + โ”œโ”€ GetCardEx2 (์นด๋“œ ๋ชฉ๋ก) + โ””โ”€ GetPeriodCardApprovalLog (์‚ฌ์šฉ๋‚ด์—ญ) + โ†“ (์‘๋‹ต) +[API Layer] โ†’ [ํ”„๋ก ํŠธ์—”๋“œ] โ†’ [์‚ฌ์šฉ์ž] +``` + +### ๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ ๊ตฌ์กฐ + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ ์—…์ฒด A (Company A) โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ ๋ฐ”๋กœ๋นŒ ์ธ์ฆ ์ •๋ณด โ”‚ โ”‚ +โ”‚ โ”‚ - CERTKEY: AAAAA โ”‚ โ”‚ +โ”‚ โ”‚ - ์‚ฌ์—…์ž๋ฒˆํ˜ธ: 123-45-67890 โ”‚ โ”‚ +โ”‚ โ”‚ - ์‚ฌ์šฉ์ž ID: user_a โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ ์นด๋“œ ๋ชฉ๋ก (๋ฐ”๋กœ๋นŒ์—์„œ ์กฐํšŒ) โ”‚ โ”‚ +โ”‚ โ”‚ - ์นด๋“œ1, ์นด๋“œ2, ์นด๋“œ3 โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ ์—…์ฒด B (Company B) โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ ๋ฐ”๋กœ๋นŒ ์ธ์ฆ ์ •๋ณด โ”‚ โ”‚ +โ”‚ โ”‚ - CERTKEY: BBBBB โ”‚ โ”‚ +โ”‚ โ”‚ - ์‚ฌ์—…์ž๋ฒˆํ˜ธ: 987-65-43210 โ”‚ โ”‚ +โ”‚ โ”‚ - ์‚ฌ์šฉ์ž ID: user_b โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ ์นด๋“œ ๋ชฉ๋ก (๋ฐ”๋กœ๋นŒ์—์„œ ์กฐํšŒ) โ”‚ โ”‚ +โ”‚ โ”‚ - ์นด๋“œ4, ์นด๋“œ5 โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +--- + +## ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค๊ณ„ + +### 1. companies (์—…์ฒด ๊ธฐ๋ณธ ์ •๋ณด ํ…Œ์ด๋ธ”) + +์—…์ฒด์˜ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. + +```sql +CREATE TABLE companies ( + id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '์—…์ฒด ID', + company_name VARCHAR(255) NOT NULL COMMENT '์—…์ฒด๋ช…', + business_number VARCHAR(20) NOT NULL COMMENT '์‚ฌ์—…์ž๋ฒˆํ˜ธ (ํ•˜์ดํ”ˆ ํฌํ•จ)', + business_number_clean VARCHAR(20) NOT NULL COMMENT '์‚ฌ์—…์ž๋ฒˆํ˜ธ (ํ•˜์ดํ”ˆ ์ œ๊ฑฐ)', + status ENUM('active', 'inactive', 'suspended') DEFAULT 'active' COMMENT '์ƒํƒœ', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '์ƒ์„ฑ์ผ์‹œ', + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '์ˆ˜์ •์ผ์‹œ', + deleted_at DATETIME NULL COMMENT '์‚ญ์ œ์ผ์‹œ (์†Œํ”„ํŠธ ์‚ญ์ œ)', + + UNIQUE KEY uk_business_number (business_number_clean), + INDEX idx_status (status), + INDEX idx_deleted_at (deleted_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='์—…์ฒด ๊ธฐ๋ณธ ์ •๋ณด'; +``` + +**์ฃผ์š” ํ•„๋“œ ์„ค๋ช…:** +- `id`: ์—…์ฒด ๊ณ ์œ  ID (๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์—์„œ ์™ธ๋ž˜ํ‚ค๋กœ ์‚ฌ์šฉ) +- `company_name`: ์—…์ฒด๋ช… +- `business_number`: ์‚ฌ์—…์ž๋ฒˆํ˜ธ (ํ‘œ์‹œ์šฉ, ํ•˜์ดํ”ˆ ํฌํ•จ) +- `business_number_clean`: ์‚ฌ์—…์ž๋ฒˆํ˜ธ (๊ฒ€์ƒ‰์šฉ, ํ•˜์ดํ”ˆ ์ œ๊ฑฐ) +- `status`: ์—…์ฒด ์ƒํƒœ (active=ํ™œ์„ฑ, inactive=๋น„ํ™œ์„ฑ, suspended=์ •์ง€) + +--- + +### 2. barobill_credentials (๋ฐ”๋กœ๋นŒ ์ธ์ฆ ์ •๋ณด ํ…Œ์ด๋ธ”) + +๊ฐ ์—…์ฒด๋ณ„ ๋ฐ”๋กœ๋นŒ API ์ธ์ฆ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. + +```sql +CREATE TABLE barobill_credentials ( + id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '์ธ์ฆ ์ •๋ณด ID', + company_id INT(11) UNSIGNED NOT NULL COMMENT '์—…์ฒด ID', + cert_key VARCHAR(500) NOT NULL COMMENT '๋ฐ”๋กœ๋นŒ CERTKEY (์•”ํ˜ธํ™” ๊ถŒ์žฅ)', + corp_num VARCHAR(20) NOT NULL COMMENT '์‚ฌ์—…์ž๋ฒˆํ˜ธ (ํ•˜์ดํ”ˆ ์ œ๊ฑฐ)', + user_id VARCHAR(100) NULL COMMENT '๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (์„ ํƒ์‚ฌํ•ญ, ๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด ์นด๋“œ ์กฐํšŒ)', + test_mode TINYINT(1) DEFAULT 0 COMMENT 'ํ…Œ์ŠคํŠธ ๋ชจ๋“œ (0=์šด์˜, 1=ํ…Œ์ŠคํŠธ)', + status ENUM('active', 'inactive') DEFAULT 'active' COMMENT '์ƒํƒœ', + last_api_call DATETIME NULL COMMENT '๋งˆ์ง€๋ง‰ API ํ˜ธ์ถœ ์ผ์‹œ', + last_error_message TEXT NULL COMMENT '๋งˆ์ง€๋ง‰ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '์ƒ์„ฑ์ผ์‹œ', + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '์ˆ˜์ •์ผ์‹œ', + + UNIQUE KEY uk_company_id (company_id), + INDEX idx_status (status), + INDEX idx_company_id (company_id), + + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='๋ฐ”๋กœ๋นŒ ์ธ์ฆ ์ •๋ณด'; +``` + +**์ฃผ์š” ํ•„๋“œ ์„ค๋ช…:** +- `company_id`: ์—…์ฒด ID (companies ํ…Œ์ด๋ธ” ์ฐธ์กฐ) +- `cert_key`: ๋ฐ”๋กœ๋นŒ CERTKEY (โš ๏ธ ๋ฏผ๊ฐ์ •๋ณด, ์•”ํ˜ธํ™” ๊ถŒ์žฅ) +- `corp_num`: ์‚ฌ์—…์ž๋ฒˆํ˜ธ (ํ•˜์ดํ”ˆ ์ œ๊ฑฐ) +- `user_id`: ๋ฐ”๋กœ๋นŒ ์‚ฌ์šฉ์ž ID (ํŠน์ • ์‚ฌ์šฉ์ž ์นด๋“œ๋งŒ ์กฐํšŒ ์‹œ ์‚ฌ์šฉ, NULL์ด๋ฉด ์ „์ฒด) +- `test_mode`: ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ์—ฌ๋ถ€ (0=์šด์˜, 1=ํ…Œ์ŠคํŠธ) +- `status`: ์ธ์ฆ ์ •๋ณด ์ƒํƒœ +- `last_api_call`: ๋งˆ์ง€๋ง‰ API ํ˜ธ์ถœ ์ผ์‹œ (๋ชจ๋‹ˆํ„ฐ๋ง์šฉ) +- `last_error_message`: ๋งˆ์ง€๋ง‰ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ (๋””๋ฒ„๊น…์šฉ) + +**๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ:** +- `cert_key`๋Š” ๋ฏผ๊ฐ์ •๋ณด์ด๋ฏ€๋กœ ์•”ํ˜ธํ™” ์ €์žฅ ๊ถŒ์žฅ +- ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ ๊ถŒํ•œ ์ตœ์†Œํ™” +- ๋กœ๊ทธ์— ๋ฏผ๊ฐ์ •๋ณด ์ถœ๋ ฅ ๊ธˆ์ง€ + +--- + +### 3. barobill_cards (์นด๋“œ ์ •๋ณด ์บ์‹œ ํ…Œ์ด๋ธ”) + +๋ฐ”๋กœ๋นŒ์—์„œ ์กฐํšŒํ•œ ์นด๋“œ ์ •๋ณด๋ฅผ ์บ์‹ฑํ•˜๋Š” ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. (์„ ํƒ์‚ฌํ•ญ) + +```sql +CREATE TABLE barobill_cards ( + id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '์นด๋“œ ID', + company_id INT(11) UNSIGNED NOT NULL COMMENT '์—…์ฒด ID', + card_num VARCHAR(50) NOT NULL COMMENT '์นด๋“œ๋ฒˆํ˜ธ', + card_company_code VARCHAR(10) NULL COMMENT '์นด๋“œ์‚ฌ ์ฝ”๋“œ', + card_company_name VARCHAR(50) NULL COMMENT '์นด๋“œ์‚ฌ ์ด๋ฆ„', + card_brand VARCHAR(20) NULL COMMENT '์นด๋“œ ๋ธŒ๋žœ๋“œ (๋น„์ž, ๋งˆ์Šคํ„ฐ์นด๋“œ ๋“ฑ)', + alias VARCHAR(100) NULL COMMENT '์นด๋“œ ๋ณ„์นญ', + card_type TINYINT(1) NULL COMMENT '์นด๋“œ ์ข…๋ฅ˜ (1=๊ฐœ์ธ, 2=๋ฒ•์ธ)', + status TINYINT(1) NULL COMMENT '์นด๋“œ ์ƒํƒœ (0=๋Œ€๊ธฐ์ค‘, 1=์ •์ƒ, 2=ํ•ด์ง€, 3=์ˆ˜์ง‘์˜ค๋ฅ˜, 4=์ผ์‹œ์ค‘์ง€)', + collect_cycle TINYINT(1) NULL COMMENT '์ˆ˜์ง‘์ฃผ๊ธฐ (1=1์ผ1ํšŒ, 2=1์ผ2ํšŒ, 3=1์ผ3ํšŒ)', + last_collect_date DATE NULL COMMENT '๋งˆ์ง€๋ง‰ ์ˆ˜์ง‘์ผ', + last_collect_result TINYINT(1) NULL COMMENT '๋งˆ์ง€๋ง‰ ์ˆ˜์ง‘๊ฒฐ๊ณผ', + regist_date DATE NULL COMMENT '๋“ฑ๋ก์ผ', + cached_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '์บ์‹œ ์ผ์‹œ', + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '์ˆ˜์ •์ผ์‹œ', + + UNIQUE KEY uk_company_card (company_id, card_num), + INDEX idx_company_id (company_id), + INDEX idx_status (status), + INDEX idx_cached_at (cached_at), + + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='๋ฐ”๋กœ๋นŒ ์นด๋“œ ์ •๋ณด ์บ์‹œ'; +``` + +**์ฃผ์š” ํ•„๋“œ ์„ค๋ช…:** +- `company_id`: ์—…์ฒด ID +- `card_num`: ์นด๋“œ๋ฒˆํ˜ธ (๋ฐ”๋กœ๋นŒ์—์„œ ์กฐํšŒํ•œ ์นด๋“œ๋ฒˆํ˜ธ) +- `card_company_code`: ์นด๋“œ์‚ฌ ์ฝ”๋“œ (01=BC, 02=KB, 04=์‚ผ์„ฑ ๋“ฑ) +- `card_company_name`: ์นด๋“œ์‚ฌ ์ด๋ฆ„ +- `card_brand`: ์นด๋“œ ๋ธŒ๋žœ๋“œ (๋น„์ž, ๋งˆ์Šคํ„ฐ์นด๋“œ ๋“ฑ) +- `alias`: ์นด๋“œ ๋ณ„์นญ +- `status`: ์นด๋“œ ์ƒํƒœ +- `cached_at`: ์บ์‹œ ์ผ์‹œ (์บ์‹œ ๋งŒ๋ฃŒ ํŒ๋‹จ์šฉ) + +**์‚ฌ์šฉ ๋ชฉ์ :** +- ๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ์ตœ์†Œํ™” (์„ฑ๋Šฅ ํ–ฅ์ƒ) +- ์˜คํ”„๋ผ์ธ ์กฐํšŒ ๊ฐ€๋Šฅ +- ์นด๋“œ ๋ชฉ๋ก ๋ณ€๊ฒฝ ์ด๋ ฅ ์ถ”์  + +**์บ์‹œ ์ „๋žต:** +- ์นด๋“œ ๋ชฉ๋ก์€ 1์‹œ๊ฐ„๋งˆ๋‹ค ๊ฐฑ์‹  ๊ถŒ์žฅ +- ์‹ค์‹œ๊ฐ„ ์กฐํšŒ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์บ์‹œ ์‚ฌ์šฉ ์•ˆ ํ•จ + +--- + +### 4. barobill_card_usage_logs (์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์บ์‹œ ํ…Œ์ด๋ธ”) + +๋ฐ”๋กœ๋นŒ์—์„œ ์กฐํšŒํ•œ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ์„ ์บ์‹ฑํ•˜๋Š” ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. (์„ ํƒ์‚ฌํ•ญ) + +```sql +CREATE TABLE barobill_card_usage_logs ( + id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '์‚ฌ์šฉ๋‚ด์—ญ ID', + company_id INT(11) UNSIGNED NOT NULL COMMENT '์—…์ฒด ID', + card_num VARCHAR(50) NOT NULL COMMENT '์นด๋“œ๋ฒˆํ˜ธ', + use_dt DATETIME NOT NULL COMMENT '์‚ฌ์šฉ์ผ์‹œ', + use_key VARCHAR(100) NULL COMMENT '์‚ฌ์šฉ ํ‚ค (๋ฐ”๋กœ๋นŒ ๊ณ ์œ ๊ฐ’)', + approval_num VARCHAR(50) NULL COMMENT '์Šน์ธ๋ฒˆํ˜ธ', + approval_amount INT(11) DEFAULT 0 COMMENT '์Šน์ธ๊ธˆ์•ก', + tax INT(11) DEFAULT 0 COMMENT '๋ถ€๊ฐ€์„ธ', + service_charge INT(11) DEFAULT 0 COMMENT '๋ด‰์‚ฌ๋ฃŒ', + total_amount INT(11) DEFAULT 0 COMMENT '์ด ๊ธˆ์•ก', + approval_type TINYINT(1) NULL COMMENT '์Šน์ธ์œ ํ˜• (1=์Šน์ธ, 2=์ทจ์†Œ)', + payment_plan VARCHAR(10) NULL COMMENT 'ํ• ๋ถ€๊ฐœ์›” (0=์ผ์‹œ๋ถˆ)', + currency_code VARCHAR(3) DEFAULT 'KRW' COMMENT 'ํ†ตํ™”์ฝ”๋“œ', + use_store_name VARCHAR(255) NULL COMMENT '๊ฐ€๋งน์ ๋ช…', + use_store_corp_num VARCHAR(20) NULL COMMENT '๊ฐ€๋งน์  ์‚ฌ์—…์ž๋ฒˆํ˜ธ', + use_store_addr TEXT NULL COMMENT '๊ฐ€๋งน์  ์ฃผ์†Œ', + use_store_ceo VARCHAR(100) NULL COMMENT '๊ฐ€๋งน์  ๋Œ€ํ‘œ์ž๋ช…', + use_store_biz_type VARCHAR(100) NULL COMMENT '๊ฐ€๋งน์  ์—…์ข…', + use_store_tel VARCHAR(20) NULL COMMENT '๊ฐ€๋งน์  ์ „ํ™”๋ฒˆํ˜ธ', + memo TEXT NULL COMMENT '๋ฉ”๋ชจ', + card_company VARCHAR(10) NULL COMMENT '์นด๋“œ์‚ฌ ์ฝ”๋“œ', + cached_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '์บ์‹œ ์ผ์‹œ', + + UNIQUE KEY uk_use_key (company_id, use_key), + INDEX idx_company_id (company_id), + INDEX idx_card_num (card_num), + INDEX idx_use_dt (use_dt), + INDEX idx_company_use_dt (company_id, use_dt), + INDEX idx_approval_type (approval_type), + INDEX idx_cached_at (cached_at), + + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='๋ฐ”๋กœ๋นŒ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์บ์‹œ'; +``` + +**์ฃผ์š” ํ•„๋“œ ์„ค๋ช…:** +- `company_id`: ์—…์ฒด ID +- `card_num`: ์นด๋“œ๋ฒˆํ˜ธ +- `use_dt`: ์‚ฌ์šฉ์ผ์‹œ +- `use_key`: ๋ฐ”๋กœ๋นŒ ๊ณ ์œ  ์‚ฌ์šฉ ํ‚ค (์ค‘๋ณต ๋ฐฉ์ง€์šฉ) +- `approval_amount`: ์Šน์ธ๊ธˆ์•ก +- `approval_type`: ์Šน์ธ์œ ํ˜• (1=์Šน์ธ, 2=์ทจ์†Œ) +- `use_store_name`: ๊ฐ€๋งน์ ๋ช… +- `cached_at`: ์บ์‹œ ์ผ์‹œ + +**์ธ๋ฑ์Šค ์ „๋žต:** +- `idx_company_use_dt`: ์—…์ฒด๋ณ„ ๊ธฐ๊ฐ„ ์กฐํšŒ ์ตœ์ ํ™” +- `idx_use_dt`: ์ „์ฒด ๊ธฐ๊ฐ„ ์กฐํšŒ ์ตœ์ ํ™” +- `uk_use_key`: ์ค‘๋ณต ๋ฐ์ดํ„ฐ ๋ฐฉ์ง€ + +**์‚ฌ์šฉ ๋ชฉ์ :** +- ๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ์ตœ์†Œํ™” +- ๋น ๋ฅธ ์กฐํšŒ ์„ฑ๋Šฅ +- ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐ ๋ฆฌํฌํŠธ ์ƒ์„ฑ + +**์บ์‹œ ์ „๋žต:** +- ์ตœ๊ทผ 3๊ฐœ์›” ๋ฐ์ดํ„ฐ๋Š” ์บ์‹œ ์œ ์ง€ +- ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ์ •๋ฆฌ +- ์‹ค์‹œ๊ฐ„ ์กฐํšŒ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ฐ”๋กœ๋นŒ API ์ง์ ‘ ํ˜ธ์ถœ + +--- + +### 5. barobill_api_logs (API ํ˜ธ์ถœ ๋กœ๊ทธ ํ…Œ์ด๋ธ”) + +๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ์ด๋ ฅ์„ ๊ธฐ๋กํ•˜๋Š” ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค. (์„ ํƒ์‚ฌํ•ญ, ๋ชจ๋‹ˆํ„ฐ๋ง์šฉ) + +```sql +CREATE TABLE barobill_api_logs ( + id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '๋กœ๊ทธ ID', + company_id INT(11) UNSIGNED NOT NULL COMMENT '์—…์ฒด ID', + api_method VARCHAR(50) NOT NULL COMMENT 'API ๋ฉ”์„œ๋“œ๋ช…', + request_params TEXT NULL COMMENT '์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ (JSON)', + response_status VARCHAR(20) NULL COMMENT '์‘๋‹ต ์ƒํƒœ (success/failure)', + response_data TEXT NULL COMMENT '์‘๋‹ต ๋ฐ์ดํ„ฐ (JSON, ์ผ๋ถ€๋งŒ ์ €์žฅ)', + error_message TEXT NULL COMMENT '์—๋Ÿฌ ๋ฉ”์‹œ์ง€', + execution_time INT(11) NULL COMMENT '์‹คํ–‰ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ)', + ip_address VARCHAR(45) NULL COMMENT '์š”์ฒญ IP ์ฃผ์†Œ', + user_agent VARCHAR(255) NULL COMMENT '์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '์ƒ์„ฑ์ผ์‹œ', + + INDEX idx_company_id (company_id), + INDEX idx_api_method (api_method), + INDEX idx_response_status (response_status), + INDEX idx_created_at (created_at), + INDEX idx_company_created (company_id, created_at), + + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ๋กœ๊ทธ'; +``` + +**์ฃผ์š” ํ•„๋“œ ์„ค๋ช…:** +- `company_id`: ์—…์ฒด ID +- `api_method`: API ๋ฉ”์„œ๋“œ๋ช… (GetCardEx2, GetPeriodCardApprovalLog ๋“ฑ) +- `request_params`: ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ (JSON ํ˜•์‹) +- `response_status`: ์‘๋‹ต ์ƒํƒœ (success/failure) +- `error_message`: ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ +- `execution_time`: ์‹คํ–‰ ์‹œ๊ฐ„ (์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง์šฉ) + +**์‚ฌ์šฉ ๋ชฉ์ :** +- API ํ˜ธ์ถœ ์ด๋ ฅ ์ถ”์  +- ์—๋Ÿฌ ๋””๋ฒ„๊น… +- ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง +- ์‚ฌ์šฉ๋Ÿ‰ ํ†ต๊ณ„ + +**๋ฐ์ดํ„ฐ ๋ณด๊ด€ ์ •์ฑ…:** +- ์ตœ๊ทผ 6๊ฐœ์›” ๋ฐ์ดํ„ฐ ๋ณด๊ด€ +- ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ์•„์นด์ด๋น™ ๋˜๋Š” ์‚ญ์ œ + +--- + +## ํ…Œ์ด๋ธ” ๊ด€๊ณ„๋„ + +``` +companies (์—…์ฒด) + โ”‚ + โ”œโ”€โ”€ 1:1 โ”€โ”€ barobill_credentials (๋ฐ”๋กœ๋นŒ ์ธ์ฆ ์ •๋ณด) + โ”‚ + โ”œโ”€โ”€ 1:N โ”€โ”€ barobill_cards (์นด๋“œ ์ •๋ณด ์บ์‹œ) + โ”‚ + โ”œโ”€โ”€ 1:N โ”€โ”€ barobill_card_usage_logs (์‚ฌ์šฉ๋‚ด์—ญ ์บ์‹œ) + โ”‚ + โ””โ”€โ”€ 1:N โ”€โ”€ barobill_api_logs (API ํ˜ธ์ถœ ๋กœ๊ทธ) +``` + +--- + +## API ๊ตฌ์กฐ + +### 1. ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ API + +**์—”๋“œํฌ์ธํŠธ**: `GET /ecard/api/cards.php` + +**์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ:** +```php +[ + 'company_id' => 1, // ์—…์ฒด ID (ํ•„์ˆ˜) + 'availOnly' => 0 // 0=์ „์ฒด, 1=์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ์นด๋“œ๋งŒ +] +``` + +**์‘๋‹ต ์˜ˆ์‹œ:** +```json +{ + "success": true, + "cards": [ + { + "cardNum": "1234567890123456", + "cardNumMasked": "1234-****-****-3456", + "cardCompany": "04", + "cardCompanyName": "์‚ผ์„ฑ์นด๋“œ", + "cardBrand": "๋น„์ž", + "alias": "๋ฒ•์ธ์นด๋“œ1", + "status": "1", + "statusName": "์ •์ƒ" + } + ], + "count": 1 +} +``` + +**๊ตฌํ˜„ ๋กœ์ง:** +1. `company_id`๋กœ `barobill_credentials` ํ…Œ์ด๋ธ”์—์„œ ์ธ์ฆ ์ •๋ณด ์กฐํšŒ +2. ๋ฐ”๋กœ๋นŒ SOAP API ํ˜ธ์ถœ (GetCardEx2) +3. ์‘๋‹ต ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ๋ฐ ๋ฐ˜ํ™˜ + +--- + +### 2. ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ API + +**์—”๋“œํฌ์ธํŠธ**: `GET /ecard/api/usage.php` + +**์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ:** +```php +[ + 'company_id' => 1, // ์—…์ฒด ID (ํ•„์ˆ˜) + 'type' => 'period', // daily/monthly/period + 'cardNum' => '', // ์นด๋“œ๋ฒˆํ˜ธ (๋นˆ๊ฐ’์ด๋ฉด ์ „์ฒด) + 'startDate' => '20240101', // ์‹œ์ž‘์ผ (YYYYMMDD) + 'endDate' => '20240131', // ์ข…๋ฃŒ์ผ (YYYYMMDD) + 'page' => 1, // ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ + 'limit' => 50 // ํŽ˜์ด์ง€๋‹น ๊ฑด์ˆ˜ +] +``` + +**์‘๋‹ต ์˜ˆ์‹œ:** +```json +{ + "success": true, + "data": { + "logs": [ + { + "cardNum": "1234-****-****-3456", + "approvalDateTime": "2024-01-15 14:30:00", + "merchantName": "์Šคํƒ€๋ฒ…์Šค ๊ฐ•๋‚จ์ ", + "merchantBizNum": "123-45-67890", + "amount": 5000, + "approvalType": "1", + "approvalTypeName": "์Šน์ธ" + } + ], + "pagination": { + "currentPage": 1, + "maxPageNum": 10, + "totalCount": 500 + }, + "summary": { + "totalAmount": 1000000, + "count": 500, + "approvalCount": 480, + "cancelCount": 20 + } + } +} +``` + +**๊ตฌํ˜„ ๋กœ์ง:** +1. `company_id`๋กœ `barobill_credentials` ํ…Œ์ด๋ธ”์—์„œ ์ธ์ฆ ์ •๋ณด ์กฐํšŒ +2. ๋ฐ”๋กœ๋นŒ SOAP API ํ˜ธ์ถœ (GetPeriodCardApprovalLog) +3. ์‘๋‹ต ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ๋ฐ ๋ฐ˜ํ™˜ +4. (์„ ํƒ) ์บ์‹œ ํ…Œ์ด๋ธ”์— ์ €์žฅ + +--- + +## ๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ + +### 1. ๋ฐ์ดํ„ฐ ๊ฒฉ๋ฆฌ + +- **์—…์ฒด๋ณ„ ๋ฐ์ดํ„ฐ ๊ฒฉ๋ฆฌ**: ๋ชจ๋“  ์ฟผ๋ฆฌ์— `company_id` ์กฐ๊ฑด ํ•„์ˆ˜ +- **๊ถŒํ•œ ๊ฒ€์ฆ**: ์„ธ์…˜์—์„œ `company_id` ํ™•์ธ ํ›„ ์ ‘๊ทผ ํ—ˆ์šฉ +- **SQL Injection ๋ฐฉ์ง€**: Prepared Statement ์‚ฌ์šฉ + +```php +// ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ์‹œ +$stmt = $pdo->prepare("SELECT * FROM barobill_credentials WHERE company_id = ?"); +$stmt->execute([$company_id]); + +// ์ž˜๋ชป๋œ ์˜ˆ์‹œ (SQL Injection ์ทจ์•ฝ) +$sql = "SELECT * FROM barobill_credentials WHERE company_id = $company_id"; +``` + +### 2. ์ธ์ฆ ์ •๋ณด ๋ณดํ˜ธ + +- **CERTKEY ์•”ํ˜ธํ™”**: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ ์‹œ ์•”ํ˜ธํ™” +- **์ ‘๊ทผ ๋กœ๊ทธ**: ์ธ์ฆ ์ •๋ณด ์กฐํšŒ ์‹œ ๋กœ๊ทธ ๊ธฐ๋ก +- **์ตœ์†Œ ๊ถŒํ•œ ์›์น™**: ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ์ •๋ณด๋งŒ ์กฐํšŒ + +```php +// CERTKEY ์•”ํ˜ธํ™” ์˜ˆ์‹œ (๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•) +function encryptCertKey($certKey) { + // ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋” ๊ฐ•๋ ฅํ•œ ์•”ํ˜ธํ™” ์‚ฌ์šฉ ๊ถŒ์žฅ + return base64_encode(openssl_encrypt($certKey, 'AES-256-CBC', $encryptionKey)); +} + +function decryptCertKey($encryptedCertKey) { + return openssl_decrypt(base64_decode($encryptedCertKey), 'AES-256-CBC', $encryptionKey); +} +``` + +### 3. API ํ˜ธ์ถœ ์ œํ•œ + +- **Rate Limiting**: ์—…์ฒด๋ณ„ API ํ˜ธ์ถœ ํšŸ์ˆ˜ ์ œํ•œ +- **์—๋Ÿฌ ์ฒ˜๋ฆฌ**: ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ๋ฏผ๊ฐ์ •๋ณด ๋…ธ์ถœ ๊ธˆ์ง€ +- **ํƒ€์ž„์•„์›ƒ ์„ค์ •**: API ํ˜ธ์ถœ ํƒ€์ž„์•„์›ƒ ์„ค์ • + +```php +// Rate Limiting ์˜ˆ์‹œ +function checkRateLimit($company_id) { + $stmt = $pdo->prepare(" + SELECT COUNT(*) as count + FROM barobill_api_logs + WHERE company_id = ? + AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR) + "); + $stmt->execute([$company_id]); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($result['count'] > 1000) { // ์‹œ๊ฐ„๋‹น 1000ํšŒ ์ œํ•œ + throw new Exception('API ํ˜ธ์ถœ ํ•œ๋„ ์ดˆ๊ณผ'); + } +} +``` + +--- + +## ๊ตฌํ˜„ ๊ฐ€์ด๋“œ + +### 1. barobill_card_config.php ์ˆ˜์ • + +๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ๋ฅผ ์ง€์›ํ•˜๋„๋ก ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. + +```php +prepare(" + SELECT + bc.cert_key, + bc.corp_num, + bc.user_id, + bc.test_mode, + bc.status + FROM {$DB}.barobill_credentials bc + WHERE bc.company_id = ? + AND bc.status = 'active' + "); + $stmt->execute([$company_id]); + $credentials = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$credentials) { + return [ + 'success' => false, + 'error' => '๋ฐ”๋กœ๋นŒ ์ธ์ฆ ์ •๋ณด๊ฐ€ ๋“ฑ๋ก๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.' + ]; + } + + // CERTKEY ๋ณตํ˜ธํ™” (์•”ํ˜ธํ™”๋œ ๊ฒฝ์šฐ) + if (function_exists('decryptCertKey')) { + $credentials['cert_key'] = decryptCertKey($credentials['cert_key']); + } + + return [ + 'success' => true, + 'data' => $credentials + ]; +} + +/** + * ๋ฐ”๋กœ๋นŒ ์นด๋“œ SOAP ์›น์„œ๋น„์Šค ํ˜ธ์ถœ ํ•จ์ˆ˜ (๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ ์ง€์›) + * + * @param int $company_id ์—…์ฒด ID + * @param string $method SOAP ๋ฉ”์„œ๋“œ๋ช… + * @param array $params SOAP ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function callBarobillCardSOAPForCompany($company_id, $method, $params = []) { + // ์ธ์ฆ ์ •๋ณด ์กฐํšŒ + $credentials = getBarobillCredentials($company_id); + if (!$credentials['success']) { + return $credentials; + } + + $certKey = $credentials['data']['cert_key']; + $corpNum = $credentials['data']['corp_num']; + $isTestMode = $credentials['data']['test_mode'] == 1; + + // SOAP URL ์„ค์ • + $soapUrl = $isTestMode + ? 'https://testws.baroservice.com/CARD.asmx?WSDL' + : 'https://ws.baroservice.com/CARD.asmx?WSDL'; + + // SOAP ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ + try { + $soapClient = new SoapClient($soapUrl, [ + 'trace' => true, + 'encoding' => 'UTF-8', + 'exceptions' => true, + 'connection_timeout' => 30 + ]); + } catch (Exception $e) { + return [ + 'success' => false, + 'error' => 'SOAP ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ ์‹คํŒจ: ' . $e->getMessage() + ]; + } + + // CERTKEY์™€ CorpNum ์ž๋™ ์ถ”๊ฐ€ + if (!isset($params['CERTKEY'])) { + $params['CERTKEY'] = $certKey; + } + if (!isset($params['CorpNum'])) { + $params['CorpNum'] = $corpNum; + } + + // API ํ˜ธ์ถœ ๋กœ๊ทธ ๊ธฐ๋ก + $startTime = microtime(true); + + try { + $result = $soapClient->$method($params); + + $executionTime = (microtime(true) - $startTime) * 1000; // ๋ฐ€๋ฆฌ์ดˆ + + // API ํ˜ธ์ถœ ๋กœ๊ทธ ์ €์žฅ + logBarobillApiCall($company_id, $method, $params, 'success', null, $executionTime); + + $resultProperty = $method . 'Result'; + if (isset($result->$resultProperty)) { + $resultData = $result->$resultProperty; + + // ์—๋Ÿฌ ์ฝ”๋“œ ์ฒดํฌ + if (is_numeric($resultData) && $resultData < 0) { + logBarobillApiCall($company_id, $method, $params, 'failure', '์—๋Ÿฌ ์ฝ”๋“œ: ' . $resultData, $executionTime); + return [ + 'success' => false, + 'error' => '๋ฐ”๋กœ๋นŒ ์นด๋“œ API ์˜ค๋ฅ˜ ์ฝ”๋“œ: ' . $resultData, + 'error_code' => $resultData + ]; + } + + return [ + 'success' => true, + 'data' => $resultData + ]; + } + + return [ + 'success' => true, + 'data' => $result + ]; + + } catch (SoapFault $e) { + $executionTime = (microtime(true) - $startTime) * 1000; + logBarobillApiCall($company_id, $method, $params, 'failure', $e->getMessage(), $executionTime); + + return [ + 'success' => false, + 'error' => 'SOAP ์˜ค๋ฅ˜: ' . $e->getMessage(), + 'error_code' => $e->getCode() + ]; + } catch (Exception $e) { + $executionTime = (microtime(true) - $startTime) * 1000; + logBarobillApiCall($company_id, $method, $params, 'failure', $e->getMessage(), $executionTime); + + return [ + 'success' => false, + 'error' => 'API ํ˜ธ์ถœ ์˜ค๋ฅ˜: ' . $e->getMessage() + ]; + } +} + +/** + * API ํ˜ธ์ถœ ๋กœ๊ทธ ์ €์žฅ + */ +function logBarobillApiCall($company_id, $method, $params, $status, $error_message = null, $execution_time = null) { + global $pdo, $DB; + + try { + $stmt = $pdo->prepare(" + INSERT INTO {$DB}.barobill_api_logs + (company_id, api_method, request_params, response_status, error_message, execution_time, ip_address, user_agent) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + "); + + $stmt->execute([ + $company_id, + $method, + json_encode($params, JSON_UNESCAPED_UNICODE), + $status, + $error_message, + $execution_time, + $_SERVER['REMOTE_ADDR'] ?? null, + $_SERVER['HTTP_USER_AGENT'] ?? null + ]); + } catch (Exception $e) { + // ๋กœ๊ทธ ์ €์žฅ ์‹คํŒจ๋Š” ๋ฌด์‹œ (์‹œ์Šคํ…œ ์˜ค๋ฅ˜ ๋ฐฉ์ง€) + error_log('API ๋กœ๊ทธ ์ €์žฅ ์‹คํŒจ: ' . $e->getMessage()); + } +} + +/** + * ์—…์ฒด๋ณ„ ์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ (๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ ์ง€์›) + */ +function getCardListForCompany($company_id, $availOnly = 0) { + $result = callBarobillCardSOAPForCompany($company_id, 'GetCardEx2', [ + 'AvailOnly' => $availOnly + ]); + + if (!$result['success']) { + return $result; + } + + $cards = []; + $data = $result['data']; + + if (!isset($data->CardEx)) { + return ['success' => true, 'data' => []]; + } + + if (!is_array($data->CardEx)) { + $cards = [$data->CardEx]; + } else { + $cards = $data->CardEx; + } + + // ์—๋Ÿฌ ์ฒดํฌ + if (count($cards) == 1 && isset($cards[0]->CardNum) && $cards[0]->CardNum < 0) { + return [ + 'success' => false, + 'error' => '์นด๋“œ ๋ชฉ๋ก ์กฐํšŒ ์‹คํŒจ', + 'error_code' => $cards[0]->CardNum + ]; + } + + // (์„ ํƒ) ์บ์‹œ ํ…Œ์ด๋ธ”์— ์ €์žฅ + // saveCardsToCache($company_id, $cards); + + return ['success' => true, 'data' => $cards]; +} + +/** + * ์—…์ฒด๋ณ„ ๊ธฐ๊ฐ„๋ณ„ ์นด๋“œ ์‚ฌ์šฉ๋‚ด์—ญ ์กฐํšŒ (๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ ์ง€์›) + */ +function getPeriodCardUsageForCompany($company_id, $cardNum = '', $startDate = '', $endDate = '', $countPerPage = 50, $currentPage = 1, $orderDirection = 2, $userId = '') { + // ์ธ์ฆ ์ •๋ณด ์กฐํšŒ + $credentials = getBarobillCredentials($company_id); + if (!$credentials['success']) { + return $credentials; + } + + $barobillUserId = $credentials['data']['user_id'] ?? ''; + if (!empty($userId)) { + $barobillUserId = $userId; + } + + $result = callBarobillCardSOAPForCompany($company_id, 'GetPeriodCardApprovalLog', [ + 'ID' => $barobillUserId, + 'CardNum' => $cardNum, + 'StartDate' => $startDate, + 'EndDate' => $endDate, + 'CountPerPage' => $countPerPage, + 'CurrentPage' => $currentPage, + 'OrderDirection' => $orderDirection + ]); + + if (!$result['success']) { + return $result; + } + + return parseCardUsageResult($result['data']); +} + +// ๊ธฐ์กด parseCardUsageResult ํ•จ์ˆ˜๋Š” ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ +// ... (๊ธฐ์กด ์ฝ”๋“œ ์œ ์ง€) +?> +``` + +### 2. cards.php ์ˆ˜์ • + +๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ๋ฅผ ์ง€์›ํ•˜๋„๋ก ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. + +```php + false, + 'error' => '์—…์ฒด ID๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.' + ], JSON_UNESCAPED_UNICODE); + exit; + } + + $availOnly = isset($_GET['availOnly']) ? intval($_GET['availOnly']) : 0; + + $result = getCardListForCompany($company_id, $availOnly); + + if ($result['success']) { + $cards = []; + foreach ($result['data'] as $card) { + // ... (๊ธฐ์กด ๋ณ€ํ™˜ ๋กœ์ง) + } + + echo json_encode([ + 'success' => true, + 'cards' => $cards, + 'count' => count($cards) + ], JSON_UNESCAPED_UNICODE); + } else { + echo json_encode([ + 'success' => false, + 'error' => $result['error'], + 'error_code' => $result['error_code'] ?? null + ], JSON_UNESCAPED_UNICODE); + } +} catch (Exception $e) { + echo json_encode([ + 'success' => false, + 'error' => '์„œ๋ฒ„ ์˜ค๋ฅ˜: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} +?> +``` + +### 3. usage.php ์ˆ˜์ • + +๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ๋ฅผ ์ง€์›ํ•˜๋„๋ก ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. + +```php + false, + 'error' => '์—…์ฒด ID๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.' + ], JSON_UNESCAPED_UNICODE); + exit; + } + + $type = $_GET['type'] ?? 'period'; + $cardNum = $_GET['cardNum'] ?? ''; + $page = max(1, intval($_GET['page'] ?? 1)); + $limit = min(100, max(10, intval($_GET['limit'] ?? 50))); + $orderDirection = intval($_GET['order'] ?? 2); + + // ... (๊ธฐ์กด ๋กœ์ง์„ getPeriodCardUsageForCompany๋กœ ๋ณ€๊ฒฝ) + + $result = getPeriodCardUsageForCompany( + $company_id, + $cardNum, + $startDate, + $endDate, + $limit, + $page, + $orderDirection + ); + + // ... (๊ธฐ์กด ์‘๋‹ต ๋กœ์ง) + +} catch (Exception $e) { + echo json_encode([ + 'success' => false, + 'error' => '์„œ๋ฒ„ ์˜ค๋ฅ˜: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE); +} +?> +``` + +--- + +## ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฐ€์ด๋“œ + +### ๊ธฐ์กด ๋‹จ์ผ ํ…Œ๋„ŒํŠธ์—์„œ ๋ฉ€ํ‹ฐํ…Œ๋„ŒํŠธ๋กœ ์ „ํ™˜ + +1. **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜** + ```sql + -- 1. companies ํ…Œ์ด๋ธ” ์ƒ์„ฑ + -- 2. barobill_credentials ํ…Œ์ด๋ธ” ์ƒ์„ฑ + -- 3. ๊ธฐ์กด ํŒŒ์ผ ๊ธฐ๋ฐ˜ ์„ค์ •์„ DB๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ + + INSERT INTO companies (company_name, business_number, business_number_clean, status) + VALUES ('๊ธฐ๋ณธ ์—…์ฒด', '123-45-67890', '1234567890', 'active'); + + INSERT INTO barobill_credentials (company_id, cert_key, corp_num, user_id, test_mode, status) + VALUES ( + 1, + (SELECT cert_key FROM file), -- ํŒŒ์ผ์—์„œ ์ฝ์€ CERTKEY + (SELECT corp_num FROM file), -- ํŒŒ์ผ์—์„œ ์ฝ์€ ์‚ฌ์—…์ž๋ฒˆํ˜ธ + NULL, + 0, + 'active' + ); + ``` + +2. **์ฝ”๋“œ ์ˆ˜์ •** + - `barobill_card_config.php`: ํŒŒ์ผ ๊ธฐ๋ฐ˜ โ†’ DB ๊ธฐ๋ฐ˜์œผ๋กœ ๋ณ€๊ฒฝ + - `cards.php`, `usage.php`: `company_id` ํŒŒ๋ผ๋ฏธํ„ฐ ์ถ”๊ฐ€ + - ์„ธ์…˜์— `company_id` ์ €์žฅ + +3. **ํ…Œ์ŠคํŠธ** + - ๊ฐ ์—…์ฒด๋ณ„๋กœ ๋…๋ฆฝ์ ์ธ ์นด๋“œ ์กฐํšŒ ํ™•์ธ + - ๋ฐ์ดํ„ฐ ๊ฒฉ๋ฆฌ ํ™•์ธ + - ๊ถŒํ•œ ๊ฒ€์ฆ ํ™•์ธ + +--- + +## ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ์œ ์ง€๋ณด์ˆ˜ + +### 1. ์ฃผ์š” ๋ชจ๋‹ˆํ„ฐ๋ง ์ง€ํ‘œ + +- API ํ˜ธ์ถœ ์„ฑ๊ณต๋ฅ  +- API ํ˜ธ์ถœ ์‘๋‹ต ์‹œ๊ฐ„ +- ์—๋Ÿฌ ๋ฐœ์ƒ ๋นˆ๋„ +- ์บ์‹œ ์ ์ค‘๋ฅ  (์บ์‹œ ์‚ฌ์šฉ ์‹œ) + +### 2. ์ •๊ธฐ ์ ๊ฒ€ ์‚ฌํ•ญ + +- ์ธ์ฆ ์ •๋ณด ๋งŒ๋ฃŒ ํ™•์ธ +- ์บ์‹œ ๋ฐ์ดํ„ฐ ์ •๋ฆฌ +- API ๋กœ๊ทธ ๋ถ„์„ +- ์„ฑ๋Šฅ ์ตœ์ ํ™” + +--- + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž ๋ฌธ์„œ](https://dev.barobill.co.kr/) +- [๋ฐ”๋กœ๋นŒ ์นด๋“œ API ๋ ˆํผ๋Ÿฐ์Šค](https://dev.barobill.co.kr/docs/references/์นด๋“œ์กฐํšŒ-API) +- PHP SOAP ํด๋ผ์ด์–ธํŠธ ๋ฌธ์„œ + +--- + +## ๋ณ€๊ฒฝ ์ด๋ ฅ + +| ๋ฒ„์ „ | ๋‚ ์งœ | ๋ณ€๊ฒฝ ๋‚ด์šฉ | ์ž‘์„ฑ์ž | +|------|------|----------|--------| +| 1.0 | 2025-12-08 | ์ดˆ๊ธฐ ๋ฌธ์„œ ์ž‘์„ฑ | - | + +--- + +**๋ฌธ์„œ ์ž‘์„ฑ์ผ**: 2025๋…„ 12์›” +**์ตœ์ข… ์ˆ˜์ •์ผ**: 2025๋…„ 12์›” +**๋ฌธ์„œ ๋ฒ„์ „**: 1.0 \ No newline at end of file diff --git a/tenant/api.php b/tenant/api.php new file mode 100644 index 0000000..efd852f --- /dev/null +++ b/tenant/api.php @@ -0,0 +1,225 @@ + false, 'message' => '๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.']); +// exit; +// } + +$pdo = db_connect(); +$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : ''; + +try { + if (!$pdo) throw new Exception("Database connection failed."); + + // DB๋ช…์ด ์ •์˜๋˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • ํ˜น์€ mydb.php์˜ $DB ์‚ฌ์šฉ + // ๋ณดํ†ต mydb.php์—์„œ $DB ๋ณ€์ˆ˜๋ฅผ ์ œ๊ณตํ•œ๋‹ค๊ณ  ๊ฐ€์ • + if (!isset($DB)) { + global $DB; + } + + switch ($action) { + case 'get_companies': + // ๋ชจ๋“  ํšŒ์‚ฌ ๊ฐ€์ ธ์˜ค๊ธฐ (ํŒŒํŠธ๋„ˆ-์ž์‹ ๊ตฌ์กฐ) + $sql = "SELECT c.*, p.company_name as parent_name, p.barobill_user_id as parent_user_id + FROM {$DB}.barobill_companies c + LEFT JOIN {$DB}.barobill_companies p ON c.parent_id = p.id + ORDER BY c.parent_id ASC, c.id ASC"; + $stmt = $pdo->query($sql); + $companies = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode(['success' => true, 'data' => $companies]); + break; + + case 'save_company': + // ํšŒ์‚ฌ ์ถ”๊ฐ€/์ˆ˜์ • + $id = isset($_POST['id']) ? intval($_POST['id']) : 0; + + $company_name = $_POST['company_name']; + $corp_num = $_POST['corp_num']; + $barobill_user_id = $_POST['barobill_user_id']; + $memo = $_POST['memo']; + + // 1. Find ID of 'cbx0913' (Parent) + $parent_sql = "SELECT id FROM {$DB}.barobill_companies WHERE barobill_user_id = 'cbx0913' LIMIT 1"; + $stmt = $pdo->query($parent_sql); + $parent_row = $stmt->fetch(PDO::FETCH_ASSOC); + + // ๋งŒ์•ฝ 'cbx0913' ๋ณธ์ธ์ด๋ฉด parent_id๋Š” NULL + if ($barobill_user_id === 'cbx0913') { + $parent_id = null; + } else { + // ๋ถ€๋ชจ๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ ID, ์—†์œผ๋ฉด NULL (ํ˜น์€ ์—๋Ÿฌ์ฒ˜๋ฆฌ) + $parent_id = $parent_row ? $parent_row['id'] : null; + } + + if ($id > 0) { + $sql = "UPDATE {$DB}.barobill_companies SET + parent_id = :parent_id, + company_name = :company_name, + corp_num = :corp_num, + barobill_user_id = :barobill_user_id, + memo = :memo + WHERE id = :id"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':id', $id, PDO::PARAM_INT); + } else { + $sql = "INSERT INTO {$DB}.barobill_companies (parent_id, company_name, corp_num, barobill_user_id, memo) + VALUES (:parent_id, :company_name, :corp_num, :barobill_user_id, :memo)"; + $stmt = $pdo->prepare($sql); + } + + $stmt->bindValue(':parent_id', $parent_id, PDO::PARAM_INT); + $stmt->bindValue(':company_name', $company_name); + $stmt->bindValue(':corp_num', $corp_num); + $stmt->bindValue(':barobill_user_id', $barobill_user_id); + $stmt->bindValue(':memo', $memo); + + if (!$stmt->execute()) { + throw new Exception(implode(", ", $stmt->errorInfo())); + } + echo json_encode(['success' => true]); + break; + + case 'delete_company': + $id = intval($_POST['id']); + $sql = "DELETE FROM {$DB}.barobill_companies WHERE id = :id"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':id', $id, PDO::PARAM_INT); + + if (!$stmt->execute()) { + throw new Exception(implode(", ", $stmt->errorInfo())); + } + echo json_encode(['success' => true]); + break; + + case 'get_cards': + $company_id = intval($_GET['company_id']); + $sql = "SELECT * FROM {$DB}.company_cards WHERE company_id = :company_id ORDER BY id DESC"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':company_id', $company_id, PDO::PARAM_INT); + $stmt->execute(); + $cards = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode(['success' => true, 'data' => $cards]); + break; + + case 'save_card': + $id = isset($_POST['id']) ? intval($_POST['id']) : 0; + $company_id = intval($_POST['company_id']); + $card_company_code = $_POST['card_company_code']; + $card_num = $_POST['card_num']; + $web_id = $_POST['web_id']; + $web_pwd = $_POST['web_pwd']; + + if ($id > 0) { + $sql = "UPDATE {$DB}.company_cards SET + card_company_code = :card_company_code, + card_num = :card_num, + web_id = :web_id, + web_pwd = :web_pwd + WHERE id = :id"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':id', $id, PDO::PARAM_INT); + } else { + $sql = "INSERT INTO {$DB}.company_cards (company_id, card_company_code, card_num, web_id, web_pwd) + VALUES (:company_id, :card_company_code, :card_num, :web_id, :web_pwd)"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':company_id', $company_id, PDO::PARAM_INT); + } + + $stmt->bindValue(':card_company_code', $card_company_code); + $stmt->bindValue(':card_num', $card_num); + $stmt->bindValue(':web_id', $web_id); + $stmt->bindValue(':web_pwd', $web_pwd); + + if (!$stmt->execute()) { + throw new Exception(implode(", ", $stmt->errorInfo())); + } + echo json_encode(['success' => true]); + break; + + case 'delete_card': + $id = intval($_POST['id']); + $sql = "DELETE FROM {$DB}.company_cards WHERE id = :id"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':id', $id, PDO::PARAM_INT); + + if (!$stmt->execute()) { + throw new Exception(implode(", ", $stmt->errorInfo())); + } + echo json_encode(['success' => true]); + break; + + case 'get_accounts': + $company_id = intval($_GET['company_id']); + $sql = "SELECT * FROM {$DB}.company_accounts WHERE company_id = :company_id ORDER BY id DESC"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':company_id', $company_id, PDO::PARAM_INT); + $stmt->execute(); + $accounts = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode(['success' => true, 'data' => $accounts]); + break; + + case 'save_account': + $id = isset($_POST['id']) ? intval($_POST['id']) : 0; + $company_id = intval($_POST['company_id']); + $bank_code = $_POST['bank_code']; + $account_num = $_POST['account_num']; + $account_pwd = $_POST['account_pwd']; + + if ($id > 0) { + $sql = "UPDATE {$DB}.company_accounts SET + bank_code = :bank_code, + account_num = :account_num, + account_pwd = :account_pwd + WHERE id = :id"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':id', $id, PDO::PARAM_INT); + } else { + $sql = "INSERT INTO {$DB}.company_accounts (company_id, bank_code, account_num, account_pwd) + VALUES (:company_id, :bank_code, :account_num, :account_pwd)"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':company_id', $company_id, PDO::PARAM_INT); + } + + $stmt->bindValue(':bank_code', $bank_code); + $stmt->bindValue(':account_num', $account_num); + $stmt->bindValue(':account_pwd', $account_pwd); + + if (!$stmt->execute()) { + throw new Exception(implode(", ", $stmt->errorInfo())); + } + echo json_encode(['success' => true]); + break; + + case 'delete_account': + $id = intval($_POST['id']); + $sql = "DELETE FROM {$DB}.company_accounts WHERE id = :id"; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(':id', $id, PDO::PARAM_INT); + + if (!$stmt->execute()) { + throw new Exception(implode(", ", $stmt->errorInfo())); + } + echo json_encode(['success' => true]); + break; + + default: + echo json_encode(['success' => false, 'message' => 'Invalid action']); + break; + } +} catch (Exception $e) { + echo json_encode(['success' => false, 'message' => $e->getMessage()]); +} +?> diff --git a/tenant/index.php b/tenant/index.php new file mode 100644 index 0000000..ab2ab93 --- /dev/null +++ b/tenant/index.php @@ -0,0 +1,506 @@ +alert('์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.'); location.href='/';"; +// exit; +// } +?> + + + + + + ๋ฐ”๋กœ๋นŒ ํ…Œ๋„ŒํŠธ ๊ด€๋ฆฌ + + + + + + + + + + + + + + + + + + + + +
+ + + +