feat: [barobill] SOAP 동기화 서비스 신규 구축
- BarobillSoapService: PHP SoapClient 기반 SOAP 래퍼 (회원/계좌/카드/인증서) - BarobillBankSyncService: 은행 거래내역 SOAP 조회 → DB 캐시 동기화 - BarobillCardSyncService: 카드 거래내역 SOAP 조회 → DB 캐시 동기화 - HometaxSyncService: 홈택스 세금계산서 upsert 동기화 - BarobillSyncController: 동기화/회원/인증서/잔액 API 11개 엔드포인트 - SyncBarobillDataJob: 매일 06:00/06:30 자동 동기화 스케줄러 - BarobillController.status() 보강: 실제 계좌/카드 수 표시
This commit is contained in:
186
app/Services/Barobill/BarobillCardSyncService.php
Normal file
186
app/Services/Barobill/BarobillCardSyncService.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Barobill;
|
||||
|
||||
use App\Models\Barobill\BarobillMember;
|
||||
use App\Services\Service;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* 바로빌 카드 거래내역 동기화 서비스 (API 독립 구현)
|
||||
*
|
||||
* MNG의 EcardController 카드 조회 패턴을 참고하여 독립 작성.
|
||||
* SOAP API를 호출하여 카드 거래내역을 DB에 캐시/동기화한다.
|
||||
*/
|
||||
class BarobillCardSyncService extends Service
|
||||
{
|
||||
public function __construct(
|
||||
protected BarobillSoapService $soapService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 카드 거래내역 동기화
|
||||
*/
|
||||
public function syncCardTransactions(int $tenantId, string $startDateYmd, string $endDateYmd): array
|
||||
{
|
||||
$member = BarobillMember::withoutGlobalScopes()
|
||||
->where('tenant_id', $tenantId)
|
||||
->first();
|
||||
|
||||
if (! $member || empty($member->barobill_id)) {
|
||||
return ['success' => false, 'error' => '바로빌 회원 정보 없음'];
|
||||
}
|
||||
|
||||
$this->soapService->initForMember($member);
|
||||
|
||||
$cards = $this->getRegisteredCards($member);
|
||||
if (empty($cards)) {
|
||||
return ['success' => true, 'message' => '등록된 카드 없음', 'synced' => 0];
|
||||
}
|
||||
|
||||
$totalSynced = 0;
|
||||
|
||||
foreach ($cards as $card) {
|
||||
$cardNum = $card['cardNum'];
|
||||
|
||||
$result = $this->soapService->getPeriodCardLog(
|
||||
$member->biz_no,
|
||||
$member->barobill_id,
|
||||
$cardNum,
|
||||
$startDateYmd,
|
||||
$endDateYmd
|
||||
);
|
||||
|
||||
if (! $result['success']) {
|
||||
Log::warning("[CardSync] 카드 조회 실패: {$cardNum}", [
|
||||
'error' => $result['error'] ?? '',
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $result['data'];
|
||||
|
||||
if (is_numeric($data) && $data < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rawLogs = [];
|
||||
if (isset($data->CardLogList) && isset($data->CardLogList->CardLog)) {
|
||||
$logs = $data->CardLogList->CardLog;
|
||||
$rawLogs = is_array($logs) ? $logs : [$logs];
|
||||
}
|
||||
|
||||
if (! empty($rawLogs)) {
|
||||
$count = $this->cacheTransactions(
|
||||
$tenantId,
|
||||
$cardNum,
|
||||
$card['cardCompany'],
|
||||
$card['cardCompanyName'],
|
||||
$rawLogs
|
||||
);
|
||||
$totalSynced += $count;
|
||||
Log::debug("[CardSync] 카드 {$cardNum}: {$count}건 저장");
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'synced' => $totalSynced,
|
||||
'cards' => count($cards),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 바로빌 등록 카드 목록 조회 (SOAP)
|
||||
*/
|
||||
public function getRegisteredCards(BarobillMember $member): array
|
||||
{
|
||||
$result = $this->soapService->getCards($member->biz_no, false);
|
||||
if (! $result['success']) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = $result['data'];
|
||||
$cardList = [];
|
||||
if (isset($data->CardEx2)) {
|
||||
$cardList = is_array($data->CardEx2) ? $data->CardEx2 : [$data->CardEx2];
|
||||
} elseif (isset($data->Card)) {
|
||||
$cardList = is_array($data->Card) ? $data->Card : [$data->Card];
|
||||
}
|
||||
|
||||
$cards = [];
|
||||
foreach ($cardList as $card) {
|
||||
if (! is_object($card)) {
|
||||
continue;
|
||||
}
|
||||
$cardNum = $card->CardNum ?? '';
|
||||
if (empty($cardNum) || (is_numeric($cardNum) && $cardNum < 0)) {
|
||||
continue;
|
||||
}
|
||||
$cards[] = [
|
||||
'cardNum' => $cardNum,
|
||||
'cardCompany' => $card->CardCompany ?? '',
|
||||
'cardCompanyName' => BarobillSoapService::$cardCompanyCodes[$card->CardCompany ?? ''] ?? '',
|
||||
'alias' => $card->Alias ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
return $cards;
|
||||
}
|
||||
|
||||
/**
|
||||
* API 응답을 DB에 배치 저장
|
||||
*/
|
||||
protected function cacheTransactions(
|
||||
int $tenantId,
|
||||
string $cardNum,
|
||||
string $cardCompany,
|
||||
string $cardCompanyName,
|
||||
array $rawLogs
|
||||
): int {
|
||||
$rows = [];
|
||||
$now = now();
|
||||
|
||||
foreach ($rawLogs as $log) {
|
||||
$useDT = $log->UseDT ?? '';
|
||||
$useDate = strlen($useDT) >= 8 ? substr($useDT, 0, 8) : '';
|
||||
$useTime = strlen($useDT) >= 14 ? substr($useDT, 8, 6) : '';
|
||||
|
||||
$rows[] = [
|
||||
'tenant_id' => $tenantId,
|
||||
'card_num' => $log->CardNum ?? $cardNum,
|
||||
'card_company' => $log->CardCompany ?? $cardCompany,
|
||||
'card_company_name' => $cardCompanyName,
|
||||
'use_dt' => $useDT,
|
||||
'use_date' => $useDate,
|
||||
'use_time' => $useTime,
|
||||
'approval_num' => $log->ApprovalNum ?? '',
|
||||
'approval_type' => $log->ApprovalType ?? '',
|
||||
'approval_amount' => floatval($log->ApprovalAmount ?? 0),
|
||||
'tax' => floatval($log->Tax ?? 0),
|
||||
'service_charge' => floatval($log->ServiceCharge ?? 0),
|
||||
'payment_plan' => $log->PaymentPlan ?? '',
|
||||
'currency_code' => $log->CurrencyCode ?? '',
|
||||
'merchant_name' => $log->MerchantName ?? '',
|
||||
'merchant_biz_num' => $log->MerchantBizNum ?? '',
|
||||
'merchant_addr' => $log->MerchantAddr ?? '',
|
||||
'merchant_ceo' => '',
|
||||
'merchant_biz_type' => '',
|
||||
'merchant_tel' => '',
|
||||
'use_key' => $log->UseKey ?? '',
|
||||
'is_manual' => false,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
}
|
||||
|
||||
$inserted = 0;
|
||||
foreach (array_chunk($rows, 100) as $batch) {
|
||||
$inserted += DB::table('barobill_card_transactions')->insertOrIgnore($batch);
|
||||
}
|
||||
|
||||
return $inserted;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user