/** * Transak API utilities — shared across rFlows and rCart. * * Handles access token management (cached 6 days) and * widget URL generation via Transak's session API. */ let _transakAccessToken: string | null = null; let _transakTokenExpiry = 0; export async function getTransakAccessToken(): Promise { if (_transakAccessToken && Date.now() < _transakTokenExpiry) return _transakAccessToken; const apiKey = process.env.TRANSAK_API_KEY; const apiSecret = process.env.TRANSAK_SECRET; if (!apiKey || !apiSecret) throw new Error("Transak credentials not configured"); const env = process.env.TRANSAK_ENV || 'PRODUCTION'; const baseUrl = env === 'PRODUCTION' ? 'https://api.transak.com' : 'https://api-stg.transak.com'; const res = await fetch(`${baseUrl}/partners/api/v2/refresh-token`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'api-secret': apiSecret, }, body: JSON.stringify({ apiKey }), }); if (!res.ok) { const text = await res.text(); throw new Error(`Transak token refresh failed (${res.status}): ${text}`); } const data = await res.json() as any; _transakAccessToken = data.data?.accessToken || data.accessToken; if (!_transakAccessToken) throw new Error("No accessToken in Transak response"); // Cache for 6 days (tokens valid for 7) _transakTokenExpiry = Date.now() + 6 * 24 * 60 * 60 * 1000; console.log('[transak] Access token refreshed'); return _transakAccessToken; } export async function createTransakWidgetUrl(params: Record): Promise { const accessToken = await getTransakAccessToken(); const env = process.env.TRANSAK_ENV || 'PRODUCTION'; const gatewayUrl = env === 'PRODUCTION' ? 'https://api-gateway.transak.com' : 'https://api-gateway-stg.transak.com'; const res = await fetch(`${gatewayUrl}/api/v2/auth/session`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'access-token': accessToken, }, body: JSON.stringify({ widgetParams: params }), }); if (!res.ok) { const text = await res.text(); // If token expired, clear cache and retry once if (res.status === 401 || res.status === 403) { _transakAccessToken = null; _transakTokenExpiry = 0; const retryToken = await getTransakAccessToken(); const retry = await fetch(`${gatewayUrl}/api/v2/auth/session`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'access-token': retryToken, }, body: JSON.stringify({ widgetParams: params }), }); if (!retry.ok) throw new Error(`Transak widget URL failed on retry (${retry.status}): ${await retry.text()}`); const retryData = await retry.json() as any; return retryData.data?.widgetUrl; } throw new Error(`Transak widget URL failed (${res.status}): ${text}`); } const data = await res.json() as any; return data.data?.widgetUrl; }