You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter Web中集成Stripe支付网关?新手入门与功能实现

Hey there! Let's break this down step by step since you're new to payment gateways and working with Flutter Web + Stripe. It's totally manageable once you map out the core flows, so let's dive in:

1. First Steps: Get Grounded in Stripe Basics

Since you're new to payment gateways, start by familiarizing yourself with Stripe's core concepts via their official docs. Key terms to learn:

  • Customer: A record of a user in Stripe, linked to their payment methods
  • PaymentIntent: Handles one-time payment flows
  • Subscription & Price: For recurring billing (you'll need a Product + Price setup first)
  • Stripe.js: Stripe's official web SDK that handles the frontend payment UI and security

Important note: Most Flutter Stripe packages (like flutter_stripe) have limited Web support right now, so we'll need to use Dart-JavaScript interop to work directly with Stripe.js in your Flutter Web app.

2. Implementing One-Time Billing

This flow requires both a backend (to handle secure Stripe API calls) and frontend (to collect payment details):

Backend (Example with Node.js)

You'll need to create a PaymentIntent and return its client_secret to the frontend. Never expose your Stripe secret key in the browser!

const stripe = require('stripe')('your_stripe_secret_key');

app.post('/create-payment-intent', async (req, res) => {
  const { amount, currency } = req.body;

  const paymentIntent = await stripe.paymentIntents.create({
    amount: amount, // Amount in cents (e.g., 1000 = $10)
    currency: currency || 'usd',
  });

  res.json({ clientSecret: paymentIntent.client_secret });
});

Frontend (Flutter Web)

Use Dart's dart:js package to interact with Stripe.js. You'll need to load Stripe.js first, then render the payment UI and confirm the payment:

import 'dart:js' as js;
import 'package:http/http.dart' as http;
import 'dart:convert';

void loadStripeScript() {
  // Load Stripe.js from Stripe's CDN
  final script = js.JsObject(js.context['document'].callMethod('createElement', ['script']));
  script['src'] = 'https://js.stripe.com/v3/';
  js.context['document']['head'].callMethod('appendChild', [script]);
}

Future<void> processOneTimePayment(int amount) async {
  // Step 1: Fetch client_secret from your backend
  final response = await http.post(
    Uri.parse('https://your-backend.com/create-payment-intent'),
    body: jsonEncode({'amount': amount}),
    headers: {'Content-Type': 'application/json'},
  );
  final clientSecret = jsonDecode(response.body)['clientSecret'];

  // Step 2: Initialize Stripe instance
  final stripe = js.context['Stripe']?('your_stripe_publishable_key');
  if (stripe == null) return;

  // Step 3: Create and mount Stripe Payment Element
  final elements = stripe.callMethod('elements', [js.jsify({'clientSecret': clientSecret})]);
  final paymentElement = elements.callMethod('create', ['payment']);
  // Mount to an HTML element (use HtmlElementView in Flutter to embed this)
  paymentElement.callMethod('mount', ['#payment-form-container']);

  // Step 4: Confirm payment
  stripe.callMethod('confirmPayment', [js.jsify({
    'elements': elements,
    'confirmParams': {'return_url': 'https://your-app.com/payment-success'},
  })]).then((result) {
    if (result['error'] != null) {
      // Handle payment failure
      print('Payment failed: ${result['error']['message']}');
    } else {
      // Handle payment success
      print('Payment succeeded!');
    }
  });
}

Note: Use HtmlElementView in Flutter Web to embed the Stripe payment form (you'll need to register an HTML element with the ID payment-form-container in your web/index.html).

3. Implementing Recurring Subscriptions

Subscriptions follow a similar flow but involve creating a Subscription object instead of a PaymentIntent:

Backend (Example with Node.js)

First, create a Product and Price (you can do this via Stripe Dashboard or API). Then create a subscription for a customer:

app.post('/create-subscription', async (req, res) => {
  const { customerId, priceId } = req.body;

  const subscription = await stripe.subscriptions.create({
    customer: customerId,
    items: [{ price: priceId }],
    payment_behavior: 'default_incomplete',
    expand: ['latest_invoice.payment_intent'],
  });

  res.json({
    subscriptionId: subscription.id,
    clientSecret: subscription.latest_invoice.payment_intent.client_secret,
  });
});

Frontend (Flutter Web)

First, create a Stripe Customer (either via backend or frontend), then trigger the subscription flow:

Future<String?> createStripeCustomer(String email) async {
  final stripe = js.context['Stripe']?('your_stripe_publishable_key');
  if (stripe == null) return null;
  
  final customer = await stripe.callMethod('customers').callMethod('create', [js.jsify({'email': email})]);
  return customer['id'];
}

Future<void> createSubscription(String customerId, String priceId) async {
  // Fetch subscription client_secret from backend
  final response = await http.post(
    Uri.parse('https://your-backend.com/create-subscription'),
    body: jsonEncode({'customerId': customerId, 'priceId': priceId}),
    headers: {'Content-Type': 'application/json'},
  );
  final data = jsonDecode(response.body);
  
  // Confirm payment (same as one-time flow)
  final stripe = js.context['Stripe']?('your_stripe_publishable_key');
  if (stripe == null) return;

  final elements = stripe.callMethod('elements', [js.jsify({'clientSecret': data['clientSecret']})]);
  stripe.callMethod('confirmPayment', [js.jsify({
    'elements': elements,
    'confirmParams': {'return_url': 'https://your-app.com/subscription-success'},
  })]).then((result) {
    if (result['error'] != null) {
      print('Subscription failed: ${result['error']['message']}');
    } else {
      print('Subscription active! ID: ${data['subscriptionId']}');
    }
  });
}
4. Canceling Recurring Payments

Canceling subscriptions must be done via your backend (since it requires the Stripe secret key). You can either cancel immediately or at the end of the current billing period:

Backend (Example with Node.js)

app.post('/cancel-subscription', async (req, res) => {
  const { subscriptionId } = req.body;

  // Option 1: Cancel immediately
  // const subscription = await stripe.subscriptions.cancel(subscriptionId);
  
  // Option 2: Cancel at the end of the current period
  const subscription = await stripe.subscriptions.update(
    subscriptionId,
    { cancel_at_period_end: true }
  );

  res.json({ status: subscription.status, cancelAt: subscription.cancel_at_period_end ? subscription.current_period_end : null });
});

Frontend (Flutter Web)

Just call your backend endpoint with the subscription ID:

Future<void> cancelSubscription(String subscriptionId) async {
  final response = await http.post(
    Uri.parse('https://your-backend.com/cancel-subscription'),
    body: jsonEncode({'subscriptionId': subscriptionId}),
    headers: {'Content-Type': 'application/json'},
  );
  final data = jsonDecode(response.body);
  print('Subscription status: ${data['status']}');
}
5. Adapting Existing Flutter Stripe Packages for Web

Yes, it's possible, but it requires some familiarity with Flutter plugin development and web JS interop:

  • Check the package's GitHub repo (like flutter_stripe) to see if there's ongoing work on Web support (look for issues tagged "web" or open PRs).
  • If you want to build it yourself: Create a web-specific implementation of the package's platform interface, wrapping Stripe.js calls in Dart methods that match the existing package's API. This way, you can use the same Dart code across mobile and web.
  • Pro tip for beginners: Start with the direct JS interop approach first. Once you're comfortable with Stripe's flows, you can tackle adapting the package if needed—it'll be much easier then.

内容的提问来源于stack exchange,提问作者Georg Panteleev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 12:47:55