import refreshTokenHelper from "../../utils/refreshTokenHelper"; import errorHandlingHelper from "../../utils/errorHandlingHelper"; import fetchHelper from "../../utils/fetchHelper"; // Proxy to JTL-FFN stocks endpoint using credentials stored on Order Source // GET /api/ffn/stocks?orderSourceId=123&$top=50&$skip=0&$orderBy=modificationInfo/createdAt const handleFunc = async (event: any, authToken: any = null) => { const token = authToken ?? await getTokenHelper(event) const query = getQuery(event) const orderSourceId = query.orderSourceId as string if(!orderSourceId) { return { status: 400, message: 'orderSourceId is required' } } // Load order source to get marketplace credentials const os: any = await fetchHelper(event, `models/c_ordersource/${orderSourceId}`, 'GET', token, null) if(!os) { return { status: 404, message: 'Order Source not found' } } if(!(os?.Marketplace?.identifier === 'jtl-ffn' || os?.marketplace === '7' || os?.Marketplace?.id === '7')) { return { status: 400, message: 'Selected Order Source is not JTL-FFN' } } const baseUrl: string = os?.marketplace_url || '' if(!baseUrl) { return { status: 400, message: 'No marketplace_url configured for this Order Source' } } // Build headers: prefer token, fallback to key/secret if present const headers: any = { 'content-type': 'application/json', 'accept': 'application/json' } if(os?.marketplace_token) { // JTL FFN expects the proprietary scheme: Authorization: ffn headers['Authorization'] = `ffn ${os.marketplace_token}` headers['x-application-id'] = 'JPCB0XLOGYOU' headers['x-application-version'] = '0.1' } if(os?.marketplace_key) headers['x-api-key'] = os.marketplace_key if(os?.marketplace_secret) headers['x-api-secret'] = os.marketplace_secret if(os?.jtl_merchantID) headers['x-merchant-id'] = os.jtl_merchantID // Build query string passthrough const params = new URLSearchParams() ;['$top', '$skip', '$orderBy'].forEach(k => { const v = (query as any)[k] if(v !== undefined) params.append(k, String(v)) }) const qs = params.toString() try { // Normalize base URL to ensure protocol exists let host = baseUrl.trim() if(!/^https?:\/\//i.test(host)) host = `https://${host}` host = host.replace(/\/$/, '') // Avoid duplicating path segments if marketplace_url already contains /api/v1/fulfiller let endpoint = '/api/v1/fulfiller/stocks' if(/\/api\/v1\/fulfiller\/stocks\/?$/i.test(host)) { endpoint = '' } else if(/\/api\/v1\/fulfiller\/?$/i.test(host)) { endpoint = '/stocks' } const url = `${host}${endpoint}${qs ? `?${qs}` : ''}` const res = await $fetch(url, { method: 'GET', headers }) return { status: 200, ...res } } catch (err: any) { const data = errorHandlingHelper(err?.data ?? err, err?.data ?? err) const status = Number(data?.status || err?.status || err?.response?.status || 500) const message = data?.message || err?.data?.message || err?.message || 'Failed to fetch FFN stocks' return { status, message } } } export default defineEventHandler(async (event) => { try { return await handleFunc(event) } catch (err: any) { try { const authToken = await refreshTokenHelper(event) return await handleFunc(event, authToken) } catch (error: any) { const data = errorHandlingHelper(err?.data ?? err, error?.data ?? error) if([401, 402, 403, 407].includes(Number(data.status))) { //@ts-ignore setCookie(event, 'user', null) } return data } } })