naverClient = new NaverApiClient(); $this->VrfcReqModel = model(VrfcReqModel::class); helper('log'); // 헬퍼 로드 } /** * 매물 정보를 처리하고 DB에 저장하는 메인 함수 * @param array $payload 큐에서 꺼낸 원본 데이터 * requestType * REG:수동검증요청 * MOD:매물정보수정-매물제공업체의 매물정보수정으로 재검증요청1차실패 후재검증요청 * CNC:사용자취소 * FIN 서비스-서비스 노출/대기검수완료상태,필요한상태인지확인필요 */ public function processArticle(array $payload) { $articleNumber = $payload['articleNumber']; $requestDatetime = date('Y-m-d H:i:s', strtotime($payload['requestDatetime'] ?? 'now')); $requestType = $payload['requestType'] ?? ''; // REG:등록 , // 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. 가공 로직 (insertVrfc에 있던 긴 배열 생성 로직) $vrfcParams = $this->mapToDatabaseParams($articleInfo, $payload); write_custom_log("VRFC_PARAMS | " . json_encode($vrfcParams, JSON_UNESCAPED_UNICODE), 'INFO', 'service'); switch ($requestType) { case 'REG': $vrfcParams['req_type'] = '10'; return $this->handleRegistration($articleNumber, $vrfcParams); break; case 'MOD': $vrfcParams['req_type'] = '20'; return $this->handleModification($articleNumber, $vrfcParams); break; case 'CNC': $vrfcParams['req_type'] = '30'; return $this->handleStatusChange($articleNumber, $vrfcParams); break; case 'FIN': $vrfcParams['req_type'] = '40'; return $this->handleStatusChange($articleNumber, $vrfcParams); break; default: throw new \Exception("알 수 없는 requestType: " . $requestType); } // 중복 체크 $existing = $this->VrfcReqModel->where('atcl_no', $articleNumber) ->first(); if ($existing) { throw new \Exception("중복 요청: " . $articleNumber . " / " . $vrfcParams['req_type']); } // 3. DB 저장 if (!$this->VrfcReqModel->insert($vrfcParams)) { $errorMessages = implode(', ', $this->VrfcReqModel->errors()); throw new \Exception("V2 매물 삽입 오류: " . $errorMessages); } return $this->VrfcReqModel->getInsertID(); } /** * API 데이터를 DB 컬럼에 맞게 변환 */ private function mapToDatabaseParams(array $articleInfo, array $payload): 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']; } } $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' => empty($confirm_doc_img_url) ? null : 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' => empty($certRegister) ? null : json_encode($certRegister, JSON_UNESCAPED_UNICODE), 'referenceFileUrl' => empty($referenceFileUrl) ? null : json_encode($referenceFileUrl, JSON_UNESCAPED_UNICODE), ]; return $vrfc_params; } /** * [REG] 신규 등록 처리 */ private function handleRegistration($articleNumber, $params) { $existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)->first(); if ($existing) { // 이미 존재한다면 업데이트로 돌리거나 예외 처리 return $this->handleModification($articleNumber, $params); } if (!$this->VrfcReqModel->insert($params)) { throw new \Exception("등록 실패: " . implode(', ', $this->VrfcReqModel->errors())); } return $this->VrfcReqModel->getInsertID(); } /** * [MOD] 수정 처리 */ private function handleModification($articleNumber, $params) { // 기존 기록이 있는지 확인 $existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)->first(); if (!$existing) { // 수정 요청인데 데이터가 없으면 새로 등록 return $this->handleRegistration($articleNumber, $params); } // 기존 데이터 업데이트 (PK인 reqSeq 기준으로 업데이트) if (!$this->VrfcReqModel->update($existing['reqSeq'], $params)) { throw new \Exception("수정 실패: " . implode(', ', $this->VrfcReqModel->errors())); } return $existing['reqSeq']; } /** * [CNC / FIN] 상태값 변경 처리 */ private function handleStatusChange($articleNumber, $statusCode, $memo) { $existing = $this->VrfcReqModel->where('atcl_no', $articleNumber)->first(); if (!$existing) { throw new \Exception("상태 변경 실패: 해당 매물 없음 ($articleNumber)"); } $updateData = [ 'stat_cd' => $statusCode, 'memo' => $existing['memo'] . " | " . $memo . "(" . date('Y-m-d H:i:s') . ")" ]; if (!$this->VrfcReqModel->update($existing['reqSeq'], $updateData)) { throw new \Exception("상태 업데이트 실패: " . $articleNumber); } return $existing['reqSeq']; } }