85 lines
3.1 KiB
JavaScript
85 lines
3.1 KiB
JavaScript
// 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 (401 Error gefangen)...");
|
|
try {
|
|
const authResponse = await client.refresh();
|
|
console.log("✅ Token erfolgreich erneuert.");
|
|
// Hier müsste man idealerweise die neuen Tokens speichern
|
|
return authResponse;
|
|
} catch (e) {
|
|
console.error("❌ Refresh fehlgeschlagen:", e.originalMessage || e);
|
|
throw e;
|
|
}
|
|
};
|
|
|
|
// --- ÄNDERUNG: KEINE VORAB-PRÜFUNG MEHR ---
|
|
// Wir vertrauen darauf, dass der Token in der .env aktuell ist (da du ihn gerade generiert hast).
|
|
// Wir entfernen client.isAccessTokenValid(), da dies oft falsch negativ ist nach Neustart.
|
|
|
|
try {
|
|
// Versuch 1: Einfach machen!
|
|
const response = await client.makeApiCall(requestOptions);
|
|
|
|
// Prüfen, ob QBO eine Fehlermeldung im Body sendet (trotz HTTP 200/400)
|
|
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 / Invalid
|
|
// Manchmal sendet QBO auch 401 im Body
|
|
if (errorCode === '3202' || errorCode === '3100') {
|
|
console.log(`⚠️ QBO meldet Token-Fehler (${errorCode}). Versuche Refresh und Retry...`);
|
|
await doRefresh();
|
|
return await client.makeApiCall(requestOptions);
|
|
}
|
|
// Anderen API-Fehler werfen (z.B. Validierung)
|
|
throw new Error(`QBO API Error ${errorCode}: ${data.fault.error[0].message}`);
|
|
}
|
|
|
|
return response;
|
|
|
|
} catch (e) {
|
|
// HTTP 401 Unauthorized fangen -> Das ist der ECHTE Indikator, dass der Token abgelaufen ist
|
|
const isAuthError = e.response?.status === 401 || (e.authResponse && e.authResponse.response && e.authResponse.response.status === 401);
|
|
|
|
if (isAuthError) {
|
|
console.log("⚠️ 401 Unauthorized erhalten. Versuche Refresh und Retry...");
|
|
await doRefresh();
|
|
return await client.makeApiCall(requestOptions);
|
|
}
|
|
|
|
// Alle anderen Fehler weiterwerfen
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getOAuthClient,
|
|
makeQboApiCall
|
|
}; |