Google Apps Script Web App向Stripe提交嵌套对象失败问题
问题背景
我用Google Apps Script(GAS)开发Web App,监听Stripe Webhook事件并回传数据。提交顶层属性时一切正常,示例代码如下:
const data = await postCustomer(customerId, { name: 'Name', email: 'email@example.com' } )
async function postCustomer(id, args) { const data = await postStripeData(id, args, ['customers']) return data } async function postStripeData(id, args, path1, path2) { const fullPath = makeFullPath(id, path1, path2) const data = await post(getStripeApiUrl() + fullPath + '?key=' + getKey(), args) return data } async function post(url, args) { const response = await UrlFetchApp.fetch(url, { 'method': 'post', 'payload': args }) if (await response.getResponseCode() === 200) { const data = await JSON.parse(response) return data } else { throw new Error("I couldn't post to this url: " + url) } }
问题描述
但提交嵌套对象时请求失败(使用真实地址信息测试):
const data = await postCustomer(customerId, { address: { country: 'US', state: 'CA', city: 'City', postal_code: '00000', line1: 'Line 1', line2: 'Line 2' } })
报错提示address是无效对象,Stripe日志显示接收的格式为:
{ "address": "{line2=Line 2, state=CA, country=US, postal_code=00000, line1=Line 1, city=City}", }
Stripe官方文档有Node.js示例,但无GAS相关内容:
const stripe = require('stripe')('sk_test_51PoHIuFYLeju0XxwXR4z3EHW3oaSqtTlD2Kr2xvUPRzhORHsjssb35rLfw1kbdQsVYdkHiYZ7vmKgWrXic30Y2XN00bvs1FZaO'); const customer = await stripe.customers.update( 'cus_NffrFeUfNV2Hib', { metadata: { order_id: '6735', }, } );
已尝试方案
- 对
address使用JSON.stringify():仍报错,Stripe日志显示:
{ "address": "{\"country\":\"US\"}" }
- 在
post()中对整个payload使用JSON.stringify():返回200响应,但客户信息未更新。 - 将
address作为Blob发送:格式错误,Stripe期望application/x-www-form-urlencoded格式,这也是UrlFetchApp.fetch()的默认格式。
解决方案
问题根源是GAS的UrlFetchApp默认会把嵌套对象直接转成字符串,而Stripe API需要的是表单编码的嵌套格式(比如address[country]=US&address[state]=CA)。
解决步骤:
- 添加工具函数,将嵌套对象转换为符合规范的扁平结构:
function flattenObject(obj, parentKey = '') { let result = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { const newKey = parentKey ? `${parentKey}[${key}]` : key; if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) { Object.assign(result, flattenObject(obj[key], newKey)); } else { result[newKey] = obj[key]; } } } return result; }
- 修改
post()函数,发送前用工具函数处理payload,同时修正原代码中错误的await使用:
async function post(url, args) { // 扁平化嵌套对象 const flattenedPayload = flattenObject(args); const response = UrlFetchApp.fetch(url, { 'method': 'post', 'payload': flattenedPayload, 'contentType': 'application/x-www-form-urlencoded' }); if (response.getResponseCode() === 200) { const data = JSON.parse(response.getContentText()); return data; } else { throw new Error(`请求失败,URL: ${url},响应码: ${response.getResponseCode()}`); } }
修改后,提交嵌套对象时,Stripe会接收到address[country]=US&address[state]=CA这类正确格式的参数,即可正常更新客户信息。
内容的提问来源于stack exchange,提问作者Alex Cap
相关产品推荐
相关产品推荐

