PHPackages                             andydefer/laravel-pawapay - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. andydefer/laravel-pawapay

ActiveLibrary[Database &amp; ORM](/categories/database)

andydefer/laravel-pawapay
=========================

Laravel SDK for integrating Pawapay Mobile Money payments (pay-ins, pay-outs, and webhooks) across African markets.

v0.7.3(1mo ago)034MITPHPPHP ^8.2

Since Jan 20Pushed 2w agoCompare

[ Source](https://github.com/andydefer/laravel-pawapay)[ Packagist](https://packagist.org/packages/andydefer/laravel-pawapay)[ RSS](/packages/andydefer-laravel-pawapay/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (48)Versions (23)Used By (0)

Laravel PawaPay SDK
===================

[](#laravel-pawapay-sdk)

[![PHP Version](https://camo.githubusercontent.com/187240af044d09d5b14a1d9d9ebdf3f7a993e4c7bc09bdb46b4ba661a891bf5b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d626c7565)](https://camo.githubusercontent.com/187240af044d09d5b14a1d9d9ebdf3f7a993e4c7bc09bdb46b4ba661a891bf5b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d626c7565)[![Laravel Version](https://camo.githubusercontent.com/10fdbd63a234c8d6ad6240ef0c52a17d5fec9cfcee2a49ce11819f8b906d568c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31322532422d6f72616e6765)](https://camo.githubusercontent.com/10fdbd63a234c8d6ad6240ef0c52a17d5fec9cfcee2a49ce11819f8b906d568c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31322532422d6f72616e6765)[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)[![Tests](https://camo.githubusercontent.com/f2c8053be22217a09d6c2e8e2c68f4ed87da611fffa8ef0e94851ead1eb3f723/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d696e746567726174696f6e25323072656164792d627269676874677265656e)](https://camo.githubusercontent.com/f2c8053be22217a09d6c2e8e2c68f4ed87da611fffa8ef0e94851ead1eb3f723/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d696e746567726174696f6e25323072656164792d627269676874677265656e)[![Coverage](https://camo.githubusercontent.com/b013d49c62c71a8fdd6dbd1ca7e7e0ba3927857391125dd919b879d65efb4cea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f7665726167652d636f6d70726568656e736976652d626c7565)](https://camo.githubusercontent.com/b013d49c62c71a8fdd6dbd1ca7e7e0ba3927857391125dd919b879d65efb4cea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f7665726167652d636f6d70726568656e736976652d626c7565)[![Mobile Money](https://camo.githubusercontent.com/67aaaba8c159d2f373765e96a4c98901b9576443e62b04ba46e5c3530dc99709/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d6f62696c652532304d6f6e65792d4166726963612d627269676874677265656e)](https://camo.githubusercontent.com/67aaaba8c159d2f373765e96a4c98901b9576443e62b04ba46e5c3530dc99709/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d6f62696c652532304d6f6e65792d4166726963612d627269676874677265656e)[![API Routes](https://camo.githubusercontent.com/a4d441d84586d3689bc9f16ac337e6233dce3f0616f4a761f89d2fbcfab72e1f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f415049253230526f757465732d6175746f6d617469632d626c7565)](https://camo.githubusercontent.com/a4d441d84586d3689bc9f16ac337e6233dce3f0616f4a761f89d2fbcfab72e1f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f415049253230526f757465732d6175746f6d617469632d626c7565)

**Laravel PawaPay SDK** est un package Laravel complet et type-safe pour intégrer les paiements mobile money PawaPay dans 21 marchés africains. Construit avec des pratiques PHP modernes, il fournit une interface fluide pour les pay-ins, pay-outs, la prédiction de fournisseurs, la gestion des webhooks et inclut une API REST complète prête à l'emploi.

🚀 Installation
--------------

[](#-installation)

### 1. Installation via Composer

[](#1-installation-via-composer)

```
composer require andydefer/laravel-pawapay
```

### 2. Installation Rapide (Recommandée)

[](#2-installation-rapide-recommandée)

Utilisez la commande d'installation pour publier toutes les ressources en une fois :

```
# Installez tout en une seule commande
php artisan pawapay:install

# Installation forcée (écrase les fichiers existants)
php artisan pawapay:install --force
```

### 3. Installation Manuelle (Optionnel)

[](#3-installation-manuelle-optionnel)

Si vous préférez un contrôle manuel, publiez des composants spécifiques :

```
# Publier uniquement la configuration
php artisan vendor:publish --provider="Pawapay\\PawapayServiceProvider" --tag="pawapay-config"

# Publier les définitions de types TypeScript
php artisan vendor:publish --provider="Pawapay\\PawapayServiceProvider" --tag="pawapay-types"

# Publier le contrôleur API
php artisan vendor:publish --provider="Pawapay\\PawapayServiceProvider" --tag="pawapay-controller"

# Publier les routes personnalisées (optionnel - les routes fonctionnent automatiquement)
php artisan vendor:publish --provider="Pawapay\\PawapayServiceProvider" --tag="pawapay-routes"

# Générer les définitions TypeScript
php artisan pawapay:generate-types
```

### 4. Configuration des Variables d'Environnement

[](#4-configuration-des-variables-denvironnement)

Ajoutez à votre fichier `.env` :

```
# Environnement (sandbox/production)
PAWAPAY_ENVIRONMENT=sandbox

# Token API de PawaPay
PAWAPAY_API_TOKEN=votre_token_api_ici

# Optionnel : Personnaliser les timeouts et tentatives
PAWAPAY_TIMEOUT=30
PAWAPAY_RETRY_TIMES=3
PAWAPAY_RETRY_SLEEP=100
```

📡 Deux Manières d'Utiliser le Package
-------------------------------------

[](#-deux-manières-dutiliser-le-package)

### Option 1 : Utilisation Directe du SDK (Recommandé pour les Intégrations Personnalisées)

[](#option-1--utilisation-directe-du-sdk-recommandé-pour-les-intégrations-personnalisées)

Utilisez le SDK directement dans vos contrôleurs ou services :

```
use Pawapay\Facades\Pawapay;

// Prédire le fournisseur mobile money
$response = Pawapay::predictProvider('+260763456789');
// Retourne: PredictProviderSuccessResponse ou PredictProviderFailureResponse

// Créer une page de paiement
$requestData = PaymentPageRequestData::fromArray([...]);
$response = Pawapay::createPaymentPage($requestData);
// Retourne: PaymentPageSuccessResponseData ou PaymentPageErrorResponseData

// Initier un dépôt direct
$requestData = InitiateDepositRequestData::fromArray([...]);
$response = Pawapay::initiateDeposit($requestData);
// Retourne: InitiateDepositResponseData

// Vérifier le statut du dépôt
$response = Pawapay::checkDepositStatus('deposit_uuid');
// Retourne: CheckDepositStatusWrapperData
```

### Option 2 : API REST Intégrée (Prête à l'Emploi)

[](#option-2--api-rest-intégrée-prête-à-lemploi)

Le package inclut une API REST complète disponible automatiquement via les routes :

```
POST   /api/pawapay/predict-provider
POST   /api/pawapay/payment-page
POST   /api/pawapay/deposits
GET    /api/pawapay/deposits/{depositId}

```

#### Points de Terminaison API Disponibles :

[](#points-de-terminaison-api-disponibles-)

MéthodeEndpointType de RetourDescription`POST``/api/pawapay/predict-provider``PredictProviderSuccessResponse` ou `PredictProviderFailureResponse`Prédire le fournisseur mobile money depuis un numéro de téléphone`POST``/api/pawapay/payment-page``PaymentPageSuccessResponseData` ou `PaymentPageErrorResponseData`Créer une page de paiement hébergée`POST``/api/pawapay/deposits``InitiateDepositResponseData`Initier un dépôt direct (sans redirection)`GET``/api/pawapay/deposits/{depositId}``CheckDepositStatusWrapperData`Vérifier le statut d'un dépôt#### Structure des Réponses API :

[](#structure-des-réponses-api-)

L'API retourne directement les objets DTO sans wrapper supplémentaire :

**Réponse de succès (exemple pour predict-provider) :**

```
{
  "country": "ZMB",
  "provider": "MTN_MOMO_ZMB",
  "phoneNumber": "260763456789"
}
```

**Réponse d'erreur (exemple pour predict-provider) :**

```
{
  "failureReason": {
    "failureCode": "INVALID_PHONE_NUMBER",
    "failureMessage": "Invalid phone number"
  }
}
```

#### Exemples d'Utilisation de l'API :

[](#exemples-dutilisation-de-lapi-)

```
// Utilisation de l'API fetch en JavaScript - Prédiction de fournisseur
const response = await fetch('/api/pawapay/predict-provider', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    },
    body: JSON.stringify({
        phoneNumber: '+260763456789'
    })
});

const data = await response.json();

// Vérifiez si c'est une réponse de succès
if (data.country && data.provider) {
    console.log('Pays:', data.country); // "ZMB"
    console.log('Fournisseur:', data.provider); // "MTN_MOMO_ZMB"
    console.log('Téléphone:', data.phoneNumber); // "260763456789"
} else if (data.failureReason) {
    console.log('Erreur:', data.failureReason.failureMessage);
    console.log('Code:', data.failureReason.failureCode);
}
```

```
# Utilisation de cURL - Création de page de paiement
curl -X POST "http://votre-app.test/api/pawapay/payment-page" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "depositId": "order_123",
    "returnUrl": "https://votre-boutique.com/payment/callback",
    "customerMessage": "Paiement pour la Commande #12345",
    "amountDetails": {
      "amount": "150.00",
      "currency": "ZMW"
    },
    "phoneNumber": "260763456789",
    "language": "EN",
    "country": "ZMB",
    "reason": "Achat en Ligne",
    "metadata": [
      {"orderId": "ORD-123"},
      {"customerId": "cust-456"}
    ]
  }'
```

#### Format des Requêtes/Réponses de l'API :

[](#format-des-requêtesréponses-de-lapi-)

**1. Prédiction de Fournisseur :**

```
// Requête
{
  "phoneNumber": "+260763456789"
}

// Réponse de succès
{
  "country": "ZMB",
  "provider": "MTN_MOMO_ZMB",
  "phoneNumber": "260763456789"
}

// Réponse d'erreur
{
  "failureReason": {
    "failureCode": "INVALID_PHONE_NUMBER",
    "failureMessage": "Invalid phone number"
  }
}
```

**2. Création de Page de Paiement :**

```
// Requête
{
  "depositId": "order_123",
  "returnUrl": "https://votre-boutique.com/payment/callback",
  "customerMessage": "Paiement pour la Commande #12345",
  "amountDetails": {
    "amount": "150.00",
    "currency": "ZMW"
  },
  "phoneNumber": "260763456789",
  "language": "EN",
  "country": "ZMB",
  "reason": "Achat en Ligne",
  "metadata": [
    {"orderId": "ORD-123"},
    {"customerId": "cust-456"}
  ]
}

// Réponse de succès
{
  "redirectUrl": "https://sandbox.pawapay.io/payment/abc123"
}

// Réponse d'erreur
{
  "depositId": "order_123",
  "status": "REJECTED",
  "failureReason": {
    "failureCode": "INVALID_AMOUNT",
    "failureMessage": "Amount is invalid"
  }
}
```

**3. Initiation de Dépôt Direct :**

```
// Requête
{
  "depositId": "deposit_123",
  "payer": {
    "type": "MMO",
    "accountDetails": {
      "phoneNumber": "+260763456789",
      "provider": "MTN_MOMO_ZMB"
    }
  },
  "amount": "100.00",
  "currency": "ZMW",
  "clientReferenceId": "INV-123456",
  "customerMessage": "Paiement pour services",
  "metadata": [
    {"orderId": "ORD-123"},
    {"customerId": "cust-456"}
  ]
}

// Réponse
{
  "depositId": "deposit_123",
  "status": "ACCEPTED",
  "created": "2024-01-15T10:30:00Z",
  "failureReason": null
}
```

**4. Vérification de Statut de Dépôt :**

```
// Requête (via paramètre de route)
GET /api/pawapay/deposits/deposit_123

// Réponse (dépôt trouvé)
{
  "status": "FOUND",
  "data": {
    "depositId": "deposit_123",
    "status": "COMPLETED",
    "amount": "100.00",
    "currency": "ZMW",
    "country": "ZMB",
    "payer": {
      "type": "MMO",
      "accountDetails": {
        "phoneNumber": "260763456789",
        "provider": "MTN_MOMO_ZMB"
      }
    },
    "customerMessage": "Paiement pour services",
    "clientReferenceId": "INV-123456",
    "providerTransactionId": "txn_789",
    "created": "2024-01-15T10:30:00Z"
  }
}

// Réponse (dépôt non trouvé)
{
  "status": "NOT_FOUND",
  "data": null
}
```

🌍 Pays et Fournisseurs Supportés
--------------------------------

[](#-pays-et-fournisseurs-supportés)

PawaPay supporte **21 pays africains** avec leurs fournisseurs mobile money respectifs :

### Couverture Complète des Pays

[](#couverture-complète-des-pays)

PaysCodeFournisseurs SupportésDevise**Bénin**`BEN`MTN\_MOMO\_BEN, MOOV\_BENXOF**Burkina Faso**`BFA`MOOV\_BFA, ORANGE\_BFAXOF**Cameroun**`CMR`MTN\_MOMO\_CMR, ORANGE\_CMRXAF**Côte d'Ivoire**`CIV`MTN\_MOMO\_CIV, ORANGE\_CIV, WAVE\_CIVXOF**RDC**`COD`VODACOM\_MPESA\_COD, AIRTEL\_COD, ORANGE\_CODCDF, USD**Éthiopie**`ETH`MPESA\_ETHETB**Gabon**`GAB`AIRTEL\_GABXAF**Ghana**`GHA`MTN\_MOMO\_GHA, AIRTELTIGO\_GHA, VODAFONE\_GHAGHS**Kenya**`KEN`MPESA\_KENKES**Lesotho**`LSO`MPESA\_LSOLSL**Malawi**`MWI`AIRTEL\_MWI, TNM\_MWIMWK**Mozambique**`MOZ`MOVITEL\_MOZ, VODACOM\_MOZMZN**Nigeria**`NGA`AIRTEL\_NGA, MTN\_MOMO\_NGANGN**République du Congo**`COG`AIRTEL\_COG, MTN\_MOMO\_COGXAF**Rwanda**`RWA`AIRTEL\_RWA, MTN\_MOMO\_RWARWF**Sénégal**`SEN`FREE\_SEN, ORANGE\_SEN, WAVE\_SENXOF**Sierra Leone**`SLE`ORANGE\_SLESLE**Tanzanie**`TZA`AIRTEL\_TZA, VODACOM\_TZA, TIGO\_TZA, HALOTEL\_TZATZS**Ouganda**`UGA`AIRTEL\_OAPI\_UGA, MTN\_MOMO\_UGAUGX**Zambie**`ZMB`AIRTEL\_OAPI\_ZMB, MTN\_MOMO\_ZMB, ZAMTEL\_ZMBZMW💰 Fonctionnalités Principales
-----------------------------

[](#-fonctionnalités-principales)

### 1. Prédiction de Fournisseur Mobile Money

[](#1-prédiction-de-fournisseur-mobile-money)

Détectez automatiquement le fournisseur mobile money à partir d'un numéro de téléphone :

```
use Pawapay\Facades\Pawapay;

$response = Pawapay::predictProvider('+260763456789');

if ($response instanceof \Pawapay\Data\Responses\PredictProviderSuccessResponse) {
    echo "Pays : " . $response->country->value; // ZMB
    echo "Fournisseur : " . $response->provider->value; // MTN_MOMO_ZMB
    echo "Téléphone : " . $response->phoneNumber; // 260763456789
} else {
    echo "Erreur : " . $response->failureReason->failureMessage;
}
```

### 2. Création de Page de Paiement

[](#2-création-de-page-de-paiement)

Créez des pages de paiement hébergées pour les clients :

```
use Pawapay\Data\PaymentPage\PaymentPageRequestData;
use Pawapay\Enums\Currency;
use Pawapay\Enums\Language;
use Pawapay\Enums\SupportedCountry;
use Pawapay\Facades\Pawapay;

$requestData = PaymentPageRequestData::fromArray([
    'depositId' => (string) \Illuminate\Support\Str::uuid(),
    'returnUrl' => 'https://votre-boutique.com/payment/complete',
    'customerMessage' => 'Paiement pour la Commande #12345',
    'amountDetails' => [
        'amount' => '150.00',
        'currency' => Currency::ZMW->value,
    ],
    'phoneNumber' => '260763456789',
    'language' => Language::EN->value,
    'country' => SupportedCountry::ZMB->value,
    'reason' => 'Achat en ligne - Électronique',
    'metadata' => [
        ['orderId' => 'ORD-123456789'],
        ['customerId' => 'cust-789012'],
        ['productId' => 'PROD-345678'],
    ],
]);

$response = Pawapay::createPaymentPage($requestData);

if ($response instanceof \Pawapay\Data\PaymentPage\PaymentPageSuccessResponseData) {
    // Redirigez le client vers la page de paiement
    return redirect($response->redirectUrl);
} else {
    // Gérez l'erreur
    return back()->withErrors([
        'payment' => $response->failureReason->failureMessage
    ]);
}
```

### 3. Initiation de Dépôt Direct

[](#3-initiation-de-dépôt-direct)

Initiez des dépôts de manière programmatique sans rediriger les utilisateurs :

```
use Pawapay\Data\Deposit\InitiateDepositRequestData;
use Pawapay\Enums\Currency;
use Pawapay\Enums\SupportedProvider;
use Pawapay\Facades\Pawapay;

$requestData = InitiateDepositRequestData::fromArray([
    'depositId' => (string) \Illuminate\Support\Str::uuid(),
    'payer' => [
        'type' => 'MMO',
        'accountDetails' => [
            'phoneNumber' => '260763456789',
            'provider' => SupportedProvider::MTN_MOMO_ZMB->value,
        ],
    ],
    'amount' => '100.00',
    'currency' => Currency::ZMW->value,
    'clientReferenceId' => 'INV-123456',
    'customerMessage' => 'Paiement pour services rendus',
    'metadata' => [
        ['orderId' => 'ORD-123456'],
        ['customerId' => 'customer@email.com'],
        ['isPII' => true],
    ],
]);

$response = Pawapay::initiateDeposit($requestData);

if ($response->isAccepted()) {
    // Dépôt accepté pour traitement
    echo "ID de dépôt : " . $response->depositId;
    echo "Statut : " . $response->status->value; // ACCEPTED
    echo "Créé le : " . $response->created;
} elseif ($response->isRejected()) {
    // Dépôt rejeté
    echo "Rejeté : " . $response->failureReason->failureMessage;
    echo "Code d'erreur : " . $response->failureReason->failureCode->value;
} elseif ($response->isDuplicateIgnored()) {
    // Requête dupliquée (idempotent)
    echo "Duplication ignorée pour : " . $response->depositId;
}
```

### 4. Vérification du Statut des Dépôts

[](#4-vérification-du-statut-des-dépôts)

Surveillez le statut des transactions en temps réel :

```
use Pawapay\Facades\Pawapay;

$depositId = 'votre_depot_uuid';
$response = Pawapay::checkDepositStatus($depositId);

if ($response->isFound()) {
    $deposit = $response->data;

    echo "ID de dépôt : " . $deposit->depositId;
    echo "Montant : " . $deposit->amount . " " . $deposit->currency->value;
    echo "Statut : " . $deposit->status->value;
    echo "Pays : " . $deposit->country->value;
    echo "Téléphone : " . $deposit->payer->accountDetails->phoneNumber;
    echo "Fournisseur : " . $deposit->payer->accountDetails->provider->value;

    // Vérifiez si la transaction est terminée
    if ($deposit->isFinalStatus()) {
        echo "Transaction terminée";
    } elseif ($deposit->isProcessing()) {
        echo "Transaction en cours";
    }

    // Accédez aux métadonnées
    if ($deposit->metadata) {
        foreach ($deposit->metadata as $meta) {
            print_r($meta);
        }
    }

    // Vérifiez la raison de l'échec
    if ($deposit->failureReason) {
        echo "Échec : " . $deposit->failureReason->failureMessage;
        echo "Code : " . $deposit->failureReason->failureCode->value;
    }
} else {
    echo "Dépôt non trouvé";
}
```

📊 Référence API Complète
------------------------

[](#-référence-api-complète)

### Énumérations (Enums)

[](#énumérations-enums)

Le package fournit des énumérations complètes pour la sécurité des types :

#### `SupportedCountry` (21 pays)

[](#supportedcountry-21-pays)

```
use Pawapay\Enums\SupportedCountry;

$country = SupportedCountry::ZMB;
echo $country->value; // "ZMB"
echo $country->name; // "Zambie"

// Obtenez tous les fournisseurs pour un pays
$providers = SupportedCountry::ZMB->getProviders();
// Retourne : [SupportedProvider::MTN_MOMO_ZMB, ...]
```

#### `SupportedProvider` (40+ fournisseurs)

[](#supportedprovider-40-fournisseurs)

```
use Pawapay\Enums\SupportedProvider;

$provider = SupportedProvider::MTN_MOMO_ZMB;
echo $provider->value; // "MTN_MOMO_ZMB"

// Obtenez le pays du fournisseur
$country = $provider->getCountry();
echo $country->value; // "ZMB"
```

#### `Currency` (17 devises)

[](#currency-17-devises)

```
use Pawapay\Enums\Currency;

$currency = Currency::ZMW;
echo $currency->value; // "ZMW"

// Communément utilisées :
Currency::ZMW; // Kwacha zambien
Currency::KES; // Shilling kényan
Currency::GHS; // Cédi ghanéen
Currency::NGN; // Naira nigérian
Currency::USD; // Dollar US (RDC)
```

#### `TransactionStatus`

[](#transactionstatus)

```
use Pawapay\Enums\TransactionStatus;

// Statuts d'initiation
TransactionStatus::ACCEPTED
TransactionStatus::REJECTED
TransactionStatus::DUPLICATE_IGNORED

// Statuts finaux
TransactionStatus::COMPLETED
TransactionStatus::FAILED

// Statuts intermédiaires
TransactionStatus::SUBMITTED
TransactionStatus::ENQUEUED
TransactionStatus::PROCESSING
TransactionStatus::IN_RECONCILIATION

// Statuts de recherche
TransactionStatus::FOUND
TransactionStatus::NOT_FOUND
```

#### `FailureCode` (27 codes détaillés)

[](#failurecode-27-codes-détaillés)

```
use Pawapay\Enums\FailureCode;

// Erreurs techniques
FailureCode::NO_AUTHENTICATION
FailureCode::INVALID_INPUT
FailureCode::MISSING_PARAMETER
FailureCode::INVALID_AMOUNT
FailureCode::INVALID_PHONE_NUMBER

// Erreurs de transaction
FailureCode::PAYMENT_NOT_APPROVED
FailureCode::INSUFFICIENT_BALANCE
FailureCode::PAYER_NOT_FOUND
FailureCode::MANUALLY_CANCELLED

// Obtenez le code de statut HTTP
$code = FailureCode::INVALID_INPUT;
echo $code->httpStatusCode(); // 400
```

#### `Language`

[](#language)

```
use Pawapay\Enums\Language;

Language::EN; // Anglais
Language::FR; // Français
```

### Data Transfer Objects (DTOs)

[](#data-transfer-objects-dtos)

Toutes les interactions API utilisent des DTOs fortement typés :

#### DTOs de Requête

[](#dtos-de-requête)

```
use Pawapay\Data\PaymentPage\PaymentPageRequestData;
use Pawapay\Data\Deposit\InitiateDepositRequestData;

// Depuis un tableau
$paymentRequest = PaymentPageRequestData::fromArray($data);

// Depuis le constructeur (type-safe)
$depositRequest = new InitiateDepositRequestData(
    depositId: 'uuid',
    payer: $payerData,
    amount: '100.00',
    currency: Currency::ZMW,
    // ... autres paramètres
);
```

#### DTOs de Réponse

[](#dtos-de-réponse)

```
use Pawapay\Data\PaymentPage\PaymentPageSuccessResponseData;
use Pawapay\Data\PaymentPage\PaymentPageErrorResponseData;
use Pawapay\Data\Deposit\InitiateDepositResponseData;
use Pawapay\Data\Responses\CheckDepositStatusWrapperData;
use Pawapay\Data\Responses\PredictProviderSuccessResponse;
use Pawapay\Data\Responses\PredictProviderFailureResponse;

// Toutes les réponses ont des méthodes d'aide
$response->isAccepted();
$response->isRejected();
$response->isFound();
$response->isNotFound();
$response->isSuccess(); // Pour PredictProviderResponseData
```

### Méthodes du Service

[](#méthodes-du-service)

#### Classe `PawapayService`

[](#classe-pawapayservice)

```
// 1. Prédiction de Fournisseur
predictProvider(string $phoneNumber): PredictProviderSuccessResponse|PredictProviderFailureResponse

// 2. Pages de Paiement
createPaymentPage(PaymentPageRequestData $request): PaymentPageSuccessResponseData|PaymentPageErrorResponseData

// 3. Dépôts Directs
initiateDeposit(InitiateDepositRequestData $request): InitiateDepositResponseData

// 4. Vérification de Statut
checkDepositStatus(string $depositId): CheckDepositStatusWrapperData
```

🎨 Génération de Types TypeScript
--------------------------------

[](#-génération-de-types-typescript)

### Générer les Définitions TypeScript

[](#générer-les-définitions-typescript)

```
php artisan pawapay:generate-types
```

#### Ce Que Cela Fait

[](#ce-que-cela-fait)

Crée des fichiers TypeScript dans `resources/js/pawapay/` :

- `enums.ts` - Toutes les énumérations Pawapay
- `types.ts` - Toutes les interfaces
- `index.ts` - Exports principaux avec fonctions utilitaires

#### Exemple d'Utilisation

[](#exemple-dutilisation)

```
import {
  SupportedProvider,
  Currency,
  TransactionStatus,
  isTransactionFinal
} from '@/js/pawapay';

const provider: SupportedProvider = SupportedProvider.MTN_MOMO_ZMB;
const currency: Currency = Currency.ZMW;
const status: TransactionStatus = TransactionStatus.COMPLETED;

if (isTransactionFinal(status)) {
  console.log('Paiement terminé');
}
```

#### Régénération Forcée

[](#régénération-forcée)

```
php artisan pawapay:generate-types --force
```

🔧 Utilisation Avancée
---------------------

[](#-utilisation-avancée)

### Idempotence

[](#idempotence)

Toutes les opérations de dépôt sont idempotentes. Utiliser le même `depositId` plusieurs fois donnera un statut `DUPLICATE_IGNORED` :

```
// Première requête
$response1 = Pawapay::initiateDeposit($requestData);
// Statut : ACCEPTED

// Deuxième requête identique
$response2 = Pawapay::initiateDeposit($requestData);
// Statut : DUPLICATE_IGNORED (pas de transaction dupliquée)
```

### Support des Métadonnées

[](#support-des-métadonnées)

Attachez des métadonnées personnalisées aux paiements pour le suivi :

```
$requestData = PaymentPageRequestData::fromArray([
    // ... autres champs
    'metadata' => [
        ['orderId' => 'ORD-123'],
        ['userId' => 456],
        ['cartId' => 'CART-789'],
        ['channel' => 'web'],
        ['version' => '2.0'],
        ['items' => json_encode(['item1', 'item2'])],
        ['custom_field' => 'custom_value'],
    ],
]);
```

Les métadonnées sont conservées tout au long du cycle de paiement et peuvent être récupérées lors de la vérification du statut du dépôt.

### Normalisation des Numéros de Téléphone

[](#normalisation-des-numéros-de-téléphone)

Le package normalise automatiquement les numéros de téléphone :

```
$response = Pawapay::predictProvider('+260 763-456-789');
echo $response->phoneNumber; // "260763456789" (normalisé)
```

### Bonnes Pratiques de Gestion des Erreurs

[](#bonnes-pratiques-de-gestion-des-erreurs)

```
use Illuminate\Http\Client\RequestException;
use Pawapay\Exceptions\PawapayApiException;

try {
    $response = Pawapay::predictProvider($phoneNumber);

    if ($response instanceof \Pawapay\Data\Responses\PredictProviderFailureResponse) {
        // L'API a retourné une erreur métier
        $errorCode = $response->failureReason->failureCode;
        $errorMessage = $response->failureReason->failureMessage;

        // Gérez des codes d'erreur spécifiques
        if ($errorCode === FailureCode::INVALID_PHONE_NUMBER) {
            return back()->withErrors(['phone' => 'Numéro de téléphone invalide']);
        }

        if ($errorCode === FailureCode::INSUFFICIENT_BALANCE) {
            return back()->withErrors(['payment' => 'Solde insuffisant']);
        }
    }

    // Traitez la réponse réussie
    return redirect($response->redirectUrl);

} catch (RequestException $e) {
    // Erreur réseau ou HTTP
    Log::error('Requête API PawaPay échouée', [
        'message' => $e->getMessage(),
        'status' => $e->response->status(),
        'body' => $e->response->body(),
    ]);

    return back()->withErrors([
        'payment' => 'Service de paiement temporairement indisponible'
    ]);

} catch (PawapayApiException $e) {
    // Exception spécifique au package
    Log::error('Erreur SDK PawaPay', [
        'message' => $e->getMessage(),
        'data' => $e->getErrorData(),
    ]);

    return back()->withErrors([
        'payment' => 'Erreur de traitement du paiement'
    ]);
}
```

⚙️ Détails de Configuration
---------------------------

[](#️-détails-de-configuration)

### Timeouts et Tentatives

[](#timeouts-et-tentatives)

Configurez dans `.env` :

```
# Timeout de requête en secondes
PAWAPAY_TIMEOUT=30

# Nombre de tentatives pour les requêtes échouées
PAWAPAY_RETRY_TIMES=3

# Délai entre les tentatives en millisecondes
PAWAPAY_RETRY_SLEEP=100
```

### En-têtes Personnalisés

[](#en-têtes-personnalisés)

Étendez les en-têtes par défaut dans la configuration :

```
// config/pawapay.php
'defaults' => [
    'headers' => [
        'Content-Type' => 'application/json',
        'Accept' => 'application/json',
        'X-Custom-Header' => 'Votre-Valeur',
    ],
],
```

### Basculement d'Environnement

[](#basculement-denvironnement)

```
// Basculer vers la production
config()->set('pawapay.environment', 'production');

// Ou utilisez .env
PAWAPAY_ENVIRONMENT=production
```

🔄 Exemples de Workflow Complet
------------------------------

[](#-exemples-de-workflow-complet)

### Flux de Paiement E-commerce (Utilisant l'API Intégrée)

[](#flux-de-paiement-e-commerce-utilisant-lapi-intégrée)

```
// Frontend JavaScript (React/Vue/etc)
async function processPayment(phoneNumber, amount, orderId) {
    try {
        // Étape 1 : Prédire le fournisseur
        const providerResponse = await fetch('/api/pawapay/predict-provider', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ phoneNumber })
        });

        const providerData = await providerResponse.json();

        // Vérifiez si c'est une réponse de succès
        if (!providerData.country || !providerData.provider) {
            throw new Error(providerData.failureReason?.failureMessage || 'Impossible de détecter le fournisseur');
        }

        // Étape 2 : Créer la page de paiement
        const paymentResponse = await fetch('/api/pawapay/payment-page', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                depositId: orderId,
                returnUrl: `${window.location.origin}/payment/callback`,
                customerMessage: `Paiement pour la Commande #${orderId}`,
                amountDetails: {
                    amount: amount.toString(),
                    currency: providerData.country === 'ZMB' ? 'ZMW' : 'XOF'
                },
                phoneNumber: providerData.phoneNumber,
                language: navigator.language.startsWith('fr') ? 'FR' : 'EN',
                country: providerData.country,
                reason: 'Achat en ligne',
                metadata: [
                    { orderId },
                    { customerId: 'id-utilisateur-actuel' }
                ]
            })
        });

        const paymentData = await paymentResponse.json();

        // Vérifiez si c'est une réponse de succès
        if (paymentData.redirectUrl) {
            // Redirigez vers la page de paiement PawaPay
            window.location.href = paymentData.redirectUrl;
        } else {
            throw new Error(paymentData.failureReason?.failureMessage || 'Échec de la création du paiement');
        }

    } catch (error) {
        console.error('Erreur de paiement :', error);
        alert('Échec du paiement : ' + error.message);
    }
}
```

### Service d'Abonnement avec Dépôts Directs (Utilisant le SDK)

[](#service-dabonnement-avec-dépôts-directs-utilisant-le-sdk)

```
class SubscriptionController
{
    public function renewSubscription(Subscription $subscription)
    {
        // Obtenez le téléphone de l'utilisateur depuis son profil
        $user = $subscription->user;

        // Créez une requête de dépôt en utilisant le SDK
        $depositId = (string) Str::uuid();

        $response = Pawapay::initiateDeposit([
            'depositId' => $depositId,
            'payer' => [
                'type' => 'MMO',
                'accountDetails' => [
                    'phoneNumber' => $user->phone_number,
                    'provider' => $user->mobile_money_provider,
                ],
            ],
            'amount' => $subscription->amount,
            'currency' => 'ZMW',
            'clientReferenceId' => 'SUB-' . $subscription->id,
            'customerMessage' => 'Renouvellement d\'abonnement mensuel',
            'metadata' => [
                ['subscriptionId' => $subscription->id],
                ['userId' => $user->id],
                ['plan' => $subscription->plan],
            ],
        ]);

        // Gérez la réponse
        if ($response->isAccepted()) {
            // Mettez en file d'attente la vérification du statut
            CheckDepositStatus::dispatch($depositId)
                ->delay(now()->addMinutes(5));

            return response()->json([
                'message' => 'Paiement initié',
                'depositId' => $depositId,
            ]);
        } else {
            return response()->json([
                'error' => $response->failureReason->failureMessage,
            ], 422);
        }
    }

    public function webhook(Request $request)
    {
        // Vérifiez la signature du webhook
        $payload = $request->all();
        $depositId = $payload['depositId'];

        // Mettez à jour l'abonnement basé sur le statut
        $status = Pawapay::checkDepositStatus($depositId);

        if ($status->isFound() && $status->data->status === TransactionStatus::COMPLETED) {
            // Mettez à jour l'abonnement
            $metadata = collect($status->data->metadata);
            $subscriptionId = $metadata->firstWhere('subscriptionId');

            Subscription::find($subscriptionId)->update([
                'status' => 'active',
                'renewed_at' => now(),
            ]);
        }

        return response()->json(['status' => 'traité']);
    }
}
```

🔐 Bonnes Pratiques de Sécurité
------------------------------

[](#-bonnes-pratiques-de-sécurité)

### 1. Stockez les Tokens API de Manière Sécurisée

[](#1-stockez-les-tokens-api-de-manière-sécurisée)

```
# Ne committez jamais les tokens dans le contrôle de version
PAWAPAY_API_TOKEN=${PAWAPAY_API_TOKEN}
```

### 2. Validez les Données d'Entrée

[](#2-validez-les-données-dentrée)

```
use Illuminate\Validation\Rule;

$validated = $request->validate([
    'phone' => [
        'required',
        'string',
        'regex:/^(?:\+?\d{1,3}[- ]?)?\d{6,14}$/'
    ],
    'amount' => [
        'required',
        'numeric',
        'min:1',
        'max:100000' // Définissez des limites raisonnables
    ],
    'currency' => [
        'required',
        Rule::in(array_column(Currency::cases(), 'value'))
    ],
]);
```

### 3. Implémentez la Vérification de Signature des Webhooks

[](#3-implémentez-la-vérification-de-signature-des-webhooks)

```
public function handleWebhook(Request $request)
{
    $signature = $request->header('X-PawaPay-Signature');
    $payload = $request->getContent();
    $secret = config('services.pawapay.webhook_secret');

    $expectedSignature = hash_hmac('sha256', $payload, $secret);

    if (!hash_equals($expectedSignature, $signature)) {
        abort(401, 'Signature de webhook invalide');
    }

    // Traitez le webhook
}
```

### 4. Surveillez et Journalisez les Transactions

[](#4-surveillez-et-journalisez-les-transactions)

```
use Illuminate\Support\Facades\Log;

class PaymentService
{
    public function initiatePayment($data)
    {
        try {
            $response = Pawapay::createPaymentPage($data);

            Log::info('Paiement initié', [
                'depositId' => $data['depositId'],
                'amount' => $data['amountDetails']['amount'],
                'currency' => $data['amountDetails']['currency'],
                'response_status' => $response->status ?? 'inconnu',
            ]);

            return $response;

        } catch (Exception $e) {
            Log::error('Échec d\'initiation de paiement', [
                'depositId' => $data['depositId'] ?? 'inconnu',
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            throw $e;
        }
    }
}
```

🔄 Guide de Migration
--------------------

[](#-guide-de-migration)

### Des Appels API Bruts au Package

[](#des-appels-api-bruts-au-package)

**Avant :**

```
public function makePayment($data)
{
    $response = Http::withToken(config('pawapay.token'))
        ->post('https://api.sandbox.pawapay.io/v2/paymentpage', $data);

    if ($response->failed()) {
        throw new Exception('Échec du paiement : ' . $response->body());
    }

    return $response->json();
}
```

**Après :**

```
use Pawapay\Facades\Pawapay;
use Pawapay\Data\PaymentPage\PaymentPageRequestData;

public function makePayment($data)
{
    $requestData = PaymentPageRequestData::fromArray($data);
    $response = Pawapay::createPaymentPage($requestData);

    if ($response instanceof \Pawapay\Data\PaymentPage\PaymentPageErrorResponseData) {
        throw new Exception('Échec du paiement : ' . $response->failureReason->failureMessage);
    }

    return $response;
}
```

### API Intégrée vs Implémentation Personnalisée

[](#api-intégrée-vs-implémentation-personnalisée)

ApprocheIdéal PourAvantages**API Intégrée**Configuration rapide, SPAs, applications mobilesConfiguration zéro, validation automatique, prêt à l'emploi**SDK Direct**Logique métier personnalisée, workflows complexesContrôle total, intégration directe, gestion d'erreurs personnalisée**Routes Personnalisées**Personnalisation API avancéeContrôle complet sur les routes et middleware🤝 Contribution
--------------

[](#-contribution)

Nous accueillons les contributions ! Voici comment commencer :

### 1. Forkez le Dépôt

[](#1-forkez-le-dépôt)

```
git clone https://github.com/andydefer/laravel-pawapay.git
cd laravel-pawapay
composer install
```

### 2. Exécutez les Tests

[](#2-exécutez-les-tests)

```
# Tests unitaires
composer test

# Tests d'intégration (nécessite un token sandbox)
PAWAPAY_API_TOKEN=votre_token composer test --group=integration

# Style de code
composer lint

# Analyse statique
composer analyse
```

### 3. Workflow de Développement

[](#3-workflow-de-développement)

```
# 1. Créez une branche de fonctionnalité
git checkout -b feature/nouveau-support-fournisseur

# 2. Faites vos modifications
# 3. Ajoutez des tests
# 4. Exécutez les tests
composer test

# 5. Vérifiez le style de code
composer lint

# 6. Committez avec un message descriptif
git commit -m "feat: ajouter le support pour un nouveau fournisseur mobile money"

# 7. Poussez et créez une PR
git push origin feature/nouveau-support-fournisseur
```

### 4. Standards de Codage

[](#4-standards-de-codage)

- Suivez les standards de codage PSR-12
- Écrivez du code compatible PHPStan niveau 9
- Ajoutez des indications de type pour toutes les méthodes
- Incluez des tests complets
- Mettez à jour la documentation pour les nouvelles fonctionnalités

📚 Ressources Supplémentaires
----------------------------

[](#-ressources-supplémentaires)

### Documentation Officielle

[](#documentation-officielle)

- [Documentation API PawaPay](https://docs.pawapay.io)
- [Documentation Laravel](https://laravel.com/docs)

### Communauté

[](#communauté)

- [Problèmes GitHub](https://github.com/andydefer/laravel-pawapay/issues)
- [Communauté Discord](https://discord.gg/votre-lien)
- [Mises à jour Twitter](https://twitter.com/votre-handle)

### Packages Similaires

[](#packages-similaires)

- [Laravel Cashier](https://laravel.com/docs/billing) - Pour l'intégration Stripe
- [Laravel Flutterwave](https://github.com/kingflamez/laravelrave) - Pour les paiements Flutterwave
- [Laravel Paystack](https://github.com/unicodeveloper/laravel-paystack) - Pour l'intégration Paystack

📄 Licence
---------

[](#-licence)

Ce package est un logiciel open-source sous licence [MIT](LICENSE).

🏆 Support
---------

[](#-support)

Si ce package vous a été utile, pensez à :

- ⭐ Étoiler le dépôt sur GitHub
- 📢 Partager avec votre réseau
- 💼 L'utiliser dans vos projets commerciaux
- 🐛 Signaler des problèmes et suggérer des fonctionnalités

📞 Besoin d'Aide ?
-----------------

[](#-besoin-daide-)

- **Documentation** : Consultez le [Wiki GitHub](https://github.com/andydefer/laravel-pawapay/wiki)
- **Problèmes** : [Problèmes GitHub](https://github.com/andydefer/laravel-pawapay/issues)
- **Email** :

---

**Laravel PawaPay SDK** - Autonomiser le commerce africain avec des paiements mobile money fluides. Construit avec ❤️ pour la communauté Laravel en Afrique et au-delà.

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance95

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~6 days

Recently: every ~17 days

Total

22

Last Release

31d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2170ec3fbad9eb4b002661ab4f58b1cc374eae4293b92904c6a74bc2818bd570?d=identicon)[andydefer](/maintainers/andydefer)

---

Top Contributors

[![andydefer](https://avatars.githubusercontent.com/u/124321745?v=4)](https://github.com/andydefer "andydefer (28 commits)")

---

Tags

phpapilaraveleloquentlaravel-packagewebhookspaymentsmobile-moneyfintechopen-sourcepayoutsafricapawaPay

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Psalm, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/andydefer-laravel-pawapay/health.svg)

```
[![Health](https://phpackages.com/badges/andydefer-laravel-pawapay/health.svg)](https://phpackages.com/packages/andydefer-laravel-pawapay)
```

###  Alternatives

[api-platform/laravel

API Platform support for Laravel

58171.8k14](/packages/api-platform-laravel)[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.4M96](/packages/mongodb-laravel-mongodb)[kirschbaum-development/eloquent-power-joins

The Laravel magic applied to joins.

1.6k32.6M46](/packages/kirschbaum-development-eloquent-power-joins)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[glushkovds/phpclickhouse-laravel

Adapter of the most popular library https://github.com/smi2/phpClickHouse to Laravel

2051.5M2](/packages/glushkovds-phpclickhouse-laravel)[yajra/laravel-oci8

Oracle DB driver for Laravel via OCI8

8793.2M25](/packages/yajra-laravel-oci8)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
