Skip to content

Réconciliation ​

Comment garantir que votre base et SOAMTAR restent toujours synchrones.

Trois lignes de défense ​

SOAMTAR utilise trois mécanismes complémentaires pour la cohérence :

  1. Webhooks (push, primaire) : événement émis dès qu'un statut change
  2. Endpoint verify (pull, à la demande) : vous interrogez POST/v1/payments/{id}/verify
  3. Cron de réconciliation interne (pull, automatique) : toutes les 5 min, SOAMTAR revérifie auprès d'Orange Money les transactions bloquées et émet les webhooks manqués

Vous, marchand, devez gérer la 4ème ligne : votre propre cron quotidien.

Cron quotidien recommandé ​

php
// Tous les jours à 03:00 (heure de Freetown, GMT)
class ReconcileSoamtarTransactions extends Command
{
    public function handle()
    {
        // Pour chaque transaction de votre DB encore en pending depuis > 30 min
        $stuck = Order::where('payment_status', 'pending')
            ->where('created_at', '<', now()->subMinutes(30))
            ->whereNotNull('soamtar_id')
            ->get();

        foreach ($stuck as $order) {
            $response = Http::withToken(env('SOAMTAR_SECRET_KEY'))
                ->post("https://app.so-amtar.com/v1/payments/{$order->soamtar_id}/verify");

            $status = $response->json('data.status');

            // Synchroniser avec votre DB
            $order->update(['payment_status' => $status]);

            // Si succès, déclencher vos workflows métier (livraison, etc.)
            if ($status === 'success' && $order->wasChanged('payment_status')) {
                FulfillOrder::dispatch($order);
            }
        }
    }
}

Audit hebdomadaire ​

Une fois par semaine, comparez les volumes :

sql
-- Votre DB
SELECT DATE(paid_at) AS day, COUNT(*) AS count, SUM(amount) AS total_sle
FROM orders
WHERE payment_status = 'success' AND paid_at >= NOW() - INTERVAL '7 days'
GROUP BY DATE(paid_at);
bash
# SOAMTAR
curl 'https://app.so-amtar.com/v1/payments?status=success&created_from=2026-04-07&per_page=100' \
  -H "Authorization: Bearer sk_live_xxx"

Tout écart > 0.01 % nécessite investigation. Contactez support@so-amtar.com avec :

  • Date de début / fin de la fenêtre
  • Volume attendu vs. observé (en SLE)
  • Liste des merchant_ref divergents

Cas de désynchronisation typiques ​

CasCauseSolution
Webhook reçu mais pas traité côté votre serveurBug applicatifRe-traiter via le dashboard "Resend"
Transaction en pending chez vous, success chez SOAMTARWebhook perduPOST/verify puis sync
Transaction success chez vous, failed chez SOAMTARRace condition rareAudit manuel + correction
Refund chez SOAMTAR, pas chez vousWebhook refund manquéGET/v1/refunds?transaction_id=...

Webhook manqué : recovery automatique ​

Si vous savez que vous avez perdu des webhooks (incident interne, déploiement raté), forcez le replay :

bash
# Pour toutes les transactions du jour
for ID in $(jq -r '.data[].id' < my-orders-today.json); do
  curl -X POST "https://app.so-amtar.com/v1/payments/$ID/verify" \
    -H "Authorization: Bearer sk_live_xxx"
done

verify n'a aucun effet si la transaction est déjà au bon statut côté SOAMTAR (idempotent). En revanche, il ré-émet le webhook vers votre endpoint si une transition vient d'être détectée.

Réconciliation comptable mensuelle ​

Comparez :

SourceChamp
Vos commandesSUM(amount) WHERE payment_status = 'success'
Dashboard SOAMTARVolume du mois (livemode = true)
Settlements reçusSUM(net_amount) reversé sur votre compte bancaire
Refunds émisSUM(amount) WHERE refund.status = 'success'

L'égalité attendue : Volume - Refunds - Fees - Disputes_perdus = Settlements. Tous les montants sont en leones (SLE).

SOAMTAR Payment API Documentation.