我正在使用 Google Apps 脚本 Web 应用程序来侦听来自 Stripe 的 Webhook 事件以及发回数据。我可以毫无问题地将值发布到顶层属性,例如:
const data = await postCustomer(customerId, {
name: 'Name',
email: '[email protected]'
}
})
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}",
}
文档显示类似,但没有显示 GAS 的示例。这是 Node.js 示例(无论我是否在有效负载对象和嵌套对象中包含尾随逗号,或者是否引用键名称,都没有什么区别):
const stripe = require('stripe')('sk_test_51PoHIuFYLeju0XxwXR4z3EHW3oaSqtTlD2Kr2xvUPRzhORHsjssb35rLfw1kbdQsVYdkHiYZ7vmKgWrXic30Y2XN00bvs1FZaO');
const customer = await stripe.customers.update(
'cus_NffrFeUfNV2Hib',
{
metadata: {
order_id: '6735',
},
}
);
我尝试在
JSON.stringify()
上使用 address
。我收到相同的错误消息,它在日志中显示如下:
{
"address": "{"country":"US"}"
}
我还尝试在
JSON.stringify()
中的整个有效负载上使用 post()
。在这种情况下,我得到了 200 的响应,并且可以成功返回响应,但客户没有得到更新。
我还尝试将
address
作为 Blob 发送,但我真的不知道如何使用它们。错误在于它的格式错误(application/x-www-form-urlencoded
是预期的,这似乎是 UrlFetchApp.fetch()
默认的格式)。
当我看到您提供的网址时,我发现了以下curl命令。
curl https://api.stripe.com/v1/customers/cus_NffrFeUfNV2Hib \
-u "sk_test_09l3shTSTKHYCzzZZsiLl2vA:" \
-d "metadata[order_id]"=6735
在属性包含对象的情况下,似乎使用
"metadata[order_id]"=6735
。如果是
{
address: {
country: 'US',
state: 'CA',
city: 'City',
postal_code: '00000',
line1: 'Line 1',
line2: 'Line 2'
}
}
下面的修改怎么样?
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)
}
}
在当前阶段,Google Apps 脚本使用同步进程。
function postCustomer(id, args) {
const data = postStripeData(id, args, ['customers'])
return data
}
function postStripeData(id, args, path1, path2) {
const fullPath = makeFullPath(id, path1, path2)
const data = post(getStripeApiUrl() + fullPath + '?key=' + getKey(), args)
return data
}
function post(url, args) {
// --- I added the below script.
args = Object.fromEntries(Object.entries(args).flatMap(([k1, v1]) =>
typeof v1 == "object" ? Object.entries(v1).map(([k2, v2]) => [`${k1}[${k2}]`, v2]) : [[k1, v1]]
));
// ---
const response = UrlFetchApp.fetch(url, {
'method': 'post',
'payload': args
})
if (response.getResponseCode() === 200) {
const data = JSON.parse(response)
return data
} else {
throw new Error("I couldn't post to this url: " + url)
}
}
这样,当运行以下脚本时,
const data = postCustomer(customerId, {
address: {
country: 'US',
state: 'CA',
city: 'City',
postal_code: '00000',
line1: 'Line 1',
line2: 'Line 2'
}
});
有效载荷如下。
{
"address[country]": "US",
"address[state]": "CA",
"address[city]": "City",
"address[postal_code]": "00000",
"address[line1]": "Line 1",
"address[line2]": "Line 2"
}