957 lines
31 KiB
Markdown
957 lines
31 KiB
Markdown
|
|
# 바로빌 카드 사용내역 조회 - 멀티테넌시 개발 문서
|
||
|
|
|
||
|
|
## 목차
|
||
|
|
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
|
||
|
|
<?php
|
||
|
|
/**
|
||
|
|
* 바로빌 카드 API 설정 파일 (멀티테넌시 지원)
|
||
|
|
*/
|
||
|
|
|
||
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . '/lib/mydb.php');
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 업체별 바로빌 인증 정보 조회
|
||
|
|
*
|
||
|
|
* @param int $company_id 업체 ID
|
||
|
|
* @return array 인증 정보
|
||
|
|
*/
|
||
|
|
function getBarobillCredentials($company_id) {
|
||
|
|
global $pdo, $DB;
|
||
|
|
|
||
|
|
$stmt = $pdo->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
|
||
|
|
<?php
|
||
|
|
/**
|
||
|
|
* 등록된 카드 목록 조회 API (멀티테넌시 지원)
|
||
|
|
*/
|
||
|
|
header('Content-Type: application/json; charset=utf-8');
|
||
|
|
|
||
|
|
require_once('barobill_card_config.php');
|
||
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . '/session.php');
|
||
|
|
|
||
|
|
try {
|
||
|
|
// 업체 ID 확인 (세션 또는 파라미터에서)
|
||
|
|
$company_id = $_SESSION['company_id'] ?? $_GET['company_id'] ?? null;
|
||
|
|
|
||
|
|
if (!$company_id) {
|
||
|
|
echo json_encode([
|
||
|
|
'success' => 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
|
||
|
|
<?php
|
||
|
|
/**
|
||
|
|
* 카드 사용내역 조회 API (멀티테넌시 지원)
|
||
|
|
*/
|
||
|
|
header('Content-Type: application/json; charset=utf-8');
|
||
|
|
|
||
|
|
require_once('barobill_card_config.php');
|
||
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . '/session.php');
|
||
|
|
|
||
|
|
try {
|
||
|
|
// 업체 ID 확인
|
||
|
|
$company_id = $_SESSION['company_id'] ?? $_GET['company_id'] ?? null;
|
||
|
|
|
||
|
|
if (!$company_id) {
|
||
|
|
echo json_encode([
|
||
|
|
'success' => 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
|