Skip to content

fix(payments): point premium/family webhook at the route that actually exists#123

Open
eltociear wants to merge 1 commit into
profullstack:masterfrom
eltociear:fix/payments-webhook-url-mismatch
Open

fix(payments): point premium/family webhook at the route that actually exists#123
eltociear wants to merge 1 commit into
profullstack:masterfrom
eltociear:fix/payments-webhook-url-mismatch

Conversation

@eltociear

Copy link
Copy Markdown

Fixes #122.

POST /api/payments was registering the CoinPayPortal webhook at ${baseUrl}/api/payments/webhook, which doesn't exist as a route — only /api/webhooks/coinpayportal does (the handler that verifies the signature and calls activateSubscription()). Since subscription access is gated entirely by the user_subscriptions table, and that table is only ever written from the webhook handler, premium/family payments confirm on CoinPayPortal's side but the app never activates the subscription.

The IPTV subscription flow doesn't have this bug — both of its payment-creation routes correctly point webhookUrl at /api/iptv/subscription/webhook, which exists. This PR makes the main payments route consistent with that.

Change:

  • src/app/api/payments/route.ts: point webhookUrl at /api/webhooks/coinpayportal.
  • src/app/api/payments/route.test.ts: added a regression test asserting the webhook URL passed to createPayment() matches the real route, so this can't silently regress again.

Couldn't run the suite locally — this sandbox doesn't have pnpm and a plain npm install didn't produce node_modules for the workspace — so I traced the new test through the existing mock setup by hand rather than executing it. Happy to adjust if CI flags anything.

…at doesn't exist

POST /api/payments creates the CoinPayPortal payment with
webhookUrl: `${baseUrl}/api/payments/webhook`, but no such route exists
in the app (only src/app/api/webhooks/coinpayportal/route.ts does, which
is the one that actually verifies the signature and calls
activateSubscription()). Since isSubscriptionActive()/isPaidSubscriptionActive()
gate access purely off the user_subscriptions table, and that table is only
ever written by activateSubscription() inside the webhook handler, every
premium/family payment made through this flow pays real crypto but never
gets the subscription activated — CoinPayPortal has nowhere to deliver the
confirmation to.

The IPTV subscription flow doesn't have this problem: both
src/app/api/iptv/subscription/route.ts and .../extend/route.ts correctly
point webhookUrl at src/app/api/iptv/subscription/webhook, which exists.
There's also no reconciliation/cron job that would catch this after the
fact (the only cron route is expire-subscriptions).

Fix: point the main payments route's webhookUrl at the real
/api/webhooks/coinpayportal route, same as the other CoinPayPortal
integrations in this codebase. Added a regression test asserting the
webhook URL passed to createPayment() actually matches an existing route.

Wasn't able to run the suite locally (this sandbox has no pnpm and plain
npm install didn't produce node_modules for the workspace) — traced the
test through the existing mock setup by hand instead; happy to fix up
anything the CI run flags.
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.

Premium/family subscription payments register a webhook URL that returns 404 — subscriptions never activate

1 participant