Support invoice-backed one-time payment flows - #55
Merged
Conversation
There was a problem hiding this comment.
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-936의payManualInvoice함수가 올바른 상태 전이와 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-856의invoices.one_time_invoice_flow.succeeds - ✅ API test에서 success, decline, requires_action 세 가지 outcome 시나리오 모두 검증됨
- ✅ Storage migration이 안전하게 기존 데이터를 마이그레이션하고
invoice_items테이블 추가
UI/API Coherence
- ✅ API documentation이 업데이트됨:
docs/COMPATIBILITY.md - ✅ API contract가 업데이트됨:
specs/000-product/contracts/api.md - ✅ Stripe compatibility registry가 업데이트되고 새로운 claim들이 추가됨
Migration Safety
- ✅ Migration 015이 안전하게 기존
invoices와payment_intents테이블을 재생성하고invoice_items테이블을 추가 - ✅ 기존 데이터에
metadata = '{}'를 기본값으로 설정하여 backward compatibility 보장 - ✅ Index들이 추가되어 query performance 최적화
요약
이 PR은:
- Billtap의 Stripe-compatible subset을 invoice-backed one-time payment flow로 확장
- Subscription update 시 Stripe-compatible proration parameters를 수용하고 evidence로 보존
- Invoice와 InvoiceItem의 metadata 보존을 통해 local billing assertion 용이성 개선
- 모든 gate (G1-G5)를 통과하고 compatibility scorecard case가 추가됨
Blocking issue가 없습니다. 모든 billing state correctness, webhook reliability, safety requirement를 충족합니다.
Reviewed by Z.ai GLM via Claude Code Action
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
proration_dateon subscription updates and persist related update evidence for local billing assertions.Verification
go test ./...npm run typechecknpm run buildgo run ./cmd/billtap compatibility scorecard --output-dir /tmp/billtap-compatibilitynpm run smoke:sdknpm run smoke:samplenpm run smoke:webdocker build -t billtap:local .PORT=3300 npm --prefix examples/sample-app startplus both sample scenario runsGate status