Skip to content
Back to skills

Payment Integration

ASecurity

Payment processing integration with Stripe and PayPal for Flutter

  • 4 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 8, 2026
developmentjavascriptgojavanodeexpresstestinggitapibackendsecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 8, 2026

npx -y skills add chimeranext/flutter-boilerplate-monorepo-template --skill payment-integration --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Payment Integration?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Payment Integration
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/chimeranext-payment-integration/badge)](https://www.skillsdirectory.com/skills/chimeranext-payment-integration)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: payment-integration
description: Payment processing integration with Stripe and PayPal for Flutter
keywords: payments, stripe, paypal, billing, subscriptions, ecommerce
---

# Skill 17: Payment Integration

## Overview

This skill provides comprehensive payment processing capabilities for Flutter applications using Stripe and PayPal. Supports one-time payments, subscriptions, and PCI-compliant payment flows.

## Features

- Stripe integration with Payment Intents
- PayPal checkout integration
- PCI DSS compliance (sensitive data never touches your server)
- Subscription management
- Apple Pay and Google Pay support
- Payment method storage
- Webhook handling

## Installation

### Dependencies

```yaml
dependencies:
  flutter_stripe: ^10.0.0
  paypal_sdk: ^1.0.0
  pay: ^1.1.2  # For Apple Pay / Google Pay
```

## Stripe Integration

### 1. Setup

```dart
import 'package:flutter_stripe/flutter_stripe.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize Stripe
  Stripe.publishableKey = 'pk_test_your_key_here';
  await Stripe.instance.applySettings();

  runApp(MyApp());
}
```

### 2. Payment Service

```dart
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class PaymentService {
  final String backendUrl;

  PaymentService({required this.backendUrl});

  /// Create a payment intent on your backend
  Future<Map<String, dynamic>> createPaymentIntent(
    double amount,
    String currency,
  ) async {
    final response = await http.post(
      Uri.parse('$backendUrl/create-payment-intent'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({
        'amount': (amount * 100).toInt(), // Stripe uses cents
        'currency': currency,
      }),
    );

    if (response.statusCode == 200) {
      return jsonDecode(response.body);
    } else {
      throw Exception('Failed to create payment intent');
    }
  }

  /// Present payment sheet
  Future<bool> presentPaymentSheet(String clientSecret) async {
    try {
      // Initialize payment sheet
      await Stripe.instance.initPaymentSheet(
        paymentSheetParameters: SetupPaymentSheetParameters(
          paymentIntentClientSecret: clientSecret,
          merchantDisplayName: '{{PROJECT_NAME}}',
          style: ThemeMode.system,
        ),
      );

      // Display payment sheet
      await Stripe.instance.presentPaymentSheet();

      return true;
    } on StripeException catch (e) {
      if (e.error.code == FailureCode.Canceled) {
        return false; // User canceled
      }
      rethrow;
    }
  }

  /// Create and confirm payment
  Future<bool> makePayment(double amount, String currency) async {
    try {
      // 1. Create payment intent
      final paymentIntent = await createPaymentIntent(amount, currency);

      // 2. Present payment sheet
      final success = await presentPaymentSheet(paymentIntent['clientSecret']);

      return success;
    } catch (e) {
      print('Payment error: $e');
      return false;
    }
  }
}
```

### 3. Payment Provider

```dart
import 'package:flutter_riverpod/flutter_riverpod.dart';

class PaymentState {
  final bool isProcessing;
  final bool paymentSuccess;
  final String? error;

  PaymentState({
    this.isProcessing = false,
    this.paymentSuccess = false,
    this.error,
  });

  PaymentState copyWith({
    bool? isProcessing,
    bool? paymentSuccess,
    String? error,
  }) {
    return PaymentState(
      isProcessing: isProcessing ?? this.isProcessing,
      paymentSuccess: paymentSuccess ?? this.paymentSuccess,
      error: error,
    );
  }
}

class PaymentNotifier extends StateNotifier<PaymentState> {
  final PaymentService _paymentService;

  PaymentNotifier(this._paymentService) : super(PaymentState());

  Future<void> processPayment(double amount, String currency) async {
    state = state.copyWith(isProcessing: true, error: null);

    try {
      final success = await _paymentService.makePayment(amount, currency);

      state = state.copyWith(
        isProcessing: false,
        paymentSuccess: success,
        error: success ? null : 'Payment was cancelled or failed',
      );
    } catch (e) {
      state = state.copyWith(
        isProcessing: false,
        paymentSuccess: false,
        error: e.toString(),
      );
    }
  }
}

final paymentProvider = StateNotifierProvider<PaymentNotifier, PaymentState>(
  (ref) => PaymentNotifier(PaymentService(backendUrl: 'https://your-api.com')),
);
```

### 4. Payment UI

```dart
class PaymentPage extends ConsumerWidget {
  const PaymentPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final paymentState = ref.watch(paymentProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('Payment')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            Text(
              'Total: \$20.00',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(height: 32),
            if (paymentState.isProcessing)
              const CircularProgressIndicator()
            else
              ElevatedButton(
                onPressed: () {
                  ref.read(paymentProvider.notifier)
                      .processPayment(20.00, 'USD');
                },
                child: const Text('Pay Now'),
              ),
            if (paymentState.error != null)
              Text(
                paymentState.error!,
                style: const TextStyle(color: Colors.red),
              ),
            if (paymentState.paymentSuccess)
              const Text(
                'Payment successful!',
                style: TextStyle(color: Colors.green),
              ),
          ],
        ),
      ),
    );
  }
}
```

## Subscription Management

```dart
class SubscriptionService {
  final String backendUrl;

  SubscriptionService({required this.backendUrl});

  Future<Map<String, dynamic>> createSubscription(
    String customerId,
    String priceId,
  ) async {
    final response = await http.post(
      Uri.parse('$backendUrl/create-subscription'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({
        'customerId': customerId,
        'priceId': priceId,
      }),
    );

    return jsonDecode(response.body);
  }

  Future<void> cancelSubscription(String subscriptionId) async {
    await http.post(
      Uri.parse('$backendUrl/cancel-subscription'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({'subscriptionId': subscriptionId}),
    );
  }
}
```

## Apple Pay / Google Pay

```dart
import 'package:pay/pay.dart';

class DigitalWalletPayment extends StatelessWidget {
  final double amount;
  final String currency;

  const DigitalWalletPayment({
    super.key,
    required this.amount,
    required this.currency,
  });

  @override
  Widget build(BuildContext context) {
    return GooglePayButton(
      paymentConfigurationAsset: 'google_pay_config.json',
      paymentItems: [
        PaymentItem(
          label: 'Total',
          amount: amount.toStringAsFixed(2),
          status: PaymentItemStatus.final_price,
        ),
      ],
      type: GooglePayButtonType.pay,
      onPaymentResult: (result) {
        // Handle payment result
        print('Payment result: $result');
      },
    );
  }
}
```

## Security Best Practices

1. **Never store card data** - Use Stripe tokens only
2. **Backend validation** - Always verify payments on server
3. **HTTPS only** - All API calls must use HTTPS
4. **PCI Compliance** - Don't handle raw card numbers
5. **Webhook verification** - Verify Stripe signatures

## Backend Requirements

Your backend must implement:

```javascript
// Node.js/Express example
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

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

  const paymentIntent = await stripe.paymentIntents.create({
    amount,
    currency,
    automatic_payment_methods: { enabled: true },
  });

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

app.post('/webhook', async (req, res) => {
  const sig = req.headers['stripe-signature'];
  const event = stripe.webhooks.constructEvent(
    req.body,
    sig,
    process.env.STRIPE_WEBHOOK_SECRET
  );

  // Handle the event
  switch (event.type) {
    case 'payment_intent.succeeded':
      // Fulfill the purchase
      break;
    case 'payment_intent.payment_failed':
      // Notify user
      break;
  }

  res.json({ received: true });
});
```

## Testing

Use Stripe test cards:
- `4242 4242 4242 4242` - Success
- `4000 0000 0000 9995` - Declined
- `4000 0000 0000 3220` - Requires 3D Secure

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in development →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.