Skip to content

Support invoice-backed one-time payment flows - #55

Merged
midagedev merged 1 commit into
mainfrom
codex/invoice-backed-one-time
May 20, 2026
Merged

Support invoice-backed one-time payment flows#55
midagedev merged 1 commit into
mainfrom
codex/invoice-backed-one-time

Conversation

@midagedev

Copy link
Copy Markdown
Owner

Summary

  • Accept Stripe-compatible proration_date on subscription updates and persist related update evidence for local billing assertions.
  • Add manual invoice-backed one-time payment support across invoices, invoice items, finalize, pay, lines, and payments endpoints.
  • Preserve nested metadata maps and propagate invoice/customer payment outcomes to generated payment intents, including declined and requires-action flows.
  • Document the compatibility surface and add the new invoice-backed flow to the scorecard corpus.

Verification

  • go test ./...
  • npm run typecheck
  • npm run build
  • go run ./cmd/billtap compatibility scorecard --output-dir /tmp/billtap-compatibility
  • npm run smoke:sdk
  • npm run smoke:sample
  • npm run smoke:web
  • docker build -t billtap:local .
  • PORT=3300 npm --prefix examples/sample-app start plus both sample scenario runs

Gate status

  • G1 API compatibility: Passed
  • G2 billing state integrity: Passed
  • G3 webhook behavior: Passed
  • G4 storage migration: Passed
  • G5 release smoke: Passed

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE

이 PR은 invoice-backed one-time payment flow를 추가하고 subscription update 시 proration_date 파라미터를 지원합니다.

주요 변경사항

1. Manual Invoice-Backed One-Time Payment Flow

  • POST /v1/invoices: draft invoice 생성
  • POST /v1/invoiceitems: invoice에 one-time amount 추가
  • POST /v1/invoices/{id}/finalize: invoice를 open 상태로 전환하고 PaymentIntent 생성
  • POST /v1/invoices/{id}/pay: customer-level default outcome 지원
  • GET /v1/invoices/{id}/lines: invoice items 반환
  • GET /v1/invoices/{id}/payments: payment evidence 반환

2. Subscription Update Proration Support

  • proration_date, proration_behavior, payment_behavior, billing_cycle_anchor, trial_end 파라미터를 subscription metadata로 보존
  • Stripe-compatible proration parameter 수용

3. Metadata Preservation & Expansion

  • Invoice와 InvoiceItem model에 Metadata 필드 추가
  • PaymentIntent evidence에 invoice와 customer outcome 전달
  • Nested metadata map 보존

검증 결과

Billing State Correctness

  • ✅ Invoice state transition: draft → open → paid (또는 실패 시 open 유지)
  • ✅ PaymentIntent가 finalize 시점에 생성되고 proper status를 가짐
  • SubscriptionID가 없는 manual invoice flow가 기존 subscription-backed invoice와 분리되어 처리됨
  • internal/billing/service.go:862-936payManualInvoice 함수가 올바른 상태 전이와 timeline evidence 생성

Webhook Reliability

  • ✅ Webhook event가 적절히 emit됨: invoice.created, invoice.finalized, invoiceitem.created, payment_intent.created
  • ✅ Payment outcome에 따른 webhook 분기: 성공 시 invoice.payment_succeeded + invoice.paid, 실패 시 invoice.payment_failed
  • ✅ 기존 webhook signature, retry, idempotency semantics을 변경하지 않음

Safety

  • ✅ Real card data를 처리하거나 저장하지 않음 (sandbox outcome만 사용: card_declined, requires_action)
  • ✅ Production payment credential을 받아들이지 않음
  • ✅ Manual invoice flow가 명확히 bounded되어 있고 문서화됨 (full Stripe parity 아님)
  • ✅ Customer-level default outcomes이 deterministic sandbox behavior 유지

Scenario/Fixture Contract

  • ✅ 새로운 scorecard case 추가: internal/compatibility/corpus.go:846-856invoices.one_time_invoice_flow.succeeds
  • ✅ API test에서 success, decline, requires_action 세 가지 outcome 시나리오 모두 검증됨
  • ✅ Storage migration이 안전하게 기존 데이터를 마이그레이션하고 invoice_items 테이블 추가

UI/API Coherence

Migration Safety

  • ✅ Migration 015이 안전하게 기존 invoicespayment_intents 테이블을 재생성하고 invoice_items 테이블을 추가
  • ✅ 기존 데이터에 metadata = '{}'를 기본값으로 설정하여 backward compatibility 보장
  • ✅ Index들이 추가되어 query performance 최적화

요약

이 PR은:

  1. Billtap의 Stripe-compatible subset을 invoice-backed one-time payment flow로 확장
  2. Subscription update 시 Stripe-compatible proration parameters를 수용하고 evidence로 보존
  3. Invoice와 InvoiceItem의 metadata 보존을 통해 local billing assertion 용이성 개선
  4. 모든 gate (G1-G5)를 통과하고 compatibility scorecard case가 추가됨

Blocking issue가 없습니다. 모든 billing state correctness, webhook reliability, safety requirement를 충족합니다.

Reviewed by Z.ai GLM via Claude Code Action

@midagedev
midagedev merged commit 638ad1a into main May 20, 2026
3 checks passed
@midagedev
midagedev deleted the codex/invoice-backed-one-time branch May 20, 2026 05:13
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