Stripe is RoundTrip's payment and subscription management platform. It handles subscription billing, payment collection, and webhook events that drive tenant lifecycle management (activation, suspension, cancellation).
What Stripe Handles
| Responsibility | Details |
|---|
| Subscription billing | Monthly/annual subscription charges per plan tier |
| Payment collection | Credit card processing, payment method management |
| Webhook events | Notifies RoundTrip of subscription changes, payment success/failure |
| Customer portal | Self-service subscription management for tenants |
Subscription Plans
RoundTrip has three subscription tiers. Each tier has a corresponding Stripe Price ID stored in Key Vault.
| Plan | Key Vault Secret | Config Key |
|---|
| Starter | Stripe--PriceId--Starter | Stripe:PriceId:Starter |
| Standard | Stripe--PriceId--Standard | Stripe:PriceId:Standard |
| Professional | Stripe--PriceId--Professional | Stripe:PriceId:Professional |
:::info Founding Customer Pricing
Early customers are offered a locked-in lower rate as founding customer pricing. This is configured at the Stripe subscription level using a discounted price or coupon — the Price IDs in Key Vault reflect the standard rates. Founding customer discounts are applied manually in the Stripe dashboard per customer.
:::
Configuration
Key Vault Secrets
| Secret Name | Config Key | Purpose |
|---|
Stripe--SecretKey | Stripe:SecretKey | Server-side API key for all Stripe API calls |
Stripe--PublishableKey | Stripe:PublishableKey | Client-side key exposed to the frontend |
Stripe--WebhookSigningSecret | Stripe:WebhookSigningSecret | Validates incoming webhook event signatures |
Stripe--PriceId--Starter | Stripe:PriceId:Starter | Stripe Price ID for Starter plan |
Stripe--PriceId--Standard | Stripe:PriceId:Standard | Stripe Price ID for Standard plan |
Stripe--PriceId--Professional | Stripe:PriceId:Professional | Stripe Price ID for Professional plan |
App Service Settings
| Setting Name | Value |
|---|
Stripe__SecretKey | @Microsoft.KeyVault(VaultName=kv-roundtrip-production;SecretName=Stripe--SecretKey) |
Stripe__PublishableKey | @Microsoft.KeyVault(VaultName=kv-roundtrip-production;SecretName=Stripe--PublishableKey) |
Stripe__WebhookSigningSecret | @Microsoft.KeyVault(VaultName=kv-roundtrip-production;SecretName=Stripe--WebhookSigningSecret) |
Stripe__PriceId__Starter | @Microsoft.KeyVault(VaultName=kv-roundtrip-production;SecretName=Stripe--PriceId--Starter) |
Stripe__PriceId__Standard | @Microsoft.KeyVault(VaultName=kv-roundtrip-production;SecretName=Stripe--PriceId--Standard) |
Stripe__PriceId__Professional | @Microsoft.KeyVault(VaultName=kv-roundtrip-production;SecretName=Stripe--PriceId--Professional) |
Webhook Events
Stripe sends webhook events to RoundTrip when subscription or payment state changes. The webhook endpoint validates the event signature using the WebhookSigningSecret before processing.
Webhook Endpoint
Key Events
| Stripe Event | What It Means | RoundTrip Action |
|---|
customer.subscription.created | New subscription activated | Activate tenant — allow full access |
customer.subscription.updated | Plan changed or subscription modified | Update tenant subscription tier |
customer.subscription.deleted | Subscription cancelled | Mark tenant as cancelled |
invoice.payment_succeeded | Payment collected successfully | Reinstate tenant if previously suspended |
invoice.payment_failed | Payment collection failed | Suspend tenant after grace period |
invoice.payment_action_required | 3D Secure or additional auth needed | Notify tenant admin via email |
:::warning Webhook Automation Not Yet Complete
Automatic tenant suspension and reinstatement on payment failure/success is a known planned feature. Currently, subscription lifecycle management is handled manually in the Stripe dashboard and RoundTrip admin panel. See Planned Enhancements below.
:::
Stripe Dashboard
| Item | Detail |
|---|
| Login | Bitwarden → "Stripe" |
| Customers | Lists all RoundTrip tenants as Stripe customers |
| Subscriptions | Active, past due, cancelled subscriptions per tenant |
| Payments | Payment history, refunds, disputes |
| Webhooks | Developers → Webhooks — shows event delivery history and failures |
| API Keys | Developers → API Keys — production and test keys |
Verifying Webhook Delivery
If you suspect webhooks are not being processed:
- Go to Stripe Dashboard → Developers → Webhooks
- Find your webhook endpoint (
/v1/billing/webhook)
- Click on it to see recent event delivery attempts
- Check the response code —
200 means RoundTrip received and processed it
- Non-200 responses indicate the endpoint rejected or failed to process the event
- Failed events can be resent manually from the Stripe dashboard
Test vs Production
Stripe has separate test and production modes. Test mode uses sk_test_ prefixed keys and does not process real payments.
| Mode | Key Prefix | Use For |
|---|
| Test | sk_test_ / pk_test_ | Local development and dev environment |
| Production | sk_live_ / pk_live_ | Production only — real payments |
:::danger Never Use Production Keys in Development
Production Stripe keys process real payments and can create real customer charges. Dev environment must always use test mode keys. Test keys are stored separately in kv-roundtrip-dev.
:::
Test Card Numbers
| Card Number | Behaviour |
|---|
4242 4242 4242 4242 | Always succeeds |
4000 0000 0000 0002 | Always declines |
4000 0025 0000 3155 | Requires 3D Secure authentication |
Planned Enhancements
| Enhancement | Priority | Notes |
|---|
| Automatic tenant suspension on payment failure | High | Webhook handler for invoice.payment_failed → suspend tenant after grace period |
| Automatic tenant reinstatement on payment success | High | Webhook handler for invoice.payment_succeeded → reinstate suspended tenant |
| Stripe Customer Portal integration | Medium | Self-service plan upgrades, payment method updates for tenant admins |
| Data retention job for cancelled tenants | Medium | Purge cancelled tenant data after 30/90 days via Hangfire recurring job |
| Usage-based billing | Low | Future — metered billing based on technician seat count |