DBの無い世界線でECアプリを作ってみた話。〜Stripe Search APIを活用〜
作ったもの
自社でDBを持たず、Stripeのダッシュボードで顧客管理、商品管理、注文管理ができる、LINEチャットコマースアプリを作りました。
友だち追加から商品詳細
単品商品購入手順
定期販売購入手順
定期販売のキャンセル手順
作った経緯
2022年4月に公開されたStripe Search APIにより、Stripeに保存している顧客、注文、商品、といった情報にクエリをかけることができるようになりました。
それにより、「自社でDBを作らなくても、Stripeに保存した情報だけでアプリが作れるのでは?」と思い、一番作り慣れているLINE×ECアプリで実験することにしました。
しかしStripe APIだけでは、以下の処理に対応できません。
- 在庫管理
- トランザクション
- 注文のステータス管理(商品準備中や配送中など)
ECサイトにおいて在庫管理は生命線といれるかもしれません。
しかし、SUZURIのようなオーダーメイドサービスを見て「注文されてから商品を作るビジネスもあるんだ」と思い在庫管理機能をなくしたECアプリを作ってみました。
他にもアパレルで多い予約販売をベースにしたECアプリにも活用でできるかと思います。
使用したStripe API
使用したStripe APIは以下の8つです。
- Search API
- Customer
- Checkout Session
- Product
- Prices
- Invoice
- Billing Portal
- Webhook(APIではないけど)
友だち追加時に使用したAPI
CustomerとSearch APIを活用してます。
const { data: customers } = await stripe.customers.search({ query: `metadata['userId']:'${userId}'` })
if (customers.length === 0) {
const lineProfile = await lineClient.getProfile(userId)
return await stripe.customers.create({
name: lineProfile.displayName || '未設定',
description: userId,
metadata: {
userId
}
})
} else {
return data[0]
}
customer作成時にmetadata
内にuserId
属性を作成することで、search
する際に以下のクエリを書くことで検索できます。
await stripe.customers.search({ query: `metadata['userId']:'${userId}'` })
参考
商品一覧と商品詳細に使用したAPI
ProductとPriceを使用してます。
export interface MsgProductList {
productId: string
priceId: string
name: string
imgUrl: string
amount: number
}
const getProducts = async (): Promise<Stripe.Product[]> => {
const { data } = await stripe.products.list()
return data
}
const products = await getProducts()
const _products: MsgProductList[] = []
await Promise.all(
products.map(async (product) => {
// @ts-ignore
const price = await stripe.prices.retrieve(product.default_price)
_products.push({
productId: product.id,
priceId: price.id,
name: product.name,
imgUrl: product.images[0],
amount: Number(price.unit_amount)
})
})
)
MsgProductList
は自分がLINE Flexメッセージに必要な情報をまとめた型になるため各々でよしなに変更をお願いします。
product
内には、default_price
という値が型に存在しなかったため、@ts-ignore
をさせていただきました。(今後改善されるかも)
商品管理は、Stripeダッシュボードの「商品」より可能です。
定期購入で使用したAPI
定期購入では、checkout.sessions.create
を使用しました。
const { url } = await stripe.checkout.sessions.create({
customer: customerId,
line_items: [
{
price: priceId,
quantity: 1
}
],
shipping_address_collection: {
allowed_countries: ['JP']
},
mode: 'subscription',
payment_method_types: ['card'],
success_url: LINE_FRIEND_URL,
cancel_url: LINE_FRIEND_URL
})
-
shipping_address_collection
でallowed_countries
をJP
のみにすることで、配送先の入力が日本で固定されます。 -
mode
をsubscription
にする。 -
success_url
とcancel_url
をLINE公式アカウント友だち追加URLにすることで、決済終了後に自動的にLINE公式アカウントのトーク画面に遷移します。
定期購入された注文は、Stripeダッシュボードの「支払い」→「サブスクリプション」より確認できます。
定期購入がキャンセルされた注文は、Stripeダッシュボードの「支払い」→「サブスクリプション」→「キャンセル済み」より確認できます。
単品購入で使用したAPI
単品購入には、invoice
を使用しました。
定期購入のようにcheckout.sessions.create
を使用しなった理由は、こちらに記載してます。
await stripe.invoiceItems.create({ customer: customerId, price: priceId })
const { id: invoiceId } = await stripe.invoices.create({
customer: customerId,
payment_settings: { payment_method_types: ['card', 'konbini'] },
collection_method: 'send_invoice',
days_until_due: 7
})
await stripe.invoices.sendInvoice(invoiceId)
const { hosted_invoice_url } = await stripe.invoices.retrieve(invoiceId)
-
payment_method_types
にkonbini
を追加することで、コンビニ決済が可能となります。 -
days_until_due
で支払いまでの有効日数を指定してます。
単品購入商品は、Stripeダッシュボードの「支払い」で確認できます。
しかし、この画面には定期販売の情報も反映されるため、説明列を「Payment for Invoice」でフィルターすればより見やすくなります。
注文履歴&マイページに使用したAPI
注文履歴&マイページには、billingPortal.sessions.create
を使用しました。
const { url } = await stripe.billingPortal.sessions.create({
customer: customer.id,
return_url: LINE_FRIEND_URL
})
-
return_url
には、LINE公式アカウントの友だち追加URLを指定することで、Billing Portal画面から容易にLINE公式アカウントに遷移することができます。
工夫した点
注文履歴
マイページには、Billing Portalを活用しており、注文履歴や定期契約内容、個人情報はすべて確認&変更ができます。
注文履歴には、Billing Portal内の「インボイス履歴」を代替としてます。
しかし、ここに表示される情報はStripe Invoice
が発行された注文のみとなります。
通常のECには定期購入だけでなく単品購入もあり、Stripe Checkout
で定期販売の商品を購入すると自動的にInvoice
が作成されますが、単品商品では作成されません。
そのため、単品購入をCheckout
で処理するのではなくInvoice
で処理する必要があります。
クロスセル
Stripeダッシュボードで商品には、クロスセルという機能があります。
Checkout Session
にて商品を購入する際、オススメしたい商品を設定することができるので購買率を上げる施策が可能です。
-
Stripeダッシュボード画面
-
Checkout Session画面
まとめ
Stripe Search APIによって、最小限のコストでECアプリが作れました。
在庫管理を妥協しなければならないデメリットはありますが、在庫を持たないビジネスには活用できる開発方法です。
今回紹介したSearch API以外にも活用できそうなものがあるので、興味ある方はぜひ使用してみてください。
今後もStripeのアップデートが楽しみです!
Discussion