UnitechPay API

Version 1.0.0

Introduction

L'API UnitechPay permet d'intégrer les paiements Wave et Orange Money dans vos applications. Elle gère également les retraits et les webhooks pour une expérience complète.

URL de base: https://api.unitech.sn/

Fonctionnalités

  • Paiements sécurisés via Wave et Orange Money
  • 3 options Orange Money: QR Code, Max It, et Orange Money
  • Génération de QR Codes Orange Money
  • URLs de redirection personnalisables pour tous les paiements
  • Retraits automatiques vers Wave, Orange Money ou comptes bancaires
  • Webhooks pour les notifications en temps réel
  • Plugin WordPress officiel disponible
  • API RESTful avec authentification par clé API

Authentification

Toutes les requêtes à l'API doivent inclure un header d'authentification avec votre clé API.

Authorization: Bearer VOTRE_CLE_API

Obtenir une clé API

Pour obtenir une clé API, vous devez créer un compte marchand sur notre plateforme. Une fois connecté, vous pourrez générer une clé API depuis votre tableau de bord.

Important: Gardez votre clé API secrète et ne la partagez jamais publiquement.

Endpoints

Méthode Endpoint Description
POST /api.php?action=create_wave_payment Créer un paiement Wave avec URLs de redirection
POST /api.php?action=create_orange_qr Générer un QR Code Orange Money
POST /api.php?action=create_orange_maxit Créer un paiement Max It avec callbacks
POST /api.php?action=create_orange_om Créer un paiement Orange Money standard
POST /api.php?action=withdraw_funds Demander un retrait automatique
POST /api.php?action=configure_webhook Configurer les webhooks
GET /api.php?action=balance Consulter le solde disponible
GET /api.php?action=transactions Lister les transactions
GET /api.php?action=withdrawals Lister les retraits

Paiements Wave

Créer un paiement Wave

POST /api.php?action=create_wave_payment

Paramètres

Paramètre Type Obligatoire Description
amount number Oui Montant du paiement en XOF
customer_number string Oui Numéro de téléphone du client
description string Non Description du paiement
callback_success string Non URL de redirection après succès
callback_cancel string Non URL de redirection après annulation

Exemple de requête

{
  "amount": 5000,
  "customer_number": "771234567",
  "description": "Paiement pour commande #123",
  "callback_success": "https://monsite.com/payment/success",
  "callback_cancel": "https://monsite.com/payment/cancel"
}

Réponse

{
  "success": true,
  "data": {
    "transaction_id": 1,
    "reference": "wave_123456",
    "payment_url": "https://pay.wave.com/c/cos-1xxxxx",
    "amount": 5000,
    "status": "pending",
    "callback_urls": {
      "success": "https://monsite.com/payment/success",
      "error": "https://monsite.com/payment/cancel"
    }
  }
}

URLs de redirection: Si non spécifiées, les URLs par défaut seront utilisées. Après paiement, l'utilisateur sera automatiquement redirigé vers l'URL appropriée.

Paiements Orange Money

QR Code

Génération de QR Code pour paiements mobiles avec callbacks personnalisés

POST /api.php?action=create_orange_qr

Max It

Paiement via l'application Max It avec redirection automatique

POST /api.php?action=create_orange_maxit

Orange Money

Paiement standard Orange Money avec callbacks

POST /api.php?action=create_orange_om

1. Générer un QR Code Orange Money

POST /api.php?action=create_orange_qr

Paramètres

Paramètre Type Obligatoire Description
amount number Oui Montant du paiement en XOF
reference string Non Référence personnalisée
description string Non Description du paiement
callback_success string Non URL de redirection après succès
callback_cancel string Non URL de redirection après annulation

Exemple de requête

{
  "amount": 5000,
  "reference": "commande_123",
  "description": "Paiement pour commande #123",
  "callback_success": "https://monsite.com/payment/success",
  "callback_cancel": "https://monsite.com/payment/cancel"
}

Réponse

