JP_Stripes & Cloudflare Meet-up 岡山でAstro / Stripe / Cloudflare Pagesのワークショップを開催しました

AWS Samurai 2023を受賞した古里さんからのお声掛けで、StripeとCloudflareを学べるイベントに参加しました。ワークショップでは、Astro / Stripe / Cloudflare Pagesについて学びました。StripeとCloudflareの連携については、決済とメールの連携があると紹介されました。具体的なコード例も提供されました。また、サブスクリプションの申込後にユーザーアカウントを作成する方法や、決済が完了するまでの処理についても説明されました。ワークショップは好評で、AstroやStripe、Cloudflareに興味がある方は是非参加してみてください。

広告ここから
広告ここまで

目次

    AWS Samurai 2023を受賞された古里さんからお声がけを頂きまして、StripeとCloudflareを一度に学べるイベントに参加してきました。

    いつものJP_Stripesポーズ

    当日のツイートまとめはTogetterにて

    Astro / Stripe / Cloudflare Pagesの山盛りワークショップを開催

    イベントでは、2時間の枠を頂いてワークショップを行いました。

    ワークショップ資料は、Zennにて無料公開しています。

    -> [Stripe x Cloudflareワークショップ] Astroを使って、サブスクリプション申し込みページを作ろう

    ワークショップ内容のその先へ

    Zennの資料からは諸事情で外したのですが、「こんなこともできますよ」を2-3本用意していました。

    せっかくなので、こちらの記事でフォローアップとして紹介します。

    CloudflareのMailChannelsを使って、顧客作成時などにメールを送信する

    サブスクリプションの契約完了時にウェルカムメールを送信するなど、決済とメールの連携はよくあるケースの1つです。

    例えば次のサンプルコードでは、「Stripeに顧客データが作成された(Checkout / Payment Linksなどでサブスク契約が完了した)時点で、MailChannelでメールを送信する」動きを実装しています。

    
                // 顧客の作成が成功した場合にトリガーされる
                case 'customer.created': {
                    const customer = event.data.object
                    await fetch('https://api.mailchannels.net/tx/v1/send', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({
                            personalizations: [{
                                to: [{
                                    email: customer.email,
                                    name: customer.name,
                                }]
                            }],
                            from: {
                                email: import.meta.env.FROM_EMAIL,
                                name: 'XXXサービス'
                            },
                            subject: 'ようこそXXXサービスへ!',
                            content: [
                                {
                                    type: 'text/plain',
                                    value: `オンボーディングのためのコンテンツ`,
                                },
                            ],
                        })
                    })
                    break
                }

    MailChannelsの使い方は、Qiitaに公開されている記事「Cloudflare Workers から MailChannels でメール送信するついでに Cloudflare Pages でコンタクトフォームを作る」をご覧ください。

    Payment Links / Checkout / 料金表での注文内容・数量を取得する

    料金表やPayment Links・Checkoutなどのリンク型・リダイレクト型決済フォームを利用した場合、「クロスセルによる商品の追加提案」や「決済ページでの注文数量の変更」などが行えます。

    参考: Stripe Checkoutを利用した注文ページで、顧客が商品の個数を変更できるようにする

    この場合、Webhookを利用して「実際に顧客が注文した商品と数量」を把握する必要があります。

    料金表・Payment Links・Checkoutいずれの場合でも、checkout.session.completedcheckout.session.async_payment_succeededを利用します。

            const body = event
            switch (event.type) {
    +            case 'checkout.session.completed': {
    +                const session = event.data.object
    +                const lineItems = await stripe.checkout.sessions.listLineItems(session.id)
    +                lineItems.data.forEach(item => {
    +                    const productId = typeof item.price.product === 'string' ? item.price.product : item.price.product.id
    +                    console.log([
    +                        `商品ID: ${productId}`,
    +                        `注文数量: ${item.quantity}`,
    +                        `金額: ${item.amount_total}`
    +                    ].join('\n'))
    +                })
                    break
                }

    顧客データが作成されました。
    Email: [email protected]
    新しいサブスクリプション申し込みがありました。
    開始日: 1682574904
    true: 1400 * 1
    商品ID: prod_LFzTo8Pi8xirKs
    注文数量: 1
    金額: 1400
    商品ID: prod_LFzdDEOEwRtuRw
    注文数量: 1
    金額: 2000

    3DSによる追加の認証やコンビニ決済など、「決済が完了するまで少し時間がかかるケース」が存在します。

    決済完了が非同期の場合は、checkout.session.async_payment_succeededイベントで改めて決済完了後にイベントが送信されます。

    checkout.session.completedにて、payment_statuspaidかどうかを判定しましょう。

    -            case 'checkout.session.completed': {
    +            case 'checkout.session.completed':
    +            case 'checkout.session.async_payment_succeeded': {
                    const session = event.data.object
    +                if (session.payment_status !== 'paid') {
    +                    break
    +                }

    サブスクリプション申込後に、システム側のユーザーアカウントを作成する

    サブスクリプションの申し込みが完了してから、ユーザーアカウントを発行する方法では、Webhookを利用します。

    このケースでは、customer.createdcustomer.subscription.createdcheckout.session.completedのWebhookイベントから、顧客やサブスクリプションの作成時・Checkoutのセッション完了時にユーザーアカウントを発行しましょう。

            switch (event.type) {
                // 顧客の作成が成功した場合にトリガーされる
                case 'customer.created': {
                    const customer = event.data.object
    +                const payload = {
    +                    name: customer.name,
    +                    email: customer.email,
    +                    phone_number: customer.phone,
    +                }
    +                await AnyUserService.createNewUser(payload)
                    console.log([
                        `顧客データが作成されました。`,
                        `Email: ${customer.email}`
                    ].join('\n'))
                    break
                }

    この方法を採用すると、Webhook APIを用意せずにZapierやAWS Step Functionsなどでワークフローを構築できるメリットもあります。

    おわりに

    盛りだくさんな内容のワークショップでしたが、概ね高評価を頂けたので、すごくホッとしています。

    デモサイトを作ったり、他の地域でもこのワークショップを開催できたりすると嬉しいなと思いますので、「AstroやStripe、Cloudflareが気になる!」という方は、お気軽に岡本やJP_Stripesコミュニティにご相談ください。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark