// qbo_helper.js require('dotenv').config(); const OAuthClient = require('intuit-oauth'); let oauthClient = null; const getOAuthClient = () => { if (!oauthClient) { oauthClient = new OAuthClient({ clientId: process.env.QBO_CLIENT_ID, clientSecret: process.env.QBO_CLIENT_SECRET, environment: process.env.QBO_ENVIRONMENT || 'sandbox', redirectUri: process.env.QBO_REDIRECT_URI, token: { access_token: process.env.QBO_ACCESS_TOKEN || '', refresh_token: process.env.QBO_REFRESH_TOKEN || '', realmId: process.env.QBO_REALM_ID } }); } return oauthClient; }; async function makeQboApiCall(requestOptions) { const client = getOAuthClient(); // Funktion zum Aktualisieren des Tokens const doRefresh = async () => { console.log("🔄 QBO Token Refresh wird ausgeführt..."); try { const authResponse = await client.refresh(); console.log("✅ Token erfolgreich erneuert."); return authResponse; } catch (e) { console.error("❌ Refresh fehlgeschlagen:", e); throw e; } }; // 1. Pre-Check: Wenn Token leer ist, sofort refreshen if (!client.token.access_token) { console.log("⚠️ Kein Access Token gefunden. Versuche sofortigen Refresh..."); await doRefresh(); } // 2. Pre-Check: Ist Token laut Zeitstempel abgelaufen? if (!client.isAccessTokenValid()) { console.log("⚠️ Token ist zeitlich abgelaufen. Refresh..."); await doRefresh(); } try { const response = await client.makeApiCall(requestOptions); // Prüfen, ob QBO trotz HTTP 200/400 eine Fehlermeldung im Body sendet const data = response.getJson ? response.getJson() : response.json; if (data.fault && data.fault.error) { const errorCode = data.fault.error[0].code; // Fehler 3202 = Missing Access Token if (errorCode === '3202') { console.log("⚠️ QBO meldet fehlenden Token (3202). Versuche Refresh und Retry..."); await doRefresh(); return await client.makeApiCall(requestOptions); } // Anderen API-Fehler werfen, damit server.js ihn fängt throw new Error(`QBO API Error ${errorCode}: ${data.fault.error[0].message}`); } return response; } catch (e) { // HTTP 401 Unauthorized fangen if (e.response?.status === 401) { console.log("⚠️ 401 Unauthorized. Versuche Refresh und Retry..."); await doRefresh(); return await client.makeApiCall(requestOptions); } throw e; } } module.exports = { getOAuthClient, makeQboApiCall };