{
  "success": true,
  "data": {
    "transaction_id": 1,
    "reference": "commande_123",
    "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA...",
    "deep_links": {
      "MAXIT": "https://sugu.orange-sonatel.com/np/dgjuu_XudhPKI1D4zud",
      "OM": "https://orangenonevsn.page.link/zzzubAUuJ7tX5uNK6"
    },
    "amount": 5000,
    "status": "pending",
    "type": "qr_code",
    "validity": 300,
    "callback_urls": {
      "success": "https://monsite.com/payment/success",
      "cancel": "https://monsite.com/payment/cancel"
    }
  }
}

Note: Le QR Code est retourné sous forme de données base64 encodées (data URI) qui peuvent être directement utilisées dans les balises <img>. Les URLs de callback permettent de rediriger automatiquement l'utilisateur après le paiement.

2. Créer un paiement Max It

POST /api.php?action=create_orange_maxit

Paramètres

Paramètre Type Obligatoire Description
amount number Oui Montant du paiement en XOF
customer_number string Oui Numéro de téléphone du client
description string Non Description du paiement
callback_success string Non URL de redirection après succès
callback_cancel string Non URL de redirection après annulation

Exemple de requête

{
  "amount": 5000,
  "customer_number": "771234567",
  "description": "Paiement pour commande #123",
  "callback_success": "https://monsite.com/payment/success",
  "callback_cancel": "https://monsite.com/payment/cancel"
}

Réponse

{
  "success": true,
  "data": {
    "transaction_id": 2,
    "reference": "orange_maxit_123456",
    "payment_url": "https://sugu.orange-sonatel.com/np/dgjuu_XudhPKI1D4zud",
    "deep_links": {
      "MAXIT": "https://sugu.orange-sonatel.com/np/dgjuu_XudhPKI1D4zud",
      "OM": "https://orangenonevsn.page.link/zzzubAUuJ7tX5uNK6"
    },
    "amount": 5000,
    "status": "pending",
    "type": "maxit",
    "callback_urls": {
      "success": "https://monsite.com/payment/success",
      "cancel": "https://monsite.com/payment/cancel"
    }
  }
}

3. Créer un paiement Orange Money

POST /api.php?action=create_orange_om

Paramètres

Paramètre Type Obligatoire Description
amount number Oui Montant du paiement en XOF
customer_number string Oui Numéro de téléphone du client
description string Non Description du paiement
callback_success string Non URL de redirection après succès
callback_cancel string Non URL de redirection après annulation

Exemple de requête

{
  "amount": 5000,
  "customer_number": "771234567",
  "description": "Paiement pour commande #123",
  "callback_success": "https://monsite.com/payment/success",
  "callback_cancel": "https://monsite.com/payment/cancel"
}

Réponse

{
  "success": true,
  "data": {
    "transaction_id": 3,
    "reference": "orange_om_123456",
    "payment_url": "https://orangenonevsn.page.link/zzzubAUuJ7tX5uNK6",
    "deep_links": {
      "MAXIT": "https://sugu.orange-sonatel.com/np/dgjuu_XudhPKI1D4zud",
      "OM": "https://orangenonevsn.page.link/zzzubAUuJ7tX5uNK6"
    },
    "amount": 5000,
    "status": "pending",
    "type": "orange_money",
    "callback_urls": {
      "success": "https://monsite.com/payment/success",
      "cancel": "https://monsite.com/payment/cancel"
    }
  }
}

Retraits automatiques

Le système de retrait automatique permet de transférer instantanément vos fonds vers vos comptes Wave, Orange Money ou bancaires avec commission de 1.5%.

Demander un retrait

POST /api.php?action=withdraw_funds

Paramètres

Paramètre Type Obligatoire Description
amount number Oui Montant à retirer en XOF
method string Oui Méthode de retrait (wave, orange, bank)
account string Oui Numéro de compte ou téléphone destinataire

Exemple de requête

{
  "amount": 10000,
  "method": "wave",
  "account": "771234567"
}

Réponse

{
  "success": true,
  "data": {
    "withdrawal_id": 1,
    "reference": "WDR_1_1671234567_9876",
    "amount": 10000,
    "commission": 150,
    "net_amount": 9850,
    "method": "wave",
    "status": "processed"
  }
}

Délais de traitement:
• Wave & Orange Money: Instantané (automatique)
• Virement bancaire: 3 à 5 jours ouvrés (traitement manuel)

Webhooks

Les webhooks permettent de recevoir des notifications en temps réel sur les événements de votre compte.

Configurer les webhooks

POST /api.php?action=configure_webhook

Paramètres

Paramètre Type Obligatoire Description
webhook_url string Oui URL de votre endpoint webhook (HTTPS requis)
events array Non Événements à écouter (tous par défaut)

Événements disponibles

  • payment_completed - Paiement réussi et fonds crédités
  • payment_failed - Paiement échoué
  • payment_expired - Paiement expiré (timeout)
  • withdrawal_processed - Retrait traité avec succès
  • withdrawal_failed - Retrait échoué

Exemple de payload webhook

{
  "event": "payment_completed",
  "transaction_id": 1,
  "reference": "wave_123456",
  "amount": 5000,
  "status": "completed",
  "method": "wave",
  "commission": 75,
  "net_amount": 4925,
  "timestamp": 1684146600,
  "signature": "hmac_sha256_signature_for_verification"
}

Sécurité: Vérifiez toujours la signature HMAC-SHA256 des webhooks en utilisant votre clé API comme secret. Cela garantit l'authenticité des notifications.

Plugins & Intégrations

UnitechPay propose plusieurs solutions d'intégration prêtes à l'emploi pour faciliter l'intégration des paiements mobile money dans vos projets.

Plugin WordPress Officiel

Intégrez facilement les paiements Wave et Orange Money dans votre site WordPress ou boutique WooCommerce avec notre plugin officiel.

Fonctionnalités:

  • ✅ Compatible WooCommerce
  • ✅ Paiements Wave et Orange Money
  • ✅ Webhooks intégrés

Avantages:

  • 🚀 Installation en 1 clic
  • 🔧 Configuration simplifiée
  • 📱 Interface responsive
  • 🔄 Mises à jour automatiques

Guide d'installation WordPress

1

Installation

Téléchargez le plugin depuis le répertoire WordPress officiel ou installez-le directement depuis votre administration WordPress (Extensions > Ajouter > Rechercher "UnitechPay").

2

Configuration

Allez dans "UnitechPay Settings" dans votre menu WordPress et configurez:

  • • Entrez votre numéro Wave et Orange Money
  • • Les options de paiement (Wave/Orange Money)
3

Activation WooCommerce

Si vous utilisez WooCommerce, activez "UnitechPay" comme méthode de paiement dans WooCommerce > Réglages > Paiements.

Intégrations à venir

Shopify App

Bientôt disponible

PrestaShop Module

En développement

Magento Extension

Prévu Q2 2025

Codes d'erreur

Code HTTP Message Description
200 Success Requête traitée avec succès
400 Bad Request Paramètres manquants ou invalides
401 Unauthorized Clé API manquante ou invalide
404 Not Found Endpoint ou ressource non trouvée
500 Internal Server Error Erreur interne du serveur

Exemples d'intégration

PHP - Paiement Wave avec callbacks

<?php
$api_url = 'https://api.unitech.sn/api.php';
$api_key = 'votre_cle_api';

// Créer un paiement Wave avec URLs de redirection
$data = [
    'amount' => 5000,
    'customer_number' => '771234567',
    'description' => 'Paiement pour commande #123',
    'callback_success' => 'https://monsite.com/payment/success',
    'callback_cancel' => 'https://monsite.com/payment/cancel'
];

$ch = curl_init($api_url . '?action=create_wave_payment');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $api_key,
        'Content-Type: application/json'
    ],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($data),
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_TIMEOUT => 30
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$result = json_decode($response, true);

if ($http_code === 200 && $result['success']) {
    // Rediriger vers le lien de paiement Wave
    header('Location: ' . $result['data']['payment_url']);
    exit;
} else {
    echo 'Erreur: ' . ($result['message'] ?? 'Erreur inconnue');
}
?>

PHP - Paiement Orange Money QR Code

<?php
// Générer un QR Code Orange Money
$data = [
    'amount' => 2500,
    'reference' => 'commande_' . uniqid(),
    'description' => 'Paiement QR Code',
    'callback_success' => 'https://monsite.com/success',
    'callback_cancel' => 'https://monsite.com/cancel'
];

$ch = curl_init($api_url . '?action=create_orange_qr');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $api_key,
        'Content-Type: application/json'
    ],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($data)
]);

