'error', 'step' => 'auth', 'message' => '인증에 실패했습니다. 올바른 인증키를 사용해 주세요.' ], 401); } // ===== 2) JSON 입력 파싱 ===== $input = file_get_contents('php://input'); $data = json_decode($input, true); if (!is_array($data)) { respond([ 'status' => 'error', 'step' => 'parse', 'message' => '전달된 JSON이 올바르지 않습니다.' ], 400); } // ===== 3) 필수 항목 검증 ===== $required = ['emp_no','name','email','type','date']; $labels = [ 'emp_no' => '사번', 'name' => '이름', 'email' => '이메일', 'type' => '퇴사 유형', 'date' => '퇴사 일자' ]; foreach ($required as $k) { if (!isset($data[$k]) || $data[$k] === '') { respond([ 'status' => 'error', 'step' => 'validation', 'message' => "필수 항목이 누락되었습니다: {$labels[$k]} 누락." ], 400); } } // ===== 4) DB 연결 ===== try { $db = new mysqli($MYSQL_HOST, $MYSQL_USER, $MYSQL_PASS, $MYSQL_DB); $db->set_charset('utf8mb4'); } catch (mysqli_sql_exception $e) { respond([ 'status' => 'error', 'step' => 'db_connect', 'message' => '데이터베이스 연결에 실패했습니다.', 'detail' => $e->getMessage() ], 500); } // ===== 5) INSERT (1062 중복 예외 캐치) ===== try { $stmt = $db->prepare(" INSERT INTO resign_info (emp_no, name, email, type, date) VALUES (?, ?, ?, ?, ?) "); $stmt->bind_param('sssss', $data['emp_no'], $data['name'], $data['email'], $data['type'], $data['date'] ); $stmt->execute(); $dbInserted = [ 'affected_rows' => $stmt->affected_rows, 'insert_id' => $stmt->insert_id ]; $stmt->close(); } catch (mysqli_sql_exception $e) { if ($e->getCode() === 1062) { $db->close(); respond([ 'status' => 'error', 'step' => 'db_insert', 'message' => '이미 등록된 퇴사자 정보입니다. (PK/UNIQUE 중복)', 'detail' => $e->getMessage() ], 409); } $db->close(); respond([ 'status' => 'error', 'step' => 'db_insert', 'message' => '퇴사자 정보를 저장하는 데 실패했습니다.', 'detail' => $e->getMessage() ], 500); } // ===== 6) 후속 작업: Descope 삭제 → (성공시에만) BEPS 상태 업데이트 ===== $result = [ 'status' => 'success', 'message' => '퇴사자 정보가 DB에 정상적으로 등록되었습니다.', 'db' => ['status' => 'ok', 'meta' => $dbInserted], 'descope' => null, 'emp_status' => null ]; $descope_ok = false; // 6-1) Descope 사용자 삭제 // if (!empty($data['email'])) { // $headers = [ // 'Content-Type: application/json', // "Authorization: Bearer {$DESCOPE_PROJECT_ID}:{$DESCOPE_MGMT_KEY}" // ]; // $body = json_encode(['loginId' => $data['email']]); // $ch = curl_init($DESCOPE_DELETE_URL); // curl_setopt_array($ch, [ // CURLOPT_RETURNTRANSFER => true, // CURLOPT_POST => true, // CURLOPT_POSTFIELDS => $body, // CURLOPT_HTTPHEADER => $headers, // CURLOPT_TIMEOUT => 15 // ]); // $resBody = curl_exec($ch); // $resCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // $resErr = curl_error($ch); // curl_close($ch); // if ($resErr) { // $result['descope'] = [ // 'status' => 'error', // 'message' => 'Descope 사용자 삭제 중 cURL 오류', // 'detail' => $resErr // ]; // $result['status'] = 'partial_success'; // } elseif ($resCode >= 200 && $resCode < 300) { // $result['descope'] = ['status' => 'ok', 'message' => 'Descope 사용자 삭제에 성공했습니다.']; // $descope_ok = true; // } else { // $result['descope'] = [ // 'status' => 'error', // 'message' => "Descope API 에러 (HTTP {$resCode})", // 'response' => json_decode($resBody, true) // ]; // $result['status'] = 'partial_success'; // } // } else { // $result['descope'] = [ // 'status' => 'skipped', // 'message' => '이메일 값이 없어 Descope 삭제를 생략했습니다.' // ]; // } // 6-1) Descope 사용자 상태 비활성화 if (!empty($data['email'])) { $headers = [ 'Content-Type: application/json', "Authorization: Bearer {$DESCOPE_PROJECT_ID}:{$DESCOPE_MGMT_KEY}" ]; $body = json_encode(['loginId'=>$data['email'],'status'=>'disabled']); $ch = curl_init($DESCOPE_STATUS_URL); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_HTTPHEADER => $headers, CURLOPT_TIMEOUT => 15 ]); $resBody = curl_exec($ch); $resCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $resErr = curl_error($ch); curl_close($ch); if ($resErr) { $result['descope'] = ['status'=>'error','detail'=>$resErr]; $result['status'] = 'partial_success'; } elseif ($resCode >= 200 && $resCode < 300) { $result['descope'] = ['status'=>'ok','message'=>'Descope 사용자 상태를 disabled로 변경했습니다.']; $descope_ok = true; } else { $result['descope'] = [ 'status'=>'error', 'http_code'=>$resCode, 'response'=>json_decode($resBody,true) ]; $result['status'] = 'partial_success'; } } else { $result['descope'] = [ 'status'=>'skipped', 'message'=>'이메일 값이 없어 Descope 상태 변경 생략' ]; } // 6-2) (조건부) BEPS 사내 emp_status 업데이트 — 오직 Descope 성공 시에만 if ($descope_ok) { $bepsPayload = [ 'email' => $data['email'], 'status' => 'inactive' ]; $ch2 = curl_init($BEPS_URL); curl_setopt_array($ch2, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($bepsPayload), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_TIMEOUT => 15 ]); $bepsRes = curl_exec($ch2); $bepsCode = curl_getinfo($ch2, CURLINFO_HTTP_CODE); $bepsErr = curl_error($ch2); curl_close($ch2); if ($bepsErr) { $result['emp_status'] = [ 'status' => 'error', 'message' => 'BEPs 상태 업데이트 중 cURL 오류', 'detail' => $bepsErr ]; $result['status'] = 'partial_success'; } elseif ($bepsCode >= 200 && $bepsCode < 300) { $result['emp_status'] = ['status' => 'ok', 'message' => 'BEPs 상태 업데이트 성공']; } else { $result['emp_status'] = [ 'status' => 'error', 'message' => "BEPs API 에러 (HTTP {$bepsCode})", 'response' => json_decode($bepsRes, true) ]; $result['status'] = 'partial_success'; } } else { $result['emp_status'] = [ 'status' => 'skipped', 'message' => 'Descope 삭제 성공시에만 BEPS 전송 정책으로 인해 전송 생략' ]; } // 정리 및 응답 $db->close(); respond($result, 200);