Integrate MonCashConnect with Lovable or Claude
This guide is written for people building their application with an AI tool (Lovable, Claude, Bolt, v0, GitHub Copilot Workspaces, etc.) who want to accept MonCash payments through MonCashConnect. No prior programming knowledge is required — but a single security mistake can drain your account. Read the next section in full before doing anything else.
What you'll end up with
- A MonCash checkout page wired to your Lovable or Claude application
- A webhook that automatically marks your orders as "paid"
- A secure setup — your keys are never exposed in public code, in the AI chat history, or in your Git repository
Prerequisites
- An active MonCashConnect account (create one at /auth)
- A Lovable, Claude (Claude.ai), Bolt or equivalent project
- A domain where your application is deployed (or an ngrok tunnel for local testing — see the webhook-testing guide)
Security — non-negotiable
Read this before anything else. A single mistake can drain your account.
Your MonCashConnect secret key (sk_proj_…) and your webhook secret (whsec_…) give anyone who holds them the power to:
- Create payments from your account (and therefore read your balance and your history)
- Request MonCash withdrawals to their number
- Have fraudulent webhooks issued with valid signatures
The golden rule
Never type your secret key or your webhook secret into an AI chat window (Lovable, Claude, ChatGPT, Bolt, etc.).
Why? The contents of your AI chat are:
- Stored server-side (Anthropic, Lovable, OpenAI, etc.) — not end-to-end encrypted
- Potentially visible to the platform's support engineers
- Sometimes indexed by internal analytics or fine-tuning tooling
- Persisted in the project history — accessible to any invited collaborator
- Backed up in logs that can be exfiltrated in case of a breach
A key that appears even once in a chat must be considered compromised forever. Revoke it immediately and generate a new one.
process.env.MCC_SECRET_KEY" or "read the key from an environment variable named MCC_SECRET_KEY". You then configure that variable inside Lovable / your host's interface — without the actual value ever passing through the chat.What can be public (safe)
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Your site URL | Safe public | Ex: https://my-shop.com — can appear in the chat without risk. |
| Your return URL | Safe public | Ex: https://my-shop.com/thanks — already shows up in the customer's browser. |
| Your webhook URL | Safe public | Ex: https://my-shop.com/api/webhook — the URL itself is not a secret. |
| The sk_proj_ prefix | Safe public | The first 8 characters. The suffix is secret. |
| The name of your MCC project | Safe public | It shows up on the user consent screen anyway. |
What is secret (NEVER paste into an AI chat)
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Full secret key | 🔒 SECRET | sk_proj_XXXXXXXXXXXXXXXXXXXXXXXX (43 characters after the prefix) |
| Full webhook secret | 🔒 SECRET | whsec_XXXXXXXXXXXXXXXXXXXXXXXX |
| MCC account password | 🔒 SECRET | Obvious, but worth mentioning. |
Step 1 — Get your keys from MonCashConnect
All configuration lives on the Developer page of your dashboard. Here's exactly where to click:
Navigate to the Developer page
- Go to moncashconnect.com and sign in (Sign in link at the top right).
- Once signed in, open the Dashboard menu.
- In the sidebar, click Developer (key icon). The direct URL is moncashconnect.com/developer.
- You'll see two tabs: "API Keys" and "Projects".
Create a project
For serious integrations (with a deployed site and a webhook), create a Project rather than just an API key. A Project bundles:
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Project name | e.g. My-Shop | Visible on the customer's consent screen. |
| Secret key | sk_proj_… | Used to sign every API request. |
| Webhook URL | https://my-shop.com/api/webhook | Where MCC sends payment confirmations. |
| Webhook secret | whsec_… | Used to verify that the webhook really comes from MCC. |
| Allowed domains | my-shop.com | Comma-separated list. CORS allow-list. |
- On /developer, click the "Projects" tab.
- Click the "New project" button (top right of the list).
- Fill in:
- Name: the name of your shop / app.
- Webhook URL:
https://your-site.com/api/moncash-webhook(you'll configure this route in step 4 — leave it blank if you don't know yet). - Allowed domains:
your-site.com, www.your-site.com(comma-separated).
- Click "Create".
- ONLY ONCE, MonCashConnect shows you:
- Your full secret key
sk_proj_xxxxxxxxxxxxxxxx - Your full webhook secret
whsec_xxxxxxxxxxxxxxxx
- Your full secret key
- Click the "Copy" buttons next to each value and paste them into a password manager (1Password, Bitwarden, the macOS keychain, etc.) — not into a text file on your desktop, and especially not into the AI chat.
Step 2 — Store your keys in the right place
You now have your two secrets in your password manager. You need to make them available to your code without the value going through the AI. The standard technique: environment variables.
If you use Lovable
- In your Lovable project, click the ⚙️ Settings icon (or the gear icon depending on your version).
- Look for the "Environment Variables" or "Secrets" section.
- Click "Add a variable".
- Create these two variables (one at a time):
MCC_SECRET_KEY=sk_proj_VOTRE_CLE_SECRETE_ICI MCC_WEBHOOK_SECRET=whsec_VOTRE_SECRET_WEBHOOK_ICI - Save. Lovable redeploys automatically. The values are encrypted at rest and injected into
process.envat runtime.
If you use Claude to generate code that you host elsewhere
Claude generates the code, but you deploy it (Vercel, Netlify, Cloudflare, etc.). Never hardcode the key inside the generated code. Instead, add the same two variables in your host's environment panel:
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Vercel | Dashboard | Settings → Environment Variables → Add |
| Netlify | Dashboard | Site settings → Environment variables → Add a variable |
| Cloudflare Pages | Dashboard | Settings → Environment variables → Add variable |
| Railway | Dashboard | Project → Variables → New variable |
| Render | Dashboard | Service → Environment → Add Environment Variable |
| Locally | .env.local | Create .env.local at the root; add .env.local to your .gitignore |
.env or .env.local into Git. Check your .gitignore:# .gitignore
.env
.env.local
.env.*.localStep 3a — Prompt for Lovable
Here's a copy-paste-ready prompt for Lovable. Notice that the key appears nowhere — we just tell Lovable to use the environment variable.
Prompt — Checkout (payment)
Ajoute une intégration de paiement MonCash via MonCashConnect.
**Côté serveur (Edge Function ou API Route) :**
- Crée une route POST `/api/moncash/create` qui reçoit { amount, orderId, returnUrl }.
- Appelle `https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-create` avec :
- Header: `Authorization: Bearer ${process.env.MCC_SECRET_KEY}`
- Body JSON: { amount, referenceId: orderId, returnUrl }
- Si la réponse est 201, renvoie au client le champ `paymentUrl`.
- Si erreur, renvoie l'erreur structurée (champ `error` + `code`).
- **N'expose JAMAIS `MCC_SECRET_KEY` côté client. Lis-la uniquement depuis process.env.**
**Côté client :**
- Sur le bouton "Payer", fais un POST à `/api/moncash/create` avec
{ amount: total_en_HTG_entier, orderId: id_de_la_commande, returnUrl: window.location.origin + "/merci" }.
- À la réception de `paymentUrl`, redirige le navigateur avec window.location.href = paymentUrl.
**Stocke la commande en BDD avec status="awaiting_payment" AVANT la redirection.**
La confirmation finale viendra par webhook (je l'ajouterai ensuite).
**Référence officielle :** docs sur https://moncashconnect.com/docs (section "Créer un paiement").Prompt — Webhook (confirmation)
Run this prompt after the checkout works, to add automatic confirmation:
Ajoute un webhook qui marque une commande comme payée quand MonCashConnect
confirme le paiement.
- Crée une route POST `/api/moncash/webhook` qui reçoit un POST de MCC.
- **Lis le corps brut (raw body) AVANT toute désérialisation JSON.**
- Récupère ces headers :
- `x-mcc-signature` (format: "sha256=<hex>")
- `x-mcc-timestamp` (epoch en secondes)
- Vérifie HMAC-SHA256 du corps brut avec process.env.MCC_WEBHOOK_SECRET ;
rejette en 401 si signature invalide.
- Rejette en 401 si abs(now - timestamp) > 300 secondes.
- Sinon parse le JSON :
- { event: "payment.completed", reference, amount, status, completedAt }
- { event: "payment.failed", reference, amount, status, completedAt }
- Trouve la commande par `reference === orderId` et mets à jour son status.
- **Réponds 200 toujours, même si la commande a déjà été marquée.**
Les retries de MCC doivent être idempotents.
**N'expose pas process.env.MCC_WEBHOOK_SECRET côté client.**
**Référence officielle :** https://moncashconnect.com/docs (section "Webhooks").Step 3b — Prompt for Claude (claude.ai)
If you use Claude (claude.ai) to generate code that you then paste into your project, here's the prompt to use. Same principle: the key never appears in the chat.
Prompt — Generate the code (Next.js example)
J'ai un projet Next.js App Router. Génère le code complet pour accepter
des paiements MonCash via l'API MonCashConnect.
**Contraintes de sécurité (impératives) :**
- Mes secrets sont dans process.env.MCC_SECRET_KEY et process.env.MCC_WEBHOOK_SECRET.
- Ne mets JAMAIS de valeur en dur. Ne demande pas la valeur de mes clés.
- Ne crée pas de variable NEXT_PUBLIC_* pour ces clés.
**Ce que je veux :**
1. `app/api/moncash/create/route.ts` :
- POST { amount: number, orderId: string, returnUrl: string }
- Appelle https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-create avec Bearer + body JSON.
- Retourne { paymentUrl } ou { error, code }.
2. `app/api/moncash/webhook/route.ts` :
- Force `export const runtime = "nodejs"` (pas Edge).
- Lis le corps avec await req.text() (jamais req.json() avant vérif HMAC).
- Récupère X-MCC-Signature (format "sha256=<hex>") et X-MCC-Timestamp.
- Vérifie HMAC-SHA256(raw_body, MCC_WEBHOOK_SECRET) en temps constant.
- Vérifie |now - timestamp| ≤ 300s.
- Parse l'événement et appelle ma fonction handleEvent(event) (laisse-la TODO).
- Renvoie 200 toujours sur succès, 401 sur signature invalide.
3. `components/PayButton.tsx` :
- Composant client avec un bouton "Payer X HTG".
- Au clic : POST vers /api/moncash/create, puis window.location.href = paymentUrl.
- Gère l'état loading + l'affichage d'erreur si le serveur renvoie un `error`.
Référence : https://moncashconnect.com/docs (section "Créer un paiement" et "Webhooks").
Donne-moi le code complet, prêt à coller, en TypeScript strict.Once the code is generated
- Copy each file into your local project.
- Create
.env.localat the root and add your real keys (from your password manager):MCC_SECRET_KEY=sk_proj_VOTRE_CLE MCC_WEBHOOK_SECRET=whsec_VOTRE_SECRET - Make sure
.env.localis in your.gitignore. - Run
npm run devand test locally with an ngrok tunnel (see /guides/webhook-testing). - For production, add the same variables in your host's dashboard (Vercel, Netlify, etc.).
Step 4 — Wire the webhook
Now that your application has a working /api/moncash/webhook route, you need to tell MonCashConnect where to send it.
- Go back to moncashconnect.com/developer.
- Click the "Projects" tab.
- Click the "⋯" (three dots) to the right of your project, then "Edit".
- In Webhook URL, paste the full URL: for example
https://my-shop.com/api/moncash/webhook. - Make sure Allowed domains contains the domain your client page will call
/api/moncash/createfrom. - Click "Save".
Test before going to production
On the /developer page, at the bottom, there's a "Webhook Tester" section. You can send a test event to your URL, check that your code answers 200, and inspect the received signature. Use this before pushing to production.
To test locally (without deploying), use ngrok or cloudflared as explained in /guides/webhook-testing.
Step 5 — Verification checklist
Tick every box before announcing your integration to real users:
What you must NEVER do (or you'll lose your money)
Never paste your secret key into the chat
Lovable, Claude, ChatGPT, Bolt — they all store history. A key that appears once in a chat is compromised. Revoke it immediately.
Never prefix a variable with NEXT_PUBLIC_, VITE_, PUBLIC_, or REACT_APP_
Those prefixes inject the value into the JavaScript bundle shipped to the browser. Anyone can read it with View Source. Just use MCC_SECRET_KEY (no public prefix).
Never commit .env, .env.local, or a secrets.json file
Check your .gitignore before any git push. If you committed by accident, revoke the key immediately on /developer and generate a new one — Git history doesn't disappear.
Don't set your webhook URL to HTTP (without the S)
MonCashConnect will refuse to sign properly, and any public wifi network can read or rewrite the requests. HTTPS is mandatory.
Don't disable the webhook HMAC verification
Without verification, anyone can send a fake "payment.completed" to your endpoint and mark an order as paid without paying.
Don't store the keys in your app's database
Environment variables only. A leaking database must not leak your MCC secrets.
Don't share your Lovable / Claude project with someone without rotating the keys
Collaborators have access to the secrets configured on the project. If you invite then un-invite, rotating is safer.
Don't use the same key on staging and production
Create TWO separate MCC projects ("My-Shop-Staging" and "My-Shop-Prod"), each with its own keys. If staging leaks, prod stays safe.
If a key leaks
- Go immediately to moncashconnect.com/developer.
- "Projects" tab → ⋯ → "Rotate keys"(or delete and recreate the project).
- Copy the new key and the new secret.
- Update the environment variables at your host.
- Redeploy. The old key is revoked immediately — any future request using it fails with 401.
- If you see suspicious payments or withdrawals, contact support at support@moncashconnect.com.