Skip to content

Cookbook PDF: CoinPay hosted checkout sessions - #137

Merged
ralyodio merged 1 commit into
mainfrom
coinpay-checkout-sessions
Oct 21, 2026
Merged

ralyodio merged 1 commit into
mainfrom
coinpay-checkout-sessions

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

What

  • /book/buy: the 15-chain picker is replaced by a receipt email field; checkout opens POST /api/checkout/sessions with customer_email, account_id (the email: guests, no accounts), property: hqtui.com, metadata {property, product, reference, email}, success /book/thanks?session={CHECKOUT_SESSION_ID}, cancel /book/buy?cancelled=1. The cs_ id is the purchase key in book_purchases; the buyer is redirected to the hosted page (any wallet coin or PayPal).
  • New /book/thanks: shows the 48h download link once paid. If the buyer is back before the webhook it asks CoinPay (GET /api/checkout/sessions/:id with the business key); otherwise it refreshes every 10 s. Before this the link only existed in the webhook response, so a buyer never got it.
  • Webhook: settles by checkout_session_id, falling back to payment_id for purchases opened before sessions (one old pending row from 2026-09). confirmed and forwarded settle; markPaid stays idempotent.
  • Tests (bun + node): session body, API call with bearer key, bad email and off-site URL rejected, session-keyed webhook, confirmed/forwarded share one key.

Checks

bun test packages/hqtui/test apps/demo/test apps/web/test, node --test for the web tests, bun run build + bun run --cwd apps/web build green locally.

🤖 Generated with Claude Code

/book/buy offered a hardcoded list of 15 chains and opened
/api/payments/create with no return URL and no buyer, so a buyer was left on
CoinPay's page and the download link only ever appeared in the webhook
response. It now asks for a receipt email and opens POST
/api/checkout/sessions (customer_email, account_id = the email, since the site
has no accounts, property hqtui.com, metadata product/reference), stores the
cs_ id as the purchase key and redirects to the hosted page: any coin the
business holds a wallet for, or PayPal.

CoinPay returns the buyer to /book/thanks?session=cs_..., which shows the
download link once the purchase is paid, asks CoinPay with the business key
when the buyer is back before the webhook, and otherwise refreshes itself.

The webhook settles by checkout_session_id, then payment_id for purchases
opened before sessions; confirmed and forwarded both settle and markPaid stays
idempotent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ralyodio
ralyodio merged commit a80c023 into main Oct 21, 2026
16 checks passed
@ralyodio
ralyodio deleted the coinpay-checkout-sessions branch October 21, 2026 13:27
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