fix:바로빌 홈택스 API 파라미터 오류 수정

- TaxType: 0(전체) → 1(과세+영세), 3(면세) 각각 조회 후 합침
  (바로빌 API에서 TaxType=0은 미지원)
- DateType: 1(작성일) → 3(전송일자)로 변경 (권장사항)
- 에러 메시지 업데이트:
  - -11010: 과세형태 오류 안내
  - -10008: 날짜형식 오류 안내 (YYYYMMDD)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
pro
2026-01-28 15:09:43 +09:00
parent 7a6f658424
commit da706bae04

View File

@@ -120,6 +120,11 @@ public function index(Request $request): View|Response
/**
* 매출 세금계산서 목록 조회 (GetPeriodTaxInvoiceSalesList)
*
* 바로빌 API 참고:
* - TaxType: 1(과세+영세), 3(면세) 만 가능 (0은 미지원)
* - DateType: 3(전송일자) 권장
* - 전체 조회 시 1, 3을 각각 조회하여 합침
*/
public function sales(Request $request): JsonResponse
{
@@ -128,7 +133,7 @@ public function sales(Request $request): JsonResponse
$endDate = $request->input('endDate', date('Ymd'));
$page = (int)$request->input('page', 1);
$limit = (int)$request->input('limit', 50);
$taxType = (int)$request->input('taxType', 0); // 0:전체, 1:과세, 2:영세, 3:면세
$taxType = (int)$request->input('taxType', 0); // 0:전체, 1:과세+영세, 3:면세
// 현재 테넌트의 바로빌 회원 정보 조회
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
@@ -150,63 +155,78 @@ public function sales(Request $request): JsonResponse
]);
}
$result = $this->callSoap('GetPeriodTaxInvoiceSalesList', [
// CorpNum은 callSoap에서 파트너사 사업자번호로 자동 설정
'UserID' => $userId,
'TaxType' => $taxType,
'DateType' => 1, // 1:작성일 기준
'StartDate' => $startDate,
'EndDate' => $endDate,
'CountPerPage' => $limit,
'CurrentPage' => $page
]);
// TaxType이 0(전체)인 경우 1(과세+영세)과 3(면세)를 각각 조회하여 합침
$taxTypesToQuery = ($taxType === 0) ? [1, 3] : [$taxType];
$allInvoices = [];
$totalSummary = ['totalAmount' => 0, 'totalTax' => 0, 'totalSum' => 0, 'count' => 0];
$lastPagination = ['currentPage' => $page, 'countPerPage' => $limit, 'maxPageNum' => 1, 'maxIndex' => 0];
if (!$result['success']) {
return response()->json([
'success' => false,
'error' => $result['error'],
'error_code' => $result['error_code'] ?? null
foreach ($taxTypesToQuery as $queryTaxType) {
$result = $this->callSoap('GetPeriodTaxInvoiceSalesList', [
'UserID' => $userId,
'TaxType' => $queryTaxType, // 1: 과세+영세, 3: 면세
'DateType' => 3, // 3: 전송일자 기준 (권장)
'StartDate' => $startDate,
'EndDate' => $endDate,
'CountPerPage' => $limit,
'CurrentPage' => $page
]);
}
$resultData = $result['data'];
if (!$result['success']) {
// 첫 번째 조회 실패 시 에러 반환
if (empty($allInvoices)) {
return response()->json([
'success' => false,
'error' => $result['error'],
'error_code' => $result['error_code'] ?? null
]);
}
continue; // 이미 일부 데이터가 있으면 계속 진행
}
// 에러 코드 체크
$errorCode = $this->checkErrorCode($resultData);
if ($errorCode && !in_array($errorCode, [-60005, -60001])) {
return response()->json([
'success' => false,
'error' => $this->getErrorMessage($errorCode),
'error_code' => $errorCode
]);
}
$resultData = $result['data'];
$errorCode = $this->checkErrorCode($resultData);
// 데이터는 경우
if ($errorCode && in_array($errorCode, [-60005, -60001])) {
return response()->json([
'success' => true,
'data' => [
'invoices' => [],
'summary' => ['totalAmount' => 0, 'totalTax' => 0, 'count' => 0],
'pagination' => ['currentPage' => 1, 'maxPageNum' => 1]
]
]);
}
// 에러 코드 체크 (데이터 없음 외의 에러)
if ($errorCode && !in_array($errorCode, [-60005, -60001])) {
if (empty($allInvoices)) {
return response()->json([
'success' => false,
'error' => $this->getErrorMessage($errorCode),
'error_code' => $errorCode
]);
}
continue;
}
// 데이터 파싱
$parsed = $this->parseInvoices($resultData, 'sales');
// 데이터가 있는 경우 파싱
if (!$errorCode || !in_array($errorCode, [-60005, -60001])) {
$parsed = $this->parseInvoices($resultData, 'sales');
$allInvoices = array_merge($allInvoices, $parsed['invoices']);
$totalSummary['totalAmount'] += $parsed['summary']['totalAmount'];
$totalSummary['totalTax'] += $parsed['summary']['totalTax'];
$totalSummary['totalSum'] += $parsed['summary']['totalSum'] ?? ($parsed['summary']['totalAmount'] + $parsed['summary']['totalTax']);
$totalSummary['count'] += $parsed['summary']['count'];
return response()->json([
'success' => true,
'data' => [
'invoices' => $parsed['invoices'],
'pagination' => [
// 페이지네이션 정보 업데이트 (마지막 조회 결과 사용)
$lastPagination = [
'currentPage' => $resultData->CurrentPage ?? 1,
'countPerPage' => $resultData->CountPerPage ?? 50,
'maxPageNum' => $resultData->MaxPageNum ?? 1,
'maxIndex' => $resultData->MaxIndex ?? 0
],
'summary' => $parsed['summary']
];
}
}
// 작성일 기준으로 정렬 (최신순)
usort($allInvoices, fn($a, $b) => strcmp($b['writeDate'] ?? '', $a['writeDate'] ?? ''));
return response()->json([
'success' => true,
'data' => [
'invoices' => $allInvoices,
'pagination' => $lastPagination,
'summary' => $totalSummary
]
]);
} catch (\Throwable $e) {
@@ -220,6 +240,11 @@ public function sales(Request $request): JsonResponse
/**
* 매입 세금계산서 목록 조회 (GetPeriodTaxInvoicePurchaseList)
*
* 바로빌 API 참고:
* - TaxType: 1(과세+영세), 3(면세) 만 가능 (0은 미지원)
* - DateType: 3(전송일자) 권장
* - 전체 조회 시 1, 3을 각각 조회하여 합침
*/
public function purchases(Request $request): JsonResponse
{
@@ -228,7 +253,7 @@ public function purchases(Request $request): JsonResponse
$endDate = $request->input('endDate', date('Ymd'));
$page = (int)$request->input('page', 1);
$limit = (int)$request->input('limit', 50);
$taxType = (int)$request->input('taxType', 0); // 0:전체, 1:과세, 2:영세, 3:면세
$taxType = (int)$request->input('taxType', 0); // 0:전체, 1:과세+영세, 3:면세
// 현재 테넌트의 바로빌 회원 정보 조회
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
@@ -250,63 +275,78 @@ public function purchases(Request $request): JsonResponse
]);
}
$result = $this->callSoap('GetPeriodTaxInvoicePurchaseList', [
// CorpNum은 callSoap에서 파트너사 사업자번호로 자동 설정
'UserID' => $userId,
'TaxType' => $taxType,
'DateType' => 1, // 1:작성일 기준
'StartDate' => $startDate,
'EndDate' => $endDate,
'CountPerPage' => $limit,
'CurrentPage' => $page
]);
// TaxType이 0(전체)인 경우 1(과세+영세)과 3(면세)를 각각 조회하여 합침
$taxTypesToQuery = ($taxType === 0) ? [1, 3] : [$taxType];
$allInvoices = [];
$totalSummary = ['totalAmount' => 0, 'totalTax' => 0, 'totalSum' => 0, 'count' => 0];
$lastPagination = ['currentPage' => $page, 'countPerPage' => $limit, 'maxPageNum' => 1, 'maxIndex' => 0];
if (!$result['success']) {
return response()->json([
'success' => false,
'error' => $result['error'],
'error_code' => $result['error_code'] ?? null
foreach ($taxTypesToQuery as $queryTaxType) {
$result = $this->callSoap('GetPeriodTaxInvoicePurchaseList', [
'UserID' => $userId,
'TaxType' => $queryTaxType, // 1: 과세+영세, 3: 면세
'DateType' => 3, // 3: 전송일자 기준 (권장)
'StartDate' => $startDate,
'EndDate' => $endDate,
'CountPerPage' => $limit,
'CurrentPage' => $page
]);
}
$resultData = $result['data'];
if (!$result['success']) {
// 첫 번째 조회 실패 시 에러 반환
if (empty($allInvoices)) {
return response()->json([
'success' => false,
'error' => $result['error'],
'error_code' => $result['error_code'] ?? null
]);
}
continue; // 이미 일부 데이터가 있으면 계속 진행
}
// 에러 코드 체크
$errorCode = $this->checkErrorCode($resultData);
if ($errorCode && !in_array($errorCode, [-60005, -60001])) {
return response()->json([
'success' => false,
'error' => $this->getErrorMessage($errorCode),
'error_code' => $errorCode
]);
}
$resultData = $result['data'];
$errorCode = $this->checkErrorCode($resultData);
// 데이터는 경우
if ($errorCode && in_array($errorCode, [-60005, -60001])) {
return response()->json([
'success' => true,
'data' => [
'invoices' => [],
'summary' => ['totalAmount' => 0, 'totalTax' => 0, 'count' => 0],
'pagination' => ['currentPage' => 1, 'maxPageNum' => 1]
]
]);
}
// 에러 코드 체크 (데이터 없음 외의 에러)
if ($errorCode && !in_array($errorCode, [-60005, -60001])) {
if (empty($allInvoices)) {
return response()->json([
'success' => false,
'error' => $this->getErrorMessage($errorCode),
'error_code' => $errorCode
]);
}
continue;
}
// 데이터 파싱
$parsed = $this->parseInvoices($resultData, 'purchase');
// 데이터가 있는 경우 파싱
if (!$errorCode || !in_array($errorCode, [-60005, -60001])) {
$parsed = $this->parseInvoices($resultData, 'purchase');
$allInvoices = array_merge($allInvoices, $parsed['invoices']);
$totalSummary['totalAmount'] += $parsed['summary']['totalAmount'];
$totalSummary['totalTax'] += $parsed['summary']['totalTax'];
$totalSummary['totalSum'] += $parsed['summary']['totalSum'] ?? ($parsed['summary']['totalAmount'] + $parsed['summary']['totalTax']);
$totalSummary['count'] += $parsed['summary']['count'];
return response()->json([
'success' => true,
'data' => [
'invoices' => $parsed['invoices'],
'pagination' => [
// 페이지네이션 정보 업데이트 (마지막 조회 결과 사용)
$lastPagination = [
'currentPage' => $resultData->CurrentPage ?? 1,
'countPerPage' => $resultData->CountPerPage ?? 50,
'maxPageNum' => $resultData->MaxPageNum ?? 1,
'maxIndex' => $resultData->MaxIndex ?? 0
],
'summary' => $parsed['summary']
];
}
}
// 작성일 기준으로 정렬 (최신순)
usort($allInvoices, fn($a, $b) => strcmp($b['writeDate'] ?? '', $a['writeDate'] ?? ''));
return response()->json([
'success' => true,
'data' => [
'invoices' => $allInvoices,
'pagination' => $lastPagination,
'summary' => $totalSummary
]
]);
} catch (\Throwable $e) {
@@ -482,10 +522,11 @@ public function diagnose(Request $request): JsonResponse
];
// 테스트 2: 매출 세금계산서 조회 (기간: 최근 1개월)
// TaxType: 1(과세+영세), 3(면세) 만 가능 / DateType: 3(전송일자) 권장
$salesResult = $this->callSoap('GetPeriodTaxInvoiceSalesList', [
'UserID' => $userId,
'TaxType' => 0,
'DateType' => 1,
'TaxType' => 1, // 1: 과세+영세 (0은 미지원)
'DateType' => 3, // 3: 전송일자 기준 (권장)
'StartDate' => date('Ymd', strtotime('-1 month')),
'EndDate' => date('Ymd'),
'CountPerPage' => 1,
@@ -661,8 +702,8 @@ private function getErrorMessage(int $errorCode): string
{
$messages = [
-10002 => '인증 실패 (-10002). CERTKEY가 올바르지 않거나 만료되었습니다.',
-10008 => '등록되지 않은 사용자입니다 (-10008). 바로빌에 등록된 사업자번호/사용자ID를 확인해주세요.',
-11010 => '세금계산서 조회 권한이 없습니다 (-11010). 바로빌 사이트에서 서비스 권한을 확인해주세요.',
-10008 => '날짜형식이 잘못되었습니다 (-10008). 날짜는 YYYYMMDD 형식(하이픈 제외)으로 입력해주세요.',
-11010 => '과세형태(TaxType)가 잘못되었습니다 (-11010). TaxType은 1(과세+영세) 또는 3(면세)만 가능합니다.',
-24005 => 'UserID가 필요합니다 (-24005). 바로빌 회원사 ID를 설정해주세요.',
-24006 => '조회된 데이터가 없습니다 (-24006).',
-25005 => '조회된 데이터가 없습니다 (-25005).',