Stripe Integration Implementation
✅ What's Been Implemented
1. StripeService (FishingLog.API/Services/StripeService.cs)
Core Stripe API wrapper service providing:
-
Payment Intents
CreatePaymentIntentAsync()- Create payment intents for one-time paymentsConfirmPaymentIntentAsync()- Confirm payment intentsGetPaymentIntentAsync()- Retrieve payment intent details
-
Refunds
CreateRefundAsync()- Process refunds for charges
-
Customers
CreateOrGetCustomerAsync()- Create or retrieve Stripe customers
-
Subscriptions
CreateSubscriptionAsync()- Create subscriptionsCancelSubscriptionAsync()- Cancel subscriptions (immediate or at period end)
-
Checkout Sessions
CreateCheckoutSessionAsync()- Create Stripe Checkout sessions for payments/subscriptions
-
Webhook Verification
ConstructWebhookEvent()- Verify webhook signatures
2. StripeWebhookController (FishingLog.API/Controllers/StripeWebhookController.cs)
Handles all Stripe webhook events:
Payment Events:
payment_intent.succeeded- Updates tournament registrations, bookings, and advertiser paymentspayment_intent.payment_failed- Marks payments as failed
Charge Events:
charge.refunded- Updates refund status in databasecharge.dispute.created- Logs disputes (can be extended for dispute handling)
Invoice Events:
invoice.payment_succeeded- Updates advertiser invoice statusinvoice.payment_failed- Marks invoices as overdue
Subscription Events:
customer.subscription.created- Handles new subscriptionscustomer.subscription.updated- Updates subscription statuscustomer.subscription.deleted- Handles subscription cancellationscustomer.subscription.paused- Updates subscription to pausedcustomer.subscription.resumed- Updates subscription to activecustomer.subscription.trial_will_end- Can trigger notifications
3. Updated AdminPaymentController
- Real Refund Processing: Now calls Stripe API to process refunds instead of just marking in database
- Error Handling: Proper error handling and logging
- Audit Logging: All refunds are logged with Stripe refund IDs
4. Payment Intent Integration in Controllers ✅
TournamentController (FishingLog.API/Controllers/TournamentController.cs)
- ✅ Payment intent creation in
RegisterForTournament()method - ✅ Creates payment intent when
RequiresPaymentis true andEntryFee > 0 - ✅ Stores
StripePaymentIntentIdin registration - ✅ Returns
StripeClientSecretfor frontend payment confirmation - ✅ Error handling with graceful fallback
CharterController (FishingLog.API/Controllers/CharterController.cs)
- ✅ Payment intent creation in
BookCharter()method - ✅ Creates payment intent when
TotalPrice > 0 - ✅ Stores
PaymentIntentIdin booking - ✅ Returns
StripeClientSecretfor frontend payment confirmation - ✅ Error handling with graceful fallback
AdvertiserController (FishingLog.API/Controllers/AdvertiserController.cs)
- ✅
POST /api/advertiser/{id}/payments/top-up- Top-up payment intent endpoint - ✅
POST /api/advertiser/{id}/payments/subscription- Subscription checkout endpoint - ✅ Automatic Stripe customer creation/retrieval
- ✅ Payment records created in database
- ✅ Returns
StripeClientSecretor checkout URL for frontend
🔧 Configuration
appsettings.json
{
"Stripe": {
"PublishableKey": "pk_test_...",
"SecretKey": "sk_test_...",
"WebhookSecret": "whsec_...",
"ApiVersion": "2025-11-17.clover"
}
}
appsettings.Development.json
Uses Stripe CLI webhook secret for local development.
🧪 Testing
Local Testing with Stripe CLI
-
Start Stripe CLI listener:
stripe listen --forward-to localhost:5001/api/stripe/webhook -
Trigger test events:
stripe trigger payment_intent.succeeded
stripe trigger payment_intent.payment_failed
stripe trigger charge.refunded -
Check logs in your application to see webhook events being processed.
Testing Refunds
- Create a test payment intent
- Confirm the payment
- Use the admin API to refund:
POST /api/admin/payments/tournament-registration/{id}/refund
{
"amount": 50.00,
"reason": "Customer requested refund"
}
✅ Integration Status
All payment intent integrations are complete! The following endpoints are ready for frontend integration:
- Tournament Registration - Returns
StripeClientSecretwhen payment required - Charter Booking - Returns
StripeClientSecretwhen booking has price - Advertiser Top-Up - Returns
StripeClientSecretfor payment confirmation - Advertiser Subscription - Returns checkout URL for redirect
Frontend can use the returned StripeClientSecret values with Stripe.js to confirm payments. Webhooks will automatically update the database when payments succeed.
📋 Next Steps (Future Enhancements)
-
Stripe Connect Integration
- Set up connected accounts for tournament organizers
- Handle account verification
- Transfer funds to organizers
-
Payment Retry Logic
- Automatically retry failed payments
- Notify users of payment failures
-
Dispute Handling
- Create Dispute entity to track disputes
- Notify admins when disputes are created
- Handle dispute resolution
-
Subscription Management
- Store Stripe customer ID in User entity
- Link subscriptions to users
- Handle subscription lifecycle events
-
Email Notifications
- Send emails on payment success/failure
- Notify users of refunds
- Subscription trial ending notifications
🔒 Security Notes
- ✅ Webhook signatures are verified
- ✅ CSRF protection disabled for webhook endpoint (not needed)
- ✅ Request body buffering enabled for signature verification
- ✅ All Stripe API calls use secret key from configuration
- ⚠️ Never commit API keys to git
- ⚠️ Use environment variables in production
📚 API Endpoints
Webhook Endpoint
POST /api/stripe/webhook- Receives Stripe webhook events
Payment Endpoints
POST /api/tournament/{id}/register- Tournament registration (returnsStripeClientSecretif payment required)POST /api/charter/listings/{id}/book- Charter booking (returnsStripeClientSecretif price > 0)POST /api/advertiser/{id}/payments/top-up- Advertiser account top-up (returnsStripeClientSecret)POST /api/advertiser/{id}/payments/subscription- Advertiser subscription checkout (returns checkout URL)
Admin Payment Endpoints
POST /api/admin/payments/tournament-registration/{id}/refund- Process refunds
🐛 Troubleshooting
Webhook Not Receiving Events
- Check Stripe CLI is running:
stripe listen - Verify webhook secret matches in appsettings
- Check application logs for errors
- Verify endpoint URL in Stripe Dashboard
Refund Fails
- Ensure charge ID exists in database
- Check Stripe API key is correct
- Verify charge hasn't already been refunded
- Check application logs for detailed error messages
Payment Intent Not Found
- Ensure
StripePaymentIntentIdis stored when creating payment - Check payment intent was created successfully
- Verify webhook is processing the correct event type