# Coinvay Vanilla JavaScript + Node kit · 1.2.0 Vanilla means browser JavaScript (not a separate product called Vanilla). Node 22.13+ uses built-in node:sqlite; no npm install is required for the supplied backend. ## Backend 1. Keep `server/` and its database on your server, not a static host. Set variables from config.env.example through your process manager's secret controls (example file is not automatically loaded). Generate a separate random INTEGRATION_ADMIN_KEY of at least 32 characters. Use an absolute COINVAY_ORDER_DB path in a private writable directory; restrict permissions and back up SQLite safely. 2. Run `node server/server.mjs` behind an HTTPS reverse proxy. It listens on 127.0.0.1:8080. Set ALLOWED_ORIGINS to the exact comma-separated storefront origins. Do not expose `/internal/orders` publicly at the proxy; allow only your application backend. Never put either the integration admin key or Coinvay API key in browser code. 3. Your authenticated application backend loads the trusted cart and POSTs `/internal/orders` with `Authorization: Bearer ` and JSON `{reference,amount,email,name,target}`. `amount` is a USD decimal string; `reference` must uniquely identify the immutable store order. Store returned `orderId` and per-order `accessToken` against that order. On retry, return your saved mapping; do not create a new reference/invoice for the same business purchase. 4. Render only that authorized order's backend, orderId and accessToken into the customer's checkout page. A per-order token grants checkout/status for that one order; keep it out of logs/URLs. Wire `coinvayButton()` to a real button as shown in example.html. Serve the script on your own storefront. 5. The browser POSTs `/orders/:id/checkout` using its per-order token; the server saves an idempotent Coinvay invoice before replying. API failures remain unpaid. 6. Set Coinvay postback to your backend `/webhook` + webhook secret on an eligible plan. Also schedule `node server/reconcile.mjs` once per minute. It processes 20 invoices per run with a rotating cursor. If relying only on polling, expected confirmation delay grows with queue size/provider health. 7. `/orders/:id/status` reads the saved paid flag with the same per-order bearer token. After payment, customers return to your page/app and check status; the gateway does not currently provide a store-specific automatic return URL. 8. Confirmed payment writes an idempotent outbox row. Your application worker must deliver the order once, using order_id as its unique delivery key, then mark `outbox.completed=1`. The generic kit does not perform store-specific fulfillment. Kajabi has its own included worker. `POST /purchase` is disabled unless you set COINVAY_CATALOG_FILE to a trusted JSON catalog. It creates anonymous purchases from allowed SKU prices/targets only; intended for the Kajabi form. Never make the catalog client-writable. Put a persistent rate limit/WAF in front of public endpoints; the sample in-process limit is only a secondary guard and resets on process restart. The server reads the socket address, not an untrusted forwarding header. ## Staging acceptance Verify wrong/absent tokens, another order's token, bad origins, request size limits, price tampering, duplicate checkout, stale signatures, wrong invoice/order/currency/amount, unpaid API status, webhook+poll retries and durable outbox state after restart. Test your own fulfillment worker. Refunds and recurring debits are outside this one-time checkout kit. ## Branding The updated Coinvay logo assets and usage instructions are included in [BRANDING.md](BRANDING.md). Use SVG on supported web surfaces and PNG for native/platform restrictions. ## Original store currency The currency-aware backend uses `currency` with a trusted decimal `amount` when creating a saved order, or integer `cents` in that currency’s minor units when calling the SDK directly (legacy field name). USD is the default for existing records. Example: `{reference:"order-123", amount:"1000.00", currency:"INR", email:"buyer@example.com"}` for `Store.create`; for `Coinvay.create`, use `{reference:"order-123", cents:100000, currency:"INR"}`. The server catalog may set `currency`. The Shopify adapter takes currency only from its authenticated payment session. Coinvay returns USD amount/currency plus originalAmount/originalCurrency and the rate snapshot. Save and compare both source and USD totals before fulfillment. Kit database upgrades add the original currency and locked USD amount without changing old USD orders. Actual FX availability and codes come from /api/currencies. No fiat conversion/remittance is performed. ## Manual or automatic account connection · 1.2.0 Use **Connect to Coinvay** to sign in and authorize this store, or retain manual API-key setup. This release adds separate checkout business name/logo and per-store signed webhooks without changing other stores. Read **CONNECT.md**, included in this package, for exact controls, environment variables, administrator-session integration, encryption/backups, permissions and staging checks. Custom app kits require your existing administrator authentication; Shopify remains subject to platform approval.