Quickstart Sandbox
Le mode Sandbox est un environnement de test gratuit intégré à MonCashConnect. Construisez votre intégration, exécutez des flux de paiement de bout en bout, voyez vos webhooks se déclencher — tout cela sans déplacer d'argent réel et sans toucher au vrai MonCash. Quand vous êtes prêt, vous échangez deux valeurs de secret et vous êtes en live. Même API, mêmes payloads, mêmes formes de réponse.
Avant de commencer
Il vous faut :
- Un compte MonCashConnect sur moncashconnect.com — pour tester en Sandbox, aucune vérification d'identité n'est requise. La vérification (KYC) n'est demandée que pour activer les paiements Live.
- Un backend capable d'émettre des requêtes HTTPS sortantes et d'héberger un endpoint webhook.
- Un domaine vers lequel rediriger vos clients après paiement.
Implémenter avec une IA
La plupart des marchands ont déjà un assistant IA dans leur workflow — Lovable, Cursor, Claude, ChatGPT, Copilot. Le prompt ci-dessous encapsule l'intégration sandbox MCC complète en un seul copier-coller : votre assistant pose trois questions, puis écrit le backend, le webhook, le bouton checkout et la page de retour.
Avant de coller : ayez sous la main votre MCC test secret + votre test webhook secret (depuis « Régénérer les clés de test » sur l'onglet Projets de la page Développeur) et le domaine de votre site.
You are implementing MonCashConnect (MCC) sandbox payments on this project.
MCC is a Stripe-style payment gateway for MonCash (Haiti's mobile money). Sandbox mode lets us test the full payment flow without moving any real money. When we're ready, the same code goes live by swapping two env values — no code change required.
The user will provide three pieces of info. Ask for them before writing code. Do not invent placeholders.
- DOMAIN: the merchant's domain (e.g. mamasoil.shop). It becomes the Origin header on the call to MCC, and must already be in MCC's "Allowed domains" list (the user adds it in the MCC dashboard).
- MCC_SECRET: starts with `sk_test_proj_`. From MCC dashboard → Developer → Projets → "Régénérer les clés de test" modal.
- MCC_WEBHOOK_SECRET: the test webhook secret from the same modal.
== MCC API contract ==
1) Create a payment — your backend → MCC
POST https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-create
Headers:
Authorization: Bearer <MCC_SECRET>
Origin: https://<DOMAIN> ← MUST match Allowed domains exactly. Server-side fetch does not set Origin automatically; set it manually.
Content-Type: application/json
Body:
{
"amount": <integer HTG, 1 to 1_000_000>,
"referenceId": "<unique id you generate, UUID is fine>",
"returnUrl": "https://<DOMAIN>/checkout/return",
"customerEmail": "optional@example.com", ← OMIT (not empty string) if absent
"customerName": "optional" ← OMIT if absent
}
Response 200:
{ paymentUrl, reference, expiresAt, livemode: false }
Redirect the browser to paymentUrl. In sandbox it's the MCC simulator (3-button page); in live it's the real MonCash URL.
2) Receive webhook — MCC → your backend
POST <your webhook endpoint, the URL the user will set in MCC project settings>
Headers:
X-MCC-Signature: sha256=<hex>
X-MCC-Timestamp: <unix seconds>
Content-Type: application/json
Body:
{
event: "payment.completed" | "payment.failed" | "payment.cancelled",
reference: "<the referenceId you sent earlier>",
amount: <integer HTG>,
status: "completed" | "failed" | "cancelled",
completedAt: <ISO8601 or null>,
livemode: false ← present on sandbox only; ABSENT on live (do NOT gate with === true)
}
Verification (CRITICAL):
a. Read the body as RAW BYTES first (e.g. req.text() in Deno, raw req in Express). Do NOT parse JSON before verifying — re-serializing reorders keys and breaks HMAC.
b. Compute expected = "sha256=" + hex(HMAC-SHA256(MCC_WEBHOOK_SECRET, rawBody))
c. Compare to X-MCC-Signature header. Reject with 401 if mismatch.
d. Only AFTER verifying, JSON.parse(rawBody) and dispatch on event.
Handle ALL three event types. Returning non-200 on any of them causes MCC to retry forever.
Return 200 with any short body on success.
3) Poll status (webhook fallback) — your return page → MCC, no auth
GET https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-status?reference=<referenceId>
Response: { reference, status, amount, ... }
Use this from the customer's /checkout/return page, polling every 3 seconds for up to 90 seconds, in case the webhook is delayed.
== Files to create ==
1. Backend endpoint `create-mcc-payment` (or your stack's equivalent)
Calls MCC pay-create with MCC_SECRET. Must handle CORS preflight (OPTIONS → 204 with CORS headers).
2. Backend endpoint `mcc-webhook`
Receives, verifies HMAC, dispatches on event. Uses raw body for HMAC, parses JSON only after verifying.
3. Frontend "Pay with MonCash" button on the checkout page
Calls create-mcc-payment with the amount, then window.location = paymentUrl.
4. Frontend `/checkout/return` page
Reads ?reference, ?error, ?cancelled from the query string. Polls pay-status every 3s up to 30 attempts (90s total) as the webhook fallback. Shows success / failed / cancelled / timeout state to the customer.
5. Two environment variables on the backend
MCC_SECRET = sk_test_proj_<...> (sandbox value for now)
MCC_WEBHOOK_SECRET = <test webhook secret>
Use GENERIC names (no _TEST_) so the live swap is a value change, not a code change.
6. The MCC project's "Webhook URL" field (the user sets this in MCC dashboard) must point at your deployed mcc-webhook endpoint.
== Critical gotchas ==
- Origin header MUST be set on the server-side fetch to MCC. Browsers add it automatically; servers do not.
- Raw body for HMAC verify, never the parsed-then-restringified payload.
- All three webhook event types (completed / failed / cancelled) must be handled — non-200 = infinite retry.
- `livemode` is `false` on sandbox payloads and ABSENT on live. Never gate logic with `livemode === true`.
- CORS preflight on create-mcc-payment — return CORS headers on OPTIONS, not just on POST.
- Omit customerEmail / customerName if absent; do not send empty string.
- amount is integer HTG between 1 and 1,000,000. Recommended test value: 100.
== Out of scope (do NOT do these) ==
- Live mode. Implement sandbox only. Live is one env swap later, not a code change.
- The merchant's own order persistence / inventory / fulfillment logic. Hand them the payment.completed event and let them wire it.
- Translating "Sandbox" to French if generating French copy. It's the product feature name and stays English (like Stripe).
== When done ==
Give the user:
1. The two env vars they need to set + the webhook URL they need to paste into the MCC project.
2. A 4-step test plan: open the simulator URL returned from pay-create, click Pay success on the MCC simulator, verify webhook arrives in your logs + your /checkout/return resolves to "completed".
3. A one-line note: going live = swap MCC_SECRET to sk_proj_<...> + MCC_WEBHOOK_SECRET to the live webhook secret, no code change.
Lovable — collez tel quel dans le chat.
Claude / ChatGPT — même copier-coller ; l'assistant vous demandera les trois valeurs.
Cursor / Copilot — ouvrez un panneau de chat dans votre repo, collez, répondez aux trois questions.
Les trois valeurs que l'IA vous demandera
- Votre domaine (ex.
mamasoil.shop) - Votre
MCC_SECRET(commence parsk_test_proj_) - Votre
MCC_WEBHOOK_SECRET(le test webhook secret)
Une fois que l'IA a implémenté et que vous avez déployé, revenez sur la section suivante pour vérifier que le contrat d'API correspond bien à ce qui a été construit.
1. Créer un projet
Connectez-vous → Développeur → Projets → Nouveau projet.
À remplir
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Nom | interne | Pour votre référence — n'apparaît nulle part côté client. |
| URL Webhook | HTTPS requise | URL où MCC POSTera les événements de paiement. |
| Domaines autorisés | exact | Domaines exacts que votre backend déclarera dans l'en-tête Origin lors des appels à l'API MCC. Mismatch = 403. |
À la soumission, une fenêtre modale s'affiche une seule fois avec QUATRE valeurs. Sauvegardez-les toutes :
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Live publishable | pk_proj_<32 hex> | Optionnelle — rendu côté client. |
| Live secret | sk_proj_<48 hex> | Bearer token pour les paiements live. |
| Live webhook secret | whsec_<48 hex> | Clé HMAC pour vérifier les webhooks live. |
| Test secret | sk_test_proj_<48 hex> | Bearer token pour le Sandbox. |
La clé publishable de test et le webhook secret de test sont également accessibles depuis l'onglet Projets (le webhook secret de test via « Régénérer les clés de test »).
2. L'API MCC
Trois endpoints. Identiques en sandbox et en live — seul le bearer token change.
2.1 Créer un paiement
https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-createEn-têtes :
Authorization: Bearer <VOTRE_SECRET>Origin: https://VOTRE-DOMAINE-AUTORISEContent-Type: application/json
Corps :
{
"amount": 100,
"referenceId": "<votre-id-unique>",
"returnUrl": "https://VOTRE-DOMAINE/checkout/return",
"customerEmail": "optionnel@example.com",
"customerName": "optionnel"
}Réponse (200) :
{
"paymentUrl": "https://moncashconnect.com/sim/<reference>?p=<short>",
"reference": "<votre-id-unique>",
"expiresAt": "2026-01-01T00:00:00Z",
"livemode": false
}Contraintes
amount: entier HTG, de 1 à 1 000 000.referenceId: votre identifiant unique (UUID recommandé), 100 chars max,[a-zA-Z0-9\-_].returnUrl: doit être en HTTPS.- L'en-tête
Originest REQUIS et doit correspondre à un domaine autorisé. - Omettez
customerEmail/customerNames'ils sont absents — les chaînes vides font échouer la validation.
Redirigez ensuite le navigateur du client vers la paymentUrl retournée. En sandbox : le simulateur MCC. En live : la vraie page MonCash.
2.2 Recevoir les webhooks
MCC POSTe votre URL webhook à chaque changement de statut. Vérifiez la signature HMAC-SHA256 avant de faire confiance au payload.
En-têtes :
Content-Type: application/jsonX-MCC-Signature: sha256=<hex>X-MCC-Timestamp: <unix seconds>
Corps :
{
"event": "payment.completed" | "payment.failed" | "payment.cancelled",
"reference": "<votre-id-unique>",
"amount": 100,
"status": "completed" | "failed" | "cancelled",
"completedAt": "2026-01-01T00:00:00Z" | null,
"livemode": false
}Vérification
- Lisez le corps de la requête en BYTES BRUTS (ne parsez pas le JSON d'abord — re-sérialiser casse le HMAC).
- Calculez
sha256=<hex>deHMAC-SHA256(votre-webhook-secret, raw-body). - Comparez à l'en-tête
X-MCC-Signature. - Si ça matche, parsez le JSON et dispatchez sur
event.
livemode vaut false sur les payloads sandbox et est ABSENT sur les payloads live. Ne gardez pas votre logique derrière livemode === true — ce ne sera jamais vrai.2.3 Sonder le statut (fallback)
https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-status?reference=<votre-id-unique>Aucune authentification requise. Renvoie la même fiche de paiement. Utile sur votre page de retour quand le webhook n'est pas encore arrivé.
3. Tester en sandbox
3.1 Préparer votre environnement
Deux secrets dans le .env de votre backend (ou équivalent) :
MCC_SECRET = sk_test_proj_<votre-test-secret>
MCC_WEBHOOK_SECRET = <votre-test-webhook-secret>MCC_SECRET, pas MCC_TEST_SECRET). En passant en live, vous échangez uniquement les valeurs — pas de changement de code.3.2 Déclencher un paiement sandbox
Montant de test recommandé : 100 HTG (~0,75 USD). Le même montant que vous utiliserez pour la vérification live ensuite — assez petit pour garder les deux tests bon marché, assez gros pour se comporter comme un vrai paiement.
Depuis votre checkout, appelez votre endpoint pay-create. La réponse vous donne une paymentUrl. Redirigez le navigateur.
3.3 Ce que vous verrez sur le simulateur
Le navigateur ouvre https://moncashconnect.com/sim/<reference>?p=<short>. Une carte centrée avec :
- Un badge ambre SANDBOX
- « Transaction de test — pas d'argent réel »
- Votre identifiant de référence
- Trois boutons :
- Pay success (vert) — bascule le statut à
completed, crédite le ledger sandbox. - Pay fail (rouge) — bascule le statut à
failed, aucun crédit. - Cancel / timeout (outline) — bascule le statut à
cancelled, aucun crédit.
- Pay success (vert) — bascule le statut à
- Un footer explicatif
Cliquez sur l'un d'eux.
3.4 Ce qui se passe ensuite
- Le statut de la transaction bascule dans la base de données MCC.
- Le webhook part vers votre endpoint avec
livemode: falseet l'événement correspondant. - Le navigateur redirige vers
<votre returnUrl>?reference=<id>(+&error=true&cancelled=truepour cancel,&error=truepour fail).
3.5 Où vérifier dans MCC
Après avoir cliqué sur un bouton du simulateur :
MCC Dashboard → /transactions
Toggle en pilule en haut : En direct | Test. Cliquez Test. Vos paiements sandbox apparaissent avec statut, montant, coloration entrée/sortie, et référence. Les transactions sandbox ne sont JAMAIS mélangées avec les live ; elles sont isolées.
Logs de votre handler webhook
Un POST doit être visible avec une signature HMAC valide et le type d'événement correspondant.
Votre page de retour
Doit refléter le résultat.
3.6 Tester les trois issues
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Pay success | payment.completed | ?reference=<id> |
| Pay fail | payment.failed | ?reference=<id>&error=true |
| Cancel | payment.cancelled | ?reference=<id>&error=true&cancelled=true |
Déclenchez un nouveau paiement par issue (chaque transaction ne peut être transitionnée qu'une seule fois).
4. Passer en live
Une fois les trois issues sandbox vérifiées proprement :
4.1 Échanger deux valeurs de secret
| Nom / Code | Type / Limite | Description |
|---|---|---|
| MCC_SECRET | sk_test_proj_… | Live : sk_proj_… |
| MCC_WEBHOOK_SECRET | test webhook secret | Live : live webhook secret |
4.2 Ce qui change en live
| Nom / Code | Type / Limite | Description |
|---|---|---|
| paymentUrl | Sandbox : simulateur MCC | Live : vraie URL MonCash (hébergée par Digicel) |
| Flux client | Sandbox : 3 boutons | Live : vraie page MonCash : téléphone, PIN, confirmation |
| Règlement | Sandbox : instantané | Live : ~5-30 s après PIN ; SMS de confirmation |
| livemode (webhook) | Sandbox : false | Live : absent |
| Argent | Sandbox : aucun | Live : HTG réels, ~3 % commission |
| Onglet Dashboard | Sandbox : Test | Live : En direct (par défaut) |
4.3 Premier test en live
Recommandé : le même montant de 100 HTG que vous avez testé en sandbox.
- Cliquez votre bouton checkout. Le navigateur ouvre une vraie URL MonCash.
- Entrez votre vrai numéro MonCash + PIN. Confirmez.
- Le navigateur redirige vers votre returnUrl avec
?reference=… - Dans les 30-60 secondes, le réconciliateur MCC met à jour la transaction à
completedet envoie le webhook. - Vérifiez dans MCC
/transactions(onglet En direct) — votre ligne 100 HTG,completed, ~3 HTG de commission, ~97 HTG net.
4.4 Limitation connue de livraison webhook
pay-status sur votre page de retour pendant jusqu'à 90 secondes. Votre client voit la confirmation immédiatement, quelle que soit la latence du webhook.5. Erreurs courantes
| Nom / Code | Type / Limite | Description |
|---|---|---|
| 403 Origin not allowed | En-tête Origin ≠ Domaines autorisés | Ajoutez le domaine au projet MCC. |
| project_lookup_failed 502 | Mauvais bearer token | Recopiez depuis le tableau de bord MCC. |
| tx_not_found_or_not_pending | Tx déjà traitée | Déclenchez un nouveau paiement. |
| bad signature (webhook) | JSON parsé utilisé pour le HMAC | Utilisez les bytes bruts du corps. |
| Webhook sandbox OK, live KO | Limitation connue, cf. §4.4 | Utilisez le fallback pay-status en sondage. |
| Console navigateur : Failed to fetch | Preflight CORS sur VOTRE backend | Renvoyez les en-têtes CORS sur OPTIONS. |
FAQ
Le Sandbox est-il payant ?
Non.
Puis-je sauter le KYC pour le sandbox ?
Oui. Le Sandbox est ouvert à tout compte signé — créez un projet, récupérez vos clés sk_test_proj_… et commencez tout de suite. La vérification d'identité (KYC) n'est demandée que pour activer le mode Live (sk_proj_…).
Les transactions sandbox sont-elles visibles aux admins MCC ?
Non. Uniquement sur votre /transactions (onglet Test). N'affectent jamais les résumés du dashboard, la finance, ou les vues admin.
Plusieurs projets ?
Oui. Chacun obtient sa propre paire de clés live + test + URL webhook.
Montant min / max ?
1 à 1 000 000 HTG.
Le sandbox simule-t-il l'UI MonCash ?
Non — trois boutons. Le sandbox teste votre intégration, pas l'UI Digicel.
Schéma de signature webhook ?
HMAC-SHA256, X-MCC-Signature: sha256=<hex>. Identique en sandbox et en live.
Passer en live = redéployer ?
Non. Seules les valeurs des variables d'environnement changent.
Remboursements ?
Pas encore exposés via l'API publique. Contactez le support MCC.
Statut
Ce guide est publié comme référence publique. Si quelque chose n'est pas clair, contactez le support MCC avec le nom de votre projet, l'extrait de log de la function, et l'UUID de référence.