$response = curl_exec($ch);
$result = json_decode($response, true);

if ($result['success']) {
    $qr_code = $result['data']['qr_code'];
    echo '<img src="' . $qr_code . '" alt="QR Code Orange Money" />';
    echo '<p>Montant: ' . number_format($result['data']['amount']) . ' XOF</p>';
    echo '<p>Référence: ' . $result['data']['reference'] . '</p>';
} else {
    echo 'Erreur: ' . $result['message'];
}
?>

Node.js - Paiement complet avec callbacks

const axios = require('axios');

const API_URL = 'https://api.unitech.sn/api.php';
const API_KEY = 'votre_cle_api';

class UnitechPayAPI {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.baseURL = API_URL;
    }

    async createWavePayment(amount, customerNumber, description, callbacks = {}) {
        const data = {
            amount,
            customer_number: customerNumber,
            description,
            callback_success: callbacks.success || 'https://monsite.com/success',
            callback_cancel: callbacks.cancel || 'https://monsite.com/cancel'
        };

        try {
            const response = await axios.post(
                `${this.baseURL}?action=create_wave_payment`,
                data,
                {
                    headers: {
                        'Authorization': `Bearer ${this.apiKey}`,
                        'Content-Type': 'application/json'
                    },
                    timeout: 30000
                }
            );

            return response.data;
        } catch (error) {
            console.error('Erreur API UnitechPay:', error.message);
            throw error;
        }
    }

    async createOrangeQR(amount, reference, description, callbacks = {}) {
        const data = {
            amount,
            reference,
            description,
            callback_success: callbacks.success,
            callback_cancel: callbacks.cancel
        };

        try {
            const response = await axios.post(
                `${this.baseURL}?action=create_orange_qr`,
                data,
                {
                    headers: {
                        'Authorization': `Bearer ${this.apiKey}`,
                        'Content-Type': 'application/json'
                    }
                }
            );

            if (response.data.success) {
                const qrCode = response.data.data.qr_code;
                console.log('QR Code généré:', qrCode.substring(0, 50) + '...');
                return response.data;
            } else {
                throw new Error(response.data.message);
            }
        } catch (error) {
            console.error('Erreur QR Code:', error.message);
            throw error;
        }
    }

    async withdrawFunds(amount, method, account) {
        const data = { amount, method, account };

        try {
            const response = await axios.post(
                `${this.baseURL}?action=withdraw_funds`,
                data,
                {
                    headers: {
                        'Authorization': `Bearer ${this.apiKey}`,
                        'Content-Type': 'application/json'
                    }
                }
            );

            return response.data;
        } catch (error) {
            console.error('Erreur retrait:', error.message);
            throw error;
        }
    }
}

// Utilisation
const unitechPay = new UnitechPayAPI(API_KEY);

// Exemple 1: Paiement Wave
unitechPay.createWavePayment(5000, '771234567', 'Test paiement', {
    success: 'https://monapp.com/payment/success',
    cancel: 'https://monapp.com/payment/cancel'
})
.then(result => {
    console.log('Paiement Wave créé:', result.data.payment_url);
})
.catch(error => {
    console.error('Erreur:', error.message);
});

// Exemple 2: QR Code Orange Money
unitechPay.createOrangeQR(2500, 'cmd_123', 'Achat produit')
.then(result => {
    console.log('QR Code créé, référence:', result.data.reference);
})
.catch(error => {
    console.error('Erreur QR:', error.message);
});

Python - Classe complète UnitechPay

import requests
import json
from typing import Dict, Optional, Any
from dataclasses import dataclass

@dataclass
class CallbackURLs:
    success: Optional[str] = None
    cancel: Optional[str] = None

