Commerce
Commerce (@kenresoft-cms/plugin-ecommerce) is a bundled plugin. Enable it under Installed Plugins (Plugins); its admin pages then appear under a Commerce group.
Catalog
Section titled “Catalog”Categories (hierarchical), products, variants and product images. Images reference Media Library items. Prices are integer minor units with a currency code, never floats. Products are draft or published; a draft product is not visible in the storefront API and returns 404 exactly like a missing slug. Only active variants are orderable.
Managing the catalog and orders needs the Editor role. The customers list needs Admin.
Customers use core accounts
Section titled “Customers use core accounts”There is no separate customer login system. A Commerce customer is an ordinary core user (Better Auth) with role none, so the same accounts, sessions, email verification and password reset apply. Commerce keeps only Commerce-specific data (such as a phone number) in its own profile table. A customer never gains CMS access. Admin customer tools only ever act on none users, never on staff.
Customers sign up, sign in and reset passwords through the core routes (/api/v1/auth/* and /api/v1/public/password-reset/*). A customer must verify their email before their first sign-in. From Astro, cms.commerce.customerAuth calls the same core auth. See Astro authentication.
Cart and checkout
Section titled “Cart and checkout”- Guest cart: the cart id travels in a cookie set by the API. A guest cart is a bearer capability: whoever holds the id holds the cart.
- Signed-in cart: one cart per customer. The first cart or checkout request made while signed in and still carrying a guest-cart cookie merges the guest cart in.
- Checkout (
POST /api/plugins/commerce/public/v1/checkout) requires anIdempotency-Keyheader, so a retried submission returns the original order rather than creating a second one. Stock is reserved atomically, so two customers cannot both buy the last unit. Guest checkout is supported.
Orders
Section titled “Orders”Order statuses: pending, paid, fulfilled, cancelled, refunded. In the admin you can move a pending order to cancelled, and a paid order to fulfilled or cancelled. Cancelling restocks. paid is set only by verified payment settlement, never by hand, and refunded is not reachable through the API today: real provider-backed refunds are not implemented.
Payments (Paystack)
Section titled “Payments (Paystack)”Payment uses Paystack’s hosted checkout only. There is no inline widget and no Paystack public key is needed.
- Set the secret:
wrangler secret put PAYSTACK_SECRET_KEY(ansk_test_…key for testing,sk_live_…for production). Unset, payment routes return503 Payments are not configured. - Register this webhook URL in the Paystack dashboard:
https://your-api-url/api/plugins/commerce/public/v1/payments/webhook. - Your storefront calls
payments.initialize()for a pending order, sends the customer to Paystack, and Paystack returns them to yourcallbackUrl, which must be an origin inCORS_ORIGINS. - The server confirms payment itself (
payments.verify()or the signed webhook), checking reference, status, amount and currency. Reaching the callback URL alone never marks an order paid.
Commerce Settings in the admin shows whether the key is configured and whether it is a test or live key, without ever revealing it.
Storefront API and Astro
Section titled “Storefront API and Astro”The storefront API lives at /api/plugins/commerce/public/v1/*: /categories, /products, /products/{slug}, /cart, /checkout, /payments, and the signed-in /customer routes (profile, addresses, orders). @kenresoft-cms/astro wraps them as cms.commerce. examples/astro-site in the CMS repository is a complete storefront reference. It is a reference, not a supported starter.