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