FunStripe is an F# library that provides a functional wrapper around the Stripe API for payment processing. This guide demonstrates the essential patterns for integrating Stripe payments in your application.
This repository uses FunStripeLite NuGet-package, but usage is identical to full FunStripe, just with a few dependencies removed. This repository is not using the official Stripe.net .NET integration, as avoiding that is exactly one key aims of the alternative, FunStripe.
This sample covers the most important use cases for a minimum viable product (MVP):
- Creating Stripe customers
- Setting up payment methods with Setup Intents
- Processing one-time payments with Payment Intents
- Handling webhooks for payment events
- Frontend integration with Stripe Elements
- .NET 6.0 or later
- Stripe account (test keys for development)
- FunStripeLite NuGet package
First, configure your Stripe keys in your application:
open FunStripe
open FunStripe.StripeModel
open FunStripe.StripeRequest
// Configure your Stripe keys (use test keys for development)
let stripePublishableKey = "pk_test_..."
let stripeSecretKey = "sk_test_..."
// Set up Stripe account configuration
type StripeAccount =
| Live
| Test
let getStripeConfig account =
match account with
| Live -> ("pk_live_...", "sk_live_...")
| Test -> (stripePublishableKey, stripeSecretKey)
let createCustomer (firstName: string) (lastName: string) (email: string) =
async {
let customerRequest = {
CustomerCreateRequest.Default with
Email = Some email
Name = Some $"{firstName} {lastName}"
Description = Some "Sample customer"
}
let! result = StripeRequest.Customer.create customerRequest
return result
}
let createSetupIntent (customerId: string) =
async {
let setupRequest = {
SetupIntentCreateRequest.Default with
Customer = Some customerId
PaymentMethodTypes = ["card"]
Usage = Some SetupIntentUsage.OffSession
}
let! result = StripeRequest.SetupIntent.create setupRequest
return result
}
let createPaymentIntent (amount: int64) (currency: string) (customerId: string) =
async {
let paymentRequest = {
PaymentIntentCreateRequest.Default with
Amount = amount
Currency = currency
Customer = Some (PaymentIntentCustomer'AnyOf.String customerId)
PaymentMethodTypes = ["card"]
ConfirmationMethod = PaymentIntentConfirmationMethod.Automatic
}
let! result = StripeRequest.PaymentIntent.create paymentRequest
return result
}
See the frontend/
directory for complete examples of:
- Stripe Elements configuration
- Card setup forms
- Payment confirmation flows
- Error handling
See the webhooks/
directory for examples of:
- Webhook endpoint setup
- Event verification
- Handling different event types
FunStripeLite uses F# Result types for comprehensive error handling:
let handlePaymentResult result =
match result with
| Ok paymentIntent ->
// Success - process the payment intent
printfn $"Payment created: {paymentIntent.Id}"
| Error stripeError ->
// Handle the error appropriately
printfn $"Error: {stripeError.StripeError.Message}"
All Stripe operations are asynchronous and return Async<Result<'T, StripeError>>
:
let processPayment() =
async {
let! customerResult = createCustomer "John" "Doe" "john@example.com"
match customerResult with
| Ok customer ->
let! paymentResult = createPaymentIntent 2000L "usd" customer.Id
return paymentResult
| Error error ->
return Error error
}
FunStripeLite.Sample/
├── README.md # This file
├── src/
│ ├── Program.fs # Main sample application
│ ├── StripeService.fs # Core Stripe operations
│ └── FunStripeLite.Sample.fsproj
├── frontend/
│ ├── index.html # Sample payment form
│ ├── stripe-integration.js # Stripe Elements integration
│ └── styles.css # Basic styling
└── webhooks/
├── WebhookHandler.fs # Webhook processing
└── Events.fs # Event type definitions
- Never expose secret keys in frontend code - only use publishable keys
- Validate webhook signatures to ensure events come from Stripe
- Use HTTPS for all payment-related endpoints
- Implement proper error handling to avoid exposing sensitive information
Use Stripe's test environment and test card numbers:
- Successful payment:
4242424242424242
- Declined payment:
4000000000000002
- 3D Secure required:
4000002500003155
For production applications, consider implementing:
- Customer portal for managing payment methods
- Subscription billing (if applicable)
- Advanced webhook handling (retries, idempotency)
- Multi-party payments and marketplace features
- Dispute handling workflows