crm_payment_integrations; the Payments UI is at /dashboard/commerce/payments, and you connect processors from /dashboard/commerce/settings.
The three processors
Hiveku Payments
White-label Stripe, onboarded inside Hiveku. Fastest to set up, no Stripe account of your own required. Hiveku charges a platform fee per transaction.
Your own Stripe
Link a Stripe account you already own via Connect OAuth. You keep your own Stripe dashboard and payouts. No Hiveku platform fee.
Authorize.Net
Bring your Authorize.Net merchant credentials. US / USD. Accept.js pay page plus CIM stored cards. No Hiveku platform fee.
You can have more than one processor connected, but a single active gateway (
crm_payment_integrations.provider) is what new invoice charges route through. If the selected provider isn’t fully connected, Hiveku falls back to whichever one is — an account never hard-fails a charge because the column still reads the default. The default is Authorize.Net.Connecting Hiveku Payments
Hiveku Payments is a fully white-labeled Stripe connected account that Hiveku creates and onboards for you. There’s no separate Stripe login — KYC and account management happen inside Hiveku via Stripe’s embedded Connect components.1
Open payment settings
Go to
/dashboard/commerce/settings and choose Hiveku Payments.2
Complete embedded onboarding
Hiveku creates a connected account on first use and renders Stripe’s embedded onboarding. You submit business and bank details in-app; Stripe manages compliance and risk.
3
Wait for charges to enable
When Stripe marks the account
charges_enabled, the connection flips to active. Until then, charges are refused with a clear “finish Stripe onboarding” message.Hiveku Payments carries a blended platform fee of
3.9% + $0.60 per transaction, attached as Stripe’s application_fee_amount on every charge. This is one all-in rate — your client never sees a separate Stripe line, and Stripe’s own processing cost is deducted out of it. On a refund, Hiveku returns its fee proportionally so you aren’t left covering the refund and eating the fee.Connecting your own Stripe
If you already have a Stripe account, link it with Connect OAuth. You keep your own Stripe dashboard, payouts, and pricing — Hiveku charges no platform fee on this connection.1
Start the OAuth flow
From
/dashboard/commerce/settings, choose Connect your existing Stripe. Hiveku redirects you to Stripe’s hosted authorize page with read_write scope.2
Authorize on Stripe
Sign in to your Stripe account and approve the connection. Stripe redirects back to Hiveku’s OAuth callback, which exchanges the code for your connected account id (
acct_…).3
Confirm it's live
Hiveku reads your account’s live
charges_enabled status and stores the link as a standard connection. Once charges are enabled and Authorize.Net isn’t also connected, Stripe is auto-selected as your active gateway.Connecting Authorize.Net
Authorize.Net is bring-your-own-credentials. It’s US / USD and uses Accept.js for the pay page plus CIM (Customer Information Manager) for stored cards.1
Gather your credentials
From your Authorize.Net merchant account you’ll need four values: API Login ID, Transaction Key, Signature Key, and Public Client Key (the last one powers client-side Accept.js tokenization).
2
Enter them in settings
Go to
/dashboard/commerce/settings, choose Authorize.Net, paste all four, and pick sandbox or production.3
Hiveku verifies and stores
On save, Hiveku runs a no-charge authentication test against the gateway to confirm the keys are live, encrypts the secrets at rest, and records the connection with the verification result.
4
Webhooks self-register
When verification succeeds, Hiveku auto-registers a per-tenant webhook with Authorize.Net (settlement, refund, void, and fraud events) so payments reconcile without you pasting a URL into the Authorize.Net dashboard. If auto-registration fails, the settings UI tells you to register it manually.
The pay page
Every invoice can be shared as a tokenized link that opens a hosted, branded pay page at/pay/{token}. The page renders your agency’s logo, brand color, and the invoice’s template design, shows the line items and balance due, and — when a processor is connected and the link allows payment — presents a Pay now panel:
- Stripe (Hiveku Payments or your own) renders a Stripe.js card element. The browser tokenizes the card into a PaymentMethod (
pm_…); only that id reaches Hiveku. - Authorize.Net renders an Accept.js form. The browser tokenizes the card into an opaque token; only that token reaches Hiveku.
Stored cards and charge-on-file
When a client opts to save a card, Hiveku stores it at the processor — never the card number itself — and keeps only a reference:- Stripe — the card is attached to a Stripe Customer as a PaymentMethod. Stored charges confirm a PaymentIntent
off_sessionagainst that customer + payment method. - Authorize.Net — a CIM customer profile holds the payment profile. Hiveku snapshots the card’s brand, last four, and expiry into
crm_customer_profiles.stored_payment_profilesso the UI can list saved cards without round-tripping the gateway on every read.
Refunds
Refund from the invoice’s payment record. Both full and partial refunds go back to the original payment method at the processor, which is the source of truth; Hiveku reflects the result and updates the invoice’s refunded amount and balance.- Stripe
Hiveku issues a refund against the original charge. For Hiveku Payments, the platform fee is refunded proportionally so you don’t cover the refund and lose the fee. For your own Stripe, there’s no Hiveku fee to return.
Reconciliation
- Automatic — the synchronous pay flow records the payment immediately, and processor webhooks are an idempotent backstop that also carry async signals (settlement, dashboard-initiated refunds, onboarding completion). Duplicate webhook deliveries can’t create duplicate ledger rows.
- Manual — for money received outside a processor (a check or wire), record it against the invoice with Mark as Paid (
POST /api/crm/invoices/{id}/record-payment).
Keeping card data off Hiveku’s servers
Both rails tokenize the card in the browser (Stripe.js or Accept.js) and send Hiveku only a token — no card number, CVC, or expiry reaches Hiveku. Saved cards live at the processor (Stripe Customers or Authorize.Net CIM profiles), and Hiveku persists only references. This keeps card entry fully outsourced to the processor.Under the hood
Data model, routes, env vars, and webhooks (for developers)
Data model, routes, env vars, and webhooks (for developers)
Provider resolutionThe gateway for an account is resolved in
src/lib/billing/providers/index.ts (resolveProviderName / getPaymentProvider). It honors crm_payment_integrations.provider ('stripe' or 'authorize_net') when that provider is connected, and otherwise falls back to whichever one is. Default: authorize_net. Both Stripe modes share the stripe provider value and the stripe_account_id column — they’re distinguished by stripe_connection_mode ('hiveku_payments' vs 'standard').Where connection state livescrm_payment_integrations (one row per account) holds:- Authorize.Net:
api_login_id_encrypted,transaction_key_encrypted,signature_key_encrypted,public_client_key(a merchant identifier, stored plaintext),sandbox,merchant_id,webhook_endpoint_id. - Stripe:
stripe_account_id,stripe_connection_mode,stripe_connect_status,stripe_charges_enabled. - Shared:
provider,connected_at,last_verified_at,last_error.
src/lib/crypto/encrypt.ts (encryptApiKey / decryptApiKey) and cached per account for 5 minutes. Stripe never stores merchant secrets in this table — charges run on the platform secret key with a Stripe-Account header scoping each call to the connected account (Connect direct charges).The payment ledger is crm_payments, unique on (account_id, gateway, gateway_transaction_id) — that constraint is what makes webhook replays idempotent. Import/migration runs are tracked in crm_payment_migrations.Settings routes (the /settings/* rows are gated by the crm.invoicing permission — read to view status, create/manage to onboard or switch, delete to disconnect; the public pay endpoint is token-scoped, not permission-gated):Server env vars
STRIPE_SECRET_KEY+NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY— required for any Stripe flow (stripeConfigured()).STRIPE_CONNECT_CLIENT_ID— required for BYO Stripe Connect OAuth.STRIPE_CONNECT_WEBHOOK_SECRET— signing secret for the platform Connect webhook.NEXT_PUBLIC_BUILDER_URL— app origin used to build OAuth redirect URIs and the Authorize.Net webhook URL (defaults tohttps://app.hiveku.com).
src/lib/billing/stripe/platform-fee.ts (PLATFORM_FEE_BPS = 390, PLATFORM_FEE_FLAT_CENTS = 60, PLATFORM_FEE_LABEL = '3.9% + $0.60').Webhook endpoints- Stripe — one platform endpoint,
POST /api/webhooks/stripe/connect, receives events for every connected account and routes byevent.account. Verified with HMAC-SHA256 over${timestamp}.${rawBody}usingSTRIPE_CONNECT_WEBHOOK_SECRET(thestripe-signatureheader). - Authorize.Net — per-tenant endpoint,
POST /api/webhooks/authorize-net/{accountId}. The account id in the path is a routing hint only; trust comes from HMAC-SHA512 over the raw body using that account’s Signature Key (thex-anet-signatureheader), plus a 5-minute timestamp window. Auto-registered on connect via Authorize.Net’s REST API (/rest/v1/webhooks, HTTP Basic auth = API Login ID : Transaction Key).
- Stripe REST:
https://api.stripe.com(charges via/v1/payment_intents, refunds via/v1/refunds, stored cards via/v1/customers+/v1/payment_methods); Connect OAuth onhttps://connect.stripe.com(/oauth/authorize,/oauth/token,/oauth/deauthorize). - Authorize.Net transaction API:
https://api.authorize.net/xml/v1/request.api(production) /https://apitest.authorize.net/xml/v1/request.api(sandbox).
Troubleshooting
Stripe shows connected but charges fail
Stripe shows connected but charges fail
A connected Stripe account can’t charge until
charges_enabled is true. Finish Stripe onboarding (or clear any verification requirements Stripe placed on the account) and re-check the status on the settings page, which re-reads it live.Can't link my own Stripe
Can't link my own Stripe
Linking your own Stripe is blocked while a Hiveku Payments account is live (it would orphan that account on Stripe). Disconnect Hiveku Payments first, then run the OAuth flow.
A refund won't go through
A refund won't go through
An Authorize.Net refund of a settled transaction needs the original card’s last four. A very old transaction may fall outside the processor’s refund window and has to be refunded from the processor’s own dashboard.
What’s next?
Send Your First Invoice
End-to-end, including connecting a processor.
Subscriptions
Recurring billing on saved cards and dunning.
Client Portal
Where clients view invoices and pay.
Reports & Analytics
Cash collected, transaction volume, and refunds.