import "server-only"; import { logApiRequest, logApiResponse } from "@/lib/api/dev-logger"; const ACCOUNTS_BASE_URL = process.env.GOOYAL_ACCOUNTS_BASE_URL!; const CLIENT_ID = process.env.GOOYAL_CLIENT_ID!; const CLIENT_SECRET = process.env.GOOYAL_CLIENT_SECRET!; function basicAuthHeader() { return "Basic " + Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString("base64"); } const ERROR_MESSAGES_FA: Record = { invalid_grant: "کد تایید نامعتبر یا منقضی شده است.", invalid_client: "خطا در پیکربندی سرویس احراز هویت. لطفاً بعداً تلاش کنید.", invalid_request: "درخواست نامعتبر است.", unsupported_grant_type: "خطا در پیکربندی سرویس احراز هویت.", }; export class GooyalAuthError extends Error { constructor( public status: number, public code: string, description?: string, ) { super(ERROR_MESSAGES_FA[code] ?? description ?? code); } } export interface GooyalTokenResponse { access_token: string; refresh_token?: string; token_type: string; expires_in: number; scope: string; } export async function refreshAccessToken(refreshToken: string): Promise { const url = `${ACCOUNTS_BASE_URL}/oauth2/token/`; const body = new URLSearchParams({ grant_type: "refresh_token", refresh_token: refreshToken, }); // Never print real tokens to the terminal — log the request shape, not the secret values. logApiRequest("gooyal", "POST", url, { grant_type: "refresh_token", refresh_token: "" }); const res = await fetch(url, { method: "POST", headers: { Authorization: basicAuthHeader(), "Content-Type": "application/x-www-form-urlencoded", }, body: body.toString(), cache: "no-store", }); const data = await res.json().catch(() => ({})); logApiResponse("gooyal", "POST", url, res.status, { ...data, access_token: data.access_token ? "" : undefined, refresh_token: data.refresh_token ? "" : undefined, }); if (!res.ok) { throw new GooyalAuthError(res.status, data.error ?? "refresh_failed", data.error_description); } return data; }