워커 서비스 생성 및 수정

This commit is contained in:
2025-12-29 20:35:55 +09:00
parent 4cfd6f1faf
commit dbeb0d6b1f
3 changed files with 120 additions and 190 deletions

View File

@@ -15,6 +15,8 @@ class NaverWorker extends BaseCommand
public function run(array $params)
{
helper('log'); // 여기서 로드 완료!
$redis = new \Redis();
try {
$redis->connect('redis', 6379);
@@ -25,200 +27,32 @@ class NaverWorker extends BaseCommand
return;
}
$naverService = new \App\Services\NaverService(); // 서비스 생성
while (true) {
try {
// 1. Redis에서 데이터를 꺼냄
$result = $redis->brPop(['naver:raw_queue'], 30);
if ($result) {
$rawData = $result[1];
try {
$responseJson = json_decode($rawData, true);
$responseJson = json_decode($result[1], true);
$payload = $responseJson['request_data'] ?? [];
if (empty($payload)) {
throw new \Exception( date("Y-m-d H:i:s") . "::빈 페이로드 데이터: " . $rawData);
}
CLI::write("Processing: " . json_encode($payload, JSON_UNESCAPED_UNICODE));
$requestType = $payload['requestType'] ?? '';
if (!in_array($requestType, ['REG', 'MOD', 'CNC', 'FIN'])) {
throw new \Exception( date("Y-m-d H:i:s") . "::잘못된 요청 유형: " . json_encode($payload, JSON_UNESCAPED_UNICODE));
}
// 2. 실제 작업 수행
/*
REG : 수동검증요청 ,
MOD 매물정보수정 - 매물제공업체의 매물정보 수정으로 재검증요청 1차 실패 후 재검증 요청 ,
CNC : 사용자취소 ,
FIN : 서비스 노출/대기 검수완료 상태(필요한 상태인지 확인 필요)
*/
switch ($requestType) {
case 'REG':
$this->insertVrfc($payload);
break;
case 'MOD':
// 수동검증요청 및 매물정보수정 처리
break;
case 'CNC':
// 사용자취소 처리
break;
case 'FIN':
// 서비스 노출/대기 검수완료 상태 처리
break;
throw new \Exception("빈 페이로드 데이터");
}
// 서비스의 함수 하나로 모든 처리 완료
$insertId = $naverService->processArticle($payload);
CLI::write("✅ Success: " . ($payload['articleNumber'] ?? 'Unknown'), 'cyan');
CLI::write("✅ Success! DB ID: $insertId", 'cyan');
} catch (\Exception $e) {
// 3. 실패 시: Helper 함수 사용
$errorMsg = $e->getMessage();
CLI::error("❌ Task Failed: $errorMsg");
// 공통 헬퍼 함수 호출
write_custom_log("FAILED_DATA | Error: $errorMsg | Data: $rawData", 'ERROR', 'failed');
}
}
} catch (\Exception $e) {
CLI::error("Worker Loop Error: " . $e->getMessage());
sleep(1);
CLI::error("❌ Task Failed: " . $e->getMessage());
// 실패 로그는 여기서 남김
helper('log');
write_custom_log("FAILED_DATA | Error: " . $e->getMessage(), 'ERROR', 'failed');
}
}
}
private function insertVrfc($payload)
{
// 1. 필수 데이터 검증
if (empty($payload['articleNumber']) || empty($payload['requestType'])) {
throw new \Exception("필수 파라미터 누락");
}
$articleNumber = $payload['articleNumber'];
$requestType = $payload['requestType'];
$requestDatetime = date('Y-m-d H:i:s', strtotime($payload['requestDatetime']));
// 2. 네이버 API 클라이언트 초기화
$naverClient = new \App\Libraries\NaverApiClient();
// 매물 정보 조회
$articleInfojson = $naverClient->getArticleInfo($articleNumber);
// if (!$articleInfojson || !isset($articleInfojson['data']) || empty($articleInfojson['code'] !== 'success')) {
// throw new \Exception("매물 정보 조회 실패: $articleNumber ::: message : " . ($articleInfojson['message'] ?? 'No response'));
// }
if (!$articleInfojson || !isset($articleInfojson['data']) || $articleInfojson['code'] !== 'success') {
$msg = $articleInfojson['message'] ?? 'No message';
throw new \Exception("네이버 API 응답 에러: $articleNumber | 메시지: $msg");
}
$articleInfo = $articleInfojson['data'];
// 받아온 정보 로그 기록
write_custom_log("ARTICLE_INFO | ArticleNumber: $articleNumber | Info: " . json_encode($articleInfo , JSON_UNESCAPED_UNICODE), 'INFO', 'service');
CLI::write("Fetched Article Info: " . json_encode($articleInfo));
/**
* $articleInfo['verificationTypeCode']
* S : 현장확인매물
* D : 홍보확인서
* N : 신홍보확인서
* M : 모바일
* T : 전화
* O : 모바일확인V2
*
* S - reciept , result 테이블 사용
* D,N,M,T,O - v2_vrfc_req , v2_article_info , v2_article_info_etc , v2_article_fail 테이블 사용
*/
// {"code":"success","message":"","data":{"articleNumber":"2500000001","realEstateType":"빌라/연립","realEstateTypeCode":"C02","cpId":"toad","cpArticleNumber":"15882606","tradeType":"전세","tradeTypeCode":"B1","statusTypeCode":"E12","verificationTypeCode":"M","isUnregisteredVerificationRequested":false,"isBuildingRegisterAreaCheckRequested":false,"isAutoVerificationRequested":false,"exposureStartDateTime":"2025-01-02 09:12:02","facilities":{"roomCount":2,"bathroomCount":1},"address":{"legalDivision":{"cityNumber":"1100000000","divisionNumber":"1168000000","sectorNumber":"1168010700","legalDivisionAddress":"서울특별시 강남구 신사동"},"isVirtualAddress":false,"correspondenceFloorCount":2,"longitude":0.0,"latitude":0.0},"space":{"totalSpace":34.5,"groundSpace":34.5,"buildingSpace":34.5,"supplySpace":34.5,"exclusiveSpace":34.5},"price":{"dealAmount":777777777,"warrantyAmount":2999999999,"leaseAmount":7777777},"floor":{"correspondenceFloorCount":2,"totalFloorCount":3,"undergroundFloorCount":null}}}
$comp_sq = '2';
$rcpt_rating = '3';
$files = $articleInfo['files'] ?? [];
$certRegister = [];
$confirm_doc_img_url = [];
$referenceFileUrl = [];
foreach ($files as $file) {
// 파일 처리 로직
$fileTypeCode = $file['fileTypeCode'];
if ( $fileTypeCode == 'RCDOC' ) {
$certRegister[] = $file['fileUrl'];
} elseif ( $fileTypeCode == 'ADDOC' ) {
$confirm_doc_img_url[] = $file['fileUrl'];
} elseif ( $fileTypeCode == 'REFER') {
$referenceFileUrl[] = $file['fileUrl'];
}
}
$vrfc_params = [
'reqSeq' => '',
'atcl_no' => $articleInfo['articleNumber'],
'step' => '',
'cpid' => $articleInfo['cpId'],
'cp_atcl_id' => $articleInfo['cpArticleNumber'],
'trade_type' => $articleInfo['tradeTypeCode'],
'realtor_nm' => $articleInfo['realtor']['realtorName'],
'realtor_tel_no' => $articleInfo['realtor']['representativeCellphoneNumber'],
'seller_tel_no' => $articleInfo['seller']['sellerTelephoneNumber'],
'vrfc_type' => $articleInfo['verificationTypeCode'],
'rgbk_confirm' => $articleInfo['isUnregisteredVerificationRequested'] ? 'Y' : 'N',
'req_type' => '',
'rdate' => $requestDatetime ?? db_now('Y-m-d H:i:s'),
'cpTelNo' => $articleInfo['seller']['sellerTelephoneNumber'],
'stat_cd' => '10',
'try_cnt' => '0',
'insert_user' => 'admin',
'insert_tm' => db_now(),
'memo' => '',
'contact_fail_cnt' => '0',
'sync_yn' => 'N',
'reg_try_cnt' => '0',
'tel_fail_cause' => null,
'rgbk_confirm_owner_nm' => $articleInfo['seller']['ownerName'] ?? null,
'direct_trad_yn' => $articleInfo['seller']['isDirectTrade'] === true ? 'Y' : 'N',
'confirm_doc_img_url' => json_encode($confirm_doc_img_url, JSON_UNESCAPED_UNICODE),
'confirm_doc_owner_check_yn' => '',
'owner_verifiable' => null,
'vrfc_cmpl_type' => null,
'rgbk_doc_img_url' => null,
'certRegister' => json_encode($certRegister, JSON_UNESCAPED_UNICODE),
'referenceFileUrl' => json_encode($referenceFileUrl, JSON_UNESCAPED_UNICODE),
];
write_custom_log("VRFC_PARAMS | " . json_encode($vrfc_params , JSON_UNESCAPED_UNICODE), 'INFO', 'service');
// if ($articleInfo['verificationTypeCode'] == 'S') { // 현장확인매물
// // 현장확인매물 처리 로직
// } else { // 그외 일반매물
// // V2 매물 처리 로직
// $v2ArticleModel = model(\App\Models\V2ArticleModel::class);
// // 매물 번호로 중복 체크
// $existingV2 = $v2ArticleModel->where('atcl_no', $articleInfo['articleNumber'])->first();
// if ($existingV2) {
// throw new \Exception("중복 매물 번호: " . $articleInfo['articleNumber']);
// }
// $v2ArticleModel->insert($vrfc_params);
// $vr_sq = $v2ArticleModel->getInsertID(); // 방금 삽입한 vr_sq 값 가져오기
// CLI::write("Inserted V2 Article with vr_sq: " . $vr_sq);
// // 오류 처리
// if ($v2ArticleModel->errors()) {
// $errorMessages = implode(', ', $v2ArticleModel->errors());
// throw new \Exception("V2 매물 삽입 오류: " . $errorMessages);
// }
// }
CLI::write("Processing: " . ($payload['articleNumber'] ?? 'Unknown'));
}
}

