mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-12 13:46:51 +00:00
Some checks are pending
CI / checks (push) Waiting to run
* feat(stripe): add Stripe payment sync and webhook support Introduce Stripe integration for automatic payment ingestion and refund tracking. Adds new fields to the payment model for Stripe IDs and status, Stripe client driver, sync service, cron job, manual API endpoint, and public webhook handler for real-time updates. Includes tests and documentation. Manual cash entry remains supported. * chore(stripe): upgrade to stripe-go v83 Upgrade Stripe SDK from v79 to v83 across the codebase. Update all imports to use github.com/stripe/stripe-go/v83 and refactor client usage to match the new API, including changes to PaymentIntents listing. Update documentation and plans to reference the new version. Remove references to the old version from go.mod and go.sum. * refactor(payment): extract payment logic to new service Moves all payment-related logic (manual payments, Stripe sync, webhook handling) from the booking service into a dedicated payment service (`internal/service/payment`). Updates server, cron, and handler wiring to inject and use the new payment service. Adjusts tests, routes, and documentation to reflect the new separation of concerns. This improves cohesion, clarifies responsibilities, and prepares for future payment features. No database schema changes are introduced. * chore(ci): add Go and templ setup to CI workflow This update enhances the CI workflow by adding steps to set up Go using the version specified in go.mod, add the Go bin directory to the PATH, and install the templ code generation tool. These additions ensure that Go-based tooling is available for subsequent CI steps.
85 lines
6.1 KiB
Markdown
85 lines
6.1 KiB
Markdown
---
|
||
date: 2025-10-03T20:02:01+0200
|
||
researcher: Codex
|
||
git_commit: ac94faedb0b491d710c36b04ac27b26890f4d062
|
||
branch: main
|
||
repository: rentease
|
||
topic: "Stripe payment ingestion & webhook strategy"
|
||
tags: [research, payments, stripe]
|
||
status: complete
|
||
last_updated: 2025-10-05
|
||
last_updated_by: Codex
|
||
---
|
||
|
||
# Research: Stripe payment ingestion & webhook strategy
|
||
|
||
## Research Question
|
||
|
||
What changes are needed to fetch Stripe payment data for a given period and replace
|
||
manual double-entry with webhook-driven updates?
|
||
|
||
## Summary
|
||
|
||
Rentease captures payments through a manual UI that posts to `/payments/:id`, with
|
||
records now persisted by a dedicated payment service in `internal/service/payment`.
|
||
Reporting features still depend on these rows—especially for card totals—so Stripe
|
||
imports share the same storage path. Stripe connectivity is also centralised in
|
||
that payment service, while configuration continues to supply the API/ webhook
|
||
secrets and `main.go` wires the Stripe client.
|
||
|
||
## Detailed Findings
|
||
|
||
### Manual Payment Entry Flow
|
||
|
||
- Booking detail page exposes a modal that posts amount and method to the server (`internal/view/booking_by_id.templ:52`, `internal/view/booking_by_id.templ:130`).
|
||
- `/payments/:id` handler binds the form payload, delegates to the payment service for creation, and re-renders the payment list (`internal/server/handle_payments.go`).
|
||
- Booking page view model preloads payments to display them alongside line items (`internal/server/handle_bookings.go:130`, permalink: <https://github.com/rjNemo/rentease/blob/ac94faedb0b491d710c36b04ac27b26890f4d062/internal/server/handle_bookings.go#L130-L179>).
|
||
|
||
### Payment Persistence & Reporting
|
||
|
||
- `payment.Service.CreatePayment` wraps repository inserts without additional de-duplication (`internal/service/payment/service.go`).
|
||
- `PgStore.CreatePayment` writes plain `amount` and `payment_method`; schema lacks external references for Stripe IDs (`internal/repository/booking/pg_store.go:150`, permalink: <https://github.com/rjNemo/rentease/blob/ac94faedb0b491d710c36b04ac27b26890f4d062/internal/repository/booking/pg_store.go#L150-L174>).
|
||
- Reports compute card totals by summing `payments` joined to bookings, so Stripe-imported transactions must populate this table to keep analytics accurate (`internal/repository/booking/pg_store.go:65`, `internal/service/booking/report.go:76`).
|
||
|
||
### Integration Hooks for Stripe API Fetch
|
||
|
||
- Configuration currently has no Stripe credentials, so `internal/config/config.go` must gain `StripeSecretKey`, `StripeWebhookSecret`, etc., and `main.go` should wire a Stripe client (`internal/config/config.go:11`, `main.go:52`).
|
||
- Extraction logic can mirror existing external service patterns (e.g., the OpenAI parser driver) by adding a `internal/driver/stripe` client and a `booking` service method to request Stripe payments and upsert records (`internal/service/booking/sync.go:7`).
|
||
- The cron binary is designed to host scheduled jobs and can trigger periodic Stripe backfills once a job runner function exists (`pkg/cron/cron.go:9`, `cmd/cron/main.go:13`).
|
||
|
||
### Webhook Considerations
|
||
|
||
- Routes under `private` require authentication, so Stripe webhooks need a new public endpoint (e.g., `/webhooks/stripe`) mounted before auth middleware in `internal/server/routes.go:8`.
|
||
- Handlers should verify Stripe signatures, deserialize events, and, for `payment_intent.succeeded` or `charge.refunded`, call into a service layer that ensures idempotent upserts (likely by storing Stripe IDs in the `payments` table).
|
||
- Payment view models already display method strings from config; mapping Stripe payment methods (card, bank redirect) to existing enums may require normalisation in the webhook handler before storing (`internal/view/item_list.templ:19`, `internal/config/host.go:41`).
|
||
|
||
### External Integration Patterns
|
||
|
||
- The OpenAI booking parser demonstrates how the app encapsulates third-party clients behind drivers and service methods, including error handling and data persistence hooks (`internal/driver/parser/client.go:17`, `internal/service/booking/sync.go:7`). This pattern can guide the Stripe integration for consistency.
|
||
|
||
## Code References
|
||
|
||
- `internal/server/handle_payments.go:16` – manual payment creation flow (perm: <https://github.com/rjNemo/rentease/blob/ac94faedb0b491d710c36b04ac27b26890f4d062/internal/server/handle_payments.go#L16-L51>)
|
||
- `internal/service/payment/service.go` – service layer inserts payments and delegates to the repository.
|
||
- `internal/repository/booking/pg_store.go:65` – card totals depend on stored payments (perm: <https://github.com/rjNemo/rentease/blob/ac94faedb0b491d710c36b04ac27b26890f4d062/internal/repository/booking/pg_store.go#L65-L174>)
|
||
- `internal/server/routes.go:8` – current route layout and auth groups (perm: <https://github.com/rjNemo/rentease/blob/ac94faedb0b491d710c36b04ac27b26890f4d062/internal/server/routes.go#L8-L46>)
|
||
- `cmd/cron/main.go:13` – cron entrypoint for scheduled jobs (perm: <https://github.com/rjNemo/rentease/blob/ac94faedb0b491d710c36b04ac27b26890f4d062/cmd/cron/main.go#L13-L44>)
|
||
|
||
## Architecture Insights
|
||
|
||
Rentease now splits business logic across `booking.Service` and `payment.Service`, with storage handled through a repository abstraction and UI forms using htmx requests. External integrations live in `internal/driver` and are injected via `main.go`. Payment records are simple and lack idempotency safeguards, so any Stripe sync must extend the schema and service methods to avoid duplicates, enforce foreign keys, and reconcile amounts with existing booking items.
|
||
|
||
## Historical Context (from ./thoughts/)
|
||
|
||
- No prior research documents found in `./thoughts` related to payments or Stripe.
|
||
|
||
## Related Research
|
||
|
||
- None available.
|
||
|
||
## Open Questions
|
||
|
||
- How will Stripe payments be matched to internal bookings (metadata, external IDs, or manual association)?
|
||
- Should the `payments` table store Stripe identifiers and status fields to enable idempotent upserts and refunds?
|
||
- What is the preferred flow for backfilling historical payments—ad hoc command, scheduled cron job, or admin-triggered API?
|
||
- Which Stripe event types should the webhook handle beyond successful payments (refunds, disputes, payouts)?
|