VibeKoding / Level 2 ยท DeveloperLevel 2 ยท Developer / Integrasi Pembayaran Stripe: Cara Memungut DuitIntegrasi Pembayaran Stripe: Cara Memungut Duit
VK

Integrasi Pembayaran Stripe: Cara Memungut DuitIntegrasi Pembayaran Stripe: Cara Memungut Duit

๐Ÿ“š Level 2 ยท DeveloperLevel 2 ยท Developer ๐ŸŒ Dual Bahasa (ID / EN) โšก VibeKoding Native

Modul praktis Level 2 VibeKoding: Integrasi Pembayaran Stripe: Cara Memungut Duit.Modul praktis Level 2 VibeKoding: Integrasi Pembayaran Stripe: Cara Memungut Duit.

When your product already has pages, authentication, a database, and a basic backend, the next practical question is: how do you charge for it.When your product already has pages, authentication, a database, and a basic backend, the next practical question is: how do you charge for it.

Many people making their first payment integration focus entirely on "how to redirect to the payment page." But what truly determines whether the system is stable is not the button -- it's the entire billing chain: who decides the price, who confirms the payment succeeded, who updates the database, and who grants or revokes access.Many people making their first payment integration focus entirely on "how to redirect to the payment page." But what truly determines whether the system is stable is not the button -- it's the entire billing chain: who decides the price, who confirms the payment succeeded, who updates the database, and who grants or revokes access.

This article is split into two parts:This article is split into two parts:

> ๐Ÿ’ก We recommend completing these chapters before continuing:> ๐Ÿ’ก We recommend completing these chapters before continuing:

>>

> - [From Database to Supabase](../database-supabase/)> - [From Database to Supabase](../database-supabase/)

> - [Using AI to Write API Code and Documentation](../ai-interface-code/)> - [Using AI to Write API Code and Documentation](../ai-interface-code/)

