feat: Accept Payments - Stripe Integration with User Tiers (#55) #56

Merged
egullickson merged 17 commits from issue-55-stripe-integration into main 2026-01-19 02:52:25 +00:00
Owner

Summary

Linked issues

  • Fixes #
  • Relates to #

Type

  • Feature
  • Bug fix
  • Chore / refactor
  • Docs

Test plan

  • Unit tests
  • Integration tests
  • Manual verification

Commands / steps:
1.
2.

Screenshots / UI notes (if applicable)

Checklist

  • Acceptance criteria met (from linked issue)
  • No secrets committed
  • Logging is appropriate (no PII)
  • Docs updated (if needed)
## Summary - Implements Issue #55 ## Linked issues - Fixes # - Relates to # ## Type - [ ] Feature - [ ] Bug fix - [ ] Chore / refactor - [ ] Docs ## Test plan - [ ] Unit tests - [ ] Integration tests - [ ] Manual verification **Commands / steps:** 1. 2. ## Screenshots / UI notes (if applicable) ## Checklist - [ ] Acceptance criteria met (from linked issue) - [ ] No secrets committed - [ ] Logging is appropriate (no PII) - [ ] Docs updated (if needed)
egullickson added 7 commits 2026-01-18 23:38:52 +00:00
- Create 4 new tables: subscriptions, subscription_events, donations, tier_vehicle_selections
- Add StripeClient wrapper with createCustomer, createSubscription, cancelSubscription,
  updatePaymentMethod, createPaymentIntent, constructWebhookEvent methods
- Implement SubscriptionsRepository with full CRUD and mapRow case conversion
- Add domain types for all subscription entities
- Install stripe npm package v20.2.0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement SubscriptionsService with getSubscription, createSubscription,
  upgradeSubscription, cancelSubscription, reactivateSubscription
- Add handleWebhookEvent for Stripe webhook processing with idempotency
- Handle 5 webhook events: subscription.created/updated/deleted, invoice.payment_succeeded/failed
- Auto-sync tier changes to user_profiles.subscription_tier
- Add public webhook endpoint POST /api/webhooks/stripe (signature verified)
- Implement 30-day grace period on payment failure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
API Endpoints (all authenticated):
- GET /api/subscriptions - current subscription status
- POST /api/subscriptions/checkout - create Stripe subscription
- POST /api/subscriptions/cancel - schedule cancellation at period end
- POST /api/subscriptions/reactivate - cancel pending cancellation
- PUT /api/subscriptions/payment-method - update payment method
- GET /api/subscriptions/invoices - billing history

Grace Period Job:
- Daily cron at 2:30 AM to check expired grace periods
- Downgrades to free tier when 30-day grace period expires
- Syncs tier to user_profiles.subscription_tier

Email Templates:
- payment_failed_immediate (first failure)
- payment_failed_7day (7 days before grace ends)
- payment_failed_1day (1 day before grace ends)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
docs: update subscription feature documentation - M7 (refs #55)
Some checks failed
Deploy to Staging / Build Images (pull_request) Successful in 6m58s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 28s
Deploy to Staging / Verify Staging (pull_request) Failing after 17s
Deploy to Staging / Notify Staging Ready (pull_request) Has been skipped
Deploy to Staging / Notify Staging Failure (pull_request) Successful in 6s
1cf4b78075
egullickson added 2 commits 2026-01-19 00:50:09 +00:00
feat: Stripe secret updates
Some checks failed
Deploy to Staging / Build Images (pull_request) Successful in 2m43s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 28s
Deploy to Staging / Verify Staging (pull_request) Failing after 6s
Deploy to Staging / Notify Staging Ready (pull_request) Has been skipped
Deploy to Staging / Notify Staging Failure (pull_request) Successful in 7s
03fa9c3103
egullickson added 1 commit 2026-01-19 01:09:07 +00:00
feat: Stripe secrets fixes
Some checks failed
Deploy to Staging / Build Images (pull_request) Successful in 26s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 28s
Deploy to Staging / Verify Staging (pull_request) Failing after 6s
Deploy to Staging / Notify Staging Ready (pull_request) Has been skipped
Deploy to Staging / Notify Staging Failure (pull_request) Successful in 6s
52c0b59a86
egullickson added 2 commits 2026-01-19 01:26:06 +00:00
- Add VITE_STRIPE_PUBLISHABLE_KEY to frontend Dockerfile build args
- Add VITE_STRIPE_PUBLISHABLE_KEY to docker-compose.yml build args
- Add :ro flag to backend Stripe secret volume mounts for consistency
- Update inject-secrets.sh with STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET
- Add Stripe secrets to staging.yaml workflow (build arg + inject step)
- Add Stripe secrets to production.yaml workflow (inject step)

Requires STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET secrets and
VITE_STRIPE_PUBLISHABLE_KEY variable to be configured in Gitea.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: Stripe secrets, more work.
Some checks failed
Deploy to Staging / Build Images (pull_request) Successful in 2m54s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 29s
Deploy to Staging / Verify Staging (pull_request) Failing after 6s
Deploy to Staging / Notify Staging Ready (pull_request) Has been skipped
Deploy to Staging / Notify Staging Failure (pull_request) Successful in 6s
29948134eb
egullickson added 1 commit 2026-01-19 01:35:28 +00:00
fix: sync docker-compose files to staging server during deploy (refs #55)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 26s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 29s
Deploy to Staging / Verify Staging (pull_request) Successful in 37s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
864a6b1e86
The staging workflow was not copying docker-compose.yml to the server,
causing configuration changes (like Stripe secrets) to not take effect.

Added rsync step to sync config, scripts, and compose files before
deployment, matching the production workflow behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
egullickson added 1 commit 2026-01-19 01:45:31 +00:00
feat: add Subscription section to Settings page (refs #55)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 2m51s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 39s
Deploy to Staging / Verify Staging (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
26f9306d6b
Added a Subscription section to the desktop Settings page that displays:
- Current subscription tier (Free/Pro/Enterprise)
- Status indicator for non-active subscriptions
- Manage button linking to the subscription management page
- Descriptive text based on current tier

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
egullickson added 1 commit 2026-01-19 01:50:42 +00:00
fix: correct subscription description when data unavailable (refs #55)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 2m50s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 29s
Deploy to Staging / Verify Staging (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 6s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
c407396b85
Fixed conditional logic for subscription description text to properly
handle the case when subscription data is not loaded or unavailable.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
egullickson added 1 commit 2026-01-19 01:53:15 +00:00
feat: add Subscription section to mobile Settings (refs #55)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 2m51s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 38s
Deploy to Staging / Verify Staging (pull_request) Successful in 6s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 6s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
d646b5db80
Added a Subscription section to the mobile Settings screen that displays:
- Current subscription tier (Free/Pro/Enterprise)
- Status indicator for non-active subscriptions
- Manage button linking to the subscription screen
- Descriptive text based on current tier

This completes the subscription section on both desktop and mobile.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
egullickson added 1 commit 2026-01-19 02:22:51 +00:00
fix: add subscriptions to migration order (refs #55)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 2m41s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 38s
Deploy to Staging / Verify Staging (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 6s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
0674056e7e
The subscriptions feature migration was not being run because it was
missing from the MIGRATION_ORDER array. Added it after ownership-costs
since it depends on user-profile (for subscription_tier enum) and
vehicles (for FK relationships).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
egullickson merged commit 0b25c655e5 into main 2026-01-19 02:52:25 +00:00
egullickson deleted branch issue-55-stripe-integration 2026-01-19 02:52:25 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: egullickson/motovaultpro#56