Webhooks

Quand l'état d'un paiement change, Tchin envoie une requête POST à votre callback_url (ou au webhook de votre application). C'est la source de vérité pour valider une commande — ne vous reposez jamais sur le seul retour navigateur, qui peut être interrompu (réseau, fermeture d'onglet…).

Format

L'envoi est de type application/x-www-form-urlencoded et les informations sont regroupées sous la clé data. Vous récupérez donc data avant de lire un champ (ex. data['status']).

Webhook
POST  https://monsite.com/tchin/webhook
Content-Type: application/x-www-form-urlencoded

data[response_code]=00
data[response_text]=Transaction completed
data[status]=completed
data[hash]=7f3b9e…(SHA-512)
data[reference]=a1b2c3d4e5f6      # = token du paiement
data[token]=…
data[amount]=5000
data[fee]=250
data[net]=4750
data[currency]=XOF
data[country]=SN
data[method]=wave-senegal
data[mode]=live
data[fail_reason]=
data[customer][name]=Awa Diop
data[customer][email]=awa@exemple.com
data[customer][phone]=771111111
Champ (dans data)Description
statuscompleted, failed, cancelled ou pending.
hashSHA-512 de votre clé privée — sert à authentifier l'origine (voir ci-dessous).
referenceLe token du paiement (à rapprocher de votre commande).
amount / fee / netMontant payé / commission Tchin (5%) / montant net crédité.
currencyDevise (toujours XOF).
country / methodPays et moyen de paiement utilisés.
modelive ou test (webhook de test en sandbox).
fail_reasonMotif, renseigné pour les statuts failed / cancelled.
customerNom, email, téléphone du payeur.

Vérifier l'origine (hash)

Chaque webhook contient un hash = SHA-512 de votre clé privée (la même que l'en-tête TCHIN-PRIVATE-KEY). Recalculez-le de votre côté et comparez : s'ils diffèrent, ignorez la requête. Cela garantit que la notification provient bien de Tchin.

Réception (PHP)

PHP
<?php
// Fichier appelé par Tchin sur votre callback_url.
// Les données arrivent en form-urlencoded, sous la clé "data".
$data = $_POST['data'] ?? [];

// 1) Authentifiez l'origine : hash = SHA-512 de VOTRE clé privée (TCHIN-PRIVATE-KEY)
$expected = hash('sha512', 'votre_cle_privee');
if (! hash_equals($expected, $data['hash'] ?? '')) {
    http_response_code(401);
    exit('Signature invalide');
}

// 2) Agissez selon le statut
if (($data['status'] ?? null) === 'completed') {
    $reference = $data['reference'];   // = le token du paiement
    $net       = (int) $data['net'];   // ce que vous recevez (après 5%)
    // → Retrouvez la commande liée à $reference
    // → Si pas déjà payée : marquez-la PAYÉE et livrez (idempotence)
}

http_response_code(200);   // accusez réception
echo 'OK';

Réception (Node.js)

JavaScript
// Node.js / Express
import express from 'express';
import crypto from 'crypto';
const app = express();
app.use(express.urlencoded({ extended: true })); // form-urlencoded

app.post('/tchin/webhook', (req, res) => {
  const d = req.body.data || {};

  const expected = crypto.createHash('sha512').update('votre_cle_privee').digest('hex');
  if (d.hash !== expected) return res.sendStatus(401);

  if (d.status === 'completed') {
    // retrouver la commande d.reference, la marquer payée (une seule fois)
  }
  res.sendStatus(200);
});

Idempotence

Un même paiement peut, dans de rares cas, déclencher plusieurs appels (latence, réessais). Identifiez chaque webhook par sa reference et n'appliquez l'effet (marquer payé, livrer) qu'une seule fois.

Bonnes pratiques

  • Vérifiez systématiquement le hash avant d'agir.
  • Répondez HTTP 200 rapidement ; traitez le reste en tâche de fond si nécessaire.
  • Votre callback_url doit être en HTTPS et accessible publiquement.
  • Le montant net = amount − fee (commission 5%).
  • En cas d'erreur (≠ 200), gardez l'opération idempotente (Tchin pourra réémettre).
Base API : https://tchin.tech/api/v1 · Tchin Documentation

Connexion / Inscription

Entrez votre email, on vous envoie un code à 6 chiffres.

En vous inscrivant, vous acceptez nos politiques.

Entrez le code

Code envoyé à .