Commit 3ab0350
feat(billing): Wave 4b — cohort test-mode (rzp_test_*) checkout routing (#268)
* feat(billing): Wave 4b — cohort test-mode (rzp_test_*) checkout routing
Enables a synthetic test-cohort team (teams.is_test_cohort=true, mig 067) to
drive a REAL Razorpay TEST-mode hosted checkout + test-card payment in CI with
NO real money and WITHOUT the live-recurring approval that blocks prod (test
mode has no recurring gate). The live billing path is provably untouched.
docs/ci/01-CI-INTEGRATION-DESIGN.md §"Razorpay test-card payment E2E".
Config (all default "" = INERT; never leak in any response):
RAZORPAY_TEST_KEY_ID / _SECRET / _WEBHOOK_SECRET
RAZORPAY_TEST_PLAN_ID_{HOBBY,HOBBY_PLUS,PRO}
Routing (CreateCheckoutAPI):
- cohort + test key/secret + tier test-plan set → mint via rzp_test_*
(resolveCheckoutTestMode), swap to the test plan_id, route the create
through test creds via a private subBody flag (subBodyTestModeKey, stripped
before Razorpay), and bypass the live-key / billing_not_configured guards.
- cohort + test mode unset/partial → inert: existing synthetic_test_cohort
403 skip; never mints against the live plan; no crash.
- non-cohort → ALWAYS the live path, regardless of test-key config.
- DB blip on is_test_cohort → fail CLOSED (live path), never route a real
customer through the test account.
Webhook: try-both verification (live secret first, then RAZORPAY_TEST_WEBHOOK_
SECRET) so a real TEST-mode subscription.charged/activated upgrades the cohort
team; live webhooks unaffected; unset test secret is a no-op; constant-time.
Tests (internal/handlers green): pure-function inert proofs (no DB, always run)
+ DB-gated routing (cohort uses test plan, inert-when-unset, inert-when-no-plan,
non-cohort live path, key-leak contract) + webhook try-both/inert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(billing): cover Wave 4b test-mode key-swap + fail-closed branches (100% patch)
The 100%-patch diff-cover gate flagged two uncovered branches:
- billing.go:305-307 — the rzp_test_* key-swap inside the PRODUCTION default
CreateSubscription closure (tests override the field, so the default body
with the flag-true branch never ran). Added ExerciseCreateSubscriptionTestMode
which invokes the default closure WITH subBodyTestModeKey set.
- billing.go:597-602 — resolveCheckoutTestMode fail-CLOSED branch on an
is_test_cohort DB error. Added TestResolveCheckoutTestMode_FailsClosedOnDBError
(closed *sql.DB → IsTestCohort errors → useTest=false).
Both confirmed covered via go tool cover on the previously-missing line ranges.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent bfd08b7 commit 3ab0350
4 files changed
Lines changed: 620 additions & 33 deletions
File tree
- internal
- config
- handlers
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
48 | 70 | | |
49 | 71 | | |
50 | 72 | | |
| |||
368 | 390 | | |
369 | 391 | | |
370 | 392 | | |
371 | | - | |
372 | | - | |
373 | | - | |
374 | | - | |
375 | | - | |
376 | | - | |
377 | | - | |
378 | | - | |
379 | | - | |
380 | | - | |
381 | | - | |
382 | | - | |
383 | | - | |
384 | | - | |
385 | | - | |
386 | | - | |
387 | | - | |
388 | | - | |
389 | | - | |
390 | | - | |
391 | | - | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
392 | 423 | | |
393 | 424 | | |
394 | 425 | | |
| |||
0 commit comments