StripeのAPIを利用して、商品情報や料金情報をサイトに表示する場合、通常Product / Priceの2APIを利用します。
const stripe = new Stripe(env.STRIPE_SECRET_API_KEY, {
apiVersion: '2022-11-15'
});
const products = await stripe.products.list();
const productWithPrice = []
for await (const product of products.data) {
const prices = await stripe.prices.list({
product: product.id
})
productWithPrice.push({
...product,
prices
})
}
return productWithPrice;
今回は別解として、Price APIだけを利用して取得する方法を紹介します。
Stripe APIは、expand
パラメタで追加のデータが取得できる
Stripeでは、取得するデータに含まれるIDを利用して、追加の情報を取得できます。
例えばPrice APIのレスポンスには、料金が紐づいている商品のIDが含まれています。
{
"data": [{
"id": "price_xxx",
"product": "product_xxx",
...
このような値を、List API呼び出し時にexpand
パラメタに指定しましょう。
const prices = await stripe.prices.list({
expand: ['data.product']
})
これによって、レスポンスのproduct
がIDではなく商品情報に変わります。
{
"data": [{
"id": "price_xxx",
"product": {
"id": "product_xxx",
...
expand
で取得したデータを元に整形する
Price APIにexpand
で商品を設定した場合、料金の配列に商品情報が入ります。
しかし実際の場面では、商品ごとにリスト表示した上で、その商品の料金プランを提示します。
そこで取得したデータを整形しましょう。
const prices = await stripe.prices.list({
expand: ['data.product']
})
const products = []
prices.data.forEach(price => {
if (typeof price.product === 'string' || price.product.deleted) {
return
}
const productId = price.product.id
const productIndex = products.findIndex(product => product.id === productId)
const priceToAdd = {
...price,
product: productId
}
if (productIndex > -1) {
products[productIndex].prices.push(priceToAdd)
} else {
products.push({
...price.product,
prices: [priceToAdd]
})
}
})
TypeScriptの場合は、型を作成しておくと便利です。
type ProductWithPrices = Stripe.Product & {
prices: Stripe.Price[]
};
const prices = await stripe.prices.list({
expand: ['data.product']
})
const products: Array<ProductWithPrices> = []
prices.data.forEach(price => {
if (typeof price.product === 'string' || price.product.deleted) {
return
}
const productId = price.product.id
const productIndex = products.findIndex(product => product.id === productId)
const priceToAdd = {
...price,
product: productId
}
if (productIndex > -1) {
products[productIndex].prices.push(priceToAdd)
} else {
products.push({
...price.product,
prices: [priceToAdd]
})
}
})
console.log(products)
関連記事