Creem

Creem checkout and webhook provider for the Nuxt template.

Creem is the default provider. It implements the PaymentProvider interface in server/payment/providers/creem-provider.ts and is registered by the factory when NUXT_CREEM_API_KEY is set.

Configuration

VariablePurpose
NUXT_PUBLIC_PAYMENT_PROVIDERSet to creem (the default) to select this provider.
NUXT_CREEM_API_KEYServer key for creating checkouts (also gates registration).
NUXT_CREEM_SERVER_IDXSelects the Creem server: 0 = production, 1 = test.
NUXT_CREEM_WEBHOOK_SECRETHMAC secret for verifying webhook signatures.
NUXT_PUBLIC_CREEM_PRODUCT_PRO_MONTHLY / _PRO_YEARLY / _LIFETIMEPublic Creem product IDs for the three plans.

See Environment Variables.

Checkout

createPayment builds a Creem checkout for the requested productId and returns { orderNo, thirdOrderNo, checkoutUrl }. The create route redirects the browser to checkoutUrl, which returns to /pay-success?orderId=<orderNo>.

Webhook

  • Path: POST /api/payment/notify/creem.
  • Signature: HMAC-SHA256 of the raw body using NUXT_CREEM_WEBHOOK_SECRET, compared to the creem-signature header. An invalid signature returns 401.
  • Handled events:
    • checkout.completed — marks the matching payment row success.
    • Subscription lifecyclesubscription.active, subscription.paid, subscription.update, subscription.trialing, subscription.paused, subscription.past_due, subscription.scheduled_cancel, subscription.canceled, and subscription.expired upsert the user's subscription row to the matching status, period, and cancel timestamps.
    • refund.created — marks the matching payment row refunded.

Local testing

  • Use the Creem test server (NUXT_CREEM_SERVER_IDX=1) and test product IDs.
  • Expose your local webhook with a tunnel and register https://<tunnel>/api/payment/notify/creem in Creem.
  • A valid signature flips the order to success; an invalid one returns 401.

Production notes

  • Set production product IDs and NUXT_CREEM_SERVER_IDX=0.
  • Add idempotency — webhooks can be delivered more than once.
  • Verify amounts server-side against your catalog before charging real users.

Verify

  • A logged-in user can start checkout from the pricing page; a payment row is created.
  • GET /api/payment/query?orderId=… returns the order status.
  • A Creem webhook with a valid signature flips the order to success.
  • Guest (logged-out) checkout returns 401, not 500.

On this page