> - [How to Deploy a Web Application](../zeabur-deployment/)> - [How to Deploy a Web Application](../zeabur-deployment/)

  1. What a minimum viable payment system looks like.What a minimum viable payment system looks like.
  2. How to integrate Stripe into your project in the fastest way possible.How to integrate Stripe into your project in the fastest way possible.
  3. How to write prompts so AI can directly add a payment system for you.How to write prompts so AI can directly add a payment system for you.
  4. If you're not building an overseas Stripe project, which payment solutions you should prioritize for different regions.If you're not building an overseas Stripe project, which payment solutions you should prioritize for different regions.
  5. ------

    1. Remember These 3 Principles First1. Remember These 3 Principles First

    If you only remember three things, remember these:If you only remember three things, remember these:

    1. Prices must be determined by the backend -- never trust the amount sent from the frontend.Prices must be determined by the backend -- never trust the amount sent from the frontend.
    2. What actually grants access is the Webhook, not the success page.What actually grants access is the Webhook, not the success page.
    3. Your own database must store the payment status -- don't rely solely on the Stripe dashboard.Your own database must store the payment status -- don't rely solely on the Stripe dashboard.
    4. These three principles are the core boundaries of any payment system. As long as the boundaries are correct, switching between Stripe, PayPal, Alipay, or WeChat Pay is essentially just "the API changes, but the architecture stays the same."These three principles are the core boundaries of any payment system. As long as the boundaries are correct, switching between Stripe, PayPal, Alipay, or WeChat Pay is essentially just "the API changes, but the architecture stays the same."

      2. What Happens If You Skip the Backend and Connect Directly from the Frontend?2. What Happens If You Skip the Backend and Connect Directly from the Frontend?

      This is the most natural idea many people have when building payments for the first time:This is the most natural idea many people have when building payments for the first time:

      • There's already a "Buy" button on the pageThere's already a "Buy" button on the page
      • Can I just let the frontend connect to Stripe directly?Can I just let the frontend connect to Stripe directly?
      • That way I don't need a backend, right?That way I don't need a backend, right?

      If you're just building a fake demo page, this thinking is fine.If you're just building a fake demo page, this thinking is fine.

      But if you're actually collecting real money, this approach usually leads to trouble.But if you're actually collecting real money, this approach usually leads to trouble.

      The most common problems are:The most common problems are:

      1. Prices can be easily tampered withPrices can be easily tampered with
      2. Requests from the browser are sent from the user's own computer. Others can modify the request content.Requests from the browser are sent from the user's own computer. Others can modify the request content.

        1. Sensitive information can be exposedSensitive information can be exposed
        2. Truly important keys, pricing logic, and membership activation logic should never be on the frontend.Truly important keys, pricing logic, and membership activation logic should never be on the frontend.

          1. You can't reliably confirm "whether this payment actually succeeded"You can't reliably confirm "whether this payment actually succeeded"
          2. The user landing on a success page doesn't mean your database has been synced correctly.The user landing on a success page doesn't mean your database has been synced correctly.

            1. Database state will be inconsistentDatabase state will be inconsistent
            2. The user might say "I already paid," but your own system has no record of it.The user might say "I already paid," but your own system has no record of it.

              So the safer division of labor should be:So the safer division of labor should be:

              • Frontend is responsible for: displaying buttons, initiating purchases, redirecting pagesFrontend is responsible for: displaying buttons, initiating purchases, redirecting pages
              • Backend is responsible for: determining prices, creating payment sessions, receiving Webhooks, updating the databaseBackend is responsible for: determining prices, creating payment sessions, receiving Webhooks, updating the database
              ๐Ÿ“– Konsep Penting๐Ÿ“– Core Concept

              The frontend can handle redirections; the backend must handle pricing and confirmation. As long as real money is involved, never put the "final pricing authority" and "post-payment activation logic" on the frontend.The frontend can handle redirections; the backend must handle pricing and confirmation. As long as real money is involved, never put the "final pricing authority" and "post-payment activation logic" on the frontend.

              3. When Is It Appropriate to Start with Stripe?3. When Is It Appropriate to Start with Stripe?

              If you're building any of the following scenarios, Stripe is usually the smoothest starting point:If you're building any of the following scenarios, Stripe is usually the smoothest starting point:

              • SaaS targeting international usersSaaS targeting international users
              • Subscription-based membership productsSubscription-based membership products
              • Digital products, templates, AI credit packsDigital products, templates, AI credit packs
              • Wanting to quickly validate monetization rather than dealing with too many local payment details upfrontWanting to quickly validate monetization rather than dealing with too many local payment details upfront

              If your primary users are in mainland China, Stripe usually wouldn't be your first choice -- I'll cover that in the appendix.If your primary users are in mainland China, Stripe usually wouldn't be your first choice -- I'll cover that in the appendix.

              4. Minimum Viable Payment Chain4. Minimum Viable Payment Chain

              Let's start with the minimum version. As long as this chain works, your payment system has a skeleton.Let's start with the minimum version. As long as this chain works, your payment system has a skeleton.

              mermaid
              flowchart LR user["User"] frontend["Frontend Page"] backend["Your Backend"] checkout["Stripe Checkout"] webhook["Stripe Webhook"] db["Supabase / Business Database"] user -->|"Click Buy"| frontend frontend -->|"Request checkout session"| backend backend -->|"Create Session with backend price"| checkout frontend -->|"Redirect to payment page"| checkout checkout -->|"Send event after payment"| webhook webhook -->|"Verify signature & update status"| backend backend -->|"Write to orders / subscriptions"| db db -->|"Frontend reads latest status after refresh"| frontend
              

              Translating this into plain language:Translating this into plain language:

              1. User clicks a button.User clicks a button.
              2. Frontend asks the backend for a payment link.Frontend asks the backend for a payment link.
              3. Backend creates a payment session using the Stripe secret key.Backend creates a payment session using the Stripe secret key.
              4. User goes to the Stripe page to pay.User goes to the Stripe page to pay.
              5. Stripe notifies you via Webhook that "the payment actually succeeded."Stripe notifies you via Webhook that "the payment actually succeeded."
              6. Your backend then updates the database.Your backend then updates the database.
              7. 5. Standard Sequence Diagram for Initiating a Payment5. Standard Sequence Diagram for Initiating a Payment

                If you prefer looking at more formal system diagrams, here's a sequence diagram:If you prefer looking at more formal system diagrams, here's a sequence diagram:

                mermaid
                sequenceDiagram autonumber actor User as User participant Frontend as Frontend Page participant Backend as Backend API participant Stripe as Stripe Checkout User->>Frontend: Click "Upgrade" or "Buy" Frontend->>Backend: POST /api/billing/create-checkout-session Note right of Frontend: Frontend sends plan / userId / email\nDoes NOT send the final charge amount Backend->>Backend: Validate plan and map to priceId Backend->>Stripe: Create Checkout Session Stripe-->>Backend: Return session.url Backend-->>Frontend: Return payment link Frontend-->>User: Redirect to Stripe payment page User->>Stripe: Complete payment
                

                6. Quick Start6. Quick Start

                If you want to integrate it into your project as fast as possible, just follow these 5 steps.If you want to integrate it into your project as fast as possible, just follow these 5 steps.

                6.1 Step 1: Create Products and Prices in the Stripe Dashboard6.1 Step 1: Create Products and Prices in the Stripe Dashboard

                The purpose of this step is not to "just configure something random" -- it's to clearly define in Stripe what you're selling and how you plan to charge for it.The purpose of this step is not to "just configure something random" -- it's to clearly define in Stripe what you're selling and how you plan to charge for it.

                In Stripe's model:In Stripe's model:

                • Product represents "what you're selling," for example Pro MembershipProduct represents "what you're selling," for example Pro Membership
                • Price represents "how much this costs and on what billing cycle," for example $9.9/month, $99/yearPrice represents "how much this costs and on what billing cycle," for example $9.9/month, $99/year

                Why do this step first?Why do this step first?

                Because later when your backend creates a Checkout Session, you don't pass a raw amount to Stripe -- you pass an existing price_id. Stripe then uses this price_id to generate the actual payment page, amount, currency, and billing cycle.Because later when your backend creates a Checkout Session, you don't pass a raw amount to Stripe -- you pass an existing price_id. Stripe then uses this price_id to generate the actual payment page, amount, currency, and billing cycle.

                If you skip this step, the "create payment link" step later won't work at all.If you skip this step, the "create payment link" step later won't work at all.

                ๐Ÿ“– Konsep Penting๐Ÿ“– Core Concept

                Many beginners feel annoyed when they see Product and Price, thinking they're learning Stripe's internal jargon. But actually, this step is doing something very straightforward: - Define clearly "what you're selling" - Define clearly "how much it costs" - Let the backend later use a stable price_id to create payment links Once you understand this layer, Checkout Sessions won't feel abstract.Many beginners feel annoyed when they see Product and Price, thinking they're learning Stripe's internal jargon. But actually, this step is doing something very straightforward: - Define clearly "what you're selling" - Define clearly "how much it costs" - Let the backend later use a stable price_id to create payment links Once you understand this layer, Checkout Sessions won't feel abstract.

                For a minimum viable subscription system, you need at least these two levels:For a minimum viable subscription system, you need at least these two levels:

                • One ProductOne Product
                • One or more Price entriesOne or more Price entries

                You can open these pages directly:You can open these pages directly:

                • Stripe Dashboard Login: [Dashboard Login](https://dashboard.stripe.com/login)Stripe Dashboard Login: [Dashboard Login](https://dashboard.stripe.com/login)
                • Stripe Products and Prices Management Docs: [Manage products and prices](https://docs.stripe.com/products-prices/manage-prices)Stripe Products and Prices Management Docs: [Manage products and prices](https://docs.stripe.com/products-prices/manage-prices)
                • Stripe Checkout Quickstart Docs: [Build a Stripe-hosted checkout page](https://docs.stripe.com/checkout/quickstart?lang=node)Stripe Checkout Quickstart Docs: [Build a Stripe-hosted checkout page](https://docs.stripe.com/checkout/quickstart?lang=node)
                • Stripe Dashboard Products Page: [Product catalog](https://dashboard.stripe.com/test/products)Stripe Dashboard Products Page: [Product catalog](https://dashboard.stripe.com/test/products)

                We recommend operating in Test mode first -- don't start building in the live environment.We recommend operating in Test mode first -- don't start building in the live environment.

                A typical minimum configuration is:A typical minimum configuration is:

                • Product: Pro PlanProduct: Pro Plan
                • Price 1: pro_monthlyPrice 1: pro_monthly
                • Price 2: pro_yearlyPrice 2: pro_yearly

                When operating in the dashboard, follow this order:When operating in the dashboard, follow this order:

                1. First create a product Pro PlanFirst create a product Pro Plan
                2. Then attach two prices under this productThen attach two prices under this product
                3. Monthly and yearly billing are really just two pricing options for the same productMonthly and yearly billing are really just two pricing options for the same product
                4. After completion, you need to note down at least:After completion, you need to note down at least:

                  • The price_id for the monthly priceThe price_id for the monthly price
                  • The price_id for the yearly priceThe price_id for the yearly price
                  • Your own plan names, e.g. pro_monthly, pro_yearlyYour own plan names, e.g. pro_monthly, pro_yearly

                  If this is your first time in the Stripe Dashboard, think of it this way:If this is your first time in the Stripe Dashboard, think of it this way:

                  • Product determines what's being sold on the payment pageProduct determines what's being sold on the payment page
                  • Price determines how much is charged on the payment pagePrice determines how much is charged on the payment page
                  • What the backend will actually use later is mainly price_idWhat the backend will actually use later is mainly price_id
                  ๐Ÿ“– Konsep Penting๐Ÿ“– Core Concept

                  The most important thing on this page is not the product name, but the price_id. Later, whether you're having AI help integrate the backend or troubleshooting issues yourself, what you'll frequently use is: - STRIPE_PRICE_PRO_MONTHLY - STRIPE_PRICE_PRO_YEARLY - The two price_id values they correspond toThe most important thing on this page is not the product name, but the price_id. Later, whether you're having AI help integrate the backend or troubleshooting issues yourself, what you'll frequently use is: - STRIPE_PRICE_PRO_MONTHLY - STRIPE_PRICE_PRO_YEARLY - The two price_id values they correspond to

                  If you want AI to walk you through the Dashboard configuration first, you can use this prompt:If you want AI to walk you through the Dashboard configuration first, you can use this prompt:

                  text
                  I'm using Stripe for the first time. Don't modify any code yet -- first help me set up the most basic billing configuration in the Stripe Dashboard. Please give me step-by-step instructions based on these official docs: - https://docs.stripe.com/products-prices/manage-prices - https://docs.stripe.com/checkout/quickstart?lang=node My situation: - I want to build the simplest membership billing - Only two plans: monthly and yearly - I don't understand terms like Product and Price yet Please: 1. First explain in simple terms what Product and Price are. 2. Then guide me step by step: which page to open first -> what to click -> what to fill in. 3. Finally remind me what I need to copy from the Dashboard for the backend to use. 4. If I might make mistakes, please remind me to always stay in test mode.
                  

                  6.2 Step 2: Prepare Environment Variables6.2 Step 2: Prepare Environment Variables

                  You typically need at least these environment variables:You typically need at least these environment variables:

                  • STRIPE_SECRET_KEYSTRIPE_SECRET_KEY
                  • STRIPE_WEBHOOK_SECRETSTRIPE_WEBHOOK_SECRET
                  • STRIPE_PRICE_PRO_MONTHLYSTRIPE_PRICE_PRO_MONTHLY
                  • STRIPE_PRICE_PRO_YEARLYSTRIPE_PRICE_PRO_YEARLY
                  • APP_URLAPP_URL
                  • SUPABASE_URLSUPABASE_URL
                  • SUPABASE_SERVICE_ROLE_KEYSUPABASE_SERVICE_ROLE_KEY

                  You can open these pages directly:You can open these pages directly:

                  • Stripe API Keys Docs: [API keys](https://docs.stripe.com/keys)Stripe API Keys Docs: [API keys](https://docs.stripe.com/keys)
                  • Stripe Dashboard API Keys Page: [API Keys](https://dashboard.stripe.com/test/apikeys)Stripe Dashboard API Keys Page: [API Keys](https://dashboard.stripe.com/test/apikeys)
                  • Stripe Webhooks Docs: [Receive Stripe events in your webhook endpoint](https://docs.stripe.com/webhooks)Stripe Webhooks Docs: [Receive Stripe events in your webhook endpoint](https://docs.stripe.com/webhooks)
                  • Stripe Dashboard Webhooks Page: [Workbench Webhooks](https://dashboard.stripe.com/test/workbench/webhooks)Stripe Dashboard Webhooks Page: [Workbench Webhooks](https://dashboard.stripe.com/test/workbench/webhooks)

                  > โš ๏ธ STRIPE_SECRET_KEY and SUPABASE_SERVICE_ROLE_KEY must only be placed on the backend.> โš ๏ธ STRIPE_SECRET_KEY and SUPABASE_SERVICE_ROLE_KEY must only be placed on the backend.

                  ๐Ÿ“– Konsep Penting๐Ÿ“– Core Concept

                  This step is not about "filling up the .env file" -- it's about placing the most sensitive parts of the payment system on the backend: - Stripe's backend secret key - Webhook signature verification secret - Your own price mapping Simply put: The frontend is only responsible for initiating purchases; the real secrets and pricing logic should stay on the server side.This step is not about "filling up the .env file" -- it's about placing the most sensitive parts of the payment system on the backend: - Stripe's backend secret key - Webhook signature verification secret - Your own price mapping Simply put: The frontend is only responsible for initiating purchases; the real secrets and pricing logic should stay on the server side.

                  You can also have AI help organize this step:You can also have AI help organize this step:

                  text
                  Please look at how my project currently stores environment variables, then help me organize the environment variables needed for Stripe. Please refer to these docs: - https://docs.stripe.com/keys - https://docs.stripe.com/webhooks My situation: - I'm a complete beginner - I can't distinguish which variables should go on the frontend vs the backend - I'm not sure whether to edit `.env`, `.env.local`, or another file in the current project Please: 1. First search where environment variables are typically stored in the current project. 2. List the minimum environment variables needed for Stripe integration. 3. Explain in simple terms what each variable does. 4. Tell me which Stripe page to visit to copy each variable. 5. If the project has an example environment variable file, please add the variable names directly.
                  

                  6.3 Step 3: Create a Checkout Session on the Backend6.3 Step 3: Create a Checkout Session on the Backend

                  You don't need to write the API yourself for this step -- just have AI reference the official docs and implement it for you.You don't need to write the API yourself for this step -- just have AI reference the official docs and implement it for you.

                  First, give it these docs:First, give it these docs:

                  • Stripe Checkout Quickstart: [Build a Stripe-hosted checkout page](https://docs.stripe.com/checkout/quickstart?lang=node)Stripe Checkout Quickstart: [Build a Stripe-hosted checkout page](https://docs.stripe.com/checkout/quickstart?lang=node)
                  • Checkout Sessions API: [Create a Checkout Session](https://docs.stripe.com/api/checkout/sessions/create)Checkout Sessions API: [Create a Checkout Session](https://docs.stripe.com/api/checkout/sessions/create)
                  • Subscriptions: [Subscriptions](https://docs.stripe.com/payments/subscriptions)Subscriptions: [Subscriptions](https://docs.stripe.com/payments/subscriptions)

                  Then paste this prompt:Then paste this prompt:

                  text
                  Please look at how my current project's backend code is organized, then help me integrate Stripe payments. Please refer to these official docs: - https://docs.stripe.com/checkout/quickstart?lang=node - https://docs.stripe.com/api/checkout/sessions/create - https://docs.stripe.com/payments/subscriptions My goal is simple: - After the user clicks the buy button, redirect to Stripe's payment page - Only two plans: monthly and yearly - Don't make me decide where to put the code -- look at the project first and place it appropriately Please: 1. First search the project to find the backend entry file, route files, and how environment variables are written. 2. Then reference the official docs to integrate the "create Stripe payment link" step. 3. Don't let me pass the amount myself -- use backend environment variables for pricing. 4. After finishing, tell me which files you changed. 5. Finally, tell me what additional configuration I need to do in the Stripe Dashboard.
                  

                  6.4 Step 4: Redirect to the Payment Page from the Frontend6.4 Step 4: Redirect to the Payment Page from the Frontend

                  The goal of this step is very simple: make the pricing page button call your backend API, then redirect to Stripe Checkout.The goal of this step is very simple: make the pricing page button call your backend API, then redirect to Stripe Checkout.

                  Reference docs:Reference docs:

                  • Stripe Checkout Integration Guide: [Build an integration with Checkout](https://docs.stripe.com/payments/checkout/build-integration)Stripe Checkout Integration Guide: [Build an integration with Checkout](https://docs.stripe.com/payments/checkout/build-integration)

                  Prompt for AI:Prompt for AI:

                  text
                  Help me connect the "Buy" button in my project to Stripe. Requirements: - Don't change the existing page, only modify the button click logic - After clicking, call the backend API to get the payment link, then redirect to Stripe - If there's an error, show a simple message to the user (e.g. "Payment temporarily unavailable, please try again later") Reference docs: https://docs.stripe.com/payments/checkout/build-integration
                  

                  6.5 Step 5: Update Database Status via Webhook6.5 Step 5: Update Database Status via Webhook

                  This is the most critical step.This is the most critical step.

                  ๐Ÿ“– Konsep Penting๐Ÿ“– Core Concept

                  Many people think "the user paid and was redirected to the success page" means everything is done. No. What matters for your system is: Whether Stripe has officially delivered the event to your Webhook, and whether your backend has successfully updated the database status.Many people think "the user paid and was redirected to the success page" means everything is done. No. What matters for your system is: Whether Stripe has officially delivered the event to your Webhook, and whether your backend has successfully updated the database status.

                  You can also have AI implement this directly following Stripe's official Webhook docs -- don't write it by hand.You can also have AI implement this directly following Stripe's official Webhook docs -- don't write it by hand.

                  Reference docs:Reference docs:

                  • Stripe Webhooks: [Receive Stripe events in your webhook endpoint](https://docs.stripe.com/webhooks)Stripe Webhooks: [Receive Stripe events in your webhook endpoint](https://docs.stripe.com/webhooks)
                  • Stripe CLI: [Stripe CLI](https://docs.stripe.com/stripe-cli)Stripe CLI: [Stripe CLI](https://docs.stripe.com/stripe-cli)
                  • Stripe CLI Usage: [Use the Stripe CLI](https://docs.stripe.com/stripe-cli/use-cli)Stripe CLI Usage: [Use the Stripe CLI](https://docs.stripe.com/stripe-cli/use-cli)

                  Prompt for AI:Prompt for AI:

                  text
                  Please continue helping me integrate the "automatically activate after successful payment" step with Stripe. Please refer to these official docs: - https://docs.stripe.com/webhooks - https://docs.stripe.com/stripe-cli - https://docs.stripe.com/stripe-cli/use-cli My goal: - After the user pays, don't just redirect to a success page - Actually change the membership status in my database to activated Please: 1. First search the current project for database-related code and how user status is stored. 2. Then add the Stripe webhook. 3. After successful payment, change the corresponding user to active, or update the membership status field currently used in the project. 4. If the project already has subscription tables, order tables, or user tables, prefer to follow the existing structure. 5. After finishing, tell me which files you changed. 6. Also tell me how to test locally whether this step actually works.
                  

                  7. Prompt for Having AI Quickly Integrate Payments7. Prompt for Having AI Quickly Integrate Payments

                  If you're using tools like Codex, Claude Code, Trae, or Cursor, you can paste the following prompt directly and have it integrate payments into your project.If you're using tools like Codex, Claude Code, Trae, or Cursor, you can paste the following prompt directly and have it integrate payments into your project.

                  text
                  Please help me integrate Stripe payments into the current project. I want to build the simplest membership billing feature that works. My requirements: 1. I'm a complete beginner -- please look at the project yourself first, then decide where to modify the code. 2. Don't make me figure out the directory structure, routing structure, or database structure myself. 3. I only want the simplest version first: two plans, monthly and yearly. 4. After clicking buy, the user should be redirected to the Stripe payment page. 5. After successful payment, the membership status in my database should change to activated. 6. Don't add too many complex features upfront, like coupons, upgrades/downgrades, or complex invoicing. Output requirements: 1. First give me a change plan. 2. Then directly modify the code. 3. Finally tell me how to test step by step locally. 4. If any step requires me to do something in the Stripe Dashboard, give me the link and key points directly.
                  

                  If you want AI to be more tailored to your project, you can also add at the beginning:If you want AI to be more tailored to your project, you can also add at the beginning:

                  • Your frontend frameworkYour frontend framework
                  • Your backend directory structureYour backend directory structure
                  • Your database table namesYour database table names
                  • Whether your current user system uses Supabase Auth or a custom Auth solutionWhether your current user system uses Supabase Auth or a custom Auth solution

                  7.1 Let AI Handle Local Integration Testing Too7.1 Let AI Handle Local Integration Testing Too

                  If you want AI to walk you through the entire local integration testing process, you can use this prompt:If you want AI to walk you through the entire local integration testing process, you can use this prompt:

                  text
                  Please continue helping me get Stripe payments actually working. I want to follow along step by step without guessing. Please refer to the official docs: - https://docs.stripe.com/webhooks - https://docs.stripe.com/stripe-cli - https://docs.stripe.com/stripe-cli/use-cli My goals: 1. Tell me which Stripe pages to open first. 2. Tell me how to get the STRIPE_WEBHOOK_SECRET. 3. Tell me how to use stripe login and stripe listen. 4. Tell me how to verify that checkout.session.completed has successfully reached my local webhook. 5. If the current project needs the frontend and backend running first, tell me the specific commands too. 6. Don't just explain principles -- output actual step-by-step instructions. 7. If I might make a mistake at some step, also tell me what the most common errors look like.
                  

                  8. The 4 Most Common Pitfalls8. The 4 Most Common Pitfalls

                  1. Treating the success page as payment successTreating the success page as payment success
                  2. What actually determines the status is the Webhook, not the frontend redirect.What actually determines the status is the Webhook, not the frontend redirect.

                    1. Letting the frontend pass the amountLetting the frontend pass the amount
                    2. This creates a serious price tampering risk.This creates a serious price tampering risk.

                      1. The Webhook route being pre-processed by express.json()The Webhook route being pre-processed by express.json()
                      2. Stripe signature verification requires the raw request body.Stripe signature verification requires the raw request body.

                        1. Not implementing idempotent handlingNot implementing idempotent handling
                        2. Webhooks may be retried. If you add membership or credits on every retry, you'll have problems.Webhooks may be retried. If you add membership or credits on every retry, you'll have problems.

                          9. One-Sentence Selection Guide9. One-Sentence Selection Guide

                          If you just want to get billing working right now:If you just want to get billing working right now:

                          Your Primary UsersFirst Solution to Try
                          International SaaS / Global usersStripe
                          Mainland China usersAlipay / WeChat Pay
                          Hong Kong or cross-border teamsStripe + local wallet / FPS aggregation solution

                          The specific differences are covered in detail in the appendix.The specific differences are covered in detail in the appendix.

                          ๐Ÿ“– Konsep Penting๐Ÿ“– Core Concept

                          Don't start by thinking "I need to integrate every payment method globally at once." A more practical order is usually: - First pick one primary payment chain based on where your main users are located - Get the minimum viable payment working first - Then add a second or third payment method based on actual user sourcesDon't start by thinking "I need to integrate every payment method globally at once." A more practical order is usually: - First pick one primary payment chain based on where your main users are located - Get the minimum viable payment working first - Then add a second or third payment method based on actual user sources

                          10. Summary10. Summary

                          At this point, you've mastered the most fundamental yet important billing chain:At this point, you've mastered the most fundamental yet important billing chain:

                          1. Frontend initiates the purchase.Frontend initiates the purchase.
                          2. Backend creates a Checkout Session.Backend creates a Checkout Session.
                          3. User pays on the Stripe page.User pays on the Stripe page.
                          4. Stripe notifies the backend via Webhook.Stripe notifies the backend via Webhook.
                          5. Backend updates the database.Backend updates the database.
                          6. Frontend displays the new membership or order status after refresh.Frontend displays the new membership or order status after refresh.
                          7. If you just want to quickly integrate payments into your project, the content above is sufficient. The appendix below can be referenced when you actually encounter issues.If you just want to quickly integrate payments into your project, the content above is sufficient. The appendix below can be referenced when you actually encounter issues.

                            ------

                            Appendix A: The Most Common Objects in StripeAppendix A: The Most Common Objects in Stripe

                            When looking at Stripe docs for the first time, it's easy to get confused by these object names. You really only need to understand these:When looking at Stripe docs for the first time, it's easy to get confused by these object names. You really only need to understand these:

                            ObjectPurposeWhat You Can Think of It As
                            ProductDescribes what you're sellingA product or membership plan
                            PriceDescribes how much it costs and the billing cycleMonthly, yearly, or one-time purchase
                            Checkout SessionStripe-hosted payment flowThe payment page
                            SubscriptionRecurring subscription relationshipAuto-renewing membership
                            CustomerThe paying userCustomer profile in Stripe
                            WebhookAsync notificationStripe telling you "what happened with this payment"

                            Appendix B: Why the success Page Does Not Equal Payment SuccessAppendix B: Why the success Page Does Not Equal Payment Success

                            Many people think "the user paid and was redirected to the success page" means the payment succeeded. This is the most common pitfall.Many people think "the user paid and was redirected to the success page" means the payment succeeded. This is the most common pitfall.

                            A Real-World ScenarioA Real-World Scenario

                            Imagine you built a membership website:Imagine you built a membership website:

                            1. User clicks "Buy Membership"User clicks "Buy Membership"
                            2. Redirected to the Stripe payment pageRedirected to the Stripe payment page
                            3. User enters credit card info and clicks payUser enters credit card info and clicks pay
                            4. Page redirects to your success.htmlPage redirects to your success.html
                            5. You wrote code on the success page: "Since they reached this page, activate their membership"You wrote code on the success page: "Since they reached this page, activate their membership"
                            6. What's the problem?What's the problem?

                              The user might not have paid at all, or might have closed the page mid-payment, but can still directly access success.html.The user might not have paid at all, or might have closed the page mid-payment, but can still directly access success.html.

                              Two Completely Different PathsTwo Completely Different Paths

                              mermaid
                              flowchart TB pay["User completes payment on Stripe"] subgraph unreliable["โŒ Unreliable path: Only checking the success page"] success["Browser redirects to success page"] fake["Frontend code assumes activated"] risk["Risk: page closed / network disconnected / URL forged / never actually paid"] success --> fake --> risk end subgraph reliable["โœ… Reliable path: Based on backend Webhook"] event["Stripe server sends Webhook"] verify["Backend verifies signature"] active["Database officially updated to paid"] event --> verify --> active end pay --> success pay --> event
                              

                              Key differences:Key differences:

                              success Page RedirectWebhook Notification
                              Who initiates itUser's browserStripe's server
                              Can it be forged?Yes, just visit the URL directlyNo, there's signature verification
                              Does it guarantee payment success?Not necessarilyYes, always
                              How does your system know?Frontend code guessesStripe officially notifies

                              What the Complete Flow Should Look LikeWhat the Complete Flow Should Look Like

                              mermaid
                              sequenceDiagram autonumber actor User as User participant Frontend as Your Website participant Stripe as Stripe participant Webhook as Your Backend API participant DB as Database User->>Stripe: Complete payment on Stripe page Note over Stripe: Money actually arrives in Stripe account Stripe-->>Frontend: Browser redirects to success page Note over Frontend: โš ๏ธ This is just a redirect<br/>Does not mean the system has confirmed Stripe->>Webhook: Send Webhook notification<br/>"checkout.session.completed" Note over Webhook: โœ… This is the official notification Webhook->>Webhook: Verify signature<br/>(ensure it's from Stripe, not a hacker) Webhook->>DB: Update user status to "paid" DB-->>Webhook: Save successful Webhook-->>Stripe: Return 200 OK Frontend->>DB: User refreshes page, query status DB-->>Frontend: Return "paid" Note over Frontend: Only now show membership features
                              

                              Potential Issues at Each StepPotential Issues at Each Step

                              Step 1: User pays on StripeStep 1: User pays on Stripe

                              This is the only moment that confirms "money was actually paid":This is the only moment that confirms "money was actually paid":

                              • User enters credit card info and clicks confirmUser enters credit card info and clicks confirm
                              • Bank charges the user's cardBank charges the user's card
                              • Stripe confirms receipt of the fundsStripe confirms receipt of the funds

                              Step 2: Browser redirects to the success page (most problematic)Step 2: Browser redirects to the success page (most problematic)

                              This step is completely unreliable because:This step is completely unreliable because:

                              • User can type yoursite.com/success directly in the browser, accessing it without payingUser can type yoursite.com/success directly in the browser, accessing it without paying
                              • User closes the page mid-payment but had copied the success link earlier, and opens it laterUser closes the page mid-payment but had copied the success link earlier, and opens it later
                              • Network issues cause the redirect to fail, but the money was already charged (user paid but didn't see the success page)Network issues cause the redirect to fail, but the money was already charged (user paid but didn't see the success page)
                              • User hits the back button and pays again, but both times redirect to the same success pageUser hits the back button and pays again, but both times redirect to the same success page

                              Step 3: Stripe sends the WebhookStep 3: Stripe sends the Webhook

                              This is Stripe proactively notifying your server "this payment has been received":This is Stripe proactively notifying your server "this payment has been received":

                              • Only Stripe's server can initiate this requestOnly Stripe's server can initiate this request
                              • The request includes a signature that your backend can verify as genuinely from StripeThe request includes a signature that your backend can verify as genuinely from Stripe
                              • Even if the success page didn't load or the user disconnected, the Webhook is still sentEven if the success page didn't load or the user disconnected, the Webhook is still sent

                              Step 4: Backend verifies the signatureStep 4: Backend verifies the signature

                              Why verify? To prevent hackers from forging notifications.Why verify? To prevent hackers from forging notifications.

                              Without verification, a hacker could send a fake notification to your server: "User A paid $1000." Your system would then activate membership for the hacker.Without verification, a hacker could send a fake notification to your server: "User A paid $1000." Your system would then activate membership for the hacker.

                              The verification process:The verification process:

                              • Stripe generates a signature using a shared secret key for the notification contentStripe generates a signature using a shared secret key for the notification content
                              • Your backend uses the same secret key to verify whether the signature matchesYour backend uses the same secret key to verify whether the signature matches
                              • Match = 100% from Stripe, no match = reject immediatelyMatch = 100% from Stripe, no match = reject immediately

                              Step 5: Update the databaseStep 5: Update the database

                              Only after verification passes, update the database:Only after verification passes, update the database:

                              • Change user status from "pending payment" to "paid"Change user status from "pending payment" to "paid"
                              • Record the order number, amount, and payment timeRecord the order number, amount, and payment time
                              • Activate the corresponding membership permissionsActivate the corresponding membership permissions

                              Step 6: Frontend queries the statusStep 6: Frontend queries the status

                              The success page should not assume "reaching this page means success." The correct approach:The success page should not assume "reaching this page means success." The correct approach:

                              • On page load, send a request to the backend: "Has this user paid?"On page load, send a request to the backend: "Has this user paid?"
                              • Backend queries the database and returns the actual statusBackend queries the database and returns the actual status
                              • Display "activation successful" or "pending confirmation" based on the resultDisplay "activation successful" or "pending confirmation" based on the result

                              A Common MistakeA Common Mistake

                              javascript
                              // Wrong: Activate directly on the success page // success.html if (window.location.pathname === '/success') { // Dangerous! Anyone can access /success activateMembership(); }
                              
                              javascript
                              // Correct: Always query the backend on every refresh // success.html async function checkStatus() { const response = await fetch('/api/user/status'); const data = await response.json(); if (data.paymentStatus === 'paid') { showMemberFeatures(); } else { showPendingMessage(); } }
                              

                              Summary in One SentenceSummary in One Sentence

                              The success page only means "browser redirect succeeded." The Webhook is what means "Stripe has officially confirmed receipt of payment."The success page only means "browser redirect succeeded." The Webhook is what means "Stripe has officially confirmed receipt of payment."

                              Your system must use the Webhook as the source of truth -- never trust the frontend redirect.Your system must use the Webhook as the source of truth -- never trust the frontend redirect.

                              Appendix C: The Most Important Subscription Events to Listen ToAppendix C: The Most Important Subscription Events to Listen To

                              EventMeaningWhat You Typically Do
                              checkout.session.completedFirst subscription activation succeededCreate a local subscription record
                              invoice.paidAuto-renewal succeededExtend the expiration date
                              invoice.payment_failedAuto-charge failedMark risk status and notify the user
                              customer.subscription.deletedSubscription canceledRevoke access or mark as expired

                              Subscription State DiagramSubscription State Diagram

                              mermaid
                              stateDiagram-v2 [*] --> NotStarted: User hasn't purchased NotStarted --> Active: checkout.session.completed Active --> Active: invoice.paid Active --> PastDue: invoice.payment_failed PastDue --> Active: User successfully pays outstanding balance Active --> Canceled: customer.subscription.deleted PastDue --> Canceled: Not recovered before expiration Canceled --> [*] state "Not Activated" as NotStarted state "Membership Active" as Active state "Payment Failed / Pending Recovery" as PastDue state "Canceled / Access Revoked" as Canceled
                              

                              Renewal / Failure / Cancellation Sequence DiagramRenewal / Failure / Cancellation Sequence Diagram

                              mermaid
                              sequenceDiagram autonumber participant Stripe as Stripe participant Webhook as Your Webhook API participant DB as Subscription / Order Table participant App as Your App actor User as User rect rgb(235, 248, 255) Stripe->>Webhook: invoice.paid Webhook->>DB: Extend current_period_end DB-->>Webhook: Update successful Webhook-->>Stripe: 200 OK App-->>User: Membership remains active end rect rgb(255, 247, 237) Stripe->>Webhook: invoice.payment_failed Webhook->>DB: Mark as past_due DB-->>Webhook: Update successful Webhook-->>Stripe: 200 OK App-->>User: Prompt to update payment method end rect rgb(254, 242, 242) Stripe->>Webhook: customer.subscription.deleted Webhook->>DB: Mark as canceled DB-->>Webhook: Update successful Webhook-->>Stripe: 200 OK App-->>User: Stop premium features end
                              

                              Appendix D: How to Choose Other Payment SolutionsAppendix D: How to Choose Other Payment Solutions

                              1. Mainland China1. Mainland China

                              If your primary users are in mainland China, the first choice is still [Alipay](https://open.alipay.com/) and [WeChat Pay](https://pay.wechatpay.cn/).If your primary users are in mainland China, the first choice is still [Alipay](https://open.alipay.com/) and [WeChat Pay](https://pay.wechatpay.cn/).

                              Business model:Business model:

                              Both use a "payment gateway" model. You need to:Both use a "payment gateway" model. You need to:

                              • Apply for merchant qualifications (business license, corporate bank account)Apply for merchant qualifications (business license, corporate bank account)
                              • User payments go directly to your merchant accountUser payments go directly to your merchant account
                              • You handle taxes, refunds, and reconciliation yourselfYou handle taxes, refunds, and reconciliation yourself

                              Technical model:Technical model:

                              Both follow a "backend creates order + frontend triggers payment + backend receives notification" model, same as Stripe.Both follow a "backend creates order + frontend triggers payment + backend receives notification" model, same as Stripe.

                              Alipay integration flow:Alipay integration flow:

                              1. Create an app on the Alipay Open PlatformCreate an app on the Alipay Open Platform
                              2. Configure public/private keys and callback URLConfigure public/private keys and callback URL
                              3. Backend calls the unified order API to generate a payment link or QR codeBackend calls the unified order API to generate a payment link or QR code
                              4. User scans the code or is redirected to payUser scans the code or is redirected to pay
                              5. Alipay sends an async notification to your backend to update the order statusAlipay sends an async notification to your backend to update the order status
                              6. WeChat Pay integration flow:WeChat Pay integration flow:

                                • JSAPI Payment: Suitable for official accounts and mini programs; users pay directly within WeChatJSAPI Payment: Suitable for official accounts and mini programs; users pay directly within WeChat
                                • Native Payment: Generates a QR code on PC; user scans to payNative Payment: Generates a QR code on PC; user scans to pay
                                • H5 Payment: Launches the WeChat App from a mobile browser to payH5 Payment: Launches the WeChat App from a mobile browser to pay

                                Flow: Backend creates order -> gets prepay_id or code_url -> frontend triggers payment -> backend receives notification to confirm successFlow: Backend creates order -> gets prepay_id or code_url -> frontend triggers payment -> backend receives notification to confirm success

                                Reference links:Reference links:

                                • Alipay Open Platform: https://open.alipay.com/Alipay Open Platform: https://open.alipay.com/
                                • WeChat Pay Merchant Docs: https://pay.wechatpay.cn/doc/v3/merchant/WeChat Pay Merchant Docs: https://pay.wechatpay.cn/doc/v3/merchant/

                                2. Hong Kong2. Hong Kong

                                The Hong Kong market is quite mixed. Common combinations:The Hong Kong market is quite mixed. Common combinations:

                                • Bank cards: Visa / MastercardBank cards: Visa / Mastercard
                                • FPS (Faster Payment System): Hong Kong's local instant transfer systemFPS (Faster Payment System): Hong Kong's local instant transfer system
                                • AlipayHK / WeChat Pay HK: Hong Kong versions of Alipay and WeChatAlipayHK / WeChat Pay HK: Hong Kong versions of Alipay and WeChat

                                Recommended combination:Recommended combination:

                                • Use [Stripe](https://stripe.com/hk) for international cards and subscriptionsUse [Stripe](https://stripe.com/hk) for international cards and subscriptions
                                • Use [Airwallex](https://www.airwallex.com/) or [Adyen](https://www.adyen.com/) to supplement local wallets and FPSUse [Airwallex](https://www.airwallex.com/) or [Adyen](https://www.adyen.com/) to supplement local wallets and FPS

                                3. International / Global SaaS3. International / Global SaaS

                                [Stripe](https://stripe.com/)[Stripe](https://stripe.com/)

                                Business model: Payment gatewayBusiness model: Payment gateway

                                • You need to apply for merchant qualifications yourself (in some countries Stripe can handle this for you)You need to apply for merchant qualifications yourself (in some countries Stripe can handle this for you)
                                • User payments go to your Stripe account, then are settled to your bank accountUser payments go to your Stripe account, then are settled to your bank account
                                • You handle tax filing yourselfYou handle tax filing yourself

                                Technical model:Technical model:

                                • Best API experience, clear documentationBest API experience, clear documentation
                                • Supports Checkout (hosted page), Elements (custom form), Payment Links (no-code)Supports Checkout (hosted page), Elements (custom form), Payment Links (no-code)
                                • Webhook notifications for payment statusWebhook notifications for payment status
                                • Supports subscriptions, invoices, multi-currencySupports subscriptions, invoices, multi-currency

                                Best for: International SaaS, indie developers, teams needing flexible customizationBest for: International SaaS, indie developers, teams needing flexible customization

                                Reference link: https://docs.stripe.com/Reference link: https://docs.stripe.com/

                                [PayPal](https://www.paypal.com/)[PayPal](https://www.paypal.com/)

                                Business model: Payment gatewayBusiness model: Payment gateway

                                • User payments go to your PayPal account, then you withdraw to your bankUser payments go to your PayPal account, then you withdraw to your bank
                                • You handle taxes yourselfYou handle taxes yourself

                                Technical model:Technical model:

                                • One-time payments: Place a button on the frontend, backend creates/confirms ordersOne-time payments: Place a button on the frontend, backend creates/confirms orders
                                • Subscriptions: First create Product and Plan, then use SDK to launchSubscriptions: First create Product and Plan, then use SDK to launch
                                • Also requires backend and Webhooks -- don't rely only on frontend callbacksAlso requires backend and Webhooks -- don't rely only on frontend callbacks

                                Best for: International businesses needing an additional channel, users accustomed to paying with PayPalBest for: International businesses needing an additional channel, users accustomed to paying with PayPal

                                Reference link: https://developer.paypal.com/docs/Reference link: https://developer.paypal.com/docs/

                                [Paddle](https://www.paddle.com/)[Paddle](https://www.paddle.com/)

                                Business model: Merchant of Record (MoR)Business model: Merchant of Record (MoR)

                                • Paddle is the "Merchant of Record" -- legally, Paddle collects payment from the userPaddle is the "Merchant of Record" -- legally, Paddle collects payment from the user
                                • Paddle handles global taxes, VAT, refunds, and compliance for youPaddle handles global taxes, VAT, refunds, and compliance for you
                                • User payments go to Paddle; after deducting taxes and fees, Paddle settles with youUser payments go to Paddle; after deducting taxes and fees, Paddle settles with you
                                • You don't need to register a company or handle taxes in each countryYou don't need to register a company or handle taxes in each country

                                Technical model:Technical model:

                                • Paddle.js: Embed a hosted checkout page on the frontendPaddle.js: Embed a hosted checkout page on the frontend
                                • Backend API: Create a transaction, hand it to checkoutBackend API: Create a transaction, hand it to checkout
                                • Webhooks sync subscription statusWebhooks sync subscription status

                                Best for: SaaS teams that don't want to deal with global taxes, especially B2B SaaSBest for: SaaS teams that don't want to deal with global taxes, especially B2B SaaS

                                Reference link: https://developer.paddle.com/Reference link: https://developer.paddle.com/

                                [Lemon Squeezy](https://www.lemonsqueezy.com/)[Lemon Squeezy](https://www.lemonsqueezy.com/)

                                Business model: Merchant of Record (MoR)Business model: Merchant of Record (MoR)

                                • Similar to Paddle, Lemon Squeezy is the "Merchant of Record"Similar to Paddle, Lemon Squeezy is the "Merchant of Record"
                                • Handles global taxes, VAT, and compliance for youHandles global taxes, VAT, and compliance for you
                                • Acquired by Stripe in 2024, but operates independentlyAcquired by Stripe in 2024, but operates independently

                                Technical model:Technical model:

                                • Hosted Checkout: Simplest option -- just generate a payment linkHosted Checkout: Simplest option -- just generate a payment link
                                • Checkout Overlay: Overlay embedded in your pageCheckout Overlay: Overlay embedded in your page
                                • Backend API: Create a checkout with flexible controlBackend API: Create a checkout with flexible control

                                Best for: Indie developers, digital products, software licensingBest for: Indie developers, digital products, software licensing

                                Reference link: https://docs.lemonsqueezy.com/Reference link: https://docs.lemonsqueezy.com/

                                4. Enterprise Solutions4. Enterprise Solutions

                                [Airwallex](https://www.airwallex.com/)[Airwallex](https://www.airwallex.com/)

                                Business model: Payment gateway + global accountsBusiness model: Payment gateway + global accounts

                                • Provides global receiving accounts (similar to virtual bank accounts)Provides global receiving accounts (similar to virtual bank accounts)
                                • Supports multi-currency collection, currency exchange, and payoutsSupports multi-currency collection, currency exchange, and payouts
                                • You handle taxes yourselfYou handle taxes yourself

                                Technical model:Technical model:

                                • Payment Links: Almost no code needed -- generate payment linksPayment Links: Almost no code needed -- generate payment links
                                • Hosted Payment Page: Hosted pageHosted Payment Page: Hosted page
                                • Drop-in / Embedded / Native API: Deep integration with high customizationDrop-in / Embedded / Native API: Deep integration with high customization
                                • Supports Alipay HK, FPS, WeChat Pay, and other local payment methodsSupports Alipay HK, FPS, WeChat Pay, and other local payment methods

                                Best for: Hong Kong teams, cross-border businesses, companies needing multi-currency accountsBest for: Hong Kong teams, cross-border businesses, companies needing multi-currency accounts

                                Reference link: https://www.airwallex.com/docs/Reference link: https://www.airwallex.com/docs/

                                [Adyen](https://www.adyen.com/)[Adyen](https://www.adyen.com/)

                                Business model: Payment gatewayBusiness model: Payment gateway

                                • Enterprise-level payment platform, processing trillions of euros in annual transaction volumeEnterprise-level payment platform, processing trillions of euros in annual transaction volume
                                • Supports online, offline, and mobile omnichannel paymentsSupports online, offline, and mobile omnichannel payments
                                • You handle taxes yourselfYou handle taxes yourself

                                Technical model:Technical model:

                                • Pay by Link: Simplest option -- generate a payment linkPay by Link: Simplest option -- generate a payment link
                                • Drop-in / Components: Standard online integrationDrop-in / Components: Standard online integration
                                • Dashboard can enable Alipay, Alipay HK, PayMe, and other local payment methodsDashboard can enable Alipay, Alipay HK, PayMe, and other local payment methods

                                Best for: Large enterprises, companies needing omnichannel paymentsBest for: Large enterprises, companies needing omnichannel payments

                                Reference link: https://docs.adyen.com/Reference link: https://docs.adyen.com/

                                5. Solution Comparison5. Solution Comparison

                                SolutionBusiness ModelTax HandlingBest For
                                StripePayment gatewayHandle yourselfInternational SaaS, developers
                                PayPalPayment gatewayHandle yourselfInternational supplementary channel
                                PaddleMoRPaddle handles for youB2B SaaS, don't want to manage taxes
                                Lemon SqueezyMoRLS handles for youIndie developers, digital products
                                AdyenPayment gatewayHandle yourselfLarge enterprises
                                AirwallexPayment gateway + accountsHandle yourselfCross-border businesses, Hong Kong teams
                                Alipay/WeChatPayment gatewayHandle yourselfMainland China users

                                6. Choose by Region6. Choose by Region

                                Your MarketRecommended Solution
                                Mainland ChinaAlipay / WeChat Pay
                                Hong KongStripe + Airwallex / Adyen
                                International SaaSStripe (manage taxes yourself) or Paddle (MoR handles taxes)
                                International digital productsStripe / Lemon Squeezy / Paddle
                                Multi-region enterpriseAdyen / Airwallex / Stripe combination