Flink plugin to work with stripe payments
npm install @flink-app/stripe-pluginA comprehensive Flink plugin for integrating Stripe payment processing, including customer management, payment intents, card setup, and Stripe Connect functionality. The plugin provides both API methods and hosted UI pages for payment flows.
- Customer creation and management
- Payment intent creation and confirmation
- Card setup with hosted UI
- Payment capture for authorized payments
- Stripe Connect integration
- Pre-built, customizable payment UI templates
- JWT-based secure token system
- MongoDB-backed session management
- Webhook callback support
- Full TypeScript support
``bash`
npm install @flink-app/stripe-plugin
`typescript
import { FlinkApp } from "@flink-app/flink";
import { stripePlugin } from "@flink-app/stripe-plugin";
function start() {
new FlinkApp
name: "My app",
plugins: [
stripePlugin({
stripeSecreteKey: process.env.STRIPE_SECRET_KEY!,
stripePublishableKey: process.env.STRIPE_PUBLISHABLE_KEY!,
JTW_TOKEN: process.env.JWT_SECRET!,
baseUrl: "/stripe", // optional, defaults to /stripe
redirectUrl: "https://yourapp.com/success", // Where to redirect after successful operations
logo: "https://yourapp.com/logo.png", // Optional logo for payment pages
stripeConnectClientID: process.env.STRIPE_CONNECT_CLIENT_ID, // For Stripe Connect
paymentCallback: (paymentIntentId, status) => {
// Handle successful payments
console.log(Payment ${paymentIntentId} status: ${status});User ${userId} connected to Stripe account ${stripeAccountId}
},
stripeConnectCallback: (userId, stripeAccountId) => {
// Handle Stripe Connect account linking
console.log();`
},
phrases: {
setupDescription: "Add your payment card",
setupButtonText: "Save Card",
setupDoneMessage: "Your card has been saved successfully",
paymentSelectCardPayButtonText: "Pay",
paymentSelectCardChangeCardButtonText: "Change Card",
paymentEnterCardPayButtonText: "Pay",
connectDoneMessage: "Your account has been connected to Stripe",
},
}),
],
}).start();
}
`typescript
import { stripePluginContext } from "@flink-app/stripe-plugin";
export interface AppContext extends FlinkContext
repos: {
// your repos
};
}
`
- stripeSecreteKey (required): Your Stripe secret API keystripePublishableKey
- (required): Your Stripe publishable API keyJTW_TOKEN
- (required): Secret for JWT token generationbaseUrl
- (optional): Base URL for plugin routes (defaults to /stripe)redirectUrl
- (optional): URL to redirect users after successful operationslogo
- (optional): Logo URL to display on payment pagesstripeConnectClientID
- (optional): Client ID for Stripe Connect integrationpaymentCallback
- (optional): Function called when payment succeedsstripeConnectCallback
- (optional): Function called when Stripe Connect linking succeedsphrases
- (optional): Customize UI text for different languagestemplates
- (optional): Override default Handlebars templates for payment pages
#### Create Customer
`typescript`
const customerId = await ctx.plugins.stripePlugin.stripeAPI.customer.create({
email: "customer@example.com",
name: "John Doe",
metadata: {
userId: "user123",
},
});
#### Check if Customer Has Payment Method
`typescript`
const hasCard = await ctx.plugins.stripePlugin.stripeAPI.customer.hasPaymentMethod({
stripeCustomerId: "cus_xxxxx",
});
#### Setup Card Registration
`typescript
const { token, redirectUrl } = await ctx.plugins.stripePlugin.stripeAPI.customer.setupCard({
stripeCustomerId: "cus_xxxxx",
});
// Redirect user to redirectUrl to complete card setup
// Example: https://yourapp.com/stripe/customer/setup-card/JWT_TOKEN
`
#### Connect to Stripe Connect
`typescript
const connectUrl = await ctx.plugins.stripePlugin.stripeAPI.customer.connectToStripeConnect({
userId: "user123",
});
// Redirect user to connectUrl to link their Stripe Connect account
`
#### Create Payment Intent
`typescript
const payment = await ctx.plugins.stripePlugin.stripeAPI.payment.create({
amount: 5000, // Amount in cents ($50.00)
currency: "usd",
customer: "cus_xxxxx",
description: "Order #12345",
capture_method: "automatic", // or "manual" for authorization only
metadata: {
orderId: "order_12345",
},
});
// payment.token - JWT token for payment confirmation
// payment.paymentUrl - URL to redirect user for payment
// payment.paymentIntentId - Stripe payment intent ID
`
#### Confirm Payment
`typescript
const result = await ctx.plugins.stripePlugin.stripeAPI.payment.confirm({
paymentIntentId: "pi_xxxxx",
});
// result.confirmed - true if payment was confirmed
// result.captured - true if payment was captured (only for automatic capture)
// result.token - JWT token if additional action needed
// result.redirectUrl - URL to redirect user if additional action needed
`
#### Create and Confirm Payment (Combined)
`typescript`
const result = await ctx.plugins.stripePlugin.stripeAPI.payment.createAndConfirm({
amount: 5000,
currency: "usd",
customer: "cus_xxxxx",
description: "Order #12345",
});
#### Capture Authorized Payment
For payments created with capture_method: "manual":
`typescript`
const captured = await ctx.plugins.stripePlugin.stripeAPI.payment.capture({
paymentIntentId: "pi_xxxxx",
amount: 5000, // Optional: partial capture amount
});
The plugin provides pre-built, secure payment pages:
1. Generate setup URL:
`typescript`
const { redirectUrl } = await ctx.plugins.stripePlugin.stripeAPI.customer.setupCard({
stripeCustomerId: "cus_xxxxx",
});
2. Redirect user to redirectUrlredirectUrl
3. User enters card details on hosted page
4. User is redirected to your upon completion
1. Create payment intent:
`typescript`
const { paymentUrl } = await ctx.plugins.stripePlugin.stripeAPI.payment.create({
amount: 5000,
currency: "usd",
customer: "cus_xxxxx",
});
2. Redirect user to paymentUrlredirectUrl
3. Plugin automatically detects if customer has saved cards
4. Shows appropriate UI (select saved card or enter new card)
5. Processes payment and redirects to your
The plugin automatically registers these routes:
- GET /stripe/customer/setup-card/:token - Card setup pageGET /stripe/customer/setup-card-done
- - Success page after card setupGET /stripe/payment/confirm/:token
- - Payment confirmation flow entryGET /stripe/payment/select-card/:token
- - Select from saved cardsGET /stripe/payment/enter-card/:token
- - Enter new card detailsGET /stripe/error
- - Error pagePOST /stripe/callback/:event
- - Webhook for payment status updatesGET /stripe/connect
- - Stripe Connect OAuth callback
Configure Stripe webhooks to point to:
``
POST https://yourapp.com/stripe/callback/charge.succeeded
The paymentCallback function will be invoked when payments succeed:
`typescript`
paymentCallback: async (paymentIntentId, status) => {
// Update order status in database
await ctx.repos.orderRepo.updateByPaymentId(paymentIntentId, {
status: status === "succeeded" ? "paid" : "authorized",
});
}
Enable users to receive payments through Stripe Connect:
1. Configure stripeConnectClientID in plugin options`
2. Generate connect URL:typescript`
const url = await ctx.plugins.stripePlugin.stripeAPI.customer.connectToStripeConnect({
userId: "user123",
});url
3. Redirect user to stripeConnectCallback
4. User completes Stripe Connect onboarding
5. is invoked with their Stripe account ID
Override default payment page templates:
`typescript`
stripePlugin({
// ... other options
templates: {
master: customMasterTemplate,
style: customStyleTemplate,
setupCard: customSetupCardTemplate,
setupDone: customSetupDoneTemplate,
error: customErrorTemplate,
paySelectCard: customPaySelectCardTemplate,
payEnterCard: customPayEnterCardTemplate,
connectDone: customConnectDoneTemplate,
},
});
Templates use Handlebars syntax.
Customize text for different languages or branding:
`typescript`
phrases: {
setupDescription: "Lägg till ditt kort",
setupButtonText: "Spara",
setupDoneMessage: "Kortet har sparats",
paymentSelectCardPayButtonText: "Betala",
paymentSelectCardChangeCardButtonText: "Byt kort",
paymentEnterCardPayButtonText: "Betala",
connectDoneMessage: "Kontot har kopplats",
}
This plugin requires MongoDB to be configured for Stripe Connect session management. The plugin automatically creates a ConnectSessionRepo repository.
- Never expose your stripeSecreteKey in client-side codepaymentCallback
- Store all secrets in environment variables
- Use the JWT token system for secure payment URLs
- Validate webhook signatures in production (enhance with signature verification)
- Use HTTPS in production for all payment flows
Use Stripe test mode credentials during development:
- Test secret key: sk_test_...pk_test_...
- Test publishable key:
- Use Stripe's test card numbers
All API methods throw errors that should be caught and handled:
`typescript`
try {
const payment = await ctx.plugins.stripePlugin.stripeAPI.payment.create({
amount: 5000,
currency: "usd",
customer: "cus_xxxxx",
});
} catch (error) {
console.error("Payment creation failed:", error);
// Handle error appropriately
}
The plugin includes comprehensive TypeScript definitions for all options, methods, and responses.
`typescript
// Create customer
const customerId = await ctx.plugins.stripePlugin.stripeAPI.customer.create({
email: user.email,
name: user.name,
});
// Setup their card
const { redirectUrl: setupUrl } = await ctx.plugins.stripePlugin.stripeAPI.customer.setupCard({
stripeCustomerId: customerId,
});
// Redirect user to setupUrl
// Later, create a payment
const hasCard = await ctx.plugins.stripePlugin.stripeAPI.customer.hasPaymentMethod({
stripeCustomerId: customerId,
});
if (hasCard) {
const result = await ctx.plugins.stripePlugin.stripeAPI.payment.createAndConfirm({
amount: 5000,
currency: "usd",
customer: customerId,
description: "Premium subscription",
});
if (result.confirmed && result.captured) {
// Payment successful
await activatePremiumSubscription(user.id);
}
}
``
MIT