Files
confirms/app/Libraries/NaverApiClient.php

609 lines
22 KiB
PHP

<?php
namespace App\Libraries;
use App\Models\common\CommonModel;
use App\Models\v2\M712Model;
use CodeIgniter\Model;
class NaverApiClient
{
protected $baseUrl = 'https://test-b2b.land.naver.com';
protected $charger = '';
private $commonModel;
public function __construct()
{
$this->commonModel = new CommonModel();
}
/**
* [GET] 매물 정보 조회
*/
public function getArticleInfo(string $articleNumber): ?array
{
$this->charger = 'admin';
$url = "{$this->baseUrl}/kiso/center/verification-article/{$articleNumber}?charger={$this->charger}";
return $this->request('GET', $url);
}
/**
* [PUT] 매물 정보 수정
* @param string $articleNumber 매물번호
* @param string charger 변경자
* @param array $updateData 수정할 데이터 (tradeType, price, space 등)
* string $tradeType 거래유형 (SALE:매매, JEONSE:전세, MONTHLY_RENT:월세, PRE_SALE:분양)
* boolean $isResidntsExistence 거주여부
* object $address 주소정보 공동 (complexNumber, pyeongTypeNumber, buildingName, hoName, correspondenceFloorCount) 비공동(legalDivisionNumber,jibunAddress,liAddress,etcAddress,referenceAddress,longitude,latitude,correspondenceFloorCount,totalFloorCount,undergroundFloorCount)
* object $price 가격정보 (dealAmount,warrantyAmount,leaseAmount,preSaleAmount,premiumAmount,preSaleOptionAmount)
* object $space 면적정보[비공동] (supplySpace,exclusiveSpace,totalSpace,groundSpace,buildingSpace)
* object $facilities 비공동시설정보 (roomCount)
*/
/** 현장확인 수정시 */
public function updateArticleInfo(string $articleNumber, array $updateData, string $charger = 'admin'): ?array
{
$this->charger = $charger;
$url = "{$this->baseUrl}/kiso/center/verification-site/{$articleNumber}?charger={$this->charger}";
log_message('info', "[updateArticleInfo] 호출됨 - URL: {$url}, 데이터: " . json_encode($updateData, JSON_UNESCAPED_UNICODE));
$result = $this->request('PUT', $url, $updateData);
log_message('info', "[updateArticleInfo] 결과 - " . ($result === null ? 'NULL' : json_encode($result, JSON_UNESCAPED_UNICODE)));
return $result;
}
/** 일반매물 수정시 */
public function v2updateArticleInfo(string $articleNumber, array $updateData, string $charger = 'admin'): ?array
{
$this->charger = $charger;
$url = "{$this->baseUrl}/kiso/center/verification-article/{$articleNumber}?charger={$this->charger}";
log_message('info', "[v2updateArticleInfo] 호출됨 - URL: {$url}, 데이터: " . json_encode($updateData, JSON_UNESCAPED_UNICODE));
$result = $this->request('PUT', $url, $updateData);
log_message('info', "[v2updateArticleInfo] 결과 - " . ($result === null ? 'NULL' : json_encode($result, JSON_UNESCAPED_UNICODE)));
return $result;
}
/**
* [POST] 4.매물검증 결과관리
* API:POST /kiso/center/verification-article/{매물번호}/report?charger={담당자명}
* @param string $articleNumber 매물번호
* @param string charger 변경자
* @param array $reportData 검증결과데이터
* string $reportType 검증결과유형 (검증통과:VERIFIED, 검증실패:FAILED, 최종실패:REJECTED)
* array $verificationConfirms 검증결과목록
* string $ownerBirthDate 소유자 생년월일
* Boolean $isOwnerVerifiable 소유자 검증여부
*/
public function postArticleVerificationReport(string $articleNumber, array $reportData, string $charger = 'admin'): ?array
{
$this->charger = $charger;
$url = "{$this->baseUrl}/kiso/center/verification-article/{$articleNumber}/report?charger={$this->charger}";
return $this->request('POST', $url, $reportData);
}
/**
* [POST] 5.현장확인 정보 전송
* API:POST /kiso/center//verification-article/media/{매물번호}
* @param string $articleNumber 매물번호
* @param array $movies 동영상 ($url)
* @param array $photos 사진 ($fileName, $url)
* @param array photo360s 360사진 ($fileName, $url, $desc)
* @param string $charger 변경자
*/
public function postArticleMediaInfo(string $articleNumber, array $movies, array $photos, array $photo360s, string $charger = 'admin'): ?array
{
$this->charger = $charger;
$url = "{$this->baseUrl}/kiso/center/verification-article/media/{$articleNumber}?charger={$this->charger}";
$data = [
'movies' => $movies,
'photos' => $photos,
'photo360s' => $photo360s
];
return $this->request('POST', $url, $data);
}
/**
* [POST] 6.매물 정보 가격수정
* @param string $articleNumber 매물번호
* @param array $priceData 가격 수정 데이터
* API:PATCH /kiso/center/verification-article/price/{매물번호}?charger={변경자}
* priceType int 가격유형 (DEAL:매매, WARRANTY:보증금, LEASE:월세, PRE_SALE:분양, PREMIUM:프리미엄, PRE_SALE_OPTION:분양옵션)
* dealAmount Int 매매금액
* warrantyAmount Int 보증금
* leaseAmount Int 월세금액
* preSaleAmount Int 분양금액
* premiumAmount Int 프리미엄금액
* preSaleOptionAmount Int 분양옵션금액
*/
public function postArticlePriceUpdate(string $articleNumber, array $priceData, string $charger = 'admin'): ?array
{
$this->charger = $charger;
$url = "{$this->baseUrl}/kiso/center/verification-article/price/{$articleNumber}?charger={$this->charger}";
return $this->request('POST', $url, $priceData);
}
/**
* 현장확인 슬롯 동기화
* API (가) - /kiso/center/site-slot
* 신규/변경 일자별 데이터 전송
* @syncData array
* @param string $baseDate 기준일자(ISO 8601 형식: YYYY-MM-DD 예: 2024-01-31)
* @param string $legalDivisionNumber 구역번호 "1111000000"
* @param object slots 오전/오후/ 슬롯 정보
[
{
"baseDate": "2025-04-30",
"legalDivisionNumber": "1111000000",
"slots": {
"am": { "max": 10, "reserved": 0 },
"pm": { "max": 100, "reserved": 0 }
}
}
]
*/
public function syncSiteSlot($syncData){
$url = $this->baseUrl . "/kiso/center/verification-site/slots";
return $this->request('POST', $url, $syncData);
}
/**
* 현장확인 매물검증 결과 관리
* API: POST /kiso/center/verification-site/{매물번호}/report?charger={담당자명}
* @param string $type 현장확인 S11: 예약, S21: 방문, S31: 검수
* @param string $code 결과코드 10000: 성공, 20000: 실패, 30000: 지연, 20121: 방문전취소, 20122:방문후취소, 20123:촬영후취소
* @param string $message 내용
* @param string $reserveDate 예약 년월일 2005-07-31
*/
public function verificationSiteReport(string $articleNumber, array $reportData, string $charger = 'admin'): ?array
{
$this->charger = $charger;
$url = "{$this->baseUrl}/kiso/center/verification-site/{$articleNumber}/report?charger={$this->charger}";
return $this->request('POST', $url, $reportData);
}
/**
* 특정 단지/평형 시세조회()
* @param string hscpNo 단지번호
* @param string ptpNo 평형번호
* API: GET /confirms/hscpMarketPriceInfo.nhn?hscpNo={단지번호}&ptpNo={평형번호}
*/
public function hscpMarketPriceInfo($hscpNo, $ptpNo){
$url = '/confirms/hscpMarketPriceInfo.nhn';
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . $url;
$data = [
'hscpNo' => $hscpNo,
'ptpNo' => $ptpNo
];
return $this->request('GET', $url, $data);
}
public function submitSyncResult(string $reserveNoList): ?array
{
$url = "{$this->baseUrl}/site/submitSyncResult.nhn";
$url .= '?reserveNoList=' . $reserveNoList;
return $this->request('GET', $url);
}
/**
* 단지상세정보조회
* hscpNo : 단지번호(숫자)
*/
public function aptDetail($hscpNo)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/confirms/APTDetail?hscpNo={$hscpNo}";
return $this->request('GET', $url);
}
/**
* 빌라 단지상세정보 조회
* hscpNo : 단지번호(숫자)
*/
public function villaDetail($hscpNo)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/confirms/villa/{$hscpNo}";
return $this->request('GET', $url);
}
/**
* 단지목록
* cortarNo : 법정동코드
*/
public function complexList($cortarNo)
{
$url = $this->commonModel->getCompanyInfo(2);
$url = $url['api_server'] . "/common/complexList.nhn?cortarNo={$cortarNo}";
return $this->request('GET', $url);
}
/**
* 평형목록
* rletNo : 단지번호
*/
public function ptpList($rletNo)
{
$url = $this->commonModel->getCompanyInfo(2);
$url = $url['api_server'] . "/common/ptpList.nhn?rletNo={$rletNo}";
return $this->request('GET', $url);
}
/**
* 가격수정
* @param String atclNo 매물번호
* @param integer dealAmt 매매가, 전세(보증금) 단위 : 만원
* @param integer wrrntAmt 전세가(보증금) 단위 : 만원
* @param integer leaseAmt 월세가 단위 : 만원
* @param integer isaleAmt 분양가 단위 : 만원
* @param integer premAmt 프리미엄 단위 : 만원
* @param integer charger 담당자id
*/
public function priceChange($atclNo, $dealAmt, $wrrntAmt, $leaseAmt, $isaleAmt, $premAmt, $charger)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/confirms/priceChange";
$postData = [
"atclNo" => $atclNo,
"dealAmt" => $dealAmt,
"wrrntAmt" => $wrrntAmt,
"leaseAmt" => $leaseAmt,
"isaleAmt" => $isaleAmt,
"premAmt" => $premAmt,
"charger" => $charger
];
return $this->request('POST', $url, $postData);
}
/**
* 매물정보수정
* @param String atclNo 매물번호
* @param integer hscpNo 단지번호
* @param integer ptpNo 평형번호
* @param String bildNm 동이름
* @param String rmNo 호수
* @param String tradeType 거래종류(A1,B1,B2 / 변경시 B1 <-> B2만 가능)
* @param integer dealAmt 매매가, 전세(보증금) 단위 : 만원
* @param integer wrrntAmt 전세가(보증금) 단위 : 만원
* @param integer leaseAmt 월세가 단위 : 만원
* @param integer isaleAmt 분양가 단위 : 만원
* @param integer premAmt 프리미엄 단위 : 만원
* @param integer floor 층
* @param integer charger 담당자id
*
* @param String addressCode 주소코드 : 비공동 주택 법정동 코드
* @param String address2 지번주소 : 비공동 주택 지번 주소
* @param String address3 기타주소 : 비공동 주택 기타 주소
* @param float splySpc 공급면적
* @param float exclsSpc 대지면적
* @param float totSpc 전체면적
* @param float grndSpc 대지면적
* @param float bldgSpc 건축면적
*
*/
public function modifyInfo($atclNo, $hscpNo, $ptpNo, $bildNm, $rmNo, $tradeType, $dealAmt, $wrrntAmt, $leaseAmt, $isaleAmt, $premAmt, $floor, $floor2, $charger, $addressCode, $address2, $address2a, $address2b, $address3, $splySpc, $exclsSpc, $totSpc, $grndSpc, $bldgSpc)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/confirms/modifyInfo";
// 공통
$postData = [
"atclNo" => $atclNo,
"tradeType" => $tradeType,
"dealAmt" => $dealAmt,
"wrrntAmt" => $wrrntAmt,
"leaseAmt" => $leaseAmt,
"isaleAmt" => $isaleAmt,
"charger" => $charger
];
// 공동주택
$apartData["hscpNo"] = $hscpNo;
$apartData["ptpNo"] = $ptpNo;
$apartData["bildNm"] = $address2; // 네이버에서 보내주는거랑 수정되어 전달하는 거랑 다른 타입임. 2014년 11월 13일 수정
$apartData["rmNo"] = $address3; // 네이버에서 보내주는거랑 수정되어 전달하는 거랑 다른 타입임. 2014년 11월 13일 수정
// $apartData["bildNm"] = $bildNm;
// $apartData["rmNo"] = $rmNo;
$apartData["premAmt"] = $premAmt;
$apartData["floor"] = $floor;
$apartData["floor2"] = $floor2;
// 비공동주택 연동
$detachData["addressCode"] = $addressCode;
$detachData["address2"] = $address2;
$detachData["address2a"] = $address2a;
$detachData["address2b"] = $address2b;
$detachData["address3"] = $address3;
$detachData["splySpc"] = $splySpc;
$detachData["exclsSpc"] = $exclsSpc;
$detachData["totSpc"] = $totSpc;
$detachData["grndSpc"] = $grndSpc;
$detachData["bldgSpc"] = $bldgSpc;
$detachData["floor"] = $floor;
$detachData["floor2"] = $floor2;
if (!empty($hscpNo)) { //공동주택일 때
$postData = array_merge($postData, $apartData);
} else { //비공동주택일 때
$postData = array_merge($postData, $detachData);
}
return $this->request('POST', $url, $postData);
}
/**
* 검증결과 전송
* @param String atclNo 매물번호
* @param boolean success 성공여부
* @param array checkList 확인정보 array('type'=>'T11','code'=>'10000','comment'=>'01|02|03'); 또는 array('type'=>'T11','code'=>'10000','comment'=>'코멘트');
* @param String charger 담당자 사번
* @param array modifyInfo 공동 비공동에 따라 다른 배열을 넘긴다.
* @param String date 상담일시
*/
public function confirm($atclNo, $success, $checkList, $charger, $modifyInfo, $date)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/confirms/confirm";
$postData = [
"atclNo" => $atclNo,
"success" => $success,
"checkList" => $checkList,
"charger" => $charger,
"modifyInfo" => $modifyInfo,
"date" => $date,
];
return $this->request('POST', $url, $postData);
}
/**
* 등기부 등본 확인 결과
* @param String atclNo 매물번호
* @param String type 1: 1차 확인(등기부확인) / 2: 2차 확인(최종확인 또는 중개업소 TM)
* @param boolean success 성공여부
* @param array checkList 확인정보
* @param String charger 담당자 사번
* @param String date 상담일시
* @param array modifyInfo 수정정보 - success:true 에서만 허용
*/
public function certification($atclNo, $type, $success, $checkList, $charger, $date, $modifyInfo, $ownerVerifiable)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/confirms/certification";
$postData = [
"atclNo" => $atclNo,
"type" => $type,
"success" => $success,
"checkList" => $checkList,
"charger" => $charger,
"date" => $date,
"modifyInfo" => $modifyInfo,
"ownerVerifiable" => $ownerVerifiable
];
return $this->request('POST', $url, $postData);
}
/**
* 등기부 등본 확인 결과
* 712 OwnerVerifiable 전송 오류 우회 테스트
*/
public function certification_712($atclNo, $type, $success, $checkList, $charger, $date, $modifyInfo, $ownerVerifiable)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/confirms/certification";
$model712 = new M712Model();
$data = $model712->getOwnerVerifiable($atclNo);
$ov = $data['OwnerVerifiable_change'];
if (isset($ov)) {
if ($ov > 0) {
$ownerVerifiable = true;
} else {
$ownerVerifiable = false;
}
} else {
$ownerVerifiable = null;
}
$postData = [
"atclNo" => $atclNo,
"type" => $type,
"success" => $success,
"checkList" => $checkList,
"charger" => $charger,
"date" => $date,
"modifyInfo" => $modifyInfo,
"ownerVerifiable" => $ownerVerifiable
];
log_message('debug', '712 certification_712 => ' . $atclNo . ' ::: ' . json_encode($postData) . PHP_EOL);
return $this->request('POST', $url, $postData);
}
/**
* 현장확인 거주인 여부 변경
*/
public function residentsExistence($reserveNumber, $isResidentsExist)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/residents/existence";
$postData = [
'reserveNumber' => $reserveNumber,
'isResidentsExist' => $isResidentsExist
];
return $this->request('POST', $url, $postData);
}
/**
* 예약확인 완료
*/
public function reserveSuccess($reserveNo, $modyfyYn, $agency, $team, $staff, $staffTel, $reserveYmd, $apm)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/site/reserveSuccess.nhn";
$getData = ['reserveNo' => $reserveNo, 'modyfyYn' => $modyfyYn, 'agency' => $agency, 'team' => $team, 'staff' => $staff, 'staffTel' => $staffTel, 'reserveYmd' => $reserveYmd, 'apm' => $apm];
return $this->request('POST', $url, $getData);
}
/**
* 예약확인 실패
*/
public function reserveFail($reserveNo, $errorCode, $etcTxt)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/site/reserveFail.nhn";
$getData = ['reserveNo' => $reserveNo, 'errorCode' => $errorCode, 'errorDesc' => $etcTxt];
return $this->request('POST', $url, $getData);
}
/**
* 촬영 실패
*/
public function shootFail($reserveNo, $errorCode, $etcTxt)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/site/shootFail.nhn";
$getData = ['reserveNo' => $reserveNo, 'errorCode' => $errorCode, 'errorDesc' => $etcTxt];
return $this->request('POST', $url, $getData);
}
/**
* 현장확인2 및 썸네일 검수 실패
*/
public function inspectFail($reserveNumber, $failDescription)
{
$url = $this->commonModel->getCompanyInfo(3);
$url = $url['api_server'] . "/site/vr/inspect/fail";
$postData = [
'reserveNumber' => $reserveNumber,
'failDescription' => $failDescription
];
return $this->request('POST', $url, $postData);
}
/**
* CURL 공통 실행 함수
*/
private function request(string $method, string $url, ?array $data = null): ?array
{
// 요청 데이터 로깅
if ($data) {
log_message('info', "[Naver API $method REQUEST] URL: $url | Data: " . json_encode($data, JSON_UNESCAPED_UNICODE));
} else {
log_message('info', "[Naver API $method REQUEST] URL: $url");
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
if ($method === 'PUT') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
if ($data) {
$payload = json_encode($data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($payload),
'X-Naver-Client-Id: yqBbvQZ123_hjH3b3Df9'
]);
}
} elseif ($method === 'GET') {
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-Naver-Client-Id: yqBbvQZ123_hjH3b3Df9'
]);
} elseif ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
if ($data) {
$payload = json_encode($data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($payload),
'X-Naver-Client-Id: yqBbvQZ123_hjH3b3Df9'
]);
}
} elseif ($method === 'PATCH') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
if ($data) {
$payload = json_encode($data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($payload),
'X-Naver-Client-Id: yqBbvQZ123_hjH3b3Df9'
]);
}
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
$curlErrno = curl_errno($ch);
curl_close($ch);
// CURL 오류 체크
if ($curlErrno !== 0) {
log_message('error', "[Naver API $method CURL ERROR] URL: $url | Error ($curlErrno): $curlError");
return [
'error' => true,
'error_type' => 'CURL_ERROR',
'curl_errno' => $curlErrno,
'curl_error' => $curlError,
'url' => $url
];
}
// 결과 로그 기록 (성공/실패 모두 기록하여 추적 가능하게 함)
if ($httpCode === 200 || $httpCode === 202) {
log_message('info', "[Naver API $method SUCCESS] URL: $url | Code: $httpCode | Response: $response");
} else {
log_message('error', "[Naver API $method FAIL] URL: $url | Code: $httpCode | Response: $response");
return [
'error' => true,
'error_type' => 'HTTP_ERROR',
'http_code' => $httpCode,
'response' => $response,
'url' => $url
];
}
return json_decode($response, true);
}
}