Skip to content

feat(api): stripe surface wave 1 — trial_end preview/confirm parity, default-amount refunds, credit note memo/oob/refund_amount - #72

Merged
midagedev merged 1 commit into
mainfrom
feat/stripe-surface-wave1
Aug 24, 2026
Merged

feat(api): stripe surface wave 1 — trial_end preview/confirm parity, default-amount refunds, credit note memo/oob/refund_amount#72
midagedev merged 1 commit into
mainfrom
feat/stripe-surface-wave1

Conversation

@midagedev

Copy link
Copy Markdown
Owner

Context

Follow-up to #71: a census of what current stripe-java 31 clients actually send found a family of gaps — some rejected (parameter_unknown), some worse: accepted-but-ignored, where the API returns 200 and drops the semantics.

Changes

  1. POST /v1/invoices/create_preview × subscription_details[trial_end] (was REJECT): allowlist + unix/now validation; previewing a trial ending now prices the first paid cycle (items + tax), not a $0 trial window.
  2. POST /v1/subscriptions/{id} × trial_end (was IGNORED — echoed into metadata, no state change): now/non-future unix ends the trial through the existing proration+invoice path (trialingactive); future unix updates the timestamp only. TestInvoicePreviewTrialEndNowMatchesConfirm pins preview↔confirm parity: subtotal=4900 tax=490 total=5390 on both sides.
  3. POST /v1/refunds (omitted amount was REJECT): defaults to the remaining refundable balance (charged − non-canceled/failed refunds); explicit amounts above the remainder are rejected.
  4. POST /v1/credit_notes × memo/out_of_band_amount/refund_amount (was REJECT): accepted, persisted (migration 021), echoed; amount defaults to oob+refund; out-of-band settlement never credits customer cash balance (pinned by test).

Verification

  • go build / go vet clean; go test ./internal/api/ ./internal/billing/ ./internal/storage/ -count=1 all green
  • 5 new tests incl. parity, future-trial_end timestamp-only, remainder refund, oob balance invariant

🤖 Generated with Claude Code

https://claude.ai/code/session_01HapqvjSLa6A6zRqe6dYyvu

…credit note memo/oob/refund_amount

Newer Stripe SDK surfaces that clients actually send, wired end to end:

- invoices/create_preview accepts subscription_details[trial_end] (unix or
  "now") and prices the first paid cycle instead of rejecting with
  parameter_unknown.
- subscriptions/{id} trial_end=now (or a non-future unix) actually ends the
  trial: trialing -> active through the existing proration/invoice path, so
  preview and confirm produce the same amount (test pins subtotal/tax/total).
  A future unix keeps updating trial_end only. Previously the param was
  echoed into metadata and silently ignored.
- refunds: omitted amount defaults to the remaining refundable balance
  (charged minus non-canceled refunds); explicit over-refunds are rejected.
- credit_notes: memo / out_of_band_amount / refund_amount are accepted,
  persisted (migration 021) and echoed; amount defaults to oob+refund.
  out_of_band settlement does not credit customer cash balance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HapqvjSLa6A6zRqe6dYyvu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant