Skip to content

[codex] Fix invoice pay outcome precedence - #56

Merged
midagedev merged 1 commit into
mainfrom
codex/invoice-pay-outcome-precedence
May 20, 2026
Merged

[codex] Fix invoice pay outcome precedence#56
midagedev merged 1 commit into
mainfrom
codex/invoice-pay-outcome-precedence

Conversation

@midagedev

Copy link
Copy Markdown
Owner

Summary

Fix invoice pay handling so payment_method and source remain payment method inputs only. Explicit outcome/billtap_outcome still override when requested, but a configured invoice-backed PaymentIntent outcome now wins over an arbitrary submitted payment method ID.

Root cause

The /v1/invoices/{id}/pay handler copied the submitted payment method into InvoicePaymentOptions.Outcome. That bypassed customer/default PaymentIntent outcome metadata for manual invoice-backed payments and turned declined or action-required fixture paths into successful payments.

Validation

  • go test ./internal/api -run TestInvoiceBackedOneTimePaymentFlow -count=1 -v
  • go test ./internal/api ./internal/billing ./internal/storage
  • go test ./...
  • git diff --check

@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

Summary

이 PR은 /v1/invoices/{id}/pay 요청에서 payment_method 파라미터가 fixture-configured PaymentIntent outcome을 우선하여 덮어쓰던 문제를 올바르게 수정합니다.

Analysis

변경 영역

api.go에서 기존에 paymentMethodID를 그대로 Outcome 필드에 전달하던 로직을 명시적인 outcome/billtap_outcome 파라미터만 확인하도록 변경했습니다.

// 변경 전
outcome := paymentMethodID

// 변경 후  
Outcome: p.first("outcome", "billtap_outcome"),

이는 payManualInvoice의 outcome 결정 우선순위와 일치합니다:

  1. 명시적 opts.Outcome
  2. PaymentIntent metadata의 configured outcome
  3. Customer-level default outcome
  4. opts.PaymentMethodID (fallback)
  5. "payment_succeeded" (default)

검증

TestInvoiceBackedOneTimePaymentFlowpayment_method 파라미터를 전달하면서 configured outcome이 우선함을 검증하는 assertion을 추가했습니다:

if failed.Metadata["billtap_last_invoice_payment_outcome"] != "card_declined" {
    t.Fatalf("failed invoice metadata = %#v, want configured outcome to win over payment_method", failed.Metadata)
}

Safety 확인

  • Real payment data 처리 없음: outcome 시뮬레이션만 처리
  • Webhook 영향 없음
  • Fixture isolation 유지
  • Production boundary 관련 변경 없음

Release gate

CI에서 Release gate가 SUCCESS로 표시되어 있습니다.

Conclusion

이 변경은 billing state correctness 관점에서 올바른 수정입니다. fixture-seeded configured outcome이 arbitrary payment_method보다 우선하도록 하는 것이 Billtap의 deterministic billing simulation 의도에 부합합니다.

Blocking issue가 없으므로 APPROVE합니다.

Reviewed by Z.ai GLM via Claude Code Action

@midagedev
midagedev merged commit 067898b into main May 20, 2026
3 checks passed
@midagedev
midagedev deleted the codex/invoice-pay-outcome-precedence branch May 20, 2026 05:39
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