rspace-online/shared/transak.ts

88 lines
2.8 KiB
TypeScript

/**
* 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<string> {
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<string, string>): Promise<string> {
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;
}