Sanity Webhook同步Stripe产品时Size的_id缺失问题排查
问题:Stripe Webhook无法获取Size对象的_id导致price_id无法回写Sanity
我开发了一个Webhook,可自动触发在Stripe中创建产品,同步标题、尺寸及关联价格,但无法将Stripe生成的price_id回写至Sanity的对应字段。持续收到以下错误:
Size ID is missing for this size: { size: '10x10', price: 100, lookup_key: null, price_id: null }
经确认,每个Size对象在Sanity Vision查询时确实存在_id,但尝试多种解构方式仍无法获取该字段。以下是Webhook代码:
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, { apiVersion: '2024-06-20', }); export async function POST(req: NextRequest) { try { const { _id, title, sizes, image } = await req.json(); if (!title) { console.log('Missing required param: name.'); return NextResponse.json({ error: 'Missing required param: name.' }, { status: 400 }); } console.log('Received product data:', { _id, title, sizes, image }); let stripeProduct; try { stripeProduct = await stripe.products.retrieve(_id); console.log('Product already exists in Stripe:', stripeProduct.id); } catch (error: any) { if (error.code === 'resource_missing')') { stripeProduct = await stripe.products.create({ id: _id, name: title, images: [image], metadata: { sanity_id: _id, }, }); console.log('Created new Stripe product:', stripeProduct.id); } else { throw error; } } for (const size of sizes) { const { size: sizeName, price, price_id, _id: sizeId } = size; console.log('Size object received:', size); console.log('Processing size:', { sizeName, price, price_id, sizeId }); if (!sizeId) { console.error('Size ID is missing for this size:', size); continue; } if (price_id) { console.log('Price ID exists, creating a new price...'); const newPrice = await stripe.prices.create({ unit_amount: price * 100, currency: 'gbp', product: stripeProduct.id, }); await updateSanityPriceId(sizeId, newPrice.id); } else { console.log('No Price ID, creating a new price...'); const newPrice = await stripe.prices.create({ unit_amount: price * 100, currency: 'gbp', product: stripeProduct.id, }); await updateSanityPriceId(sizeId, newPrice.id); } } return NextResponse.json({ message: 'Product and prices synced with Stripe successfully.' }); } catch (error) { console.error('Error syncing with Stripe:', error); return NextResponse.json({ message: 'Internal Server Error' }, { status: 500 }); } } async function updateSanityPriceId(sizeId: string, priceId: string) { try { const response = await fetch(`https://${process.env.NEXT_PUBLIC_SANITY_PROJECT_ID}.api.sanity.io/v2024-06-20/data/mutate/production`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.SANITY_WRITE_TOKEN}`, }, body: JSON.stringify({ mutations: [ { patch: { _id: sizeId, set: { price_id: priceId }, }, }, ], }), }); const result = await response.json(); if (result.error) { console.error('Error from Sanity:', result.error); } else { console.log('Updated Sanity with new price ID:', result); } } catch (error) { console.error('Error updating Sanity with new price ID:', error); } }
解决方案
修复语法错误
代码中catch块存在多余引号,导致代码执行异常:// 错误写法 if (error.code === 'resource_missing')') { // 正确写法 if (error.code === 'resource_missing') { }确认请求体中的Size字段
在POST函数开头打印完整请求数据,确认sizes数组中的每个对象是否真的包含_id:const fullData = await req.json(); console.log('Full request payload:', fullData);调整解构方式
避免解构失败,直接访问字段而非解构:// 替换原解构代码 const sizeName = size.size; const price = size.price; const price_id = size.price_id; const sizeId = size._id; // 直接访问size._id检查Sanity Webhook投影配置
确认Sanity的Webhook是否返回了Size对象的_id字段。在Sanity Webhook设置中,调整Projection参数,确保包含所需字段:{_id, title, sizes[]{_id, size, price, price_id}, image}优化重复代码
原代码中price_id存在/不存在的分支逻辑完全一致,可合并简化:console.log(price_id ? 'Price ID exists, creating a new price...' : 'No Price ID, creating a new price...'); const newPrice = await stripe.prices.create({ unit_amount: price * 100, currency: 'gbp', product: stripeProduct.id, }); await updateSanityPriceId(sizeId, newPrice.id);
内容的提问来源于stack exchange,提问作者MindMapper
相关产品推荐
相关产品推荐

