alouspike/cmi-payment

Laravel package for CMI (Centre Monetique Interbancaire) payment gateway integration - Moroccan banking payment solution

Maintainers

Package info

github.com/alouspike/cmi-payment

pkg:composer/alouspike/cmi-payment

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-02-27 15:24 UTC

This package is auto-updated.

Last update: 2026-04-27 15:43:42 UTC


README

Dernière version Téléchargements Licence Version PHP

Package Laravel pour l'intégration de la passerelle de paiement CMI (Centre Monétique Interbancaire) — la solution de paiement bancaire marocaine.

Fonctionnalités

  • API fluide pour initier les paiements facilement
  • Génération et vérification sécurisée du hash HMAC
  • Support multi-boutiques (SaaS)
  • Intégration des événements Laravel
  • Journalisation des transactions en base de données
  • Contrôleur de callback intégré
  • Vue Blade de redirection avec auto-submit
  • Commande Artisan de test
  • Zéro dépendance externe

Prérequis

  • PHP 8.1+
  • Laravel 10, 11 ou 12

Installation

composer require alouspike/cmi-payment

Le package se découvre automatiquement. Pas besoin d'enregistrer manuellement le service provider.

Publier la configuration

php artisan vendor:publish --tag=cmi-config

Publier et exécuter les migrations

php artisan vendor:publish --tag=cmi-migrations
php artisan migrate

Publier les vues (optionnel)

php artisan vendor:publish --tag=cmi-views

Configuration

Ajoutez ces variables à votre fichier .env :

CMI_CLIENT_ID=votre_id_marchand
CMI_STORE_KEY=votre_cle_secrete
CMI_OK_URL=https://votresite.com/payment/success
CMI_FAIL_URL=https://votresite.com/payment/failed
CMI_SHOP_URL=https://votresite.com
CMI_CALLBACK_URL=https://votresite.com/cmi/callback
CMI_SANDBOX=true
CMI_HASH_ALGORITHM=SHA512
CMI_CURRENCY=504
CMI_LANG=fr
CMI_STORE_TRANSACTIONS=true

Options complètes

Paramètre Défaut Description
CMI_CLIENT_ID '' ID marchand fourni par CMI
CMI_STORE_KEY '' Clé secrète pour la génération du hash
CMI_BASE_URI testpayment.cmi.co.ma/... URL de la passerelle
CMI_OK_URL '' URL de redirection en cas de succès
CMI_FAIL_URL '' URL de redirection en cas d'échec
CMI_SHOP_URL '' URL de la boutique
CMI_CALLBACK_URL '' URL de callback serveur
CMI_CURRENCY 504 Devise par défaut (504 = MAD)
CMI_LANG fr Langue par défaut
CMI_AUTO_REDIRECT true Redirection automatique après paiement
CMI_SESSION_TIMEOUT 1800 Timeout de session en secondes
CMI_HASH_ALGORITHM SHA512 Algorithme de hash (SHA512 ou SHA256)
CMI_STORE_TRANSACTIONS true Journaliser les transactions en BDD
CMI_SANDBOX true Mode sandbox
CMI_ROUTE_PREFIX cmi Préfixe des routes

URL de production

Pour la production, modifiez :

CMI_BASE_URI=https://payment.cmi.co.ma/fim/est3Dgate
CMI_SANDBOX=false

Utilisation

Paiement simple

use Cmi;

// Dans votre contrôleur
public function pay()
{
    return Cmi::amount(150.00)
        ->orderId('CMD-001')
        ->email('client@email.com')
        ->pay();
}

Paiement avancé

use Cmi;
use Alouspike\CmiPayment\Enums\Currency;
use Alouspike\CmiPayment\Enums\Language;

return Cmi::amount(250.50)
    ->orderId('CMD-002')
    ->customerName('Ahmed Alami')
    ->email('ahmed@email.com')
    ->phone('0661000000')
    ->currency(Currency::MAD)
    ->lang(Language::FR)
    ->description('Achat en ligne #002')
    ->billingAddress('123 Rue Hassan II', 'Casablanca', 'MA')
    ->sessionTimeout(600)
    ->autoRedirect(true)
    ->okUrl('https://monsite.com/custom/success')
    ->failUrl('https://monsite.com/custom/fail')
    ->extraData(['champ_personnalise' => 'valeur'])
    ->pay();

Multi-Boutiques (SaaS)

return Cmi::useCredentials(
    clientId: $shop->cmi_client_id,
    storeKey: $shop->cmi_store_key,
)->amount(100.00)
  ->orderId('CMD-003')
  ->email('test@test.com')
  ->pay();

Gestion des callbacks

Automatique (Contrôleur intégré)

Le package enregistre automatiquement une route POST /cmi/callback qui gère la vérification du hash, la mise à jour des transactions et le dispatch des événements.