class UnitechPayAPI:
    def __init__(self, api_key: str, base_url: str = "https://api.unitech.sn/api.php"):
        self.api_key = api_key
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        })

    def _make_request(self, action: str, data: Dict[str, Any]) -> Dict[str, Any]:
        """Effectuer une requête à l'API"""
        try:
            response = self.session.post(
                f"{self.base_url}?action={action}",
                json=data,
                timeout=30
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            raise Exception(f"Erreur API: {e}")

    def create_wave_payment(
        self, 
        amount: float, 
        customer_number: str, 
        description: str = "",
        callbacks: Optional[CallbackURLs] = None
    ) -> Dict[str, Any]:
        """Créer un paiement Wave avec callbacks"""
        data = {
            "amount": amount,
            "customer_number": customer_number,
            "description": description
        }
        
        if callbacks:
            if callbacks.success:
                data["callback_success"] = callbacks.success
            if callbacks.cancel:
                data["callback_cancel"] = callbacks.cancel

        result = self._make_request("create_wave_payment", data)
        
        if not result.get("success"):
            raise Exception(f"Erreur Wave: {result.get('message', 'Erreur inconnue')}")
        
        return result

    def create_orange_qr(
        self, 
        amount: float, 
        reference: Optional[str] = None,
        description: str = "",
        callbacks: Optional[CallbackURLs] = None
    ) -> Dict[str, Any]:
        """Générer un QR Code Orange Money"""
        data = {
            "amount": amount,
            "description": description
        }
        
        if reference:
            data["reference"] = reference
            
        if callbacks:
            if callbacks.success:
                data["callback_success"] = callbacks.success
            if callbacks.cancel:
                data["callback_cancel"] = callbacks.cancel

        result = self._make_request("create_orange_qr", data)
        
        if not result.get("success"):
            raise Exception(f"Erreur QR Code: {result.get('message', 'Erreur inconnue')}")
        
        return result

    def create_orange_maxit(
        self, 
        amount: float, 
        customer_number: str, 
        description: str = "",
        callbacks: Optional[CallbackURLs] = None
    ) -> Dict[str, Any]:
        """Créer un paiement Max It"""
        data = {
            "amount": amount,
            "customer_number": customer_number,
            "description": description
        }
        
        if callbacks:
            if callbacks.success:
                data["callback_success"] = callbacks.success
            if callbacks.cancel:
                data["callback_cancel"] = callbacks.cancel

        result = self._make_request("create_orange_maxit", data)
        
        if not result.get("success"):
            raise Exception(f"Erreur Max It: {result.get('message', 'Erreur inconnue')}")
        
        return result

    def withdraw_funds(self, amount: float, method: str, account: str) -> Dict[str, Any]:
        """Demander un retrait"""
        data = {
            "amount": amount,
            "method": method,  # wave, orange, bank
            "account": account
        }

        result = self._make_request("withdraw_funds", data)
        
        if not result.get("success"):
            raise Exception(f"Erreur retrait: {result.get('message', 'Erreur inconnue')}")
        
        return result

    def get_balance(self) -> Dict[str, Any]:
        """Consulter le solde"""
        return self._make_request("balance", {})

# Exemple d'utilisation
if __name__ == "__main__":
    # Initialiser l'API
    api = UnitechPayAPI("votre_cle_api")
    
    try:
        # Créer des URLs de callback
        callbacks = CallbackURLs(
            success="https://monsite.com/success",
            cancel="https://monsite.com/cancel"
        )
        
        # Créer un paiement Wave
        wave_payment = api.create_wave_payment(
            amount=5000,
            customer_number="771234567",
            description="Paiement test",
            callbacks=callbacks
        )
        print(f"Paiement Wave: {wave_payment['data']['payment_url']}")
        
        # Générer un QR Code Orange Money
        qr_payment = api.create_orange_qr(
            amount=2500,
            reference="test_qr_123",
            description="Paiement QR Code",
            callbacks=callbacks
        )
        print(f"QR Code généré: {qr_payment['data']['reference']}")
        
        # Consulter le solde
        balance = api.get_balance()
        print(f"Solde actuel: {balance['data']['balance']} XOF")
        
        # Effectuer un retrait
        withdrawal = api.withdraw_funds(
            amount=1000,
            method="wave",
            account="771234567"
        )
        print(f"Retrait effectué: {withdrawal['data']['net_amount']} XOF net")
        
    except Exception as e:
        print(f"Erreur: {e}")

Flutter/Dart - Intégration complète avec callbacks

import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/material.dart';

class CallbackUrls {
  final String? success;
  final String? cancel;

  CallbackUrls({this.success, this.cancel});

  Map<String, dynamic> toMap() {
    final map = <String, dynamic>{};
    if (success != null) map['callback_success'] = success;
    if (cancel != null) map['callback_cancel'] = cancel;
    return map;
  }
}

class UnitechPayAPI {
  static const String baseUrl = 'https://api.unitech.sn/api.php';
  final String apiKey;

  UnitechPayAPI(this.apiKey);

  Future<Map<String, dynamic>> _makeRequest(
    String action, 
    Map<String, dynamic> data
  ) async {
    try {
      final response = await http.post(
        Uri.parse('$baseUrl?action=$action'),
        headers: {
          'Authorization': 'Bearer $apiKey',
          'Content-Type': 'application/json',
        },
        body: json.encode(data),
      ).timeout(const Duration(seconds: 30));

      if (response.statusCode == 200) {
        return json.decode(response.body);
      } else {
        throw Exception('HTTP ${response.statusCode}: ${response.body}');
      }
    } catch (e) {
      throw Exception('Erreur réseau: $e');
    }
  }

  Future<Map<String, dynamic>> createWavePayment({
    required double amount,
    required String customerNumber,
    String? description,
    CallbackUrls? callbacks,
  }) async {
    final data = {
      'amount': amount,
      'customer_number': customerNumber,
      if (description != null) 'description': description,
      if (callbacks != null) ...callbacks.toMap(),
    };

    final result = await _makeRequest('create_wave_payment', data);

    if (result['success'] != true) {
      throw Exception(result['message'] ?? 'Erreur Wave inconnue');
    }

    return result;
  }

  Future<Map<String, dynamic>> createOrangeQR({
    required double amount,
    String? reference,
    String? description,
    CallbackUrls? callbacks,
  }) async {
    final data = {
      'amount': amount,
      if (reference != null) 'reference': reference,
      if (description != null) 'description': description,
      if (callbacks != null) ...callbacks.toMap(),
    };

    final result = await _makeRequest('create_orange_qr', data);

    if (result['success'] != true) {
      throw Exception(result['message'] ?? 'Erreur QR Code inconnue');
    }

    return result;
  }

  Future<Map<String, dynamic>> createOrangeMaxIt({
    required double amount,
    required String customerNumber,
    String? description,
    CallbackUrls? callbacks,
  }) async {
    final data = {
      'amount': amount,
      'customer_number': customerNumber,
      if (description != null) 'description': description,
      if (callbacks != null) ...callbacks.toMap(),
    };

    final result = await _makeRequest('create_orange_maxit', data);

    if (result['success'] != true) {
      throw Exception(result['message'] ?? 'Erreur Max It inconnue');
    }

    return result;
  }

  Future<Map<String, dynamic>> withdrawFunds({
    required double amount,
    required String method,
    required String account,
  }) async {
    final data = {
      'amount': amount,
      'method': method,
      'account': account,
    };

    final result = await _makeRequest('withdraw_funds', data);

    if (result['success'] != true) {
      throw Exception(result['message'] ?? 'Erreur retrait inconnue');
    }

    return result;
  }
}

// Widget exemple d'utilisation
class PaymentWidget extends StatefulWidget {
  @override
  _PaymentWidgetState createState() => _PaymentWidgetState();
}

class _PaymentWidgetState extends State<PaymentWidget> {
  final UnitechPayAPI api = UnitechPayAPI('votre_cle_api');
  bool isLoading = false;

  Future<void> createWavePayment() async {
    setState(() { isLoading = true; });
    
    try {
      final callbacks = CallbackUrls(
        success: 'https://monapp.com/success',
        cancel: 'https://monapp.com/cancel',
      );
      
      final result = await api.createWavePayment(
        amount: 5000,
        customerNumber: '771234567',
        description: 'Paiement test Flutter',
        callbacks: callbacks,
      );

      final paymentUrl = result['data']['payment_url'];
      print('URL de paiement: $paymentUrl');
      
      // Rediriger vers le navigateur
      // await launchUrlString(paymentUrl);
      
    } catch (e) {
      print('Erreur: $e');
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Erreur: $e')),
      );
    } finally {
      setState(() { isLoading = false; });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('UnitechPay Demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: isLoading ? null : createWavePayment,
              child: isLoading 
                ? CircularProgressIndicator()
                : Text('Payer avec Wave'),
            ),
          ],
        ),
      ),
    );
  }
}