Z ZAFEW

Documentation API

L'API ZAFEW vous permet d'accepter des paiements MonCash en HTG depuis votre site ou application. Toutes les requêtes sont en JSON sur HTTPS. Les réponses utilisent les codes HTTP standards.

Comment ZAFEW s'utilise

Deux façons d'encaisser : intégrer cette API avec votre clé (sk_test_ / sk_live_) pour créer des paiements depuis votre site ou application, ou utiliser le QR code et votre espace marchand, sans écrire une ligne de code. Dans tous les cas, votre client paie sur la page MonCash officielle : ZAFEW ne voit jamais son code secret, puis vous reverse le montant net sur votre numéro MonCash.

Cette page décrit le chemin API, destiné aux développeurs.

Base URL : https://zafew.com/v1

Authentification

Chaque requête doit inclure votre clé API secrète dans l'en-tête Authorization. Les clés sk_test_ opèrent en sandbox, les clés sk_live_ en production.

Authorization: Bearer sk_test_votre_cle_api

Votre clé API n'est affichée qu'une seule fois à sa création. Stockez-la dans un gestionnaire de secrets, jamais dans votre code source.

Environnements

La sandbox simule tout le cycle de paiement sans argent réel. Les soldes sandbox et production sont strictement séparés. Le passage en production se fait en changeant simplement de clé API, aucun changement de code n'est nécessaire.

En sandbox, la payment_url renvoyée par pay-create ouvre un simulateur de paiement : votre client (ou vous-même) peut y confirmer ou annuler le paiement, exactement comme sur la vraie page MonCash : crédit du solde, webhooks et redirections returnUrl/cancelUrl compris.

EnvironnementPréfixe de cléArgent réel
Sandboxsk_test_Non
Productionsk_live_Oui (KYC requis)

Créer un paiement

POST /v1/pay-create

Crée un paiement MonCash et retourne l'URL de la page de paiement hébergée vers laquelle rediriger votre client.

Paramètres

ChampTypeDescription
amountdécimalMontant en HTG (max 75 000)
referenceIdstringVotre référence de commande
returnUrlURLOptionnel, retour après succès
cancelUrlURLOptionnel, retour après annulation
curl https://zafew.com/v1/pay-create \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cmd-1042" \
  -d '{
    "amount": "1500.00",
    "referenceId": "cmd-1042",
    "returnUrl": "https://maboutik.ht/merci"
  }'

Réponse 201 :

{
  "transaction_id": 87,
  "payment_url": "https://.../pay/...",
  "status": "pending"
}

Redirection du client (returnUrl / cancelUrl)

Fournissez returnUrl (retour après un paiement réussi) et cancelUrl (retour si le client annule ou en cas d'échec). MonCash y renverra le client, avec orderId et referenceId en paramètres. Si vous ne les fournissez pas, le client est redirigé vers une page de résultat ZAFEW par défaut.

Important — lien de paiement à usage unique. Le lien MonCash (payment_url) contient un jeton à usage unique. Ne le laissez pas traîner comme lien cliquable : certains navigateurs et extensions préchargent les liens, ce qui consomme le jeton (le client verra « session expired »). Redirigez le client immédiatement au moment de payer (window.location = payment_url) ou ouvrez-le uniquement au clic. Un QR code fonctionne toujours (il n'est pas préchargé).

SDK et exemples de code

ZAFEW fournit des SDK officiels pour PHP, Node.js et Python, couvrant toute l'API marchand (paiements, statut, solde, historique, retraits) et la vérification des webhooks. À exécuter côté serveur uniquement (votre clé sk_ ne doit jamais atteindre le navigateur).

Installation

PHP
composer require zafew/zafew-php
Node.js
npm install zafew
Python
pip install zafew

Exemples ci-dessous : créer un paiement et vérifier un webhook. Toutes les méthodes (getPayment, getBalance, listTransactions, withdraw) sont documentées dans le README de chaque SDK.

Avec le SDK — toutes les méthodes

<?php
$client = new \Zafew\Client(getenv("ZAFEW_SECRET_KEY"));

$payment = $client->createPayment([
  "amount" => "1500.00", "referenceId" => "cmd-1042",
  "returnUrl" => "https://maboutik.ht/merci",
]);
$status  = $client->getPayment($payment["transaction_id"]);
$balance = $client->getBalance();
$txns    = $client->listTransactions(1);
$payout  = $client->withdraw("1000.00");

Sans SDK (HTTP brut) — créer un paiement

<?php
// Créer un paiement — cURL, aucune dépendance
$ch = curl_init("https://zafew.com/v1/pay-create");
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST           => true,
  CURLOPT_HTTPHEADER     => [
    "Authorization: Bearer " . getenv("ZAFEW_SECRET_KEY"),
    "Content-Type: application/json",
    "Idempotency-Key: cmd-1042",
  ],
  CURLOPT_POSTFIELDS => json_encode([
    "amount"      => "1500.00",
    "referenceId" => "cmd-1042",
    "returnUrl"   => "https://maboutik.ht/merci",
  ]),
]);
$res = json_decode(curl_exec($ch), true);
curl_close($ch);

// Rediriger le client IMMÉDIATEMENT (lien à usage unique)
header("Location: " . $res["payment_url"]);

Vérifier la signature d'un webhook

<?php
// Le corps BRUT est requis pour recalculer la signature
$body      = file_get_contents("php://input");
$signature = $_SERVER["HTTP_X_ZAFEW_SIGNATURE"] ?? "";
$expected  = hash_hmac("sha256", $body, getenv("ZAFEW_WEBHOOK_SECRET"));