Utilisation du Trait

Dans votre contrôleur, utilisez le trait CmiGateway pour gérer les redirections OK/Fail :

use Alouspike\CmiPayment\Traits\CmiGateway;
use Alouspike\CmiPayment\CmiPaymentResponse;

class PaymentController extends Controller
{
    use CmiGateway;

    protected function onCmiPaymentSuccess(CmiPaymentResponse $response)
    {
        $orderId = $response->getOrderId();
        // Mettre à jour la commande, notifier l'utilisateur...
        return redirect()->route('orders.show', $orderId)
            ->with('success', 'Paiement effectué avec succès !');
    }

    protected function onCmiPaymentFailed(CmiPaymentResponse $response)
    {
        return redirect()->route('checkout')
            ->with('error', 'Le paiement a échoué. Veuillez réessayer.');
    }
}

Puis dans vos routes :

Route::post('/payment/success', [PaymentController::class, 'cmiOk']);
Route::post('/payment/failed', [PaymentController::class, 'cmiFail']);

Vérification manuelle du hash

use Cmi;

if (Cmi::verifyHash($request->all())) {
    // Le hash est valide
}

Événements

Le package dispatch les événements suivants :

Événement Quand
CmiCallbackReceived Chaque callback reçu
CmiPaymentSucceeded ProcReturnCode === '00' (paiement approuvé)
CmiPaymentFailed Paiement échoué

Écouter les événements

// Dans EventServiceProvider ou avec Event::listen
use Alouspike\CmiPayment\Events\CmiPaymentSucceeded;
use Alouspike\CmiPayment\Events\CmiPaymentFailed;

Event::listen(CmiPaymentSucceeded::class, function ($event) {
    $response = $event->response;
    $orderId = $response->getOrderId();
    $amount = $response->getAmount();
    // Envoyer un email de confirmation, mettre à jour le statut...
});

Event::listen(CmiPaymentFailed::class, function ($event) {
    $response = $event->response;
    // Journaliser l'échec, notifier l'administrateur...
});

Méthodes de CmiPaymentResponse

Méthode Retour Description
isSuccessful() bool Si le paiement a réussi
isFailed() bool Si le paiement a échoué
getOrderId() ?string ID de la commande
getAmount() ?string Montant du paiement
getProcReturnCode() ?string Code retour CMI
getAuthCode() ?string Code d'autorisation
getTransId() ?string ID de la transaction
getCardBrand() ?string Marque de la carte (Visa, MC...)
getMaskedPan() ?string Numéro de carte masqué
getClientIp() ?string Adresse IP du client
getStatus() string Statut : approved/declined/error
getErrMsg() ?string Message d'erreur éventuel
toArray() array Données complètes de la réponse

Commande Artisan

php artisan cmi:test

Vérifie votre configuration CMI et affiche un exemple de code de paiement.

Cartes de test

Utilisez ces cartes en mode sandbox :

Type de carte Numéro Expiration CVV
Visa 4000 0000 0000 0002 Toute date future 3 chiffres
Mastercard 5200 0000 0000 0007 Toute date future 3 chiffres
Visa (3DS) 4000 0000 0000 0051 Toute date future 3 chiffres

Note : Les numéros de cartes de test peuvent varier selon votre contrat CMI. Contactez le support CMI pour les identifiants de test exacts.

Dépannage

Erreurs "Hash invalide"

  • Vérifiez que CMI_STORE_KEY correspond exactement à ce que CMI vous a fourni
  • Assurez-vous que CMI_HASH_ALGORITHM correspond à votre configuration CMI (SHA512 ou SHA256)
  • Vérifiez que votre URL de callback est accessible depuis internet (CMI envoie des requêtes serveur à serveur)

Callback non reçu

  • L'URL de callback doit être accessible publiquement (pas localhost)
  • Assurez-vous que votre pare-feu autorise les requêtes POST provenant des serveurs CMI
  • Vérifiez que la route cmi/callback n'est pas bloquée par un middleware

Token CSRF invalide

Le package exclut automatiquement les routes CMI de la vérification CSRF. Si vous rencontrez toujours des problèmes, assurez-vous que les routes du package sont chargées correctement.

Transaction non sauvegardée

  • Assurez-vous d'avoir exécuté php artisan migrate
  • Vérifiez que CMI_STORE_TRANSACTIONS=true dans votre .env

Sécurité

  • Toutes les données de callback sont vérifiées via le hash HMAC avant traitement
  • La clé secrète n'est jamais exposée dans les formulaires ou le code côté client
  • Les données de transaction sont validées côté serveur
  • Le middleware VerifyCmiHash peut être appliqué à n'importe quelle route pour une sécurité supplémentaire
  • La protection CSRF est maintenue sur toutes les routes non-CMI

Licence

Licence MIT. Voir LICENSE pour plus d'informations.