From 2ab35342787e3c5664f270b24643ff8a3b2383a9 Mon Sep 17 00:00:00 2001 From: aweso Date: Wed, 14 Jan 2026 09:15:03 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B0=94=EB=A1=9C=EB=B9=8C=20=EC=A0=84?= =?UTF-8?q?=EC=9E=90=EC=84=B8=EA=B8=88=EA=B3=84=EC=82=B0=EC=84=9C=20?= =?UTF-8?q?=EC=86=94=EB=A3=A8=EC=85=98=20=EC=97=B0=EA=B2=B0?= 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 --- apikey/barobill_api_key.txt | 1 + apikey/barobill_api_key.txt.example | 1 + apikey/barobill_cert_id.txt | 39 + apikey/barobill_cert_id.txt.example | 3 + apikey/barobill_cert_key.txt | 37 + apikey/barobill_corp_num.txt | 1 + apikey/barobill_test_mode.txt | 1 + apikey/barobill_test_mode.txt.example | 1 + apikey/barobill_user_id.txt | 1 + apikey/claude_api.txt | 1 + apikey/gcs_config.txt | 2 + apikey/gemini_api_key.txt | 1 + apikey/google_api.txt | 1 + apikey/google_service_account.json | 13 + apikey/google_vertex_api.txt | 1 + apikey/notion.txt | 1 + apikey/opendart.txt | 1 + barobill_registration/index.php | 2 +- etax/README_DB.md | 132 +++ etax/api/API_URL_GUIDE.md | 73 ++ etax/api/README.md | 147 ++++ etax/api/barobill_config.php | 418 ++++++++++ etax/api/debug_test.php | 34 + etax/api/delete.php | 163 ++++ etax/api/deleted_ids.json | 5 + etax/api/invoices.php | 170 ++++ etax/api/invoices_data.json | 318 ++++++++ etax/api/issue.php | 226 +++++ etax/api/status.php | 168 ++++ etax/barobill_api_info.php | 433 ++++++++++ etax/dev.md | 27 + etax/index.php | 1086 +++++++++++++++++++++++++ lib/DotEnv.php | 45 + lib/func.php | 45 + lib/helper.php | 21 + 35 files changed, 3618 insertions(+), 1 deletion(-) create mode 100644 apikey/barobill_api_key.txt create mode 100644 apikey/barobill_api_key.txt.example create mode 100644 apikey/barobill_cert_id.txt create mode 100644 apikey/barobill_cert_id.txt.example create mode 100644 apikey/barobill_cert_key.txt create mode 100644 apikey/barobill_corp_num.txt create mode 100644 apikey/barobill_test_mode.txt create mode 100644 apikey/barobill_test_mode.txt.example create mode 100644 apikey/barobill_user_id.txt create mode 100644 apikey/claude_api.txt create mode 100644 apikey/gcs_config.txt create mode 100644 apikey/gemini_api_key.txt create mode 100644 apikey/google_api.txt create mode 100644 apikey/google_service_account.json create mode 100644 apikey/google_vertex_api.txt create mode 100644 apikey/notion.txt create mode 100644 apikey/opendart.txt create mode 100644 etax/README_DB.md create mode 100644 etax/api/API_URL_GUIDE.md create mode 100644 etax/api/README.md create mode 100644 etax/api/barobill_config.php create mode 100644 etax/api/debug_test.php create mode 100644 etax/api/delete.php create mode 100644 etax/api/deleted_ids.json create mode 100644 etax/api/invoices.php create mode 100644 etax/api/invoices_data.json create mode 100644 etax/api/issue.php create mode 100644 etax/api/status.php create mode 100644 etax/barobill_api_info.php create mode 100644 etax/dev.md create mode 100644 etax/index.php create mode 100644 lib/DotEnv.php create mode 100644 lib/func.php create mode 100644 lib/helper.php diff --git a/apikey/barobill_api_key.txt b/apikey/barobill_api_key.txt new file mode 100644 index 0000000..af2f171 --- /dev/null +++ b/apikey/barobill_api_key.txt @@ -0,0 +1 @@ +2DD6C76C-04DB-44F7-B6E9-3FC0B2211826 \ No newline at end of file diff --git a/apikey/barobill_api_key.txt.example b/apikey/barobill_api_key.txt.example new file mode 100644 index 0000000..af2f171 --- /dev/null +++ b/apikey/barobill_api_key.txt.example @@ -0,0 +1 @@ +2DD6C76C-04DB-44F7-B6E9-3FC0B2211826 \ No newline at end of file diff --git a/apikey/barobill_cert_id.txt b/apikey/barobill_cert_id.txt new file mode 100644 index 0000000..61a4c04 --- /dev/null +++ b/apikey/barobill_cert_id.txt @@ -0,0 +1,39 @@ +=========================================== +๋ฐ”๋กœ๋นŒ ์ธ์ฆ์„œ ID (์„ ํƒ์‚ฌํ•ญ) +=========================================== + +โš ๏ธ ์ฃผ์˜: ์ด๊ฒƒ์€ ๋กœ๊ทธ์ธ ์ด๋ฉ”์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค! + +์ด ํŒŒ์ผ์—๋Š” ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ๋“ฑ๋กํ•œ +๊ณต๋™์ธ์ฆ์„œ ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ์˜ ID๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”. + +=========================================== +์„ค์ • ๋ฐฉ๋ฒ•: +=========================================== + +1. ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ(https://dev.barobill.co.kr) ๋กœ๊ทธ์ธ + - ๋กœ๊ทธ์ธ ์ด๋ฉ”์ผ: admin@codebridge-x.com (์ด๊ฒƒ ์•„๋‹˜!) + +2. ๊ฐœ๋ฐœ์ž์„ผํ„ฐ ๋ฉ”๋‰ด์—์„œ "์ธ์ฆ์„œ ๊ด€๋ฆฌ" ๋˜๋Š” "์ธ์ฆ์„œ ๋“ฑ๋ก" ๋ฉ”๋‰ด ์ฐพ๊ธฐ + +3. ๊ณต๋™์ธ์ฆ์„œ ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ ๋“ฑ๋ก + - ์ธ์ฆ์„œ ํŒŒ์ผ(.pfx ๋˜๋Š” .p12) ์—…๋กœ๋“œ + - ์ธ์ฆ์„œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ + +4. ๋“ฑ๋ก ํ›„ ๋ฐœ๊ธ‰๋ฐ›์€ "์ธ์ฆ์„œ ID" ๋ณต์‚ฌ + - ์˜ˆ: "CERT-2024-ABC123-XYZ789" + - ๋˜๋Š” ์ˆซ์ž/๋ฌธ์ž ์กฐํ•ฉ์˜ ๊ณ ์œ  ID + +5. ์•„๋ž˜์— ์ธ์ฆ์„œ ID ์ž…๋ ฅ: + +[์—ฌ๊ธฐ์— ์ธ์ฆ์„œ ID ์ž…๋ ฅ] + +=========================================== +์ฐธ๊ณ : +=========================================== + +- ์šด์˜ ํ™˜๊ฒฝ: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰ ์‹œ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค +- ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ: ์ธ์ฆ์„œ ID ์—†์ด๋„ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค + (barobill_test_mode.txt์— "true"๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฉด ์„ ํƒ์‚ฌํ•ญ) +- ์ธ์ฆ์„œ๊ฐ€ ์—†์œผ๋ฉด ์‹ค์ œ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ๋ฅผ ๋ฐœํ–‰ํ•  ์ˆ˜ ์—†์ง€๋งŒ, + ํ…Œ์ŠคํŠธ API์—์„œ๋Š” ๊ฐ€์ƒ์˜ ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค diff --git a/apikey/barobill_cert_id.txt.example b/apikey/barobill_cert_id.txt.example new file mode 100644 index 0000000..a2061e7 --- /dev/null +++ b/apikey/barobill_cert_id.txt.example @@ -0,0 +1,3 @@ +์—ฌ๊ธฐ์— ๋ฐ”๋กœ๋นŒ ์ธ์ฆ์„œ ID๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š” (์„ ํƒ์‚ฌํ•ญ) +์˜ˆ: cert-id-here + diff --git a/apikey/barobill_cert_key.txt b/apikey/barobill_cert_key.txt new file mode 100644 index 0000000..7e57088 --- /dev/null +++ b/apikey/barobill_cert_key.txt @@ -0,0 +1,37 @@ +=========================================== +๋ฐ”๋กœ๋นŒ CERTKEY (์ธ์ฆ์„œ ํ‚ค) - ํ•„์ˆ˜ +=========================================== + +โš ๏ธ ์ค‘์š”: ์ด๊ฒƒ์€ ๋กœ๊ทธ์ธ ์ด๋ฉ”์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค! + +์ด ํŒŒ์ผ์—๋Š” ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ๋“ฑ๋กํ•œ +๊ณต๋™์ธ์ฆ์„œ ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ์˜ CERTKEY๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”. + +=========================================== +์„ค์ • ๋ฐฉ๋ฒ•: +=========================================== + +1. ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ(https://dev.barobill.co.kr) ๋กœ๊ทธ์ธ + +2. ๊ฐœ๋ฐœ์ž์„ผํ„ฐ ๋ฉ”๋‰ด์—์„œ "์ธ์ฆ์„œ ๊ด€๋ฆฌ" ๋˜๋Š” "์ธ์ฆ์„œ ๋“ฑ๋ก" ๋ฉ”๋‰ด ์ฐพ๊ธฐ + +3. ๊ณต๋™์ธ์ฆ์„œ ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ ๋“ฑ๋ก + - ์ธ์ฆ์„œ ํŒŒ์ผ(.pfx ๋˜๋Š” .p12) ์—…๋กœ๋“œ + - ์ธ์ฆ์„œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ + +4. ๋“ฑ๋ก ํ›„ ๋ฐœ๊ธ‰๋ฐ›์€ "CERTKEY" ๋ณต์‚ฌ + - ์˜ˆ: "CERT-2024-ABC123-XYZ789" + - ๋˜๋Š” ์ˆซ์ž/๋ฌธ์ž ์กฐํ•ฉ์˜ ๊ณ ์œ  ํ‚ค + +5. ์•„๋ž˜์— CERTKEY ์ž…๋ ฅ: + +[์—ฌ๊ธฐ์— CERTKEY ์ž…๋ ฅ] + +=========================================== +์ฐธ๊ณ : +=========================================== + +- ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰์— ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค +- CERTKEY๊ฐ€ ์—†์œผ๋ฉด ์‹ค์ œ API๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค +- ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ๋„ CERTKEY๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค + diff --git a/apikey/barobill_corp_num.txt b/apikey/barobill_corp_num.txt new file mode 100644 index 0000000..7c0a821 --- /dev/null +++ b/apikey/barobill_corp_num.txt @@ -0,0 +1 @@ +6648603713 \ No newline at end of file diff --git a/apikey/barobill_test_mode.txt b/apikey/barobill_test_mode.txt new file mode 100644 index 0000000..f32a580 --- /dev/null +++ b/apikey/barobill_test_mode.txt @@ -0,0 +1 @@ +true \ No newline at end of file diff --git a/apikey/barobill_test_mode.txt.example b/apikey/barobill_test_mode.txt.example new file mode 100644 index 0000000..f32a580 --- /dev/null +++ b/apikey/barobill_test_mode.txt.example @@ -0,0 +1 @@ +true \ No newline at end of file diff --git a/apikey/barobill_user_id.txt b/apikey/barobill_user_id.txt new file mode 100644 index 0000000..70bfd2d --- /dev/null +++ b/apikey/barobill_user_id.txt @@ -0,0 +1 @@ +cbx0913 diff --git a/apikey/claude_api.txt b/apikey/claude_api.txt new file mode 100644 index 0000000..48370e8 --- /dev/null +++ b/apikey/claude_api.txt @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/apikey/gcs_config.txt b/apikey/gcs_config.txt new file mode 100644 index 0000000..9667bbc --- /dev/null +++ b/apikey/gcs_config.txt @@ -0,0 +1,2 @@ +bucket_name=codebridge-speech-audio-files + diff --git a/apikey/gemini_api_key.txt b/apikey/gemini_api_key.txt new file mode 100644 index 0000000..85fa17f --- /dev/null +++ b/apikey/gemini_api_key.txt @@ -0,0 +1 @@ +AIzaSyAS3bAzmXlhhZHgO3buFiTGzavXZ6ubYq8 \ No newline at end of file diff --git a/apikey/google_api.txt b/apikey/google_api.txt new file mode 100644 index 0000000..39f4a79 --- /dev/null +++ b/apikey/google_api.txt @@ -0,0 +1 @@ +f7d58533aa1dba0db19d799d85f22686684521d2 \ No newline at end of file diff --git a/apikey/google_service_account.json b/apikey/google_service_account.json new file mode 100644 index 0000000..227553c --- /dev/null +++ b/apikey/google_service_account.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "codebridge-chatbot", + "private_key_id": "bc6e2c8d65ac9567824b1c3bae245f2249c52aed", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDddbnvIMgXEul\nQKi2hY+LS1zJLHDLlVzlhJ3WU8XJP38z2BeINSSwoUXnLLiCrhideDBoY7p6sD//\nFG6/3dNarsj+UwBDUPcbD8aoxjRUM637BNprb0dOexfLifnKxdDYrsGf1ZwaGvk1\nVtyzvZ0FKsmvMmZJhTwPQD1Qng0ewtRs63U2kV/K/2CMB/Vgw2vh2KzbaJtOncBB\nZ++ZnRAlQntnmvQON2hP+Q/N43oHCOXz6TshphN2EoEgncKkuQxkSHFAPBKtAR0B\nf4sfQ6jFBGJaYcLCm1vIioirw6zNam5CvkbJnuhG6DfSiczynOKH71Y5XvldKAn9\nQY9LDQWnAgMBAAECggEAP9hbBUEHV+et8eGn+k6wL6DDQxcYFPfJ61KhN+QPRAhQ\npX+dWCl7vZJAQh3SeyUg9zbOIRsKS48MqGZlMpjjs8hJ8QDtog9tV9KUYoazixmC\nZ+8S5Wro0NLWV+7OwBRTfqO+rVXZ8pEC/BBOcQuroYdzb5232aYCkzy5in7F7FjH\nMCAxUDJhCM4yv05zM/8SV1Ypn6/f1+ZhIpkzCxFlA/Gx85l7pwV6LCaZjYgDiNAY\nDbVEccshrdKXBVKhkyuuGToDLsiRCdish5zdyA8COPr4tflnXvkvQk0MwjZTEygC\nJ8Ceh7oTY44A/rzSqo2kXaCCByGVnFAXJ3z1JoRbCQKBgQDsANCgHZHSzyvgGlyk\nFST7lgS36r1zNEwyGMIZC/edglXqXGeDnelTiSii3MQcq3fqXvXgVr6Pk/vLHf11\nz8zPVg/lJeYhrz6EF2loMN8rhp0yjzYRMT7AZ8kITtCV5HEgmnU+/o4mNwJfN6qK\n26HTSjjmujAjejDL7my+8naSHQKBgQDUBZop2CZdrEALVp3DIw07ZeFEbnG8j5U9\nvJveaz9wZWZnMlxJgc+dk6I1bZHqlIGU3vJ95xJ6JjnoRhPSi1yceaUFEU9UkQLY\n0XuQwsgaFRJLqHcTwZi1Z//IGagtPkAYXDsJDoRr2CEz2lzwd5RV0XCmDoZN9xV6\n+wnOpGlrkwKBgAE3l9vbiy79JorHWAb4nPI3OdsA+O0pLeNsQUQDzckgLPVCeL4z\nCEsIAA+m99P2Bm5NAxOfHuh6qOfJRc9fvPyswvQ5l9BAqR/hRwfkiKIe1Zy3JF4+\nVMaFQoIqdeTwAq1aXpRul6kWy4pWLSj+LP17+oMmHq1wKeRDXIg3k+j5AoGAQGfD\nQNrMLMBaZBdXrSNErbpxB5yVKDZlm29j2diyWK40wTxnFF0+eBuUtq4mGSArjNF8\n0AoVbs2V4Z0IAHkdFNtO6Y8sjf/O4ZYg9wR0TJgCCsGOCo5QmSqSZHKGx9eVGNFL\njaC/URNCYsH+YX2xrbAFjCv1WFGqUMVZYVBIRckCgYEA3yPZlawHMbHtFXFPL+by\nANKqtgX5mKO7E90kqTTumhOpkuywe3okR30wfs/kzX24cL/+brXs7naYyPDYRZz5\nxAMPGa5D4BvVchz1EBQh4lygA6gRlX2Yy/B3grpyZyCaSANX8sReML3wzn+AQze4\nfVaQ2YB6//fwv/5s95n1FAM=\n-----END PRIVATE KEY-----\n", + "client_email": "vertex-ai-client@codebridge-chatbot.iam.gserviceaccount.com", + "client_id": "114574435593304532521", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/vertex-ai-client%40codebridge-chatbot.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" + } \ No newline at end of file diff --git a/apikey/google_vertex_api.txt b/apikey/google_vertex_api.txt new file mode 100644 index 0000000..85fa17f --- /dev/null +++ b/apikey/google_vertex_api.txt @@ -0,0 +1 @@ +AIzaSyAS3bAzmXlhhZHgO3buFiTGzavXZ6ubYq8 \ No newline at end of file diff --git a/apikey/notion.txt b/apikey/notion.txt new file mode 100644 index 0000000..9e9d582 --- /dev/null +++ b/apikey/notion.txt @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/apikey/opendart.txt b/apikey/opendart.txt new file mode 100644 index 0000000..a4a0890 --- /dev/null +++ b/apikey/opendart.txt @@ -0,0 +1 @@ +ad5002bf2c7d2f93eac3c6f9ff1d4b63bf3027bb \ No newline at end of file diff --git a/barobill_registration/index.php b/barobill_registration/index.php index a7a1bd5..439dbf6 100644 --- a/barobill_registration/index.php +++ b/barobill_registration/index.php @@ -60,7 +60,7 @@ ํ˜„ํ™ฉ - + ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ diff --git a/etax/README_DB.md b/etax/README_DB.md new file mode 100644 index 0000000..a8e34ed --- /dev/null +++ b/etax/README_DB.md @@ -0,0 +1,132 @@ +# ์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ + +## ํ…Œ์ด๋ธ” ๊ตฌ์กฐ + +### 1. etax_tenants (ํ…Œ๋„ŒํŠธ ๊ด€๋ฆฌ) +๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ ํ™˜๊ฒฝ์—์„œ ๊ฐ ๊ณ ๊ฐ์‚ฌ(ํ…Œ๋„ŒํŠธ)์˜ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. + +**์ฃผ์š” ํ•„๋“œ:** +- `id`: ํ…Œ๋„ŒํŠธ ๊ณ ์œ  ID +- `name`: ๊ธฐ์—…๋ช… +- `bizno`: ์‚ฌ์—…์ž๋ฒˆํ˜ธ (UNIQUE) +- `barobill_api_key`: ๋ฐ”๋กœ๋นŒ API ํ‚ค +- `barobill_cert_id`: ๋ฐ”๋กœ๋นŒ ์ธ์ฆ์„œ ID +- `status`: ํ™œ์„ฑ ์ƒํƒœ (active/inactive/suspended) + +### 2. etax_certificates (์ธ์ฆ์„œ ๊ด€๋ฆฌ) +๊ฐ ํ…Œ๋„ŒํŠธ์˜ ๊ณต๋™์ธ์ฆ์„œ ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +**์ฃผ์š” ํ•„๋“œ:** +- `id`: ์ธ์ฆ์„œ ๊ณ ์œ  ID +- `tenant_id`: ํ…Œ๋„ŒํŠธ ID (FK) +- `type`: ์ธ์ฆ์„œ ์œ ํ˜• (public/financial) +- `valid_from`, `valid_to`: ์ธ์ฆ์„œ ์œ ํšจ๊ธฐ๊ฐ„ +- `barobill_cert_id`: ๋ฐ”๋กœ๋นŒ ์ธ์ฆ์„œ ID + +### 3. etax_tax_invoices (์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฉ”์ธ) +์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ์˜ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. + +**์ฃผ์š” ํ•„๋“œ:** +- `id`: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๊ณ ์œ  ID +- `tenant_id`: ํ…Œ๋„ŒํŠธ ID (FK) +- `issue_key`: ๋ฐ”๋กœ๋นŒ ๋ฐœํ–‰ ํ‚ค (UNIQUE) +- `supply_amt`, `vat`, `total`: ๊ธˆ์•ก ์ •๋ณด +- `write_date`, `supply_date`: ์ž‘์„ฑ์ผ์ž, ๊ณต๊ธ‰์ผ์ž +- `state`: ์ƒํƒœ (draft/issued/sent/cancelled) +- `nts_receipt_no`: ๊ตญ์„ธ์ฒญ ์ ‘์ˆ˜๋ฒˆํ˜ธ + +### 4. etax_parties (๊ณต๊ธ‰์ž/์ˆ˜์ทจ์ž ์ •๋ณด) +์„ธ๊ธˆ๊ณ„์‚ฐ์„œ์˜ ๊ณต๊ธ‰์ž์™€ ์ˆ˜์ทจ์ž ์ •๋ณด๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. + +**์ฃผ์š” ํ•„๋“œ:** +- `id`: ๊ณ ์œ  ID +- `invoice_id`: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ID (FK) +- `role`: ์—ญํ•  (supplier/recipient/trustee) +- `bizno`, `corp_name`, `ceo`: ์‚ฌ์—…์ž ์ •๋ณด +- `addr`, `email`, `tel`: ์—ฐ๋ฝ์ฒ˜ ์ •๋ณด + +### 5. etax_line_items (ํ’ˆ๋ชฉ ์ƒ์„ธ) +์„ธ๊ธˆ๊ณ„์‚ฐ์„œ์˜ ํ’ˆ๋ชฉ๋ณ„ ์ƒ์„ธ ์ •๋ณด๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. + +**์ฃผ์š” ํ•„๋“œ:** +- `id`: ๊ณ ์œ  ID +- `invoice_id`: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ID (FK) +- `item_name`: ํ’ˆ๋ชฉ๋ช… +- `qty`, `unit_price`: ์ˆ˜๋Ÿ‰, ๋‹จ๊ฐ€ +- `supply_amt`, `vat`: ๊ณต๊ธ‰๊ฐ€์•ก, ๋ถ€๊ฐ€์„ธ +- `vat_type`: ๋ถ€๊ฐ€์„ธ ์œ ํ˜• (vat/zero/exempt) + +### 6. etax_transmission_logs (์ „์†ก ๋กœ๊ทธ) +๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ๋ฐ ๊ตญ์„ธ์ฒญ ์ „์†ก ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. + +**์ฃผ์š” ํ•„๋“œ:** +- `id`: ๋กœ๊ทธ ๊ณ ์œ  ID +- `invoice_id`: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ID (FK) +- `transmission_type`: ์ „์†ก ์œ ํ˜• (issue/cancel/nts_send) +- `status`: ์ƒํƒœ (success/failed/pending) +- `response_data`: API ์‘๋‹ต ๋ฐ์ดํ„ฐ +- `error_message`: ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ + +## ์„ค์น˜ ๋ฐฉ๋ฒ• + +### 1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑ (์„ ํƒ์‚ฌํ•ญ) +```sql +CREATE DATABASE IF NOT EXISTS `chandj` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +USE `chandj`; +``` + +### 2. ์Šคํ‚ค๋งˆ ์‹คํ–‰ +```bash +# MySQL/MariaDB ์ ‘์† +mysql -u chandj -p chandj < etax/db_schema.sql +``` + +๋˜๋Š” phpMyAdmin์ด๋‚˜ ๋‹ค๋ฅธ DB ๊ด€๋ฆฌ ๋„๊ตฌ์—์„œ `etax/db_schema.sql` ํŒŒ์ผ์„ ์‹คํ–‰ํ•˜์„ธ์š”. + +### 3. ๊ถŒํ•œ ํ™•์ธ +ํ…Œ์ด๋ธ”์ด ์ •์ƒ์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ: +```sql +SHOW TABLES LIKE 'etax_%'; +``` + +## ์‚ฌ์šฉ ๋ฐฉ๋ฒ• + +### PHP์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ +```php +require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php"); +$pdo = db_connect(); + +// ํ…Œ๋„ŒํŠธ ์กฐํšŒ ์˜ˆ์‹œ +$stmt = $pdo->prepare("SELECT * FROM etax_tenants WHERE id = ?"); +$stmt->execute([$tenant_id]); +$tenant = $stmt->fetch(PDO::FETCH_ASSOC); +``` + +### ๋ฉ€ํ‹ฐํ…Œ๋„Œ์‹œ ์ฟผ๋ฆฌ ์˜ˆ์‹œ +```php +// ํ•ญ์ƒ tenant_id๋กœ ํ•„ํ„ฐ๋ง +$stmt = $pdo->prepare(" + SELECT * FROM etax_tax_invoices + WHERE tenant_id = ? AND state = 'issued' + ORDER BY created_at DESC +"); +$stmt->execute([$tenant_id]); +$invoices = $stmt->fetchAll(PDO::FETCH_ASSOC); +``` + +## ์ฃผ์˜์‚ฌํ•ญ + +1. **์™ธ๋ž˜ํ‚ค ์ œ์•ฝ์กฐ๊ฑด**: ๋ชจ๋“  ์™ธ๋ž˜ํ‚ค๋Š” CASCADE ์‚ญ์ œ๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด, ๋ถ€๋ชจ ๋ ˆ์ฝ”๋“œ ์‚ญ์ œ ์‹œ ์ž์‹ ๋ ˆ์ฝ”๋“œ๋„ ์ž๋™ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค. + +2. **์ธ๋ฑ์Šค**: ์ž์ฃผ ์กฐํšŒ๋˜๋Š” ํ•„๋“œ์— ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ์ธ๋ฑ์Šค๊ฐ€ ํ•„์š”ํ•˜๋ฉด ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง ํ›„ ์ถ”๊ฐ€ํ•˜์„ธ์š”. + +3. **๋ฌธ์ž์…‹**: utf8mb4๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ชจ์ง€ ๋“ฑ ๋ชจ๋“  ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. + +4. **๋ณด์•ˆ**: + - `barobill_api_key`๋Š” ์•”ํ˜ธํ™”ํ•˜์—ฌ ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. + - `kms_key_ref`๋Š” ์•”ํ˜ธํ™”๋œ ์ธ์ฆ์„œ ์ฐธ์กฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. + +## ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ + +๊ธฐ์กด JSON ํŒŒ์ผ(`invoices_data.json`)์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋ ค๋ฉด ๋ณ„๋„์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + diff --git a/etax/api/API_URL_GUIDE.md b/etax/api/API_URL_GUIDE.md new file mode 100644 index 0000000..2c92e24 --- /dev/null +++ b/etax/api/API_URL_GUIDE.md @@ -0,0 +1,73 @@ +# ๋ฐ”๋กœ๋นŒ API ์—”๋“œํฌ์ธํŠธ URL ์„ค์ • ๊ฐ€์ด๋“œ + +## ํ˜„์žฌ ์˜ค๋ฅ˜ + +``` +Could not resolve host: test-api.barobill.co.kr +``` + +์ด ์˜ค๋ฅ˜๋Š” DNS ํ•ด๊ฒฐ ์‹คํŒจ๋กœ, API ์—”๋“œํฌ์ธํŠธ URL์ด ์ž˜๋ชป๋˜์—ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. + +## ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• + +### 1. ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ์ •ํ™•ํ•œ URL ํ™•์ธ + +1. [๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ](https://dev.barobill.co.kr) ๋กœ๊ทธ์ธ +2. API ๋ฌธ์„œ ๋˜๋Š” ์ƒ˜ํ”Œ ์ฝ”๋“œ ํ™•์ธ +3. ์‹ค์ œ API ์—”๋“œํฌ์ธํŠธ URL ํ™•์ธ + +### 2. ์ผ๋ฐ˜์ ์ธ ๋ฐ”๋กœ๋นŒ API URL ํŒจํ„ด + +๋ฐ”๋กœ๋นŒ API๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ URL ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +#### ์šด์˜ ํ™˜๊ฒฝ +- `https://api.barobill.co.kr` +- `https://www.barobill.co.kr/api` +- `https://barobill.co.kr/api` + +#### ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ +- `https://test.barobill.co.kr` +- `https://test-api.barobill.co.kr` (ํ˜„์žฌ ์‚ฌ์šฉ ์ค‘ - DNS ์˜ค๋ฅ˜ ๋ฐœ์ƒ) +- `https://dev.barobill.co.kr/api` +- ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ณ„๋„ ํ…Œ์ŠคํŠธ URL + +### 3. ์„ค์ • ํŒŒ์ผ ์ˆ˜์ • + +`etax/api/barobill_config.php` ํŒŒ์ผ์˜ ๋‹ค์Œ ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•˜์„ธ์š”: + +```php +$barobillApiBaseUrl = $isTestMode + ? 'https://์‹ค์ œ_ํ…Œ์ŠคํŠธ_URL' // ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ํ™•์ธํ•œ URL + : 'https://์‹ค์ œ_์šด์˜_URL'; // ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ํ™•์ธํ•œ URL +``` + +### 4. API ํ‚ค ํ™•์ธ + +ํ˜„์žฌ `apikey/barobill_api_key.txt` ํŒŒ์ผ์— API ํ‚ค๊ฐ€ ์ œ๋Œ€๋กœ ์ž…๋ ฅ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. + +- API ํ‚ค๊ฐ€ ์—†์œผ๋ฉด ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค +- API ํ‚ค๊ฐ€ ์žˆ์œผ๋ฉด ์‹ค์ œ ๋ฐ”๋กœ๋นŒ API๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค + +### 5. ๋„คํŠธ์›Œํฌ/DNS ํ™•์ธ + +๋งŒ์•ฝ URL์ด ๋งž๋Š”๋ฐ๋„ DNS ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด: + +1. **์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ ํ™•์ธ** +2. **๋ฐฉํ™”๋ฒฝ ์„ค์ • ํ™•์ธ** +3. **DNS ์„œ๋ฒ„ ๋ณ€๊ฒฝ** (Google DNS: 8.8.8.8, 8.8.4.4) +4. **ํ˜ธ์ŠคํŠธ ํŒŒ์ผ ํ™•์ธ** (Windows: C:\Windows\System32\drivers\etc\hosts) + +### 6. ์ž„์‹œ ํ•ด๊ฒฐ์ฑ… (์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ) + +์‹ค์ œ API ์—ฐ๋™ ์ „๊นŒ์ง€๋Š”: + +1. `apikey/barobill_api_key.txt` ํŒŒ์ผ์„ ๋น„์›Œ๋‘๊ฑฐ๋‚˜ +2. ํŒŒ์ผ ๋‚ด์šฉ์„ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜๋ฉด +3. ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ๋กœ ๋™์ž‘ํ•˜์—ฌ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค + +## ์ฐธ๊ณ  ์ž๋ฃŒ + +- [๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ](https://dev.barobill.co.kr) +- [๋ฐ”๋กœ๋นŒ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ API ๋ฌธ์„œ](https://dev.barobill.co.kr/docs/references/%EC%84%B8%EA%B8%88%EA%B3%84%EC%82%B0%EC%84%9C-API) +- ๋ฐ”๋กœ๋นŒ ๊ณ ๊ฐ์ง€์›: 1544-9256 + diff --git a/etax/api/README.md b/etax/api/README.md new file mode 100644 index 0000000..4b3bfbd --- /dev/null +++ b/etax/api/README.md @@ -0,0 +1,147 @@ +# ๋ฐ”๋กœ๋นŒ API ์—ฐ๋™ ๊ฐ€์ด๋“œ + +## โš ๏ธ ์ค‘์š”: ๋ฐ”๋กœ๋นŒ์€ SOAP ์›น์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค + +๋ฐ”๋กœ๋นŒ API๋Š” REST API๊ฐ€ ์•„๋‹Œ **SOAP ์›น์„œ๋น„์Šค**๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. +- ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ: `https://testws.baroservice.com/TI.asmx?WSDL` +- ์šด์˜ ํ™˜๊ฒฝ: `https://ws.baroservice.com/TI.asmx?WSDL` + +## API ํ‚ค ์„ค์ • + +### 1. ํ•„์ˆ˜ ํŒŒ์ผ ์ƒ์„ฑ + +`apikey` ํด๋”์— ๋‹ค์Œ ํŒŒ์ผ๋“ค์„ ์ƒ์„ฑํ•˜์„ธ์š”: + +#### ํ•„์ˆ˜ ํŒŒ์ผ +- `barobill_cert_key.txt`: CERTKEY (์ธ์ฆ์„œ ํ‚ค) + - ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ์ธ์ฆ์„œ ๋“ฑ๋ก ํ›„ ๋ฐœ๊ธ‰๋ฐ›์€ CERTKEY + - ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰์— ํ•„์ˆ˜ + +- `barobill_corp_num.txt`: ์‚ฌ์—…์ž๋ฒˆํ˜ธ + - ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ๋ฅผ ๋ฐœํ–‰ํ•  ํšŒ์‚ฌ์˜ ์‚ฌ์—…์ž๋ฒˆํ˜ธ + - ํ•˜์ดํ”ˆ(-) ์—†์ด ์ˆซ์ž๋งŒ ์ž…๋ ฅ + - ์˜ˆ: `1234567890` + +#### ์„ ํƒ ํŒŒ์ผ +- `barobill_test_mode.txt`: ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ์‚ฌ์šฉ ์‹œ "test" ๋˜๋Š” "true" ์ž…๋ ฅ + - ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ: `https://testws.baroservice.com/TI.asmx?WSDL` + - ์šด์˜ ํ™˜๊ฒฝ: `https://ws.baroservice.com/TI.asmx?WSDL` + +### 2. CERTKEY ๋ฐœ๊ธ‰ ๋ฐฉ๋ฒ• + +1. [๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ](https://dev.barobill.co.kr) ์ ‘์† +2. ํšŒ์›๊ฐ€์ž… ๋ฐ ๋กœ๊ทธ์ธ +3. ๊ฐœ๋ฐœ์ž์„ผํ„ฐ ๋ฉ”๋‰ด์—์„œ "์ธ์ฆ์„œ ๊ด€๋ฆฌ" ๋˜๋Š” "์ธ์ฆ์„œ ๋“ฑ๋ก" ๋ฉ”๋‰ด ์ฐพ๊ธฐ +4. ๊ณต๋™์ธ์ฆ์„œ(.pfx ๋˜๋Š” .p12 ํŒŒ์ผ) ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ ์—…๋กœ๋“œ +5. ์ธ์ฆ์„œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ๋ฐ ๋“ฑ๋ก +6. ๋“ฑ๋ก ์™„๋ฃŒ ํ›„ ๋ฐœ๊ธ‰๋ฐ›์€ **CERTKEY** ํ™•์ธ + - ์˜ˆ: "CERT-2024-ABC123-XYZ789" ๋˜๋Š” ์ˆซ์ž/๋ฌธ์ž ์กฐํ•ฉ์˜ ๊ณ ์œ  ํ‚ค +7. `apikey/barobill_cert_key.txt` ํŒŒ์ผ์— CERTKEY ์ €์žฅ + +### 3. ์‚ฌ์—…์ž๋ฒˆํ˜ธ ์„ค์ • + +1. ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ๋ฅผ ๋ฐœํ–‰ํ•  ํšŒ์‚ฌ์˜ ์‚ฌ์—…์ž๋ฒˆํ˜ธ ํ™•์ธ +2. ํ•˜์ดํ”ˆ(-) ์—†์ด ์ˆซ์ž๋งŒ ์ž…๋ ฅ + - ์˜ˆ: `123-45-67890` โ†’ `1234567890` +3. `apikey/barobill_corp_num.txt` ํŒŒ์ผ์— ์ €์žฅ + +### 4. ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ์„ค์ • + +ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด: + +1. `apikey/barobill_test_mode.txt` ํŒŒ์ผ ์ƒ์„ฑ +2. ํŒŒ์ผ ๋‚ด์šฉ์— `test` ๋˜๋Š” `true` ์ž…๋ ฅ +3. ์ €์žฅ + +## API ์—”๋“œํฌ์ธํŠธ + +### ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰ (์ €์žฅ + ๋ฐœ๊ธ‰) +- **SOAP ๋ฉ”์„œ๋“œ**: `RegistAndIssueTaxInvoice` +- **ํŒŒ์ผ**: `issue.php` +- **๋ฌธ์„œ**: `etax/docs/barobill-api-doc/TAXINVOICE/RegistAndIssueTaxInvoice.php` + +### ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์กฐํšŒ +- **SOAP ๋ฉ”์„œ๋“œ**: `GetTaxInvoice` +- **ํŒŒ์ผ**: `invoices.php` +- **๋ฌธ์„œ**: `etax/docs/barobill-api-doc/TAXINVOICE/GetTaxInvoice.php` + +### ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ƒํƒœ ์กฐํšŒ +- **SOAP ๋ฉ”์„œ๋“œ**: `GetTaxInvoiceStateEX` +- **๋ฌธ์„œ**: `etax/docs/barobill-api-doc/TAXINVOICE/GetTaxInvoiceStateEX.php` + +### ๊ตญ์„ธ์ฒญ ์ „์†ก +- **SOAP ๋ฉ”์„œ๋“œ**: `SendToNTS` +- **ํŒŒ์ผ**: `status.php` +- **๋ฌธ์„œ**: `etax/docs/barobill-api-doc/TAXINVOICE/SendToNTS.php` + +## SOAP API ์‚ฌ์šฉ ์˜ˆ์ œ + +### ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰ + +```php +require_once(__DIR__ . '/barobill_config.php'); + +$invoiceData = [ + 'issueKey' => 'MGT20241201123456', // ๊ด€๋ฆฌ๋ฒˆํ˜ธ (MgtKey) + 'supplierBizno' => '1234567890', + 'supplierName' => '๊ณต๊ธ‰์ž ํšŒ์‚ฌ๋ช…', + 'recipientBizno' => '0987654321', + 'recipientName' => '์ˆ˜์ทจ์ธ ํšŒ์‚ฌ๋ช…', + 'supplyDate' => '2024-12-01', + 'items' => [ + [ + 'name' => 'ํ’ˆ๋ชฉ๋ช…', + 'spec' => '๊ทœ๊ฒฉ', + 'qty' => '1', + 'unitPrice' => 10000, + 'supplyAmt' => 10000, + 'vat' => 1000 + ] + ], + 'memo' => '๋น„๊ณ ' +]; + +$result = issueTaxInvoice($invoiceData); +``` + +### ๊ตญ์„ธ์ฒญ ์ „์†ก + +```php +require_once(__DIR__ . '/barobill_config.php'); + +$mgtKey = 'MGT20241201123456'; // ๊ด€๋ฆฌ๋ฒˆํ˜ธ +$result = sendToNTS($mgtKey); +``` + +## ์ฐธ๊ณ  ๋ฌธ์„œ + +- [๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ](https://dev.barobill.co.kr) +- [๋ฐ”๋กœ๋นŒ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ API ๋ฌธ์„œ](https://dev.barobill.co.kr/docs/references/%EC%84%B8%EA%B8%88%EA%B3%84%EC%82%B0%EC%84%9C-API) +- ๋กœ์ปฌ ๋ฌธ์„œ: `etax/docs/barobill-api-doc/` ํด๋” + +## ์ฃผ์˜์‚ฌํ•ญ + +1. **CERTKEY์™€ ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋Š” ์ ˆ๋Œ€ ๊ณต๊ฐœ ์ €์žฅ์†Œ์— ์ปค๋ฐ‹ํ•˜์ง€ ๋งˆ์„ธ์š”** +2. `.gitignore`์— `apikey/*.txt` (์˜ˆ์ œ ํŒŒ์ผ ์ œ์™ธ) ์ถ”๊ฐ€ ๊ถŒ์žฅ +3. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ๊ณผ ์šด์˜ ํ™˜๊ฒฝ์˜ CERTKEY๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌํ•˜์„ธ์š” +4. SOAP ํด๋ผ์ด์–ธํŠธ๋Š” PHP์˜ `SoapClient` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค +5. PHP 7.3 ์ด์ƒ์—์„œ `SoapClient` ํ™•์žฅ์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค + +## ๋ฌธ์ œ ํ•ด๊ฒฐ + +### SOAP ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ ์‹คํŒจ + +- PHP `SoapClient` ํ™•์žฅ์ด ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ +- `php -m | grep soap` ๋ช…๋ น์œผ๋กœ ํ™•์ธ +- ์„ค์น˜๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด PHP ํ™•์žฅ ์„ค์น˜ ํ•„์š” + +### CERTKEY ์˜ค๋ฅ˜ + +- CERTKEY๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž…๋ ฅ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ +- ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ์ธ์ฆ์„œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋“ฑ๋ก๋˜์—ˆ๋Š”์ง€ ํ™•์ธ +- ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ๋Š” CERTKEY๊ฐ€ ์„ ํƒ์‚ฌํ•ญ์ผ ์ˆ˜ ์žˆ์Œ + +### ์‚ฌ์—…์ž๋ฒˆํ˜ธ ์˜ค๋ฅ˜ + +- ํ•˜์ดํ”ˆ(-) ์—†์ด ์ˆซ์ž๋งŒ ์ž…๋ ฅํ–ˆ๋Š”์ง€ ํ™•์ธ +- ๋ฐœํ–‰์ž ์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธ diff --git a/etax/api/barobill_config.php b/etax/api/barobill_config.php new file mode 100644 index 0000000..c52547f --- /dev/null +++ b/etax/api/barobill_config.php @@ -0,0 +1,418 @@ +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 ์ฝ๊ธฐ (์ธ์ฆ์„œ ํ‚ค) +// ์šฐ์„ ์ˆœ์œ„: barobill_cert_key.txt > barobill_api_key.txt (๊ธฐ์กด ํ˜ธํ™˜์„ฑ) +$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; + } +} +// ๊ธฐ์กด barobill_api_key.txt๋„ CERTKEY๋กœ ์‚ฌ์šฉ (ํ˜ธํ™˜์„ฑ) +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 = $content; + // ํ•˜์ดํ”ˆ ์ œ๊ฑฐ + $barobillCorpNum = str_replace('-', '', $barobillCorpNum); + } +} + +// ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ํ™•์ธ +$isTestMode = false; +if (file_exists($testModeFile)) { + $testMode = trim(file_get_contents($testModeFile)); + $isTestMode = (strtolower($testMode) === 'test' || strtolower($testMode) === 'true'); +} + +// ๋ฐ”๋กœ๋นŒ SOAP ์›น์„œ๋น„์Šค URL +// ๋ฌธ์„œ ์ฐธ๊ณ : etax/docs/barobill-api-doc/_lib/BaroService_TI.php +$barobillSoapUrl = $isTestMode + ? 'https://testws.baroservice.com/TI.asmx?WSDL' // ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ + : 'https://ws.baroservice.com/TI.asmx?WSDL'; // ์šด์˜ ํ™˜๊ฒฝ + +// SOAP ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” +$barobillSoapClient = null; +// ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ๋Š” CERTKEY ์—†์ด๋„ SOAP ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ์‹œ๋„ +if (!empty($barobillCertKey) || $isTestMode) { + try { + $barobillSoapClient = new SoapClient($barobillSoapUrl, [ + 'trace' => true, + 'encoding' => 'UTF-8', + 'exceptions' => true, + 'connection_timeout' => 30 + ]); + } catch (Throwable $e) { + // SOAP ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ ์‹คํŒจ ์‹œ null ์œ ์ง€ (Class not found ๋“ฑ Fatal Error ํฌํ•จ) + error_log('๋ฐ”๋กœ๋นŒ SOAP ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ ์‹คํŒจ: ' . $e->getMessage()); + } +} + +/** + * ๋ฐ”๋กœ๋นŒ SOAP ์›น์„œ๋น„์Šค ํ˜ธ์ถœ ํ•จ์ˆ˜ + * + * @param string $method SOAP ๋ฉ”์„œ๋“œ๋ช… (์˜ˆ: 'RegistAndIssueTaxInvoice') + * @param array $params SOAP ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function callBarobillSOAP($method, $params = []) { + global $barobillSoapClient, $barobillCertKey, $barobillCorpNum, $isTestMode; + + if (!$barobillSoapClient) { + 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/TI.asmx?WSDL' : 'https://ws.baroservice.com/TI.asmx?WSDL' + ] + ]; + } + + // ํ…Œ์ŠคํŠธ ๋ชจ๋“œ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ CERTKEY ํ•„์ˆ˜ + if (empty($barobillCertKey) && !$isTestMode) { + return [ + 'success' => false, + 'error' => 'CERTKEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. apikey/barobill_cert_key.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜์„ธ์š”.' + ]; + } + + // ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ CERTKEY๊ฐ€ ์—†์œผ๋ฉด ๋นˆ ๋ฌธ์ž์—ด๋กœ ์ฒ˜๋ฆฌ (๋ฐ”๋กœ๋นŒ ํ…Œ์ŠคํŠธ API๊ฐ€ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Œ) + if (empty($barobillCertKey) && $isTestMode) { + $barobillCertKey = ''; // ๋นˆ ๋ฌธ์ž์—ด๋กœ ์‹œ๋„ + } + + // ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ ์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์—†์œผ๋ฉด ๋”๋ฏธ ์‚ฌ์—…์ž๋ฒˆํ˜ธ ์‚ฌ์šฉ + if (empty($barobillCorpNum)) { + if ($isTestMode) { + // ํ…Œ์ŠคํŠธ ๋ชจ๋“œ: ๋”๋ฏธ ์‚ฌ์—…์ž๋ฒˆํ˜ธ ์‚ฌ์šฉ (๋ฐ”๋กœ๋นŒ ํ…Œ์ŠคํŠธ API๊ฐ€ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Œ) + $barobillCorpNum = '1234567890'; // ํ…Œ์ŠคํŠธ์šฉ ๋”๋ฏธ ์‚ฌ์—…์ž๋ฒˆํ˜ธ + error_log('๋ฐ”๋กœ๋นŒ ํ…Œ์ŠคํŠธ ๋ชจ๋“œ: ์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์—†์–ด์„œ ๋”๋ฏธ ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.'); + } else { + // ์šด์˜ ๋ชจ๋“œ: ์‚ฌ์—…์ž๋ฒˆํ˜ธ ํ•„์ˆ˜ + return [ + 'success' => false, + 'error' => '์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. apikey/barobill_corp_num.txt ํŒŒ์ผ์„ ํ™•์ธํ•˜์„ธ์š”.' + ]; + } + } + + try { + // CERTKEY์™€ CorpNum์„ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ž๋™ ์ถ”๊ฐ€ + if (!isset($params['CERTKEY'])) { + $params['CERTKEY'] = $barobillCertKey; + } + if (!isset($params['CorpNum']) && !isset($params['CorpNum'])) { + // CorpNum์ด ํŒŒ๋ผ๋ฏธํ„ฐ์— ์—†์œผ๋ฉด ์ถ”๊ฐ€ (์ผ๋ถ€ ๋ฉ”์„œ๋“œ๋Š” Invoice ๋‚ด๋ถ€์— ์žˆ์Œ) + if (!isset($params['Invoice']['InvoicerParty']['CorpNum'])) { + // Invoice ๊ตฌ์กฐ๊ฐ€ ์—†์œผ๋ฉด ์ตœ์ƒ์œ„์— ์ถ”๊ฐ€ + if (!isset($params['CorpNum'])) { + $params['CorpNum'] = $barobillCorpNum; + } + } + } + + // ๋””๋ฒ„๊น…: ์ „๋‹ฌ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ๋กœ๊ทธ (๋ฏผ๊ฐ ์ •๋ณด๋Š” ๋งˆ์Šคํ‚น) + error_log('๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ - Method: ' . $method . ', CorpNum: ' . $barobillCorpNum . ', CERTKEY: ' . (empty($barobillCertKey) ? '(์—†์Œ)' : substr($barobillCertKey, 0, 10) . '...')); + + // SOAP ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ + $result = $barobillSoapClient->$method($params); + + // ๊ฒฐ๊ณผ์—์„œ Result ์†์„ฑ ์ถ”์ถœ + $resultProperty = $method . 'Result'; + if (isset($result->$resultProperty)) { + $resultData = $result->$resultProperty; + + // ๊ฒฐ๊ณผ๊ฐ€ ์Œ์ˆ˜๋ฉด ์˜ค๋ฅ˜ ์ฝ”๋“œ + if (is_numeric($resultData) && $resultData < 0) { + // ์˜ค๋ฅ˜ ์ฝ”๋“œ์— ๋”ฐ๋ฅธ ๋ฉ”์‹œ์ง€ ๋งคํ•‘ + $errorMessages = [ + -11101 => '์‚ฌ์—…์ž๋ฒˆํ˜ธ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. apikey/barobill_corp_num.txt ํŒŒ์ผ์— ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์—…์ž๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.', + -11102 => 'CERTKEY๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ CERTKEY๋ฅผ ํ™•์ธํ•˜์„ธ์š”.', + -11103 => '์ธ์ฆ์„œ๊ฐ€ ๋งŒ๋ฃŒ๋˜์—ˆ๊ฑฐ๋‚˜ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.', + -26001 => '๋ฐœํ–‰์— ํ•„์š”ํ•œ ๊ณต๋™์ธ์ฆ์„œ๊ฐ€ ๋“ฑ๋ก๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ๋นŒ ์›น์‚ฌ์ดํŠธ(https://www.barobill.co.kr)์— ๋กœ๊ทธ์ธํ•˜์—ฌ ๊ณต๋™์ธ์ฆ์„œ๋ฅผ ๋“ฑ๋กํ•˜๊ณ , CERTKEY์™€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.', + -32000 => '์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', + ]; + + $errorMessage = isset($errorMessages[$resultData]) + ? $errorMessages[$resultData] + : '๋ฐ”๋กœ๋นŒ API ์˜ค๋ฅ˜ ์ฝ”๋“œ: ' . $resultData; + + // GetErrString API๋กœ ์ƒ์„ธ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์กฐํšŒ ์‹œ๋„ (CERTKEY๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ) + $detailedError = null; + if (!empty($barobillCertKey) && $barobillSoapClient) { + try { + $errStringResult = $barobillSoapClient->GetErrString([ + 'CERTKEY' => $barobillCertKey, + 'ErrCode' => $resultData + ]); + if (isset($errStringResult->GetErrStringResult) && $errStringResult->GetErrStringResult >= 0) { + $detailedError = $errStringResult->GetErrStringResult; + } + } catch (Exception $e) { + // GetErrString ํ˜ธ์ถœ ์‹คํŒจ ์‹œ ๋ฌด์‹œ + } + } + + return [ + 'success' => false, + 'error' => $errorMessage, + 'error_code' => $resultData, + 'error_detail' => $detailedError ? "์ƒ์„ธ ์˜ค๋ฅ˜: " . $detailedError : null, + 'soap_request' => $barobillSoapClient->__getLastRequest(), + 'soap_response' => $barobillSoapClient->__getLastResponse() + ]; + } + + return [ + 'success' => true, + 'data' => $resultData, + 'soap_request' => $barobillSoapClient->__getLastRequest(), + 'soap_response' => $barobillSoapClient->__getLastResponse() + ]; + } + + return [ + 'success' => true, + 'data' => $result, + 'soap_request' => $barobillSoapClient->__getLastRequest(), + 'soap_response' => $barobillSoapClient->__getLastResponse() + ]; + + } catch (SoapFault $e) { + return [ + 'success' => false, + 'error' => 'SOAP ์˜ค๋ฅ˜: ' . $e->getMessage(), + 'error_code' => $e->getCode(), + 'error_detail' => [ + 'fault_code' => $e->faultcode ?? null, + 'fault_string' => $e->faultstring ?? null, + 'soap_request' => $barobillSoapClient ? $barobillSoapClient->__getLastRequest() : null, + 'soap_response' => $barobillSoapClient ? $barobillSoapClient->__getLastResponse() : null + ] + ]; + } catch (Throwable $e) { + return [ + 'success' => false, + 'error' => 'API ํ˜ธ์ถœ ์˜ค๋ฅ˜ (์น˜๋ช…์ ): ' . $e->getMessage(), + 'error_detail' => [ + 'exception_type' => get_class($e), + 'soap_request' => $barobillSoapClient ? $barobillSoapClient->__getLastRequest() : null, + 'soap_response' => $barobillSoapClient ? $barobillSoapClient->__getLastResponse() : null + ] + ]; + } +} + +/** + * ๋ฐ”๋กœ๋นŒ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰ (์ €์žฅ + ๋ฐœ๊ธ‰) + * + * ๋ฌธ์„œ ์ฐธ๊ณ : etax/docs/barobill-api-doc/TAXINVOICE/RegistAndIssueTaxInvoice.php + * + * @param array $invoiceData ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐ์ดํ„ฐ + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function issueTaxInvoice($invoiceData) { + global $barobillCorpNum; + + // MgtKey ์ƒ์„ฑ (๊ด€๋ฆฌ๋ฒˆํ˜ธ) - ์œ ๋‹ˆํฌํ•œ ํ‚ค ์ƒ์„ฑ + $mgtKey = $invoiceData['issueKey'] ?? 'MGT' . date('YmdHis') . rand(1000, 9999); + + // ๊ณต๊ธ‰๊ฐ€์•ก, ๋ถ€๊ฐ€์„ธ, ํ•ฉ๊ณ„ ๊ณ„์‚ฐ + $supplyAmt = 0; + $vat = 0; + foreach ($invoiceData['items'] ?? [] as $item) { + $itemSupplyAmt = floatval($item['supplyAmt'] ?? 0); + $itemVat = floatval($item['vat'] ?? 0); + $supplyAmt += $itemSupplyAmt; + $vat += $itemVat; + } + $total = $supplyAmt + $vat; + + // TaxType ๊ฒฐ์ •: ๋ถ€๊ฐ€์„ธ๊ฐ€ 0์›์ด๋ฉด ์˜์„ธ(2) ๋˜๋Š” ๋ฉด์„ธ(3)๋กœ ์„ค์ • + // ๊ณผ์„ธ(1)๋Š” ๋ถ€๊ฐ€์„ธ๊ฐ€ 0์› ์ด์ƒ์ด์–ด์•ผ ํ•จ + $taxType = 1; // ๊ธฐ๋ณธ๊ฐ’: ๊ณผ์„ธ + if ($vat == 0) { + // ๋ถ€๊ฐ€์„ธ๊ฐ€ 0์›์ด๋ฉด ์˜์„ธ๋กœ ์„ค์ • (๋˜๋Š” ๋ฉด์„ธ๋กœ ์„ค์ • ๊ฐ€๋Šฅ) + $taxType = 2; // 2: ์˜์„ธ + } + + // ๋ฐ”๋กœ๋นŒ SOAP API ์ŠคํŽ™์— ๋งž๊ฒŒ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ + // ๋ฌธ์„œ ์ฐธ๊ณ : etax/docs/barobill-api-doc/TAXINVOICE/RegistAndIssueTaxInvoice.php + $taxInvoice = [ + 'IssueDirection' => 1, // 1: ์ •๋ฐœํ–‰, 2: ์—ญ๋ฐœํ–‰ + 'TaxInvoiceType' => 1, // 1: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ, 2: ๊ณ„์‚ฐ์„œ + 'ModifyCode' => '', // ์ˆ˜์ •์‚ฌ์œ ์ฝ”๋“œ (์‹ ๊ทœ๋ฐœํ–‰์‹œ ๋นˆ๊ฐ’) + 'TaxType' => $taxType, // 1: ๊ณผ์„ธ, 2: ์˜์„ธ, 3: ๋ฉด์„ธ (๋ถ€๊ฐ€์„ธ๊ฐ€ 0์ด๋ฉด ์˜์„ธ๋กœ ์„ค์ •) + 'TaxCalcType' => 1, // 1: ์†Œ๊ณ„ํ•ฉ๊ณ„, 2: ํ•ญ๋ชฉํ•ฉ๊ณ„ + 'PurposeType' => 2, // 1: ์˜์ˆ˜, 2: ์ฒญ๊ตฌ, 3: ์—†์Œ + 'WriteDate' => date('Ymd', strtotime($invoiceData['writeDate'] ?? date('Y-m-d'))), // ์ž‘์„ฑ์ผ์ž (YYYYMMDD) + 'AmountTotal' => number_format($supplyAmt, 0, '', ''), // ๊ณต๊ธ‰๊ฐ€์•ก ํ•ฉ๊ณ„ + 'TaxTotal' => number_format($vat, 0, '', ''), // ๋ถ€๊ฐ€์„ธ ํ•ฉ๊ณ„ + 'TotalAmount' => number_format($total, 0, '', ''), // ํ•ฉ๊ณ„๊ธˆ์•ก + 'Cash' => '0', // ํ˜„๊ธˆ + 'ChkBill' => '0', // ์–ด์Œ + 'Note' => '0', // ์™ธ์ƒ + 'Credit' => number_format($total, 0, '', ''), // ์™ธ์ƒ๋ฏธ์ˆ˜๊ธˆ (ํ•ฉ๊ณ„๊ธˆ์•ก๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•จ) + 'Remark1' => $invoiceData['memo'] ?? '', // ๋น„๊ณ 1 + 'Remark2' => '', // ๋น„๊ณ 2 + 'Remark3' => '', // ๋น„๊ณ 3 + 'Kwon' => '', // ๊ถŒ + 'Ho' => '', // ํ˜ธ + 'SerialNum' => '', // ์ผ๋ จ๋ฒˆํ˜ธ + 'InvoicerParty' => [ + 'MgtNum' => $mgtKey, // ๊ด€๋ฆฌ๋ฒˆํ˜ธ + 'CorpNum' => $barobillCorpNum, // ๋ฐœํ–‰์ž ์‚ฌ์—…์ž๋ฒˆํ˜ธ (CERTKEY์™€ ์—ฐ๊ฒฐ๋œ ์‚ฌ์—…์ž๋ฒˆํ˜ธ ์‚ฌ์šฉ) + 'TaxRegID' => '', // ์ข…์‚ฌ์—…์žฅ๋ฒˆํ˜ธ + 'CorpName' => $invoiceData['supplierName'] ?? '', // ์ƒํ˜ธ + 'CEOName' => $invoiceData['supplierCeo'] ?? '', // ๋Œ€ํ‘œ์ž๋ช… + 'Addr' => $invoiceData['supplierAddr'] ?? '', // ์ฃผ์†Œ + 'BizType' => '', // ์—…ํƒœ + 'BizClass' => '', // ์ข…๋ชฉ + 'ContactID' => $invoiceData['supplierContactId'] ?? 'cbx0913', // ๋‹ด๋‹น์ž ์•„์ด๋”” (๋ฐ”๋กœ๋นŒ ์›นํŽ˜์ด์ง€ ID) + 'ContactName' => $invoiceData['supplierContact'] ?? '', // ๋‹ด๋‹น์ž๋ช… + 'TEL' => $invoiceData['supplierTel'] ?? '', // ์ „ํ™”๋ฒˆํ˜ธ + 'HP' => '', // ํœด๋Œ€ํฐ + 'Email' => $invoiceData['supplierEmail'] ?? '', // ์ด๋ฉ”์ผ + ], + 'InvoiceeParty' => [ + 'MgtNum' => '', // ๊ด€๋ฆฌ๋ฒˆํ˜ธ + 'CorpNum' => str_replace('-', '', $invoiceData['recipientBizno'] ?? ''), // ์‚ฌ์—…์ž๋ฒˆํ˜ธ + 'TaxRegID' => '', // ์ข…์‚ฌ์—…์žฅ๋ฒˆํ˜ธ + 'CorpName' => $invoiceData['recipientName'] ?? '', // ์ƒํ˜ธ + 'CEOName' => $invoiceData['recipientCeo'] ?? '', // ๋Œ€ํ‘œ์ž๋ช… + 'Addr' => $invoiceData['recipientAddr'] ?? '', // ์ฃผ์†Œ + 'BizType' => '', // ์—…ํƒœ + 'BizClass' => '', // ์ข…๋ชฉ + 'ContactID' => '', // ๋‹ด๋‹น์ž ์•„์ด๋”” + 'ContactName' => $invoiceData['recipientContact'] ?? '', // ๋‹ด๋‹น์ž๋ช… + 'TEL' => $invoiceData['recipientTel'] ?? '', // ์ „ํ™”๋ฒˆํ˜ธ + 'HP' => '', // ํœด๋Œ€ํฐ + 'Email' => $invoiceData['recipientEmail'] ?? '', // ์ด๋ฉ”์ผ + ], + 'BrokerParty' => [], // ์œ„์ˆ˜ํƒ ๊ฑฐ๋ž˜์‹œ์—๋งŒ ์‚ฌ์šฉ + 'TaxInvoiceTradeLineItems' => [ + 'TaxInvoiceTradeLineItem' => [] + ] + ]; + + // ํ’ˆ๋ชฉ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ + foreach ($invoiceData['items'] ?? [] as $item) { + $taxInvoice['TaxInvoiceTradeLineItems']['TaxInvoiceTradeLineItem'][] = [ + 'PurchaseExpiry' => '', // ๊ณต์ œ๊ธฐํ•œ + 'Name' => $item['name'] ?? '', // ํ’ˆ๋ช… + 'Information' => $item['spec'] ?? '', // ๊ทœ๊ฒฉ + 'ChargeableUnit' => $item['qty'] ?? '1', // ์ˆ˜๋Ÿ‰ + 'UnitPrice' => number_format(floatval($item['unitPrice'] ?? 0), 0, '', ''), // ๋‹จ๊ฐ€ + 'Amount' => number_format(floatval($item['supplyAmt'] ?? 0), 0, '', ''), // ๊ณต๊ธ‰๊ฐ€์•ก + 'Tax' => number_format(floatval($item['vat'] ?? 0), 0, '', ''), // ๋ถ€๊ฐ€์„ธ + 'Description' => $item['description'] ?? '', // ๋น„๊ณ  + ]; + } + + // SOAP ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ + $params = [ + 'CorpNum' => $barobillCorpNum, // ๋ฐœํ–‰์ž ์‚ฌ์—…์ž๋ฒˆํ˜ธ + 'Invoice' => $taxInvoice, + 'SendSMS' => false, // SMS ๋ฐœ์†ก ์—ฌ๋ถ€ + 'ForceIssue' => false, // ๊ฐ•์ œ๋ฐœํ–‰ ์—ฌ๋ถ€ + 'MailTitle' => '', // ์ด๋ฉ”์ผ ์ œ๋ชฉ + ]; + + return callBarobillSOAP('RegistAndIssueTaxInvoice', $params); +} + +/** + * ๋ฐ”๋กœ๋นŒ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์กฐํšŒ + * + * ๋ฌธ์„œ ์ฐธ๊ณ : etax/docs/barobill-api-doc/TAXINVOICE/GetTaxInvoice.php + * + * @param string $mgtKey ๊ด€๋ฆฌ๋ฒˆํ˜ธ (MgtKey) + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function getTaxInvoice($mgtKey) { + global $barobillCorpNum; + + $params = [ + 'CorpNum' => $barobillCorpNum, + 'MgtKey' => $mgtKey + ]; + + return callBarobillSOAP('GetTaxInvoice', $params); +} + +/** + * ๋ฐ”๋กœ๋นŒ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ƒํƒœ ์กฐํšŒ + * + * ๋ฌธ์„œ ์ฐธ๊ณ : etax/docs/barobill-api-doc/TAXINVOICE/GetTaxInvoiceStateEX.php + * + * @param string $mgtKey ๊ด€๋ฆฌ๋ฒˆํ˜ธ (MgtKey) + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function getTaxInvoiceState($mgtKey) { + global $barobillCorpNum; + + $params = [ + 'CorpNum' => $barobillCorpNum, + 'MgtKey' => $mgtKey + ]; + + return callBarobillSOAP('GetTaxInvoiceStateEX', $params); +} + +/** + * ๋ฐ”๋กœ๋นŒ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๊ตญ์„ธ์ฒญ ์ „์†ก + * + * ๋ฌธ์„œ ์ฐธ๊ณ : etax/docs/barobill-api-doc/TAXINVOICE/SendToNTS.php + * + * @param string $mgtKey ๊ด€๋ฆฌ๋ฒˆํ˜ธ (MgtKey) + * @return array ์‘๋‹ต ๋ฐ์ดํ„ฐ + */ +function sendToNTS($mgtKey) { + global $barobillCorpNum; + + $params = [ + 'CorpNum' => $barobillCorpNum, + 'MgtKey' => $mgtKey + ]; + + return callBarobillSOAP('SendToNTS', $params); +} + +?> + diff --git a/etax/api/debug_test.php b/etax/api/debug_test.php new file mode 100644 index 0000000..5c7efc3 --- /dev/null +++ b/etax/api/debug_test.php @@ -0,0 +1,34 @@ +load(); + echo ".env loaded.\n"; + } catch (Exception $e) { + echo "Error loading .env: " . $e->getMessage() . "\n"; + } +} else { + echo ".env file NOT found.\n"; +} + +$root = getenv('DOCUMENT_ROOT'); +echo "DOCUMENT_ROOT from getenv: " . var_export($root, true) . "\n"; +echo "DOCUMENT_ROOT from \$_ENV: " . var_export($_ENV['DOCUMENT_ROOT'] ?? 'unset', true) . "\n"; +echo "DOCUMENT_ROOT from \$_SERVER: " . var_export($_SERVER['DOCUMENT_ROOT'] ?? 'unset', true) . "\n"; diff --git a/etax/api/delete.php b/etax/api/delete.php new file mode 100644 index 0000000..3d523ed --- /dev/null +++ b/etax/api/delete.php @@ -0,0 +1,163 @@ + false, + "error" => "Method not allowed" + ], JSON_UNESCAPED_UNICODE); + exit; +} + +// ์š”์ฒญ ๋ณธ๋ฌธ์—์„œ invoiceId ๊ฐ€์ ธ์˜ค๊ธฐ +$rawInput = file_get_contents('php://input'); +$input = json_decode($rawInput, true); +$invoiceId = $input['invoiceId'] ?? $_GET['invoiceId'] ?? null; + +// ๋””๋ฒ„๊น…: ์š”์ฒญ ๋ฐ์ดํ„ฐ ๋กœ๊ทธ +error_log("Delete request - Raw input: " . $rawInput); +error_log("Delete request - Parsed input: " . print_r($input, true)); +error_log("Delete request - invoiceId: " . var_export($invoiceId, true)); + +if (!$invoiceId) { + http_response_code(400); + echo json_encode([ + "success" => false, + "error" => "invoiceId is required", + "debug" => [ + "rawInput" => $rawInput, + "parsedInput" => $input, + "getParams" => $_GET + ] + ], JSON_UNESCAPED_UNICODE); + exit; +} + +$dataFile = __DIR__ . '/invoices_data.json'; + +// ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ +$existingData = []; +if (file_exists($dataFile)) { + $fileContent = file_get_contents($dataFile); + if ($fileContent !== false) { + $existingData = json_decode($fileContent, true); + if (!is_array($existingData)) { + $existingData = []; + } + } else { + error_log("Failed to read invoices_data.json file"); + } +} else { + error_log("invoices_data.json file does not exist"); +} + +if (!isset($existingData['invoices'])) { + $existingData['invoices'] = []; +} + +// ๋””๋ฒ„๊น…: ํ˜„์žฌ ํŒŒ์ผ์— ์žˆ๋Š” ID ๋ชฉ๋ก +$currentIds = array_map(function($inv) { + return $inv['id'] ?? 'no-id'; +}, $existingData['invoices']); +error_log("Current invoice IDs in file: " . implode(', ', $currentIds)); +error_log("Looking for invoiceId: " . $invoiceId); + +// ์‚ญ์ œ๋œ ID ๋ชฉ๋ก ํŒŒ์ผ +$deletedIdsFile = __DIR__ . '/deleted_ids.json'; +$deletedIds = []; + +// ์‚ญ์ œ๋œ ID ๋ชฉ๋ก ์ฝ๊ธฐ +if (file_exists($deletedIdsFile)) { + $deletedContent = file_get_contents($deletedIdsFile); + if ($deletedContent !== false) { + $deletedIds = json_decode($deletedContent, true); + if (!is_array($deletedIds)) { + $deletedIds = []; + } + } +} + +// ๊ธฐ๋ณธ mock ๋ฐ์ดํ„ฐ์ธ ๊ฒฝ์šฐ, ์‚ญ์ œ๋œ ID ๋ชฉ๋ก์— ์ถ”๊ฐ€ +$defaultMockIds = ['inv_001', 'inv_002', 'inv_003']; +if (in_array($invoiceId, $defaultMockIds)) { + // ์ด๋ฏธ ์‚ญ์ œ๋œ ๊ฒฝ์šฐ + if (in_array($invoiceId, $deletedIds)) { + http_response_code(404); + echo json_encode([ + "success" => false, + "error" => "Invoice not found", + "message" => "์ด๋ฏธ ์‚ญ์ œ๋œ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค." + ], JSON_UNESCAPED_UNICODE); + exit; + } + + // ์‚ญ์ œ๋œ ID ๋ชฉ๋ก์— ์ถ”๊ฐ€ + $deletedIds[] = $invoiceId; + $deletedIds = array_unique($deletedIds); // ์ค‘๋ณต ์ œ๊ฑฐ + file_put_contents($deletedIdsFile, json_encode($deletedIds, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + echo json_encode([ + "success" => true, + "message" => "Invoice deleted successfully", + "deletedId" => $invoiceId + ], JSON_UNESCAPED_UNICODE); + exit; +} + +// ํ•ด๋‹น ID์˜ ์ธ๋ณด์ด์Šค ์ฐพ์•„์„œ ์‚ญ์ œ +$beforeCount = count($existingData['invoices']); +$foundInvoice = null; +foreach ($existingData['invoices'] as $index => $invoice) { + $currentId = $invoice['id'] ?? ''; + // ๋ฌธ์ž์—ด ๋น„๊ต (ํƒ€์ž… ๋ณ€ํ™˜) + if ((string)$currentId === (string)$invoiceId) { + $foundInvoice = $invoice; + unset($existingData['invoices'][$index]); + break; + } +} +$existingData['invoices'] = array_values($existingData['invoices']); // ์ธ๋ฑ์Šค ์žฌ์ •๋ ฌ +$afterCount = count($existingData['invoices']); + +if ($beforeCount === $afterCount) { + // ์‚ญ์ œํ•  ํ•ญ๋ชฉ์ด ์—†์—ˆ์Œ + error_log("Invoice not found - beforeCount: $beforeCount, afterCount: $afterCount"); + http_response_code(404); + echo json_encode([ + "success" => false, + "error" => "Invoice not found", + "message" => "ํ•ด๋‹น ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์‚ญ์ œ๋˜์—ˆ๊ฑฐ๋‚˜ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ•ญ๋ชฉ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.", + "debug" => [ + "invoiceId" => $invoiceId, + "invoiceIdType" => gettype($invoiceId), + "totalInvoices" => $beforeCount, + "availableIds" => $currentIds + ] + ], JSON_UNESCAPED_UNICODE); + exit; +} + +// ํŒŒ์ผ์— ์ €์žฅ +$jsonData = json_encode($existingData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +$saveResult = @file_put_contents($dataFile, $jsonData); + +if ($saveResult === false) { + http_response_code(500); + echo json_encode([ + "success" => false, + "error" => "Failed to save data" + ], JSON_UNESCAPED_UNICODE); + exit; +} + +echo json_encode([ + "success" => true, + "message" => "Invoice deleted successfully", + "deletedId" => $invoiceId +], JSON_UNESCAPED_UNICODE); +?> + diff --git a/etax/api/deleted_ids.json b/etax/api/deleted_ids.json new file mode 100644 index 0000000..4723510 --- /dev/null +++ b/etax/api/deleted_ids.json @@ -0,0 +1,5 @@ +[ + "inv_001", + "inv_002", + "inv_003" +] \ No newline at end of file diff --git a/etax/api/invoices.php b/etax/api/invoices.php new file mode 100644 index 0000000..89eeabe --- /dev/null +++ b/etax/api/invoices.php @@ -0,0 +1,170 @@ + "inv_001", + "issueKey" => "BARO-2024-001", + "supplierBizno" => "123-45-67890", + "supplierName" => "(์ฃผ)๊ฑด์ถ•์ž์žฌ", + "recipientBizno" => "987-65-43210", + "recipientName" => "๋Œ€๋ฐ• ๊ฑด์„ค(์ฃผ)", + "supplyDate" => "2024-11-01", + "items" => [ + [ + "name" => "์‹œ๋ฉ˜ํŠธ 50kg", + "qty" => 100, + "unitPrice" => 8000, + "supplyAmt" => 800000, + "vat" => 80000, + "vatType" => "vat" + ], + [ + "name" => "์ฒ ๊ทผ 10mm", + "qty" => 50, + "unitPrice" => 12000, + "supplyAmt" => 600000, + "vat" => 60000, + "vatType" => "vat" + ] + ], + "totalSupplyAmt" => 1400000, + "totalVat" => 140000, + "total" => 1540000, + "status" => "sent", + "ntsReceiptNo" => "NTS-2024-001234", + "memo" => "์ •๊ธฐ ๋‚ฉํ’ˆ", + "createdAt" => "2024-11-01T10:30:00", + "sentAt" => "2024-11-01T10:35:00" + ], + [ + "id" => "inv_002", + "issueKey" => "BARO-2024-002", + "supplierBizno" => "123-45-67890", + "supplierName" => "(์ฃผ)๊ฑด์ถ•์ž์žฌ", + "recipientBizno" => "111-22-33333", + "recipientName" => "๊ฐ•๋‚จ ๋ถ€๋™์‚ฐ(์ฃผ)", + "supplyDate" => "2024-11-05", + "items" => [ + [ + "name" => "๋„๋ฐฐ์ง€", + "qty" => 200, + "unitPrice" => 5000, + "supplyAmt" => 1000000, + "vat" => 100000, + "vatType" => "vat" + ] + ], + "totalSupplyAmt" => 1000000, + "totalVat" => 100000, + "total" => 1100000, + "status" => "issued", + "memo" => "", + "createdAt" => "2024-11-05T14:20:00" + ], + [ + "id" => "inv_003", + "issueKey" => "BARO-2024-003", + "supplierBizno" => "123-45-67890", + "supplierName" => "(์ฃผ)๊ฑด์ถ•์ž์žฌ", + "recipientBizno" => "555-66-77777", + "recipientName" => "์„ฑ์ˆ˜ ์ธํ…Œ๋ฆฌ์–ด(์ฃผ)", + "supplyDate" => "2024-11-10", + "items" => [ + [ + "name" => "ํƒ€์ผ 30x30", + "qty" => 500, + "unitPrice" => 3000, + "supplyAmt" => 1500000, + "vat" => 150000, + "vatType" => "vat" + ], + [ + "name" => "์ ‘์ฐฉ์ œ", + "qty" => 20, + "unitPrice" => 15000, + "supplyAmt" => 300000, + "vat" => 30000, + "vatType" => "vat" + ] + ], + "totalSupplyAmt" => 1800000, + "totalVat" => 180000, + "total" => 1980000, + "status" => "sent", + "ntsReceiptNo" => "NTS-2024-001567", + "memo" => "๊ธด๊ธ‰ ๋‚ฉํ’ˆ", + "createdAt" => "2024-11-10T09:15:00", + "sentAt" => "2024-11-10T09:20:00" + ] +]; + +// ์‚ญ์ œ๋œ ID ๋ชฉ๋ก ์ฝ๊ธฐ +$deletedIdsFile = __DIR__ . '/deleted_ids.json'; +$deletedIds = []; +if (file_exists($deletedIdsFile)) { + $deletedContent = file_get_contents($deletedIdsFile); + if ($deletedContent !== false) { + $deletedIds = json_decode($deletedContent, true); + if (!is_array($deletedIds)) { + $deletedIds = []; + } + } +} + +// ๊ธฐ๋ณธ mock ๋ฐ์ดํ„ฐ์—์„œ ์‚ญ์ œ๋œ ํ•ญ๋ชฉ ์ œ์™ธ +$invoices = array_filter($invoices, function($invoice) use ($deletedIds) { + return !in_array($invoice['id'] ?? '', $deletedIds); +}); +$invoices = array_values($invoices); // ์ธ๋ฑ์Šค ์žฌ์ •๋ ฌ + +// ํŒŒ์ผ์—์„œ ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ (์žˆ๋Š” ๊ฒฝ์šฐ) +$dataFile = __DIR__ . '/invoices_data.json'; +if (file_exists($dataFile)) { + $fileContent = file_get_contents($dataFile); + if ($fileContent !== false) { + $savedData = json_decode($fileContent, true); + if (json_last_error() === JSON_ERROR_NONE && isset($savedData['invoices']) && is_array($savedData['invoices']) && count($savedData['invoices']) > 0) { + // ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ์—์„œ๋„ ์‚ญ์ œ๋œ ํ•ญ๋ชฉ ์ œ์™ธ + $savedData['invoices'] = array_filter($savedData['invoices'], function($invoice) use ($deletedIds) { + return !in_array($invoice['id'] ?? '', $deletedIds); + }); + $savedData['invoices'] = array_values($savedData['invoices']); + + // ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์šฐ์„ ํ•˜๊ณ , ๊ธฐ๋ณธ mock ๋ฐ์ดํ„ฐ์™€ ๋ณ‘ํ•ฉ + // ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ตœ์‹ ์ด๋ฏ€๋กœ ๋จผ์ € ๋ฐฐ์น˜ + $invoices = array_merge($savedData['invoices'], $invoices); + // ์ค‘๋ณต ์ œ๊ฑฐ (id ๊ธฐ์ค€) - ๋จผ์ € ๋‚˜์˜จ ๊ฒƒ์ด ์œ ์ง€๋จ (์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์šฐ์„ ) + $uniqueInvoices = []; + $seenIds = []; + foreach ($invoices as $invoice) { + if (!in_array($invoice['id'], $seenIds)) { + $uniqueInvoices[] = $invoice; + $seenIds[] = $invoice['id']; + } + } + $invoices = $uniqueInvoices; + } elseif (json_last_error() !== JSON_ERROR_NONE) { + error_log("invoices_data.json JSON ํŒŒ์‹ฑ ์˜ค๋ฅ˜: " . json_last_error_msg()); + } + } else { + error_log("invoices_data.json ํŒŒ์ผ ์ฝ๊ธฐ ์‹คํŒจ: " . $dataFile); + } +} + +// ์ตœ์‹ ์ˆœ ์ •๋ ฌ +usort($invoices, function($a, $b) { + return strtotime($b['createdAt'] ?? $b['supplyDate']) - strtotime($a['createdAt'] ?? $a['supplyDate']); +}); + +$response = [ + "success" => true, + "invoices" => $invoices, + "count" => count($invoices) +]; + +echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +?> + diff --git a/etax/api/invoices_data.json b/etax/api/invoices_data.json new file mode 100644 index 0000000..a17f63c --- /dev/null +++ b/etax/api/invoices_data.json @@ -0,0 +1,318 @@ +{ + "invoices": [ + { + "id": "inv_1764734934", + "issueKey": "MGT202512031308547398", + "mgtKey": "MGT202512031308547398", + "supplierBizno": "664-86-03713", + "supplierName": "(์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€์—‘์Šค", + "recipientBizno": "843-22-01859", + "recipientName": "์กฐ์€์ง€๊ฒŒ์ฐจ", + "supplyDate": "2025-11-06", + "items": [ + { + "name": "์‹œ๋ฉ˜ํŠธ 50kg", + "qty": 49, + "unitPrice": 37827, + "vatType": "zero", + "supplyAmt": 1853523, + "vat": 0, + "total": 1853523 + }, + { + "name": "์ ‘์ฐฉ์ œ", + "qty": 32, + "unitPrice": 377796, + "vatType": "exempt", + "supplyAmt": 12089472, + "vat": 0, + "total": 12089472 + } + ], + "totalSupplyAmt": 13942995, + "totalVat": 0, + "total": 13942995, + "status": "issued", + "memo": "๊ธด๊ธ‰ ๋‚ฉํ’ˆ", + "createdAt": "2025-12-03T13:08:54", + "barobillInvoiceId": "1" + }, + { + "id": "inv_1764735037", + "issueKey": "MGT202512031310379183", + "mgtKey": "MGT202512031310379183", + "supplierBizno": "664-86-03713", + "supplierName": "(์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€์—‘์Šค", + "recipientBizno": "311-46-00378", + "recipientName": "๊น€์ธํƒœ", + "supplyDate": "2025-11-23", + "items": [ + { + "name": "ํƒ€์ผ 30x30", + "qty": 19, + "unitPrice": 152719, + "vatType": "exempt", + "supplyAmt": 2901661, + "vat": 0, + "total": 2901661 + }, + { + "name": "์š•์กฐ", + "qty": 48, + "unitPrice": 202442, + "vatType": "exempt", + "supplyAmt": 9717216, + "vat": 0, + "total": 9717216 + } + ], + "totalSupplyAmt": 12618877, + "totalVat": 0, + "total": 12618877, + "status": "issued", + "memo": "์ƒ˜ํ”Œ ๋‚ฉํ’ˆ", + "createdAt": "2025-12-03T13:10:37", + "barobillInvoiceId": "1" + }, + { + "id": "inv_1765062685", + "issueKey": "MGT202512070811254622", + "mgtKey": "MGT202512070811254622", + "supplierBizno": "664-86-03713", + "supplierName": "(์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€์—‘์Šค", + "recipientBizno": "406-05-25709", + "recipientName": "์Šค์นด์ด์ต์Šคํ”„๋ ˆ์Šค", + "supplyDate": "2025-11-09", + "items": [ + { + "name": "๋ฐฐ๊ด€์ž์žฌ", + "qty": 82, + "unitPrice": 283655, + "vatType": "vat", + "supplyAmt": 23259710, + "vat": 2325971, + "total": 25585681 + }, + { + "name": "๋ชฉ์žฌ ํ•ฉํŒ", + "qty": 97, + "unitPrice": 196766, + "vatType": "vat", + "supplyAmt": 19086302, + "vat": 1908630, + "total": 20994932 + }, + { + "name": "์œ ๋ฆฌ 5mm", + "qty": 51, + "unitPrice": 240496, + "vatType": "vat", + "supplyAmt": 12265296, + "vat": 1226529, + "total": 13491825 + } + ], + "totalSupplyAmt": 54611308, + "totalVat": 5461130, + "total": 60072438, + "status": "issued", + "memo": "๊ณ„์•ฝ ๋‚ฉํ’ˆ", + "createdAt": "2025-12-07T08:11:25", + "barobillInvoiceId": "1" + }, + { + "id": "inv_1765114676", + "issueKey": "MGT202512072237565827", + "mgtKey": "MGT202512072237565827", + "supplierBizno": "664-86-03713", + "supplierName": "(์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€์—‘์Šค", + "recipientBizno": "107-81-78114", + "recipientName": "(์ฃผ)์ด์ƒ๋„คํŠธ์›์Šค", + "supplyDate": "2025-11-14", + "items": [ + { + "name": "๋ฐฐ๊ด€์ž์žฌ", + "qty": 6, + "unitPrice": 238878, + "vatType": "vat", + "supplyAmt": 1433268, + "vat": 143326, + "total": 1576594 + }, + { + "name": "์ ‘์ฐฉ์ œ", + "qty": 79, + "unitPrice": 313735, + "vatType": "vat", + "supplyAmt": 24785065, + "vat": 2478506, + "total": 27263571 + }, + { + "name": "๋ณ€๊ธฐ", + "qty": 80, + "unitPrice": 441883, + "vatType": "vat", + "supplyAmt": 35350640, + "vat": 3535064, + "total": 38885704 + } + ], + "totalSupplyAmt": 61568973, + "totalVat": 6156896, + "total": 67725869, + "status": "issued", + "memo": "๋ณด์ˆ˜ ๋‚ฉํ’ˆ", + "createdAt": "2025-12-07T22:37:56", + "barobillInvoiceId": "1" + }, + { + "id": "inv_1765114749", + "issueKey": "MGT202512072239096510", + "mgtKey": "MGT202512072239096510", + "supplierBizno": "664-86-03713", + "supplierName": "(์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€์—‘์Šค", + "recipientBizno": "843-22-01859", + "recipientName": "์กฐ์€์ง€๊ฒŒ์ฐจ", + "supplyDate": "2025-11-24", + "items": [ + { + "name": "์œ ๋ฆฌ 5mm", + "qty": 91, + "unitPrice": 409294, + "vatType": "vat", + "supplyAmt": 37245754, + "vat": 3724575, + "total": 40970329 + }, + { + "name": "์ ‘์ฐฉ์ œ", + "qty": 39, + "unitPrice": 320606, + "vatType": "vat", + "supplyAmt": 12503634, + "vat": 1250363, + "total": 13753997 + }, + { + "name": "๋ณ€๊ธฐ", + "qty": 33, + "unitPrice": 140978, + "vatType": "vat", + "supplyAmt": 4652274, + "vat": 465227, + "total": 5117501 + } + ], + "totalSupplyAmt": 54401662, + "totalVat": 5440165, + "total": 59841827, + "status": "issued", + "memo": "์ •๊ธฐ ๋‚ฉํ’ˆ", + "createdAt": "2025-12-07T22:39:09", + "barobillInvoiceId": "1" + }, + { + "id": "inv_1765120032", + "issueKey": "MGT202512080007129289", + "mgtKey": "MGT202512080007129289", + "supplierBizno": "664-86-03713", + "supplierName": "(์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€์—‘์Šค", + "recipientBizno": "107-81-78114", + "recipientName": "(์ฃผ)์ด์ƒ๋„คํŠธ์›์Šค", + "supplyDate": "2025-11-13", + "items": [ + { + "name": "์œ ๋ฆฌ 5mm", + "qty": 90, + "unitPrice": 122746, + "vatType": "vat", + "supplyAmt": 11047140, + "vat": 1104714, + "total": 12151854 + } + ], + "totalSupplyAmt": 11047140, + "totalVat": 1104714, + "total": 12151854, + "status": "issued", + "memo": "๋ณด์ˆ˜ ๋‚ฉํ’ˆ", + "createdAt": "2025-12-08T00:07:12", + "barobillInvoiceId": "1" + }, + { + "id": "inv_1768349618", + "issueKey": "MGT202601140913384780", + "mgtKey": "MGT202601140913384780", + "supplierBizno": "664-86-03713", + "supplierName": "(์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€์—‘์Šค", + "recipientBizno": "107-81-78114", + "recipientName": "(์ฃผ)์ด์ƒ๋„คํŠธ์›์Šค", + "supplyDate": "2026-01-10", + "items": [ + { + "name": "ํŽ˜์ธํŠธ 18L", + "qty": 79, + "unitPrice": 90747, + "vatType": "vat", + "supplyAmt": 7169013, + "vat": 716901, + "total": 7885914 + }, + { + "name": "์ ‘์ฐฉ์ œ", + "qty": 67, + "unitPrice": 162463, + "vatType": "vat", + "supplyAmt": 10885021, + "vat": 1088502, + "total": 11973523 + }, + { + "name": "์กฐ๋ช…๊ธฐ๊ตฌ", + "qty": 25, + "unitPrice": 408336, + "vatType": "vat", + "supplyAmt": 10208400, + "vat": 1020840, + "total": 11229240 + } + ], + "totalSupplyAmt": 28262434, + "totalVat": 2826243, + "total": 31088677, + "status": "issued", + "memo": "๊ต์ฒด ๋‚ฉํ’ˆ", + "createdAt": "2026-01-14T09:13:38", + "barobillInvoiceId": "1" + }, + { + "id": "inv_1768349638", + "issueKey": "MGT202601140913583219", + "mgtKey": "MGT202601140913583219", + "supplierBizno": "664-86-03713", + "supplierName": "(์ฃผ)์ฝ”๋“œ๋ธŒ๋ฆฟ์ง€์—‘์Šค", + "recipientBizno": "311-46-00378", + "recipientName": "๊น€์ธํƒœ", + "supplyDate": "2026-01-14", + "items": [ + { + "name": "๋ณ€๊ธฐ", + "qty": 68, + "unitPrice": 136303, + "vatType": "vat", + "supplyAmt": 9268604, + "vat": 926860, + "total": 10195464 + } + ], + "totalSupplyAmt": 9268604, + "totalVat": 926860, + "total": 10195464, + "status": "issued", + "memo": "A\/S ๋‚ฉํ’ˆ", + "createdAt": "2026-01-14T09:13:58", + "barobillInvoiceId": "1" + } + ] +} \ No newline at end of file diff --git a/etax/api/issue.php b/etax/api/issue.php new file mode 100644 index 0000000..e576dc7 --- /dev/null +++ b/etax/api/issue.php @@ -0,0 +1,226 @@ + false, + "error" => "Invalid request data" + ], JSON_UNESCAPED_UNICODE); + exit; +} + +// ๋ฐ”๋กœ๋นŒ API ํ˜ธ์ถœ ๋˜๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜ +// ํ…Œ์ŠคํŠธ ๋ชจ๋“œ: SOAP ํด๋ผ์ด์–ธํŠธ๋งŒ ์žˆ์œผ๋ฉด ์‹ค์ œ API ํ˜ธ์ถœ ์‹œ๋„ (CERTKEY๋Š” ์„ ํƒ์‚ฌํ•ญ) +// ์šด์˜ ๋ชจ๋“œ: SOAP ํด๋ผ์ด์–ธํŠธ์™€ CERTKEY ๋ชจ๋‘ ํ•„์š” +$useRealAPI = !empty($barobillSoapClient) && ($isTestMode || !empty($barobillCertKey)); + +// ๋””๋ฒ„๊น… ์ •๋ณด: ์‹ค์ œ API ํ˜ธ์ถœ ์—ฌ๋ถ€ ํ™•์ธ +$debugInfo = [ + 'hasSoapClient' => !empty($barobillSoapClient), + 'hasCertKey' => !empty($barobillCertKey), + 'hasCorpNum' => !empty($barobillCorpNum), + 'isTestMode' => $isTestMode ?? false, + 'soapUrl' => $barobillSoapUrl ?? null, + 'willUseRealAPI' => $useRealAPI +]; + +if ($useRealAPI) { + // ์‹ค์ œ ๋ฐ”๋กœ๋นŒ SOAP API ํ˜ธ์ถœ + $apiResult = issueTaxInvoice($input); + + if ($apiResult['success']) { + $apiData = $apiResult['data']; + + // SOAP ์‘๋‹ต์—์„œ MgtKey ์ถ”์ถœ (RegistAndIssueTaxInvoice๋Š” MgtKey๋ฅผ ๋ฐ˜ํ™˜) + // ์‘๋‹ต์ด ์ˆซ์ž(์–‘์ˆ˜)๋ฉด ์„ฑ๊ณต, ๊ทธ ๊ฐ’์ด ๋ฐ”๋กœ๋นŒ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ID์ผ ์ˆ˜ ์žˆ์Œ + // ๋˜๋Š” ๊ฐ์ฒด์ผ ๊ฒฝ์šฐ MgtKey ์†์„ฑ ํ™•์ธ + $mgtKey = ''; + if (is_object($apiData) && isset($apiData->MgtKey)) { + $mgtKey = $apiData->MgtKey; + } elseif (is_array($apiData) && isset($apiData['MgtKey'])) { + $mgtKey = $apiData['MgtKey']; + } else { + // MgtKey๊ฐ€ ์—†์œผ๋ฉด ์ž…๋ ฅ์—์„œ ์ƒ์„ฑํ•œ ํ‚ค ์‚ฌ์šฉ + $mgtKey = $input['issueKey'] ?? 'MGT' . date('YmdHis') . rand(1000, 9999); + } + + // ์ƒˆ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ + $newInvoice = [ + "id" => "inv_" . time(), + "issueKey" => $mgtKey, // MgtKey๋ฅผ issueKey๋กœ ์‚ฌ์šฉ + "mgtKey" => $mgtKey, // ๋ฐ”๋กœ๋นŒ ๊ด€๋ฆฌ๋ฒˆํ˜ธ + "supplierBizno" => $input['supplierBizno'] ?? '', + "supplierName" => $input['supplierName'] ?? '', + "recipientBizno" => $input['recipientBizno'] ?? '', + "recipientName" => $input['recipientName'] ?? '', + "supplyDate" => $input['supplyDate'] ?? date('Y-m-d'), + "items" => $input['items'] ?? [], + "totalSupplyAmt" => $input['totalSupplyAmt'] ?? 0, + "totalVat" => $input['totalVat'] ?? 0, + "total" => $input['total'] ?? 0, + "status" => "issued", + "memo" => $input['memo'] ?? '', + "createdAt" => date('Y-m-d\TH:i:s'), + "barobillInvoiceId" => is_numeric($apiData) ? (string)$apiData : ($apiData->InvoiceID ?? '') + ]; + + // ํŒŒ์ผ์— ์ €์žฅ + $dataFile = __DIR__ . '/invoices_data.json'; + $existingData = []; + if (file_exists($dataFile)) { + $fileContent = file_get_contents($dataFile); + if ($fileContent !== false) { + $existingData = json_decode($fileContent, true); + if (!is_array($existingData)) { + $existingData = []; + } + } + } + + if (!isset($existingData['invoices'])) { + $existingData['invoices'] = []; + } + + $existingData['invoices'][] = $newInvoice; + + // ์ตœ๋Œ€ 100๊ฐœ๊นŒ์ง€๋งŒ ์ €์žฅ + if (count($existingData['invoices']) > 100) { + $existingData['invoices'] = array_slice($existingData['invoices'], -100); + } + + // ํŒŒ์ผ ์ €์žฅ ์‹œ๋„ ๋ฐ ์—๋Ÿฌ ํ™•์ธ + $jsonData = json_encode($existingData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + $saveResult = @file_put_contents($dataFile, $jsonData); + $saveSuccess = ($saveResult !== false); + + if (!$saveSuccess) { + $errorMsg = "ํŒŒ์ผ ์ €์žฅ ์‹คํŒจ: " . $dataFile; + if (!is_writable(dirname($dataFile))) { + $errorMsg .= " (๋””๋ ‰ํ† ๋ฆฌ ์“ฐ๊ธฐ ๊ถŒํ•œ ์—†์Œ)"; + } elseif (!is_writable($dataFile) && file_exists($dataFile)) { + $errorMsg .= " (ํŒŒ์ผ ์“ฐ๊ธฐ ๊ถŒํ•œ ์—†์Œ)"; + } + error_log("์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ €์žฅ ์‹คํŒจ: " . $errorMsg); + } + + $response = [ + "success" => true, + "message" => "์„ธ๊ธˆ๊ณ„์‚ฐ์„œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋ฐœํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", + "data" => [ + "issueKey" => $newInvoice['issueKey'], + "mgtKey" => $newInvoice['mgtKey'], + "barobillInvoiceId" => $newInvoice['barobillInvoiceId'], + "status" => "issued", + "issuedAt" => $newInvoice['createdAt'] + ], + "invoice" => $newInvoice, + "api_response" => $apiData, + "soap_request" => $apiResult['soap_request'] ?? null, + "soap_response" => $apiResult['soap_response'] ?? null, + "saved" => $saveSuccess, + "dataFile" => $saveSuccess ? null : $dataFile, + "simulation" => false, + "debug" => $debugInfo, + "note" => "โœ… ์‹ค์ œ ๋ฐ”๋กœ๋นŒ API๋ฅผ ํ˜ธ์ถœํ–ˆ์Šต๋‹ˆ๋‹ค." + ]; + } else { + $response = [ + "success" => false, + "error" => $apiResult['error'] ?? "API ํ˜ธ์ถœ ์‹คํŒจ", + "error_code" => $apiResult['error_code'] ?? null, + "error_detail" => $apiResult['error_detail'] ?? null, + "soap_request" => $apiResult['soap_request'] ?? null, + "soap_response" => $apiResult['soap_response'] ?? null + ]; + } +} else { + // ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ (API ํ‚ค๊ฐ€ ์—†์„ ๋•Œ) + $issueKey = "BARO-" . date('Y') . "-" . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT); + + $newInvoice = [ + "id" => "inv_" . time(), + "issueKey" => $issueKey, + "supplierBizno" => $input['supplierBizno'] ?? '', + "supplierName" => $input['supplierName'] ?? '', + "recipientBizno" => $input['recipientBizno'] ?? '', + "recipientName" => $input['recipientName'] ?? '', + "supplyDate" => $input['supplyDate'] ?? date('Y-m-d'), + "items" => $input['items'] ?? [], + "totalSupplyAmt" => $input['totalSupplyAmt'] ?? 0, + "totalVat" => $input['totalVat'] ?? 0, + "total" => $input['total'] ?? 0, + "status" => "issued", + "memo" => $input['memo'] ?? '', + "createdAt" => date('Y-m-d\TH:i:s'), + "barobillInvoiceId" => "BB-" . uniqid() + ]; + + // ํŒŒ์ผ์— ์ €์žฅ + $dataFile = __DIR__ . '/invoices_data.json'; + $existingData = []; + if (file_exists($dataFile)) { + $fileContent = file_get_contents($dataFile); + if ($fileContent !== false) { + $existingData = json_decode($fileContent, true); + if (!is_array($existingData)) { + $existingData = []; + } + } + } + + if (!isset($existingData['invoices'])) { + $existingData['invoices'] = []; + } + + $existingData['invoices'][] = $newInvoice; + + if (count($existingData['invoices']) > 100) { + $existingData['invoices'] = array_slice($existingData['invoices'], -100); + } + + // ํŒŒ์ผ ์ €์žฅ ์‹œ๋„ ๋ฐ ์—๋Ÿฌ ํ™•์ธ + $jsonData = json_encode($existingData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + $saveResult = @file_put_contents($dataFile, $jsonData); + $saveSuccess = ($saveResult !== false); + + if (!$saveSuccess) { + $errorMsg = "ํŒŒ์ผ ์ €์žฅ ์‹คํŒจ: " . $dataFile; + if (!is_writable(dirname($dataFile))) { + $errorMsg .= " (๋””๋ ‰ํ† ๋ฆฌ ์“ฐ๊ธฐ ๊ถŒํ•œ ์—†์Œ)"; + } elseif (!is_writable($dataFile) && file_exists($dataFile)) { + $errorMsg .= " (ํŒŒ์ผ ์“ฐ๊ธฐ ๊ถŒํ•œ ์—†์Œ)"; + } + error_log("์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ €์žฅ ์‹คํŒจ: " . $errorMsg); + } + + $response = [ + "success" => true, + "message" => "์„ธ๊ธˆ๊ณ„์‚ฐ์„œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋ฐœํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ)", + "data" => [ + "issueKey" => $issueKey, + "barobillInvoiceId" => $newInvoice['barobillInvoiceId'], + "status" => "issued", + "issuedAt" => $newInvoice['createdAt'] + ], + "invoice" => $newInvoice, + "simulation" => true, + "saved" => $saveSuccess, + "dataFile" => $saveSuccess ? null : $dataFile, + "debug" => $debugInfo, + "warning" => "โš ๏ธ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ๋ฐ”๋กœ๋นŒ API๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๋ฉด CERTKEY๋ฅผ ์„ค์ •ํ•˜์„ธ์š”." + ]; + + usleep(500000); // 0.5์ดˆ ์ง€์—ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ +} + +echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +?> + diff --git a/etax/api/status.php b/etax/api/status.php new file mode 100644 index 0000000..cd8e935 --- /dev/null +++ b/etax/api/status.php @@ -0,0 +1,168 @@ + false, + "error" => "Invoice ID is required" + ], JSON_UNESCAPED_UNICODE); + exit; +} + +$invoiceId = $input['invoiceId']; +// SOAP ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์—ˆ๊ณ  CERTKEY๊ฐ€ ์žˆ์œผ๋ฉด ์‹ค์ œ API ํ˜ธ์ถœ +$useRealAPI = !empty($barobillSoapClient) && !empty($barobillCertKey); + +// ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ +$dataFile = __DIR__ . '/invoices_data.json'; +$existingData = []; +if (file_exists($dataFile)) { + $existingData = json_decode(file_get_contents($dataFile), true); + if (!is_array($existingData)) { + $existingData = []; + } +} + +// ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ์—์„œ๋„ ์ฐพ๊ธฐ +$defaultInvoices = [ + [ + "id" => "inv_001", + "issueKey" => "BARO-2024-001", + "status" => "sent" + ], + [ + "id" => "inv_002", + "issueKey" => "BARO-2024-002", + "status" => "issued" + ], + [ + "id" => "inv_003", + "issueKey" => "BARO-2024-003", + "status" => "sent" + ] +]; + +$allInvoices = array_merge($defaultInvoices, $existingData['invoices'] ?? []); + +// ํ•ด๋‹น ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ฐพ๊ธฐ +$invoice = null; +foreach ($allInvoices as $inv) { + if ($inv['id'] === $invoiceId) { + $invoice = $inv; + break; + } +} + +if (!$invoice) { + http_response_code(404); + echo json_encode([ + "success" => false, + "error" => "Invoice not found" + ], JSON_UNESCAPED_UNICODE); + exit; +} + +if ($useRealAPI && isset($invoice['issueKey'])) { + // ์‹ค์ œ ๋ฐ”๋กœ๋นŒ SOAP API ํ˜ธ์ถœ - ๊ตญ์„ธ์ฒญ ์ „์†ก + // issueKey๋ฅผ MgtKey๋กœ ์‚ฌ์šฉ + $mgtKey = $invoice['mgtKey'] ?? $invoice['issueKey']; + $apiResult = sendToNTS($mgtKey); + + if ($apiResult['success']) { + $apiData = $apiResult['data']; + + // SOAP ์‘๋‹ต์—์„œ NTS ์ ‘์ˆ˜๋ฒˆํ˜ธ ์ถ”์ถœ + $ntsReceiptNo = ''; + if (is_object($apiData) && isset($apiData->NTSConfirmNum)) { + $ntsReceiptNo = $apiData->NTSConfirmNum; + } elseif (is_array($apiData) && isset($apiData['NTSConfirmNum'])) { + $ntsReceiptNo = $apiData['NTSConfirmNum']; + } + + // ์ƒํƒœ ์—…๋ฐ์ดํŠธ + $invoice['status'] = 'sent'; + $invoice['ntsReceiptNo'] = $ntsReceiptNo; + $invoice['sentAt'] = date('Y-m-d\TH:i:s'); + + // ํŒŒ์ผ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ + if (isset($existingData['invoices'])) { + foreach ($existingData['invoices'] as &$inv) { + if ($inv['id'] === $invoiceId) { + $inv = $invoice; + break; + } + } + file_put_contents($dataFile, json_encode($existingData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + } + + $response = [ + "success" => true, + "message" => "๊ตญ์„ธ์ฒญ ์ „์†ก์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", + "data" => [ + "issueKey" => $invoice['issueKey'] ?? '', + "mgtKey" => $mgtKey, + "ntsReceiptNo" => $invoice['ntsReceiptNo'], + "status" => "sent", + "sentAt" => $invoice['sentAt'] + ], + "invoice" => $invoice, + "api_response" => $apiData, + "soap_request" => $apiResult['soap_request'] ?? null, + "soap_response" => $apiResult['soap_response'] ?? null + ]; + } else { + $response = [ + "success" => false, + "error" => $apiResult['error'] ?? "API ํ˜ธ์ถœ ์‹คํŒจ", + "error_code" => $apiResult['error_code'] ?? null, + "error_detail" => $apiResult['error_detail'] ?? null, + "soap_request" => $apiResult['soap_request'] ?? null, + "soap_response" => $apiResult['soap_response'] ?? null + ]; + } +} else { + // ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ + $ntsReceiptNo = "NTS-" . date('Y') . "-" . str_pad(rand(100000, 999999), 6, '0', STR_PAD_LEFT); + + $invoice['status'] = 'sent'; + $invoice['ntsReceiptNo'] = $ntsReceiptNo; + $invoice['sentAt'] = date('Y-m-d\TH:i:s'); + + // ํŒŒ์ผ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ + if (isset($existingData['invoices'])) { + foreach ($existingData['invoices'] as &$inv) { + if ($inv['id'] === $invoiceId) { + $inv = $invoice; + break; + } + } + file_put_contents($dataFile, json_encode($existingData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + } + + usleep(800000); // 0.8์ดˆ ์ง€์—ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ + + $response = [ + "success" => true, + "message" => "๊ตญ์„ธ์ฒญ ์ „์†ก์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ)", + "data" => [ + "issueKey" => $invoice['issueKey'] ?? '', + "ntsReceiptNo" => $ntsReceiptNo, + "status" => "sent", + "sentAt" => $invoice['sentAt'] + ], + "invoice" => $invoice, + "simulation" => true + ]; +} + +echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +?> + diff --git a/etax/barobill_api_info.php b/etax/barobill_api_info.php new file mode 100644 index 0000000..762f2ad --- /dev/null +++ b/etax/barobill_api_info.php @@ -0,0 +1,433 @@ +load(); +require_once(getenv('DOCUMENT_ROOT') . "/session.php"); +?> + + + + + + ๋ฐ”๋กœ๋นŒ API ์ •๋ณด + + + + + + ๐Ÿ  + ํ™ˆ์œผ๋กœ + + +
+
+

๐Ÿ“‹ ๋ฐ”๋กœ๋นŒ API ์ •๋ณด

+

์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์†”๋ฃจ์…˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ๋ฐ”๋กœ๋นŒ API ๊ฐ€์ด๋“œ

+
+ + +
+

1. ๋ฐ”๋กœ๋นŒ ๊ฐœ์š”

+
+

๋ฐ”๋กœ๋นŒ์€ ๊ธฐ์—…์˜ ์žฌ๋ฌดํšŒ๊ณ„ ๋””์ง€ํ„ธ ์ „ํ™˜์„ ์ง€์›ํ•˜๋Š” Fin-tech ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค.

+

๋‹ค์–‘ํ•œ ์ „์ž๋ฌธ์„œ ๋ฐœํ–‰ ๋ฐ ๊ด€๋ฆฌ API๋ฅผ ์ œ๊ณตํ•˜์—ฌ ๊ธฐ์—…์˜ ์—…๋ฌด ์ž๋™ํ™”๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

+
+

๊ฐœ๋ฐœ์ž์„ผํ„ฐ URL: https://dev.barobill.co.kr

+
+ + +
+

2. ์ฃผ์š” API ์„œ๋น„์Šค

+ +

2.1 ์ „์ž๋ฌธ์„œ API

+

์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ, ๊ฑฐ๋ž˜๋ช…์„ธ์„œ, ์ฒญ๊ตฌ์„œ, ๊ฒฌ์ ์„œ ๋“ฑ ๋‹ค์–‘ํ•œ ์ „์ž๋ฌธ์„œ์˜ ๋ฐœํ–‰ ๋ฐ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

+
    +
  • ์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰: ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰ ๋ฐ ๊ตญ์„ธ์ฒญ ์ „์†ก
  • +
  • ์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ทจ์†Œ: ๋ฐœํ–‰๋œ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ทจ์†Œ
  • +
  • ์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์กฐํšŒ: ๋ฐœํ–‰ ๋‚ด์—ญ ๋ฐ ์ƒํƒœ ์กฐํšŒ
  • +
  • ๊ฑฐ๋ž˜๋ช…์„ธ์„œ ๋ฐœํ–‰: ๊ฑฐ๋ž˜๋ช…์„ธ์„œ ๋ฐœํ–‰ ๋ฐ ๊ด€๋ฆฌ
  • +
  • ์ฒญ๊ตฌ์„œ/๊ฒฌ์ ์„œ ๋ฐœํ–‰: ๋‹ค์–‘ํ•œ ์ „์ž๋ฌธ์„œ ๋ฐœํ–‰
  • +
+

์ „์ž๋ฌธ์„œ API ์ƒ์„ธ๋ณด๊ธฐ

+ +

2.2 ๋ฉ”์‹œ์ง• API

+

SMS, LMS, MMS ๋“ฑ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ์˜ ๋ฌธ์ž ์ „์†ก ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

+
    +
  • ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰ ์•Œ๋ฆผ
  • +
  • ์ธ์ฆ์„œ ๋งŒ๋ฃŒ ์•Œ๋ฆผ
  • +
  • ์‹œ์Šคํ…œ ์•Œ๋ฆผ
  • +
+

๋ฉ”์‹œ์ง• API ์ƒ์„ธ๋ณด๊ธฐ

+ +

2.3 ํŒฉ์Šค ์ „์†ก API

+

HWP, DOC, XLS, PDF ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฌธ์„œ ํŒŒ์ผ์˜ ํŒฉ์Šค ์ „์†ก ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

+

ํŒฉ์Šค API ์ƒ์„ธ๋ณด๊ธฐ

+
+ + +
+

3. ์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ API ์ƒ์„ธ

+ +

3.1 ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ

+
+

โš ๏ธ ์ค‘์š”: ์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰์„ ์œ„ํ•ด์„œ๋Š” ๊ณต๋™์ธ์ฆ์„œ ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

+
+
    +
  • ๊ณต๋™์ธ์ฆ์„œ ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ ๋“ฑ๋ก
  • +
  • ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ ํšŒ์›๊ฐ€์ž…
  • +
  • API ํ‚ค ๋ฐœ๊ธ‰
  • +
  • ์ธ์ฆ์„œ ๋“ฑ๋ก ๋ฐ ์—ฐ๋™
  • +
+ +

3.2 ์ฃผ์š” API ๊ธฐ๋Šฅ

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
๊ธฐ๋Šฅ์„ค๋ช…ํ•„์ˆ˜ ์ •๋ณด
์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ๋ฐœํ–‰ ๋ฐ ๊ตญ์„ธ์ฒญ ์ „์†ก๊ณต๊ธ‰์ž/์ˆ˜์ทจ์ž ์ •๋ณด, ํ’ˆ๋ชฉ ์ •๋ณด, ๊ธˆ์•ก ์ •๋ณด
์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ทจ์†Œ๋ฐœํ–‰๋œ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์ทจ์†Œ๋ฐœํ–‰ ํ‚ค, ์ทจ์†Œ ์‚ฌ์œ 
์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์กฐํšŒ๋ฐœํ–‰ ๋‚ด์—ญ ๋ฐ ์ƒํƒœ ์กฐํšŒ๋ฐœํ–‰ ํ‚ค ๋˜๋Š” ๊ฒ€์ƒ‰ ์กฐ๊ฑด
๊ตญ์„ธ์ฒญ ์ „์†ก๋ฐœํ–‰๋œ ์„ธ๊ธˆ๊ณ„์‚ฐ์„œ๋ฅผ ๊ตญ์„ธ์ฒญ์œผ๋กœ ์ „์†ก๋ฐœํ–‰ ํ‚ค
์ „์†ก ์ƒํƒœ ํ™•์ธ๊ตญ์„ธ์ฒญ ์ „์†ก ์ƒํƒœ ๋ฐ ์ ‘์ˆ˜๋ฒˆํ˜ธ ํ™•์ธ๋ฐœํ–‰ ํ‚ค
+ +

3.3 API ์š”์ฒญ ์˜ˆ์‹œ (์˜ˆ์ƒ)

+
+ POST /api/taxinvoice/issue +
+

Headers:

+
+Authorization: Bearer {API_KEY}
+Content-Type: application/json +
+

Request Body (์˜ˆ์ƒ):

+
+{
+  "certId": "์ธ์ฆ์„œID",
+  "supplier": {
+    "bizno": "์‚ฌ์—…์ž๋ฒˆํ˜ธ",
+    "corpName": "์ƒํ˜ธ",
+    "ceo": "๋Œ€ํ‘œ์ž๋ช…"
+  },
+  "recipient": { ... },
+  "items": [ ... ],
+  "writeDate": "2024-01-01",
+  "supplyDate": "2024-01-01"
+} +
+
+ + +
+

4. ๊ฐœ๋ฐœ์ž ์ง€์›

+
    +
  • ๊ฐœ๋ฐœ ๊ฐ€์ด๋“œ: ์ƒ์„ธํ•œ API ๋ฌธ์„œ ๋ฐ ๊ฐ€์ด๋“œ ์ œ๊ณต
  • +
  • ์ƒ˜ํ”Œ ์ฝ”๋“œ: Java, Python, PHP, .NET ๋“ฑ ๋‹ค์–‘ํ•œ ์–ธ์–ด ์ง€์›
  • +
  • ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ: ์‹ค์ œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ๊ณผ ๋™์ผํ•œ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ์ œ๊ณต
  • +
  • ์ „๋‹ด ์—”์ง€๋‹ˆ์–ด ์ง€์›: ๊ฐœ๋ฐœ ์ƒ๋‹ด ๋ฐ ๊ธฐ์ˆ  ์ง€์› ์ œ๊ณต
  • +
+

๊ฐœ๋ฐœ์ž์„ผํ„ฐ ๋ฐ”๋กœ๊ฐ€๊ธฐ

+
+ + +
+

5. API ์—ฐ๋™ ์ ˆ์ฐจ

+
    +
  1. ํšŒ์›๊ฐ€์ž…: ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ ํšŒ์›๊ฐ€์ž…
  2. +
  3. API ํ‚ค ๋ฐœ๊ธ‰: ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์—์„œ API ํ‚ค ๋ฐœ๊ธ‰
  4. +
  5. ์ธ์ฆ์„œ ๋“ฑ๋ก: ๊ณต๋™์ธ์ฆ์„œ ๋˜๋Š” ๊ธˆ์œต์ธ์ฆ์„œ ๋“ฑ๋ก
  6. +
  7. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ์„ค์ •: ๋ฐ”๋กœ๋นŒ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ์—ฐ๋™ ํ…Œ์ŠคํŠธ
  8. +
  9. ๊ฐœ๋ฐœ ๋ฐ ์—ฐ๋™: API ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์—ฐ๋™ ๋ฐ ๊ฐœ๋ฐœ ์ง„ํ–‰
  10. +
  11. ํ”„๋กœ๋•์…˜ ์—ฐ๋™: ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ ๊ตฌ์ถ• ํ›„ ์„œ๋น„์Šค ์˜คํ”ˆ
  12. +
+
+ + +
+

6. ์š”๊ธˆ ์•ˆ๋‚ด

+
+

๋ฐ”๋กœ๋นŒ์€ ํŒŒํŠธ๋„ˆ ์œ ํ˜•์— ๋”ฐ๋ผ ํ• ์ธํ˜•๊ณผ ์ˆ˜์ตํ˜•์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์—ฐ๋™ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

+

์ž์„ธํ•œ ์š”๊ธˆ ์•ˆ๋‚ด๋Š” ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ์˜ ํŒŒํŠธ๋„ˆ/์š”๊ธˆ ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

+
+

์š”๊ธˆ ์•ˆ๋‚ด ๋ณด๊ธฐ

+
+ + +
+

7. ์ง€์› ์–ธ์–ด

+

๋ฐ”๋กœ๋นŒ API๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐœ๋ฐœ ์–ธ์–ด๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:

+
    +
  • Java
  • +
  • Python
  • +
  • PHP
  • +
  • .NET (C#)
  • +
  • ๊ธฐํƒ€ REST API๋ฅผ ์ง€์›ํ•˜๋Š” ๋ชจ๋“  ์–ธ์–ด
  • +
+
+ + +
+

8. ๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ

+
+

โš ๏ธ ๋ณด์•ˆ ์ฃผ์˜์‚ฌํ•ญ:

+
    +
  • API ํ‚ค๋Š” ์ ˆ๋Œ€ ๊ณต๊ฐœ๋˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•˜์„ธ์š”.
  • +
  • ์ธ์ฆ์„œ๋Š” ์•”ํ˜ธํ™”ํ•˜์—ฌ ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅํ•˜์„ธ์š”.
  • +
  • HTTPS๋ฅผ ํ†ตํ•ด์„œ๋งŒ API๋ฅผ ํ˜ธ์ถœํ•˜์„ธ์š”.
  • +
  • ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ๋กœ๊ทธ์— ๊ธฐ๋กํ•˜์ง€ ๋งˆ์„ธ์š”.
  • +
+
+
+ + + + + +
+

10. ๋‹ค์Œ ๋‹จ๊ณ„

+
    +
  1. ๋ฐ”๋กœ๋นŒ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ ํšŒ์›๊ฐ€์ž… ๋ฐ API ํ‚ค ๋ฐœ๊ธ‰
  2. +
  3. ๊ฐœ๋ฐœ ๊ฐ€์ด๋“œ ๋ฐ ์ƒ˜ํ”Œ ์ฝ”๋“œ ๋‹ค์šด๋กœ๋“œ
  4. +
  5. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ API ์—ฐ๋™ ํ…Œ์ŠคํŠธ
  6. +
  7. ์ธ์ฆ์„œ ๋“ฑ๋ก ๋ฐ ์—ฐ๋™
  8. +
  9. ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ํ†ตํ•ฉ
  10. +
+

์ „๋žต ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ธฐ

+
+
+ + + diff --git a/etax/dev.md b/etax/dev.md new file mode 100644 index 0000000..8669ca5 --- /dev/null +++ b/etax/dev.md @@ -0,0 +1,27 @@ +# Etax ๊ฐœ๋ฐœ ๋…ธํŠธ + +## API ์˜ค๋ฅ˜ ํ•ด๊ฒฐ ๊ฐ€์ด๋“œ + +### ๋ฐ”๋กœ๋นŒ SOAP ํด๋ผ์ด์–ธํŠธ ๋ฏธ์„ค์น˜ ์˜ค๋ฅ˜ (500 Error) + +**๋ฌธ์ œ ์ƒํ™ฉ:** +์„œ๋ฒ„์— PHP SOAP ํ™•์žฅ ๋ชจ๋“ˆ์ด ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š์€ ๊ฒฝ์šฐ(`Class 'SoapClient' not found`), `new SoapClient()` ํ˜ธ์ถœ ์‹œ ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜(Fatal Error)๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ HTTP 500 ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. + +**ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:** +`soapClient` ์ƒ์„ฑ ๋กœ์ง์„ `try-catch` ๋ธ”๋ก์œผ๋กœ ๊ฐ์‹ธ๋˜, `Exception`์ด ์•„๋‹Œ **`Throwable`**์„ catchํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. PHP 7+์—์„œ๋Š” ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜๊ฐ€ `Error` ๊ฐ์ฒด๋กœ ๋˜์ ธ์ง€๋ฉฐ, ์ด๋Š” `Exception`์ด ์•„๋‹Œ `Throwable` ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. + +**์ˆ˜์ • ์˜ˆ์‹œ:** +```php +$barobillSoapClient = null; +try { + $barobillSoapClient = new SoapClient($url, $options); +} catch (Throwable $e) { + // Class not found ๋“ฑ์˜ Fatal Error๋„ ์—ฌ๊ธฐ์„œ ์žกํž˜ + error_log('SOAP Client ์ƒ์„ฑ ์‹คํŒจ: ' . $e->getMessage()); + // ์ดํ›„ ๋กœ์ง์—์„œ $barobillSoapClient๊ฐ€ null์ผ ๊ฒฝ์šฐ์˜ ๋Œ€์ฒด ๋กœ์ง(์˜ˆ: ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ) ์ˆ˜ํ–‰ +} +``` + +**์ ์šฉ ํŒŒ์ผ:** +- `etax/api/barobill_config.php` +- `etax/api/issue.php` (์ „์—ญ ์—๋Ÿฌ ํ•ธ๋“ค๋ง) diff --git a/etax/index.php b/etax/index.php new file mode 100644 index 0000000..1e30649 --- /dev/null +++ b/etax/index.php @@ -0,0 +1,1086 @@ + + + + + + ์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ ์†”๋ฃจ์…˜ - ๋ฐ”๋กœ๋นŒ ์—ฐ๋™ + + + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/lib/DotEnv.php b/lib/DotEnv.php new file mode 100644 index 0000000..c2a547a --- /dev/null +++ b/lib/DotEnv.php @@ -0,0 +1,45 @@ +path = $path; + } + + public function load(): void + { + if (!is_readable($this->path)) { + throw new \RuntimeException(sprintf('%s file is not readable', $this->path)); + } + + $lines = file($this->path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach ($lines as $line) { + if (strpos(trim($line), '#') === 0) { + continue; + } + + list($name, $value) = explode('=', $line, 2); + $name = trim($name); + $value = trim($value); + + if (!array_key_exists($name, $_SERVER) && !array_key_exists($name, $_ENV)) { + putenv(sprintf('%s=%s', $name, $value)); + $_ENV[$name] = $value; + $_SERVER[$name] = $value; + } + } + } + } +} diff --git a/lib/func.php b/lib/func.php new file mode 100644 index 0000000..e58d1d7 --- /dev/null +++ b/lib/func.php @@ -0,0 +1,45 @@ + + + + + + + + + +query($sql); + + While($row=$stmh->fetch(PDO::FETCH_ASSOC)) + { + $num=$row["num"]; + $len_subject=strlen($row["subject"]); + $subject=$row["subject"]; + if($len_subject>$char_limit) + { + $subject=mb_substr($row["subject"],0,$char_limit,'utf-8'); + $subject=$subject . "..."; // ๊ธ€์ž์ˆ˜๊ฐ€ ์ดˆ๊ณผํ•˜๋ฉด ...์œผ๋กœ ํ‘œ๊ธฐ๋จ + } + $regist_day=substr($row["regist_day"],0,10); + $page=1; + + echo("
$regist_day
+
"); + + } + } catch (PDOException $Exception) { + print "์˜ค๋ฅ˜: ". $Exception->getMessage(); + + } + } + ?> \ No newline at end of file diff --git a/lib/helper.php b/lib/helper.php new file mode 100644 index 0000000..f3eb0cd --- /dev/null +++ b/lib/helper.php @@ -0,0 +1,21 @@ + + location.href = '$url'; + + "; +} + +function alert($msg) +{ + print " + + "; +} + +?> \ No newline at end of file