$30 off During Our Annual Pro Sale. View Details »

Stripe & Next.js + AWS Amplify で会員 + 定期課金機能 / JP_Stripes20210903

Stripe & Next.js + AWS Amplify で会員 + 定期課金機能 / JP_Stripes20210903

Hidetaka Okamoto
PRO

September 03, 2021
Tweet

More Decks by Hidetaka Okamoto

Other Decks in Programming

Transcript

  1. Stripe & Next.js + AWS Amplify
    Ͱձһ + ఆظ՝ۚػೳ
    JP_Stripes Online
    Hidetaka Okamoto #JP_Stripes

    View Slide

  2. H i d e t a k a
    O k a m o t o
    • Digitalcube Co. Ltd.
    • JavaScript Developer
    • WordPress 4.7 / 5.0 / 5.3 Core
    contributor

    View Slide

  3. H i d e t a k a
    O k a m o t o
    • Digitalcube Co. Ltd.
    • JavaScript Developer
    • WordPress 4.7 / 5.0 / 5.3 Core
    contributor
    https://zenn.dev/hideokamoto/books/e961b4bad92429

    View Slide

  4. Agenda
    • ࠷খݶͷ։ൃ޻਺Ͱ༗ྉձһϝσΟΞΛ࡞Δ
    • Next.js / Stripe / AWS AmplifyͰ࣮૷͢Δ
    • ઃܭɾ։ൃ࣌ͷ஫ҙ఺
    • ʮਖ਼͘͠SaaSʹґଘ͢Δʯ
    #JP_Stripes

    View Slide

  5. Agenda
    • ࠷খݶͷ։ൃ޻਺Ͱ༗ྉձһϝσΟΞΛ࡞Δ
    • Next.js / Stripe / AWS AmplifyͰ࣮૷͢Δ
    • ઃܭɾ։ൃ࣌ͷ஫ҙ఺
    • ʮਖ਼͘͠SaaSʹґଘ͢Δʯ
    #JP_Stripes

    View Slide

  6. ؾʹͳΔπʔϧ΍
    ৽ػೳͰ༡Ϳ৔ॴ͕ཉ͍͠

    View Slide

  7. ݸਓαΠτʹ
    શ෦ϒνࠐΜͩ
    #JP_Stripes
    https://wp-kyoto.net Ͱ
    9݄தެ։༧ఆ

    View Slide

  8. • AWS Amplify: Authentication
    • AWS CDK: IaC
    • Stripe: Subscription
    • Algolia: Advanced Search
    • Next.js: Framework
    • Ionic: UI library
    • WordPress: Headless CMS
    • Capacitor / Sentry / etc…
    #JP_Stripes
    ٕज़ελοΫ

    View Slide

  9. ༗ྉձһαΠτ։ൃͷγϣʔτΧοτίʔε
    • ෳࡶͳػೳ͸͢΂ͯSaaS / Frameworkʹ೚ͤΔ
    • ΞϓϦ͸ʮAPIΛΑͼͩ͢ʯʮAPIͷ݁ՌΛදࣔ͢ΔʯʹಛԽ
    • ʮܾࡁʯͱʮೝূೝՄʯΛͲΕ͚ͩ࠷୹ڑ཭Ͱ࡞ΕΔ͔͕伴
    • ೝূೝՄ: Auth0 / Cognito / Firebase / Superbase / etc…
    • ܾࡁ: Stripe / pay.jp / PayPal / Paidy / etc…
    #JP_Stripes

    View Slide

  10. Stripeͷ
    Low codeܥػೳΛ׆༻
    #JP_Stripes

    View Slide

  11. #JP_Stripes
    SpeakerDeck

    View Slide

  12. SaaS APIΛ׆༻ͯ͠ɺίʔυͷྔΛ཈͑Δ
    • ܾࡁͱܾࡁ؅ཧ͸΄΅ඞͣඞཁʹͳΔػೳཁ݅
    • StripeͰܾࡁ͢Δ৔߹ɺҎԼͷ2఺͕Low CodeԽͰ͖Δ
    • ஫จϑΥʔϜ(Χʔυ / ߪೖऀ৘ใೖྗ) -> Checkout
    • ఆظ՝ۚ৘ใ؅ཧ -> Customer Portal
    • ʮࣗ༝ͱޮ཰ʯͲͬͪΛॏࢹ͢Δ͔ͰಓΛબ΅͏
    #JP_Stripes

    View Slide

  13. Agenda
    • ࠷খݶͷ։ൃ޻਺Ͱ༗ྉձһϝσΟΞΛ࡞Δ
    • Next.js / Stripe / AWS AmplifyͰ࣮૷͢Δ
    • ઃܭɾ։ൃ࣌ͷ஫ҙ఺
    • ʮਖ਼͘͠SaaSʹґଘ͢Δʯ
    #JP_Stripes

    View Slide

  14. Next.js & AWS AmplifyʹStripeΛ૊ΈࠐΉ
    • React AppଆʹStripe JS SDK
    • REST APIଆʹStripe Nodejs SDK
    • CheckoutͱCustomer Portal͚ͩͳΒReact SDK͸ෆཁ
    • React SDK͸Stripe ElementΛ࢖͏ͨΊͷSDK
    • APIΩʔͷऔΓѻ͍ʹ஫ҙʢޙड़ʣ
    #JP_Stripes

    View Slide

  15. SSM·ͨ͸Secret Manager͔ΒAPIΩʔΛऔಘ
    export const createStripeClient = async () => {
    const data = await new SSM({ region: “us-east-1"ɹ})
    .getParameter({
    Name: !!process.env.AWS_LAMBDA_FUNCTION_NAME ? "STRIPE_LIVE_SECRET_KEY":
    "STRIPE_TEST_SECRET_KEY",
    WithDecryption: true,
    }).promise();
    const stripe = new Stripe(data.Parameter?.Value;, {
    apiVersion: "2020-08-27",
    maxNetworkRetries: 3,
    });
    return stripe;
    }; #JP_Stripes

    View Slide

  16. Stripe CustomerͱCognito User poolͷ࿈ܞ
    // Authorization HeaderͳͲͰऔಘͨ͠tokenͰCognito UserΛGet
    const user = await cognito.getUser({
    AccessToken: req.headers.authorization || “"
    }).promise()
    // User attributes͔ΒEmailΛऔಘ
    const emailAttribute = user.UserAttributes.find((data) => data.Name === "email");
    const email = emailAttribute?.Value || “";
    // EmailΛ͔ͭͬͯStripe CustomerΛ࡞੒
    const customer = await stripe.customers.create({ email });
    #JP_Stripes

    View Slide

  17. Stripe CustomerͱCognito User poolͷ࿈ܞ
    // ࡞੒ͨ͠Stripe Customer
    const customer = await stripe.customers.create({ email });
    // User Attributeʹอଘ͢Δ
    await cognito
    .updateUserAttributes({
    AccessToken: req.headers.authorization,
    UserAttributes: [{
    Name: "custom:stripeCustomerId",
    Value: customer.id,
    }],
    }).promise();
    #JP_Stripes

    View Slide

  18. Customer idΛηοτͯ͠checkout.sessions.create
    const session = await stripe.checkout.sessions.create({
    customer: customerId,
    allow_promotion_codes: true,
    line_items: [{
    price: price.id,
    quantity: 1,
    }],
    mode: "subscription",
    success_url: `${appUrl.replace(/\/$/, "")}/mypages/subscriptions`,
    cancel_url: `${appUrl.replace(/\/$/, "")}/mypages/plans`,
    payment_method_types: ["card"],
    });
    res.status(200).json({ session_id: session.id });
    #JP_Stripes

    View Slide

  19. Customer Portal͸Customer IDΛ࢖͏
    // Cognito͔ΒϢʔβʔΛऔಘ
    const user = await cognito.getUser({ AccessToken: req.headers.authorization }).promise()
    const attribute = user.UserAttributes.find((data) => {
    return data.Name === “custom:stripeCustomerId"
    });
    // Customer Poral SessionΛ࡞੒
    const session = await stripe.billingPortal.sessions.create({
    customer: attribute?.Value,
    return_url: `${appUrl.replace(/\/$/, "")}/mypages/subscriptions`,
    });
    res.status(200).json({ url: session.url });
    #JP_Stripes

    View Slide

  20. #JP_Stripes
    ໘౗ͳ
    ੥ٻ؅ཧܥը໘͕
    ͨͬͨ4ߦͰ࡞ΕΔ

    View Slide

  21. APIͰϙʔλϧͷURLΛੜ੒ͯ͠ϦμΠϨΫτ
    const { push } = useRouter();
    return ( {
    const session = await Auth.currentSession();
    const token = session.getAccessToken().getJwtToken();
    const data = await fetch("/api/portal", {
    method: "POST",
    headers: {
    "Content-Type": "application/json",
    Authorization: token,
    },
    }).then(data => data.json());
    push(data.url);
    }}>Button)
    #JP_Stripes

    View Slide

  22. ࣮૷࣌ͷϙΠϯτ
    1. StripeͷCustomer IDΛϢʔβʔ৘ใͱඥ͚ͮΔඞཁ͋Γ
    • Customer Portal Linkͷੜ੒͸αʔόʔଆॲཧ
    2. Customer Portalʹग़͢ίϯςϯπͷ੍ޚ͸ݪଇDashboard
    • API͔ΒͳΒઃఆ͸ෳ਺࡞ΕΔ໛༷ʢະݕূʣ
    3. Stripe Secret APIΩʔͷѻ͍͕ෆ҆ͳΒ੍ݶ෇͖ΩʔΛ࢖͓͏
    #JP_Stripes

    View Slide

  23. Agenda
    • ࠷খݶͷ։ൃ޻਺Ͱ༗ྉձһϝσΟΞΛ࡞Δ
    • Next.js / Stripe / AWS AmplifyͰ࣮૷͢Δ
    • ઃܭɾ։ൃ࣌ͷ஫ҙ఺
    • ʮਖ਼͘͠SaaSʹґଘ͢Δʯ
    #JP_Stripes

    View Slide

  24. ར༻ن໿ϖʔδͱ
    ϓϥΠόγʔϙϦγʔϖʔδ
    ͸ొ࿥ඞਢ
    #JP_Stripes

    View Slide

  25. #JP_Stripes
    AWS Amplify͸
    Next.jsΛLambda@edge
    Ͱ࣮ߦ͢Δ

    View Slide

  26. #JP_Stripes
    ͍͍ͩͨ
    ͜Εͩͱࢥͬͯ
    ѻ͓͏

    View Slide

  27. ΞϓϦ֎ͰStripeͷσʔλ͕มΘΔ͜ͱʹ஫ҙ
    • ϓϥϯมߋɾղ໿ɾϢʔβʔ৘ใͷมߋͳͲͷૢ࡞
    • Customer PortalͰى͖ͨมߋΛγεςϜʹ൓өͤ͞Δඞཁ͕͋Δ
    • Stripe WebhookͰΠϕϯτΛड͚ͯσʔλΛมߋ͠Α͏
    • Customer Portalʹ͸ʮCustomer࡟আʯ͕ݱঢ়ͳ͍
    1. Subscriptions.delete WebhookͰσʔλΛফ͢
    2. CognitoͳͲͷϢʔβʔ࡟আ࣌ʹফ͢Α͏ʹγεςϜΛߏங
    #JP_Stripes

    View Slide

  28. ඞཁͳAPIΛݺͼग़ͯ͠
    ػೳΛ։ൃ͢Δ

    ඞཁͳWebhookΠϕϯτΛ
    Subscribeͯ͠։ൃ͢Δ

    View Slide

  29. Agenda
    • ࠷খݶͷ։ൃ޻਺Ͱ༗ྉձһϝσΟΞΛ࡞Δ
    • Next.js / Stripe / AWS AmplifyͰ࣮૷͢Δ
    • ઃܭɾ։ൃ࣌ͷ஫ҙ఺
    • ʮਖ਼͘͠SaaSʹґଘ͢Δʯ
    #JP_Stripes

    View Slide

  30. ઃఆ߲໨͸೔ʹ೔ʹ૿Ճ͍ͯ͠Δ

    View Slide

  31. Customer Portalͱ
    ಉ౳ͷػೳΛ
    ࣗલͰ։ൃɾఏڙͰ͖Δ͔ʁ

    View Slide

  32. ίΞϏδωεྖҬ֎ͷػೳΛ୭͕࡞Δ͔ʁ
    A. ࣗྗ։ൃ͢Δ͜ͱͰɺσβΠϯ΍࢓༷ͷࣗ༝౓Λ֬อͰ͖Δ
    • ػೳ͕૿͑Δͱอकɾӡ༻ͷൣғ΋૿͑Δ
    • ͦͷࣗ༝Λ׆༻Ͱ͖Δ͚ͩͷ։ൃϦιʔε͕͋Δ͔൱͔
    B. SaaS / Low Codeʹҕৡͯ͠ɺॏཁͳػೳʹूத͢Δ
    • ϕϯμʔ͕࠷దͱ͢ΔUI΍ػೳΛৗʹड͚औΕΔ
    • υϝΠϯ΍σβΠϯɾػೳͷ੍໿Λڐ༰Ͱ͖Δ͔൱͔ #JP_Stripes

    View Slide

  33. ΠϕϯτۦಈͳγεςϜ͔ͩΒͰ͖Δ͜ͱ
    #JP_Stripes
    • Checkout / Customer Portal͸WebhookͰγεςϜͱ࿈ܞ͢Δ࢓૊Έ
    • ϓϥϯมߋͳͲͷΠϕϯτΛड͚ͯಈ࡞͢ΔγεςϜʹͳΔ
    • ʮಉ͡ΠϕϯτΛൃՐͰ͖Ε͹ʯ͍ͭͰ΋ஔ͖׵͑Ͱ͖Δ
    • ্ཱͪ͛࣌͸྆ػೳΛ࢖ͬͯίΞ։ൃʹϦιʔεΛूத͢Δ
    • Ҡߦ͢Δ࣌͸ɺΠϕϯτ୯ҐͰஈ֊తʹ੾Γସ͍͑ͯ͘
    • ʮΠϕϯτۦಈΞʔΩςΫνϟʯ΁ͷୈҰาʹ

    View Slide

  34. More info

    View Slide

  35. ϝʔϧͰߋ৽৘ใΛ
    ͬ͟ͱݟͰ͖Δ
    Developer Digest
    #JP_Stripes
    https://stripe.dev/

    View Slide

  36. https://www.youtube.com/stripedevelopers

    View Slide

  37. Thanks!
    • ࠷খݶͷ։ൃ޻਺Ͱ༗ྉձһϝσΟΞΛ࡞Δ
    • Next.js / Stripe / AWS AmplifyͰ࣮૷͢Δ
    • ઃܭɾ։ൃ࣌ͷ஫ҙ఺
    • ʮਖ਼͘͠SaaSʹґଘ͢Δʯ
    #JP_Stripes

    View Slide