import { string } from 'alga-js' import refreshTokenHelper from "../../../utils/refreshTokenHelper" import errorHandlingHelper from "../../../utils/errorHandlingHelper" import fetchHelper from "../../../utils/fetchHelper" import getTokenHelper from "../../../utils/getTokenHelper" export default defineEventHandler(async (event) => { const query = getQuery(event) const code = query.code as string | undefined const state = query.state as string | undefined // UID of the order source // If user declined or error occurred on eBay side if (!code || !state) { const errorMsg = encodeURIComponent(query.error_description as string || 'eBay authorization was declined or failed') return sendRedirect(event, `/settings/order-sources?oauth_error=${errorMsg}`, 302) } // Look up the order source by UID let orderSource: any = null let token: string | null = null try { token = await getTokenHelper(event) const res: any = await fetchHelper( event, `models/c_ordersource?$filter=${string.urlEncode(`C_OrderSource_UU eq '${state}'`)}`, 'GET', token, null ) orderSource = res?.records?.[0] } catch (err: any) { try { token = await refreshTokenHelper(event) const res: any = await fetchHelper( event, `models/c_ordersource?$filter=${string.urlEncode(`C_OrderSource_UU eq '${state}'`)}`, 'GET', token, null ) orderSource = res?.records?.[0] } catch (error: any) { const errorMsg = encodeURIComponent('Failed to fetch order source during OAuth callback') return sendRedirect(event, `/settings/order-sources?oauth_error=${errorMsg}`, 302) } } if (!orderSource) { const errorMsg = encodeURIComponent('Order source not found') return sendRedirect(event, `/settings/order-sources?oauth_error=${errorMsg}`, 302) } const orderSourceId = orderSource.id const clientId = orderSource.SHOPWARE_KEY || orderSource.marketplace_key const clientSecret = orderSource.SHOPWARE_SECRET || orderSource.marketplace_secret const ruName = orderSource.ebay_ru_name const environment = orderSource.ebay_environment || 'production' if (!clientId || !clientSecret || !ruName) { const errorMsg = encodeURIComponent('Order source missing eBay credentials') return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_error=${errorMsg}`, 302) } // Exchange authorization code for tokens const tokenUrl = environment === 'sandbox' ? 'https://api.sandbox.ebay.com/identity/v1/oauth2/token' : 'https://api.ebay.com/identity/v1/oauth2/token' const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64') let tokenResponse: any = null try { tokenResponse = await $fetch(tokenUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': `Basic ${credentials}`, }, body: new URLSearchParams({ grant_type: 'authorization_code', code: code, redirect_uri: ruName, }).toString(), }) } catch (err: any) { console.error('eBay token exchange error:', err?.data || err?.message || err) const errorMsg = encodeURIComponent(err?.data?.error_description || 'Failed to exchange authorization code for tokens') return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_error=${errorMsg}`, 302) } if (!tokenResponse?.access_token) { const errorMsg = encodeURIComponent('eBay did not return an access token') return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_error=${errorMsg}`, 302) } // Build token JSON blob to store const tokenBlob = JSON.stringify({ access_token: tokenResponse.access_token, refresh_token: tokenResponse.refresh_token, token_type: tokenResponse.token_type, expires_in: tokenResponse.expires_in, refresh_token_expires_in: tokenResponse.refresh_token_expires_in, obtained_at: new Date().toISOString(), }) // Save tokens to order source in iDempiere try { await fetchHelper(event, `models/c_ordersource/${orderSourceId}`, 'PUT', token, { marketplace_token: tokenBlob, tableName: 'c_ordersource', }) } catch (err: any) { // Try with refreshed token try { token = await refreshTokenHelper(event) await fetchHelper(event, `models/c_ordersource/${orderSourceId}`, 'PUT', token, { marketplace_token: tokenBlob, tableName: 'c_ordersource', }) } catch (error: any) { console.error('Failed to save eBay tokens:', error?.data || error?.message || error) const errorMsg = encodeURIComponent('Tokens obtained but failed to save to order source') return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_error=${errorMsg}`, 302) } } return sendRedirect(event, `/settings/order-sources/${orderSourceId}/edit?oauth_success=1`, 302) })