diff --git a/src/app/api/creation/execute/route.ts b/src/app/api/creation/execute/route.ts index b1daf6f..e41a994 100644 --- a/src/app/api/creation/execute/route.ts +++ b/src/app/api/creation/execute/route.ts @@ -1,7 +1,7 @@ import { NextRequest } from 'next/server' import { getServerSession } from 'next-auth' import { authOptions } from '@/lib/auth' -import { fetchPendingProducts } from '@/lib/creationSheets' +import { fetchPendingProducts, writeShopifyIdToSheet } from '@/lib/creationSheets' import { generateDescriptions } from '@/lib/openaiClient' import { ensureMetafieldDefinition, setProductMetafield } from '@/lib/shopifyMetafields' import { addProductToCollection } from '@/lib/shopifyCollections' @@ -92,6 +92,7 @@ export async function POST(req: NextRequest) { await prisma.productCreation.create({ data: { userId, sheetTab: product.tab, sheetRow: product.rowNumber, shopifyId, sku: product.sku, title: product.title, status: 'success' }, }) + await writeShopifyIdToSheet(product.tab, product.rowNumber, shopifyId) created++ } catch (err) { const message = err instanceof Error ? err.message : 'Erreur inconnue' diff --git a/src/lib/creationSheets.ts b/src/lib/creationSheets.ts index a739db9..d9a3029 100644 --- a/src/lib/creationSheets.ts +++ b/src/lib/creationSheets.ts @@ -80,6 +80,53 @@ export function parseTabRows(tab: string, headers: string[], rows: string[][], d .filter((p): p is PendingProduct => p !== null) } +/** + * Écrit l'ID Shopify en colonne A de la ligne correspondante dans Google Sheets. + * Utilise un compte de service avec accès éditeur sur la feuille. + */ +export async function writeShopifyIdToSheet(tab: string, rowNumber: number, shopifyId: string): Promise { + const sheetId = process.env.GOOGLE_SHEETS_ID + const email = process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL + const rawKey = process.env.GOOGLE_SERVICE_ACCOUNT_KEY + if (!sheetId || !email || !rawKey) return + + // Génère un JWT pour l'authentification Google + const privateKey = rawKey.replace(/\\n/g, '\n') + const now = Math.floor(Date.now() / 1000) + const header = Buffer.from(JSON.stringify({ alg: 'RS256', typ: 'JWT' })).toString('base64url') + const payload = Buffer.from(JSON.stringify({ + iss: email, + scope: 'https://www.googleapis.com/auth/spreadsheets', + aud: 'https://oauth2.googleapis.com/token', + iat: now, + exp: now + 3600, + })).toString('base64url') + + const { createSign } = await import('crypto') + const sign = createSign('RSA-SHA256') + sign.update(`${header}.${payload}`) + const signature = sign.sign(privateKey, 'base64url') + const jwt = `${header}.${payload}.${signature}` + + const tokenRes = await fetch('https://oauth2.googleapis.com/token', { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: jwt }), + }) + if (!tokenRes.ok) return + const { access_token } = await tokenRes.json() as { access_token: string } + + const range = encodeURIComponent(`${tab}!A${rowNumber}`) + await fetch( + `https://sheets.googleapis.com/v4/spreadsheets/${sheetId}/values/${range}?valueInputOption=RAW`, + { + method: 'PUT', + headers: { Authorization: `Bearer ${access_token}`, 'Content-Type': 'application/json' }, + body: JSON.stringify({ range: `${tab}!A${rowNumber}`, majorDimension: 'ROWS', values: [[shopifyId]] }), + }, + ) +} + export async function fetchPendingProducts( alreadyCreatedRows: Set, tabFilter?: string,