if (!hash_equals($expected, $signature)) {
  http_response_code(400);
  exit("signature invalide");
}
$event = json_decode($body, true);
if ($event["event"] === "payment.succeeded") {
  // livrer la commande : $event["data"]["reference_id"]
}
http_response_code(200);

Le corps d'un webhook est {"event": "...", "data": {...}}. Recalculez toujours le HMAC sur le corps brut reçu, jamais sur une version re-sérialisée.

Statut d'un paiement

GET /v1/payments/:transaction_id

Vérifie le statut auprès de MonCash et crédite votre solde si le paiement est confirmé. Ne vous fiez jamais au seul retour navigateur, appelez toujours cet endpoint (ou attendez le webhook) avant de livrer une commande.

{
  "transaction_id": 87,
  "status": "succeeded",
  "amount": "1500.00",
  "commission_amount": "37.50",
  "net_amount": "1462.50"
}

Statuts possibles : pending, succeeded, failed, cancelled

Ne laissez pas votre client bloqué sur la page MonCash. Après l'avoir redirigé, sondez ce statut depuis votre page toutes les 3 s. Au bout de quelques minutes sans confirmation, la session MonCash a expiré : affichez votre propre message « session expirée, recommencez » plutôt que de le laisser sur la page MonCash figée.

Exemple de suivi côté client. La clé API reste sur votre serveur : le navigateur interroge votre backend, qui appelle GET /v1/payments/:id avec la clé et ne renvoie que le statut.

const deadline = Date.now() + 10 * 60 * 1000;  // 10 min -> session MonCash expirée
async function suivre(id) {
  if (Date.now() > deadline) return afficherExpire();   // votre message « session expirée »
  // /mon-backend/statut/:id relaie GET /v1/payments/:id (clé API côté serveur)
  const { status } = await (await fetch(`/mon-backend/statut/${id}`)).json();
  if (status === "succeeded") return afficherPaye();
  if (status === "failed" || status === "cancelled") return afficherEchec();
  setTimeout(() => suivre(id), 3000);                    // encore « pending »
}

Solde

GET /v1/merchant/balance

Retourne le solde de l'environnement correspondant à votre clé API.

{
  "environment": "sandbox",
  "solde_disponible": "1462.50",
  "solde_en_attente": "0.00",
  "updated_at": "2026-07-10T21:03:33Z"
}

Historique des transactions

GET /v1/merchant/transactions

Liste paginée (25 par page, paramètre ?page=) des transactions de l'environnement de votre clé.

Retraits

Par défaut, le retrait est automatique : dès qu'un paiement est confirmé, le montant net part vers votre numéro MonCash, sans aucune action de votre part — généralement en quelques minutes. Vous n'avez normalement pas besoin de l'endpoint ci-dessous.

Retrait manuel (optionnel)

POST /v1/merchant/withdraw

Transfère une partie de votre solde disponible vers le numéro MonCash configuré sur votre compte. Le montant est réservé immédiatement puis transféré ; en cas d'échec, il est automatiquement recrédité. Des frais de retrait de 10% sont déduits : vous recevez le montant net (net_amount dans la réponse). Minimum 100 HTG, maximum 75 000 HTG par retrait.

curl https://zafew.com/v1/merchant/withdraw \
  -H "Authorization: Bearer sk_test_..." \
  -d '{"amount": "1000.00"}'

Webhooks

Configurez une URL de webhook dans votre dashboard pour être notifié en temps réel. Chaque livraison est signée : l'en-tête X-Zafew-Signature contient le HMAC-SHA256 (hex) du corps brut, calculé avec votre secret de signature whsec_....

Événements

  • payment.succeeded : paiement confirmé, solde crédité
  • payment.failed : paiement échoué
  • withdrawal.completed : retrait transféré
  • withdrawal.failed : retrait échoué, montant recrédité

Vérifier la signature (Python)

import hashlib, hmac

def verify(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(signature, expected)

Répondez 2xx rapidement. Sans réponse, nous retentons avec backoff exponentiel (jusqu'à 6 tentatives).

Idempotence

Passez un en-tête Idempotency-Key unique sur pay-create : en cas de retry réseau, la même transaction est retournée au lieu d'en créer une seconde.

Limites

Paramètre Valeur
Montant max / transaction75 000 HTG
DeviseHTG uniquement
Commission par paiement (plan Gratuit)4,99%
Frais de retrait (plan Gratuit)8,99% (min 100 HTG, max 75 000 HTG par retrait)
Limite de requêtes : création de paiement100 requêtes / minute
Limite de requêtes : autres endpoints300 requêtes / minute

Les taux ci-dessus sont ceux du plan Gratuit. Les abonnements Pro et Business réduisent la commission et les frais de retrait. Voir les plans

Qui paie les frais ?

Rien ne vous oblige à absorber la commission sur votre marge. La plupart des marchands intègrent leurs frais directement dans leur prix de vente, comme une TVA ou des frais de service affichés au client final. Vos taux exacts dépendent de votre plan (voir la page Tarifs) ; un abonnement les réduit.

Exemple (plan Gratuit, 6%)

Vous voulez toucher 1 000 HTG net par vente après la commission de 6%. Affichez un prix de 1 000 ÷ 0,94 ≈ 1 064 HTG à votre client. Formule générale : divisez le montant voulu par (1 − votre taux de commission).

Sécurité

Avant de passer en mode réel, sécurisez votre intégration : gardez votre clé sk_live_ côté serveur uniquement, vérifiez la signature X-Zafew-Signature de chaque webhook, imposez HTTPS, validez vos entrées, et utilisez un referenceId unique par commande.

Guide complet des bonnes pratiques de sécurité

Support

Une question ? Rejoignez le groupe Telegram

Posez vos questions d'intégration, signalez un problème et suivez les annonces. L'équipe y répond directement.

Rejoindre