View File

@@ -2,7 +2,7 @@
namespace App\Models;
use CodeIgniter\Model;
class V2ArticleModel extends Model {
class VrfcReqModel extends Model {
// Model implementation here
protected $table = 'v2_vrfc_req';
protected $primaryKey = 'vr_sq';

View File

@@ -0,0 +1,96 @@
<?php
namespace App\Services;
use App\Libraries\NaverApiClient;
use App\Models\V2ArticleModel;
use App\Models\VrfcReqModel;
class NaverService
{
protected $naverClient;
protected $VrfcReqModel;
public function __construct()
{
$this->naverClient = new NaverApiClient();
$this->VrfcReqModel = model(VrfcReqModel::class);
helper('log'); // 헬퍼 로드
}
/**
* 매물 정보를 처리하고 DB에 저장하는 메인 함수
*/
public function processArticle(array $payload)
{
$articleNumber = $payload['articleNumber'];
$requestDatetime = date('Y-m-d H:i:s', strtotime($payload['requestDatetime'] ?? 'now'));
// 1. 네이버 API 호출
$response = $this->naverClient->getArticleInfo($articleNumber);
if (!$response || !isset($response['data']) || $response['code'] !== 'success') {
$msg = $response['message'] ?? 'No message';
throw new \Exception("네이버 API 응답 에러: $articleNumber | 메시지: $msg");
}
$articleInfo = $response['data'];
// 로그 기록
write_custom_log("ARTICLE_INFO | ArticleNumber: $articleNumber", 'INFO', 'service');
// 2. 파라미터 매핑 (기존의 $vrfc_params 생성 로직)
$vrfcParams = $this->mapVrfcParams($articleInfo, $requestDatetime);
// 3. DB 저장
if (!$this->v2ArticleModel->insert($vrfcParams)) {
$errorMessages = implode(', ', $this->v2ArticleModel->errors());
throw new \Exception("V2 매물 삽입 오류: " . $errorMessages);
}
return $this->v2ArticleModel->getInsertID();
}
/**
* API 데이터를 DB 컬럼에 맞게 변환
*/
private function mapVrfcParams(array $articleInfo, string $requestDatetime): array
{
$files = $articleInfo['files'] ?? [];
$certRegister = [];
$confirm_doc_img_url = [];
$referenceFileUrl = [];
foreach ($files as $file) {
$fileTypeCode = $file['fileTypeCode'];
if ($fileTypeCode == 'RCDOC') {
$certRegister[] = $file['fileUrl'];
} elseif ($fileTypeCode == 'ADDOC') {
$confirm_doc_img_url[] = $file['fileUrl'];
} elseif ($fileTypeCode == 'REFER') {
$referenceFileUrl[] = $file['fileUrl'];
}
}
return [
'atcl_no' => $articleInfo['articleNumber'],
'cpid' => $articleInfo['cpId'],
'cp_atcl_id' => $articleInfo['cpArticleNumber'],
'trade_type' => $articleInfo['tradeTypeCode'],
'realtor_nm' => $articleInfo['realtor']['realtorName'] ?? '',
'realtor_tel_no' => $articleInfo['realtor']['representativeCellphoneNumber'] ?? '',
'seller_tel_no' => $articleInfo['seller']['sellerTelephoneNumber'] ?? '',
'vrfc_type' => $articleInfo['verificationTypeCode'],
'rgbk_confirm' => ($articleInfo['isUnregisteredVerificationRequested'] ?? false) ? 'Y' : 'N',
'rdate' => $requestDatetime,
'stat_cd' => '10',
'insert_user' => 'admin',
'insert_tm' => date('Y-m-d H:i:s'),
'rgbk_confirm_owner_nm' => $articleInfo['seller']['ownerName'] ?? null,
'confirm_doc_img_url' => json_encode($confirm_doc_img_url, JSON_UNESCAPED_UNICODE),
'certRegister' => json_encode($certRegister, JSON_UNESCAPED_UNICODE),
'referenceFileUrl' => json_encode($referenceFileUrl, JSON_UNESCAPED_UNICODE),
// 필요한 나머지 컬럼들 추가...
];
}
}