'HS256','typ'=>'JWT']; $segments = []; $segments[] = base64url_encode(json_encode($header)); $segments[] = base64url_encode(json_encode($payload)); $signing_input = implode('.', $segments); $signature = hash_hmac('sha256', $signing_input, $secret, true); $segments[] = base64url_encode($signature); return implode('.', $segments); } /* ========================= cURL 요청 함수 ========================= */ function curl_json($url, $method='GET', $headers=[], $body=null) { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => $body, CURLOPT_TIMEOUT => 10 ]); $response = curl_exec($ch); $err = curl_error($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($err) { throw new Exception($err); } return [$code, $response]; } /* ========================= MODE 분기 ========================= */ $mode = $_GET['mode'] ?? 'request'; try { /* ========================= 1️⃣ 매직링크 발급 요청 ========================= */ if ($mode === 'request') { // JWT payload (3분 유효) $payload = [ 'system' => $SYSTEM, 'iat' => time(), 'exp' => time() + 180 ]; $jwt = create_jwt($payload, $SECRET_KEY); [$code, $res] = curl_json( $AUTH_SERVER.'/auth/sentinel', 'POST', [ 'Authorization: Bearer '.$jwt, 'Content-Type: application/json' ], json_encode([ 'phoneNumber' => $PHONE ]) ); echo json_encode([ 'step' => 'sentinel_request', 'http_code' => $code, 'response' => json_decode($res, true) ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); exit; } /* ========================= 2️⃣ 매직링크 상태 확인 ========================= */ if ($mode === 'status') { $token = $_GET['token'] ?? ''; if (!$token) { throw new Exception('token 필요'); } $payload = [ 'system' => $SYSTEM, 'iat' => time(), 'exp' => time() + 180 ]; $jwt = create_jwt($payload, $SECRET_KEY); [$code, $res] = curl_json( $AUTH_SERVER.'/auth/status?token='.$token, 'GET', [ 'Authorization: Bearer '.$jwt ] ); $data = json_decode($res, true); // 🔴 여기부터가 "로그인 처리" if (!empty($data['loggedIn'])) { $stmt = $pdo->prepare(" SELECT member_id, user_id, user_nm, auth_bc FROM kngil.users WHERE REPLACE(tel_no, '-', '') = :phone AND use_yn = 'Y' LIMIT 1 "); $stmt->execute([':phone' => $PHONE]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if (!$user) { throw new Exception('해당 번호로 등록된 사용자 없음'); } $_SESSION['login'] = [ 'member_id' => $user['member_id'], 'user_id' => $user['user_id'], 'user_nm' => $user['user_nm'], 'auth_bc' => $user['auth_bc'] ]; echo json_encode([ 'status' => 'success', 'message' => '자동 로그인 완료' ]); exit; } echo json_encode([ 'status' => 'pending' ]); exit; } } catch (Exception $e) { echo json_encode([ 'error' => true, 'message' => $e->getMessage() ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); }