ynkap-payment
Version: 
Module de paiement Y-Nkap pour Angular - Intégration simple des paiements mobiles (Orange Money, MTN Mobile Money)
1,382 lines (1,110 loc) • 37.5 kB
Markdown
# 💳 Y-Nkap Payment Module for Angular
[](https://badge.fury.io/js/ynkap-payment)
[](https://angular.io/)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
Le module Y-Nkap pour Angular offre une **intégration simple et robuste** des paiements mobiles (Orange Money, MTN Mobile Money) dans vos applications Angular. Développé par **SIEWE FORTUNE**, ce module fournit une solution complète avec gestion avancée des erreurs, retry automatique, notifications élégantes, et interface utilisateur optimisée.
## **Fonctionnalités principales**
✅ **Intégration en une ligne** : Composant `<ynkap-pay-button>` prêt à l'emploi
✅ **Interface moderne** : Modale responsive avec thèmes light/dark
✅ **Retry intelligent** : Gestion automatique des erreurs avec backoff exponentiel
✅ **Notifications élégantes** : Cards de notification positionnées à droite
✅ **Confirmations d'annulation** : Interface de confirmation pour les annulations
✅ **Messages user-friendly** : Séparation messages techniques/utilisateur
✅ **Sécurisé** : Authentification par clés API, validation stricte
✅ **Mobile-first** : Optimisé pour Orange Money et MTN Mobile Money
✅ **TypeScript** : Support complet avec types stricts
✅ **Architecture modulaire** : Services séparés et réutilisables
## **Table des matières**
- [Installation](#-installation)
- [Configuration](#-configuration)
- [Utilisation rapide](#-utilisation-rapide)
- [Composants disponibles](#-composants-disponibles)
- [Services et API](#-services-et-api)
- [Gestion des erreurs](#-gestion-des-erreurs)
- [Notifications et confirmations](#-notifications-et-confirmations)
- [Personnalisation](#-personnalisation)
- [Exemples avancés](#-exemples-avancés)
- [Architecture](#-architecture)
- [Support](#-support)
## 📦 **Installation**
### Prérequis
- Angular 16+
- TypeScript 5.0+
- Node.js 18+
### Installation via npm
```bash
npm install ynkap-payment --save
```
### Installation via yarn
```bash
yarn add ynkap-payment
```
## ⚙️ **Configuration**
### 1. Import du module
Importez `YnkapModule` dans votre module principal :
```typescript
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { YnkapModule } from 'ynkap-payment';
@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule, // Requis pour les animations
    // Configuration Y-Nkap
    YnkapModule.forRoot({
      apiKey: 'your-api-key',
      apiSecret: 'your-api-secret',
      merchantId: 'your-merchant-id',
      environment: 'sandbox' // 'sandbox' | 'production'
    })
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
```
### 2. Configuration des environnements
```typescript
// environments/environment.ts
export const environment = {
  production: false,
  ynkap: {
    apiKey: 'sandbox-api-key',
    apiSecret: 'sandbox-api-secret',
    merchantId: 'sandbox-merchant-id',
    environment: 'sandbox' as const
  }
};
// environments/environment.prod.ts
export const environment = {
  production: true,
  ynkap: {
    apiKey: 'prod-api-key',
    apiSecret: 'prod-api-secret',
    merchantId: 'prod-merchant-id',
    environment: 'production' as const
  }
};
```
### 3. Configuration dynamique
```typescript
import { ConfigurationService } from 'ynkap-payment';
constructor(private ynkapConfig: ConfigurationService) {}
ngOnInit() {
  // Configuration à l'exécution
  this.ynkapConfig.initialize({
    apiKey: 'dynamic-api-key',
    apiSecret: 'dynamic-api-secret',
    merchantId: 'dynamic-merchant-id',
    environment: 'production'
  });
}
```
## 🚀 **Utilisation rapide**
### Exemple minimal
```html
<!-- Utilisation la plus simple -->
<ynkap-pay-button
  [amount]="1000"
  [currency]="'XAF'"
  merchantReference="ORDER-123"
  description="Achat produit"
  (paymentSuccess)="onSuccess($event)"
  (paymentError)="onError($event)"
  (paymentCancel)="onCancel()">
  <img src="assets/logo-y-nkap.jpg" alt="Y-Nkap" class="ynkap-logo">
  Payer 1000 XAF
</ynkap-pay-button>
```
```typescript
import { Component } from '@angular/core';
import { PaymentResponse, YnkapError } from 'ynkap-payment';
@Component({
  selector: 'app-payment',
  template: `
    <div class="payment-container">
      <h2>Paiement sécurisé</h2>
      <ynkap-pay-button
        [amount]="1000"
        [currency]="'XAF'"
        merchantReference="ORDER-123"
        description="Achat d'un produit de démonstration"
        [theme]="'light'"
        (paymentSuccess)="onSuccess($event)"
        (paymentError)="onError($event)"
        (paymentCancel)="onCancel()">
        <img src="assets/logo-y-nkap.jpg" alt="Y-Nkap" class="ynkap-logo">
        Payer avec Y-Nkap
      </ynkap-pay-button>
    </div>
  `
})
export class PaymentComponent {
  onSuccess(response: PaymentResponse): void {
    console.log('Paiement réussi:', response);
    // Redirection vers page de succès
    // this.router.navigate(['/success']);
  }
  onError(error: YnkapError): void {
    console.error('Erreur de paiement:', error);
    // Les notifications d'erreur s'affichent automatiquement
    // Pas besoin d'action supplémentaire
  }
  onCancel(): void {
    console.log('Paiement annulé par l\'utilisateur');
    // Gérer l'annulation si nécessaire
  }
}
```
## 🧩 **Composants disponibles**
### 1. **YnkapPayButtonComponent**
Le composant principal qui affiche un bouton de paiement avec modale intégrée.
```html
<ynkap-pay-button
  [amount]="montant"
  [currency]="'XAF'"
  [merchantReference]="reference"
  [description]="description"
  [theme]="'light'"
  [primaryColor]="'#007bff'"
  (paymentSuccess)="onSuccess($event)"
  (paymentError)="onError($event)"
  (paymentCancel)="onCancel()">
  <!-- Contenu personnalisé du bouton -->
  <span class="custom-button-content">
    <i class="fas fa-credit-card"></i>
    Payer maintenant
  </span>
</ynkap-pay-button>
```
#### **Propriétés d'entrée (Inputs)**
| Propriété | Type | Requis | Description |
|-----------|------|--------|-------------|
| `amount` | `number` | ✅ | Montant à payer |
| `currency` | `string` | ❌ | Devise (défaut: 'XAF') |
| `merchantReference` | `string` | ✅ | Référence unique du marchand |
| `description` | `string` | ❌ | Description du paiement |
| `theme` | `'light' \| 'dark'` | ❌ | Thème de l'interface (défaut: 'light') |
| `primaryColor` | `string` | ❌ | Couleur principale personnalisée |
#### **Événements de sortie (Outputs)**
| Événement | Type | Description |
|-----------|------|-------------|
| `paymentSuccess` | `PaymentResponse` | Émis lors d'un paiement réussi |
| `paymentError` | `YnkapError` | Émis lors d'une erreur de paiement |
| `paymentCancel` | `void` | Émis lors de l'annulation du paiement |
### 2. **PaymentComponent** (Interne)
Composant de formulaire de paiement utilisé à l'intérieur de la modale. Généralement pas utilisé directement.
## 🔧 **Services et API**
### 1. **PaymentService**
Service principal pour gérer les paiements.
```typescript
import { PaymentService, PaymentRequest } from 'ynkap-payment';
constructor(private paymentService: PaymentService) {}
// Initier un paiement
initiatePayment() {
  const request: PaymentRequest = {
    amount: 1000,
    currency: 'XAF',
    merchantReference: 'ORDER-123',
    description: 'Achat produit',
    customer: {
      phone: '677123456',
      name: 'John Doe',
      email: 'john@example.com'
    }
  };
  this.paymentService.initiatePayment(request).subscribe({
    next: (response) => console.log('Paiement initié:', response),
    error: (error) => console.error('Erreur:', error)
  });
}
// Obtenir les méthodes de paiement disponibles
getPaymentMethods() {
  this.paymentService.availablePaymentMethods$.subscribe(
    methods => console.log('Méthodes disponibles:', methods)
  );
}
// Historique des transactions
getTransactionHistory() {
  this.paymentService.transactionHistory$.subscribe(
    history => console.log('Historique:', history)
  );
}
```
### 2. **ConfigurationService**
Service pour gérer la configuration de l'API.
```typescript
import { ConfigurationService } from 'ynkap-payment';
constructor(private configService: ConfigurationService) {}
// Vérifier si le module est initialisé
checkInitialization() {
  if (this.configService.isInitialized()) {
    console.log('Y-Nkap est configuré');
  } else {
    console.log('Configuration requise');
  }
}
// Obtenir la configuration actuelle
getCurrentConfig() {
  const config = this.configService.currentConfig;
  console.log('Configuration actuelle:', config);
}
// Mettre à jour la configuration
updateConfig() {
  this.configService.updateConfig({
    environment: 'production'
  });
}
```
### 3. **NotificationService**
Service pour afficher des notifications élégantes.
```typescript
import { NotificationService } from 'ynkap-payment';
constructor(private notificationService: NotificationService) {}
// Afficher une notification de succès
showSuccess() {
  this.notificationService.showSuccess(
    'Paiement réussi',
    'Votre transaction a été traitée avec succès.'
  );
}
// Afficher une notification d'erreur
showError() {
  this.notificationService.showError(
    'Paiement échoué',
    'Une erreur est survenue lors du traitement.'
  );
}
// Afficher une notification d'information
showInfo() {
  this.notificationService.showInfo(
    'Information',
    'Votre paiement est en cours de traitement.'
  );
}
```
### 4. **ConfirmationService**
Service pour afficher des dialogues de confirmation.
```typescript
import { ConfirmationService } from 'ynkap-payment';
constructor(private confirmationService: ConfirmationService) {}
// Confirmation d'annulation de paiement
confirmCancelPayment() {
  this.confirmationService.confirmCancelPayment().subscribe(confirmed => {
    if (confirmed) {
      console.log('Paiement annulé');
    } else {
      console.log('Annulation annulée');
    }
  });
}
// Confirmation personnalisée
customConfirmation() {
  this.confirmationService.confirm({
    title: 'Confirmer l\'action',
    message: 'Êtes-vous sûr de vouloir continuer ?',
    confirmText: 'Oui, continuer',
    cancelText: 'Annuler'
  }).subscribe(confirmed => {
    console.log('Réponse:', confirmed);
  });
}
```
## ⚠️ **Gestion des erreurs**
### Types d'erreurs
Le module Y-Nkap utilise une classe `YnkapError` personnalisée qui sépare les messages techniques des messages utilisateur :
```typescript
interface YnkapError extends Error {
  code: string;                    // Code d'erreur technique
  message: string;                 // Message technique (pour les logs)
  userMessage: string;             // Message convivial pour l'utilisateur
  retryable?: boolean;             // Indique si l'erreur est retryable
  transactionId?: string;          // ID de transaction si disponible
  details?: any;                   // Détails supplémentaires
}
```
### Codes d'erreur courants
| Code | Description | Retryable | Message utilisateur |
|------|-------------|-----------|-------------------|
| `AUTH_ERROR` | Clé API non configurée | ✅ | "Paiement échoué, veuillez réessayer" |
| `NETWORK_ERROR` | Problème de connexion | ✅ | "Problème de connexion, veuillez réessayer" |
| `PAYMENT_ERROR` | Erreur générique de paiement | ✅ | "Paiement échoué, veuillez réessayer" |
| `INSUFFICIENT_FUNDS` | Solde insuffisant | ❌ | "Solde insuffisant" |
| `PAYMENT_DECLINED` | Paiement refusé | ❌ | "Paiement refusé par votre opérateur" |
| `INVALID_PHONE` | Numéro invalide | ❌ | "Numéro de téléphone invalide" |
### Gestion avancée des erreurs
```typescript
import { YnkapError, ErrorCategory } from 'ynkap-payment';
export class PaymentComponent {
  handleError(error: YnkapError): void {
    // Log du message technique pour debugging
    console.error('Technical Error:', error.getTechnicalMessage());
    // Affichage du message utilisateur
    console.log('User Message:', error.getUserMessage());
    // Gestion par catégorie
    switch (error.code) {
      case 'AUTH_ERROR':
        // Erreur de configuration - notifier l'équipe technique
        this.notifyTechnicalTeam(error);
        break;
      case 'NETWORK_ERROR':
        // Erreur réseau - retry automatique géré par le module
        break;
      case 'PAYMENT_DECLINED':
        // Paiement refusé - proposer une autre méthode
        this.suggestAlternativeMethod();
        break;
      default:
        // Erreur générique
        break;
    }
    // Les notifications d'erreur s'affichent automatiquement
    // Pas besoin d'action supplémentaire
  }
  private notifyTechnicalTeam(error: YnkapError): void {
    // Envoyer l'erreur technique à votre système de monitoring
    this.monitoringService.logError({
      message: error.getTechnicalMessage(),
      code: error.code,
      timestamp: new Date(),
      context: 'Y-Nkap Payment'
    });
  }
}
```
### Système de retry automatique
Le module inclut un système de retry intelligent :
```typescript
// Configuration du retry (automatique)
const retryConfig = {
  maxRetries: 3,
  baseDelayMs: 1000,
  maxDelayMs: 10000,
  backoffMultiplier: 2
};
// Le retry est automatique pour les erreurs retryables
// L'utilisateur voit un bouton "Réessayer" après que la notification ait disparu
```
## 🔔 **Notifications et confirmations**
### Notifications automatiques
Le module affiche automatiquement des notifications élégantes pour tous les événements :
- **Succès** : Notification verte à droite de l'écran
- **Erreur** : Notification rouge à droite de l'écran
- **Information** : Notification bleue à droite de l'écran
```typescript
// Les notifications s'affichent automatiquement
// Aucune configuration supplémentaire requise
// Pour des notifications personnalisées :
import { NotificationService } from 'ynkap-payment';
constructor(private notificationService: NotificationService) {}
showCustomNotification() {
  this.notificationService.showSuccess(
    'Commande validée',
    'Votre commande a été enregistrée avec succès.',
    7000 // Durée en ms (optionnel)
  );
}
```
### Confirmations d'annulation
Le module demande automatiquement confirmation avant d'annuler un paiement :
```typescript
// Confirmation automatique lors de :
// - Clic sur le bouton X de fermeture
// - Clic sur "Retour" avec des données saisies
// - Événement d'annulation
// Pour des confirmations personnalisées :
import { ConfirmationService } from 'ynkap-payment';
constructor(private confirmationService: ConfirmationService) {}
showCustomConfirmation() {
  this.confirmationService.confirm({
    title: 'Supprimer l\'élément',
    message: 'Cette action est irréversible. Continuer ?',
    confirmText: 'Supprimer',
    cancelText: 'Annuler'
  }).subscribe(confirmed => {
    if (confirmed) {
      // Action confirmée
    }
  });
}
```
### Timing des notifications
Le module gère intelligemment l'affichage des éléments :
1. **Erreur de paiement** → Notification d'erreur apparaît à droite
2. **Immédiatement** → Section d'erreur dans le formulaire masquée
3. **Après 5 secondes** → Notification disparaît automatiquement
4. **Après 5.5 secondes** → Section d'erreur avec bouton "Réessayer" apparaît
Cela évite les conflits visuels et offre une expérience utilisateur fluide.
## 🎨 **Personnalisation**
### Thèmes
Le module supporte deux thèmes prédéfinis :
```html
<!-- Thème clair (défaut) -->
<ynkap-pay-button [theme]="'light'" [amount]="1000">
  Payer avec thème clair
</ynkap-pay-button>
<!-- Thème sombre -->
<ynkap-pay-button [theme]="'dark'" [amount]="1000">
  Payer avec thème sombre
</ynkap-pay-button>
```
### Couleurs personnalisées
```html
<ynkap-pay-button
  [amount]="1000"
  [primaryColor]="'#28a745'"
  [theme]="'light'">
  Payer avec couleur personnalisée
</ynkap-pay-button>
```
### Contenu du bouton personnalisé
```html
<ynkap-pay-button [amount]="1000">
  <!-- Contenu HTML personnalisé -->
  <div class="custom-button-content">
    <img src="assets/payment-icon.svg" alt="Paiement">
    <span class="amount">{{ amount | currency:'XAF' }}</span>
    <span class="text">Payer maintenant</span>
  </div>
</ynkap-pay-button>
```
### Styles CSS personnalisés
```css
/* Personnalisation du bouton */
ynkap-pay-button .ynkap-pay-button {
  border-radius: 25px;
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: 1px;
}
/* Personnalisation de la modale */
ynkap-pay-button .ynkap-modal {
  border-radius: 20px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
/* Personnalisation des notifications */
.ynkap-notification-card {
  border-radius: 15px;
  backdrop-filter: blur(10px);
}
```
## 📋 **Interfaces TypeScript**
### PaymentRequest
```typescript
interface PaymentRequest {
  amount: number;                    // Montant en centimes
  currency: string;                  // Code devise (XAF, EUR, USD)
  merchantReference: string;         // Référence unique du marchand
  description?: string;              // Description du paiement
  customer?: {
    phone: string;                   // Numéro de téléphone
    name?: string;                   // Nom du client
    email?: string;                  // Email du client
  };
  metadata?: Record<string, any>;    // Métadonnées personnalisées
}
```
### PaymentResponse
```typescript
interface PaymentResponse {
  status: 'success' | 'pending' | 'failed';
  transaction?: PaymentTransaction;
  error?: YnkapError;
  message?: string;
}
```
### PaymentTransaction
```typescript
interface PaymentTransaction {
  id: string;                        // ID unique de la transaction
  merchantReference: string;         // Référence du marchand
  amount: number;                    // Montant
  currency: string;                  // Devise
  status: TransactionStatus;         // Statut de la transaction
  paymentMethod: PaymentMethod;      // Méthode de paiement utilisée
  customer: {
    phone: string;
    name?: string;
    email?: string;
  };
  createdAt: Date;                   // Date de création
  updatedAt: Date;                   // Dernière mise à jour
  metadata?: Record<string, any>;    // Métadonnées
}
```
### PaymentMethod
```typescript
interface PaymentMethod {
  id: string;                        // Identifiant unique
  name: string;                      // Nom affiché
  type: 'mobile_money';              // Type de paiement
  provider: 'mtn' | 'orange';        // Fournisseur
  icon: string;                      // URL de l'icône
  enabled: boolean;                  // Disponibilité
  fees?: {
    fixed?: number;                  // Frais fixes
    percentage?: number;             // Pourcentage
  };
}
```
### ApiConfig
```typescript
interface ApiConfig {
  apiKey: string;                    // Clé API Y-Nkap
  apiSecret: string;                 // Secret API Y-Nkap
  merchantId: string;                // ID du marchand
  environment: 'sandbox' | 'production'; // Environnement
  baseUrl?: string;                  // URL de base personnalisée
  timeout?: number;                  // Timeout des requêtes (ms)
}
```
### YnkapError
```typescript
interface YnkapError extends Error {
  code: string;                      // Code d'erreur
  message: string;                   // Message technique
  userMessage: string;               // Message pour l'utilisateur
  retryable?: boolean;               // Peut être retryé
  transactionId?: string;            // ID de transaction
  details?: any;                     // Détails supplémentaires
  // Méthodes
  getUserMessage(): string;          // Message utilisateur
  getTechnicalMessage(): string;     // Message technique
}
```
```
## 💡 **Exemples avancés**
### 1. Intégration avec un panier e-commerce
```typescript
import { Component } from '@angular/core';
import { PaymentResponse, YnkapError } from 'ynkap-payment';
@Component({
  selector: 'app-checkout',
  template: `
    <div class="checkout-container">
      <div class="order-summary">
        <h3>Résumé de la commande</h3>
        <div class="items">
          <div *ngFor="let item of cartItems" class="item">
            <span>{{ item.name }}</span>
            <span>{{ item.price | currency:'XAF' }}</span>
          </div>
        </div>
        <div class="total">
          <strong>Total: {{ getTotal() | currency:'XAF' }}</strong>
        </div>
      </div>
      <div class="payment-section">
        <ynkap-pay-button
          [amount]="getTotal()"
          [currency]="'XAF'"
          [merchantReference]="orderId"
          [description]="getOrderDescription()"
          [theme]="'light'"
          (paymentSuccess)="onPaymentSuccess($event)"
          (paymentError)="onPaymentError($event)"
          (paymentCancel)="onPaymentCancel()">
          <div class="payment-button-content">
            <i class="fas fa-lock"></i>
            Paiement sécurisé
          </div>
        </ynkap-pay-button>
      </div>
    </div>
  `
})
export class CheckoutComponent {
  cartItems = [
    { name: 'Produit 1', price: 5000 },
    { name: 'Produit 2', price: 3000 },
    { name: 'Livraison', price: 1000 }
  ];
  orderId = `ORDER-${Date.now()}`;
  getTotal(): number {
    return this.cartItems.reduce((sum, item) => sum + item.price, 0);
  }
  getOrderDescription(): string {
    return `Commande ${this.orderId} - ${this.cartItems.length} article(s)`;
  }
  onPaymentSuccess(response: PaymentResponse): void {
    // 1. Sauvegarder la transaction
    this.saveOrder(response.transaction);
    // 2. Vider le panier
    this.clearCart();
    // 3. Envoyer email de confirmation
    this.sendConfirmationEmail(response.transaction);
    // 4. Rediriger vers page de succès
    this.router.navigate(['/order-success'], {
      queryParams: { orderId: this.orderId }
    });
  }
  onPaymentError(error: YnkapError): void {
    // Analytics pour tracking des erreurs
    this.analytics.track('payment_error', {
      error_code: error.code,
      order_id: this.orderId,
      amount: this.getTotal()
    });
  }
  onPaymentCancel(): void {
    // Analytics pour tracking des abandons
    this.analytics.track('payment_cancelled', {
      order_id: this.orderId,
      amount: this.getTotal()
    });
  }
}
```
### 2. Gestion des abonnements récurrents
```typescript
@Component({
  selector: 'app-subscription',
  template: `
    <div class="subscription-plans">
      <div *ngFor="let plan of plans" class="plan-card">
        <h3>{{ plan.name }}</h3>
        <div class="price">{{ plan.price | currency:'XAF' }}/mois</div>
        <ynkap-pay-button
          [amount]="plan.price"
          [merchantReference]="generateSubscriptionRef(plan)"
          [description]="'Abonnement ' + plan.name"
          (paymentSuccess)="onSubscriptionPayment($event, plan)">
          S'abonner
        </ynkap-pay-button>
      </div>
    </div>
  `
})
export class SubscriptionComponent {
  plans = [
    { id: 'basic', name: 'Basic', price: 5000 },
    { id: 'premium', name: 'Premium', price: 10000 },
    { id: 'enterprise', name: 'Enterprise', price: 20000 }
  ];
  generateSubscriptionRef(plan: any): string {
    return `SUB-${plan.id}-${this.userId}-${Date.now()}`;
  }
  onSubscriptionPayment(response: PaymentResponse, plan: any): void {
    // Créer l'abonnement
    this.subscriptionService.createSubscription({
      userId: this.userId,
      planId: plan.id,
      transactionId: response.transaction?.id,
      startDate: new Date(),
      status: 'active'
    }).subscribe(() => {
      // Programmer les paiements récurrents
      this.scheduleRecurringPayments(plan);
    });
  }
}
```
### 3. Intégration avec un système de wallet
```typescript
@Component({
  selector: 'app-wallet',
  template: `
    <div class="wallet-container">
      <div class="balance">
        <h3>Solde actuel</h3>
        <div class="amount">{{ balance | currency:'XAF' }}</div>
      </div>
      <div class="recharge-section">
        <h4>Recharger le wallet</h4>
        <div class="amount-buttons">
          <button *ngFor="let amount of rechargeAmounts"
                  (click)="rechargeWallet(amount)"
                  class="amount-btn">
            {{ amount | currency:'XAF' }}
          </button>
        </div>
        <div class="custom-amount">
          <input [(ngModel)]="customAmount"
                 type="number"
                 placeholder="Montant personnalisé">
          <ynkap-pay-button
            [amount]="customAmount"
            [merchantReference]="generateRechargeRef()"
            [description]="'Recharge wallet'"
            (paymentSuccess)="onRechargeSuccess($event)">
            Recharger
          </ynkap-pay-button>
        </div>
      </div>
    </div>
  `
})
export class WalletComponent {
  balance = 0;
  customAmount = 0;
  rechargeAmounts = [1000, 5000, 10000, 25000, 50000];
  rechargeWallet(amount: number): void {
    const ref = this.generateRechargeRef();
    // Utiliser le service directement pour plus de contrôle
    this.paymentService.initiatePayment({
      amount: amount,
      currency: 'XAF',
      merchantReference: ref,
      description: `Recharge wallet - ${amount} XAF`,
      customer: {
        phone: this.userService.currentUser.phone,
        name: this.userService.currentUser.name
      }
    }).subscribe({
      next: (response) => this.handleRechargeResponse(response),
      error: (error) => this.handleRechargeError(error)
    });
  }
  onRechargeSuccess(response: PaymentResponse): void {
    // Mettre à jour le solde
    this.balance += response.transaction?.amount || 0;
    // Sauvegarder en base
    this.walletService.updateBalance(this.balance);
    // Notification de succès
    this.notificationService.showSuccess(
      'Recharge réussie',
      `Votre wallet a été rechargé de ${response.transaction?.amount} XAF`
    );
  }
  generateRechargeRef(): string {
    return `WALLET-${this.userId}-${Date.now()}`;
  }
}
```
## 🏗️ **Architecture**
### Structure modulaire
```
ynkap-payment/
├── src/
│   ├── lib/
│   │   ├── ynkap.module.ts              # Module principal
│   │   ├── configuration/               # Configuration API
│   │   │   ├── configuration.service.ts
│   │   │   └── models/
│   │   ├── payment/                     # Services de paiement
│   │   │   ├── payment.service.ts
│   │   │   ├── payment/                 # Composant formulaire
│   │   │   ├── retry/                   # Système de retry
│   │   │   └── models/
│   │   ├── pay-button/                  # Composant bouton
│   │   │   ├── pay-button.component.ts
│   │   │   └── pay-button.component.html
│   │   ├── notification/                # Système de notifications
│   │   │   ├── notification.service.ts
│   │   │   └── notification.component.ts
│   │   ├── confirmation/                # Dialogues de confirmation
│   │   │   ├── confirmation.service.ts
│   │   │   └── confirmation.component.ts
│   │   ├── auth/                        # Authentification
│   │   │   └── auth.service.ts
│   │   └── error-handling/              # Gestion d'erreurs
│   │       ├── error-handling.service.ts
│   │       └── models/
│   └── public-api.ts                    # Exports publics
```
### Flux de données
```mermaid
graph TD
    A[PayButtonComponent] --> B[PaymentService]
    B --> C[AuthService]
    B --> D[ConfigurationService]
    B --> E[API Y-Nkap]
    F[PaymentComponent] --> B
    F --> G[NotificationService]
    F --> H[ConfirmationService]
    I[RetryService] --> B
    J[ErrorHandlingService] --> G
    E --> K[PaymentResponse]
    K --> L[Success/Error Events]
```
### Services principaux
| Service | Responsabilité | Singleton |
|---------|----------------|-----------|
| `ConfigurationService` | Gestion de la configuration API | ✅ |
| `PaymentService` | Logique métier des paiements | ✅ |
| `AuthService` | Authentification avec l'API | ✅ |
| `NotificationService` | Affichage des notifications | ✅ |
| `ConfirmationService` | Dialogues de confirmation | ✅ |
| `RetryService` | Gestion des tentatives | ✅ |
| `ErrorHandlingService` | Traitement des erreurs | ✅ |
### Cycle de vie d'un paiement
1. **Initialisation** : Configuration du module avec les clés API
2. **Déclenchement** : Clic sur le bouton de paiement
3. **Authentification** : Vérification des credentials
4. **Sélection méthode** : Choix MTN/Orange Money
5. **Saisie données** : Numéro de téléphone
6. **Validation** : Contrôles côté client
7. **Envoi API** : Requête vers Y-Nkap
8. **Traitement** : Gestion de la réponse
9. **Notification** : Affichage du résultat
10. **Retry** : En cas d'erreur retryable
## 🔧 **Configuration avancée**
### Variables d'environnement
```typescript
// environment.ts
export const environment = {
  production: false,
  ynkap: {
    apiKey: process.env['YNKAP_API_KEY'] || 'sandbox-key',
    apiSecret: process.env['YNKAP_API_SECRET'] || 'sandbox-secret',
    merchantId: process.env['YNKAP_MERCHANT_ID'] || 'sandbox-merchant',
    environment: 'sandbox' as const,
    // Configuration avancée
    timeout: 30000,                    // 30 secondes
    retryAttempts: 3,
    retryDelay: 1000,
    enableLogging: true,
    enableAnalytics: false
  }
};
```
### Configuration du module
```typescript
// app.module.ts
import { YnkapModule } from 'ynkap-payment';
import { environment } from './environments/environment';
@NgModule({
  imports: [
    YnkapModule.forRoot({
      ...environment.ynkap,
      // Intercepteurs personnalisés
      interceptors: [
        CustomAuthInterceptor,
        LoggingInterceptor
      ],
      // Configuration des notifications
      notifications: {
        position: 'top-right',
        duration: 5000,
        enableSound: false
      },
      // Configuration des confirmations
      confirmations: {
        theme: 'modern',
        enableBackdropClick: false
      }
    })
  ]
})
export class AppModule { }
```
### Personnalisation des styles
```scss
// styles.scss
// Variables Y-Nkap
:root {
  --ynkap-primary-color: #007bff;
  --ynkap-success-color: #28a745;
  --ynkap-error-color: #dc3545;
  --ynkap-warning-color: #ffc107;
  --ynkap-border-radius: 8px;
  --ynkap-box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  --ynkap-transition: all 0.3s ease;
}
// Thème sombre
[data-theme="dark"] {
  --ynkap-bg-color: #1a1a1a;
  --ynkap-text-color: #ffffff;
  --ynkap-border-color: #333333;
}
// Personnalisation du bouton
.ynkap-pay-button {
  background: linear-gradient(135deg, var(--ynkap-primary-color), #0056b3);
  border: none;
  border-radius: var(--ynkap-border-radius);
  box-shadow: var(--ynkap-box-shadow);
  transition: var(--ynkap-transition);
  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
  }
}
// Personnalisation de la modale
.ynkap-modal {
  border-radius: 16px;
  backdrop-filter: blur(10px);
  .ynkap-modal-header {
    background: linear-gradient(135deg, #f8f9fa, #e9ecef);
  }
}
// Personnalisation des notifications
.ynkap-notification-card {
  border-radius: 12px;
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  &.ynkap-notification-success {
    background: linear-gradient(135deg, #d4edda, #c3e6cb);
  }
  &.ynkap-notification-error {
    background: linear-gradient(135deg, #f8d7da, #f5c6cb);
  }
}
```
## 🧪 **Tests et développement**
### Tests unitaires
Le module Y-Nkap inclut une suite de tests complète :
```bash
# Lancer tous les tests
npm test
# Tests avec couverture
npm run test:coverage
# Tests en mode watch
npm run test:watch
```
### Tests d'intégration
```typescript
import { TestBed } from '@angular/core/testing';
import { YnkapModule, PaymentService } from 'ynkap-payment';
describe('Y-Nkap Integration Tests', () => {
  let paymentService: PaymentService;
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        YnkapModule.forRoot({
          apiKey: 'test-api-key',
          apiSecret: 'test-api-secret',
          merchantId: 'test-merchant',
          environment: 'sandbox'
        })
      ]
    });
    paymentService = TestBed.inject(PaymentService);
  });
  it('should initiate payment successfully', (done) => {
    const request = {
      amount: 1000,
      currency: 'XAF',
      merchantReference: 'TEST-123',
      description: 'Test payment'
    };
    paymentService.initiatePayment(request).subscribe({
      next: (response) => {
        expect(response.status).toBe('success');
        done();
      },
      error: done.fail
    });
  });
});
```
### Mode développement
```typescript
// Activer les logs détaillés
YnkapModule.forRoot({
  // ... configuration
  enableDebugMode: true,
  logLevel: 'verbose'
});
// Les logs apparaîtront dans la console :
// [Y-Nkap] Payment initiated: {...}
// [Y-Nkap] API Request: POST /payments
// [Y-Nkap] API Response: 200 {...}
```
## 📚 **Migration et compatibilité**
### Versions supportées
| Version Y-Nkap | Angular | TypeScript | Node.js |
|-----------------|---------|------------|---------|
| 1.x.x | 16+ | 5.0+ | 18+ |
| 2.x.x | 17+ | 5.2+ | 18+ |
### Migration depuis v1.x
```typescript
// Avant (v1.x)
import { YnkapPaymentModule } from '@yaba-in/ynkap-payment';
YnkapPaymentModule.forRoot({
  apiKey: 'key',
  environment: 'sandbox'
});
// Après (v2.x)
import { YnkapModule } from 'ynkap-payment';
YnkapModule.forRoot({
  apiKey: 'key',
  apiSecret: 'secret',  // Nouveau requis
  merchantId: 'id',     // Nouveau requis
  environment: 'sandbox'
});
```
### Breaking changes v2.0
- ✅ **Ajout** : `apiSecret` et `merchantId` requis
- ✅ **Ajout** : Système de notifications automatiques
- ✅ **Ajout** : Confirmations d'annulation
- ✅ **Ajout** : Messages user-friendly vs techniques
- ✅ **Amélioration** : Retry intelligent avec timing
- ⚠️ **Changement** : Structure des événements d'erreur
- ⚠️ **Suppression** : Propriété `webhookUrl` (déplacée vers backend)
## 🆘 **Support et communauté**
### Documentation officielle
- 📖 **Documentation complète** : [docs.y-nkap.com](https://docs.y-nkap.com)
- 🎯 **Guide d'intégration** : [integration.y-nkap.com](https://integration.y-nkap.com)
- 🔧 **API Reference** : [api.y-nkap.com](https://api.y-nkap.com)
### Support technique
- 💬 **Discord** : [discord.gg/ynkap](https://discord.gg/ynkap)
- 📧 **Email** : support@y-nkap.com
- 🐛 **Issues GitHub** : [github.com/ynkap/angular-sdk/issues](https://github.com/ynkap/angular-sdk/issues)
- 📞 **Support téléphonique** : +237 6XX XXX XXX (heures ouvrables)
### Ressources développeurs
- 🎥 **Tutoriels vidéo** : [youtube.com/ynkap](https://youtube.com/ynkap)
- 📝 **Blog technique** : [blog.y-nkap.com](https://blog.y-nkap.com)
- 💻 **Exemples de code** : [github.com/ynkap/examples](https://github.com/ynkap/examples)
- 🚀 **Starter templates** : [github.com/ynkap/starters](https://github.com/ynkap/starters)
### Contribution
```bash
# Cloner le repository
git clone https://github.com/ynkap/angular-sdk.git
# Installer les dépendances
npm install
# Lancer en mode développement
npm run dev
# Lancer les tests
npm test
# Build de production
npm run build
```
### Roadmap
- 🔄 **Q1 2024** : Support des paiements par QR Code
- 💳 **Q2 2024** : Intégration cartes bancaires
- 🌍 **Q3 2024** : Support multi-devises avancé
- 📱 **Q4 2024** : SDK React Native
## 📄 **Licence**
Ce projet est sous licence **MIT**. Voir le fichier [LICENSE](LICENSE) pour plus de détails.
## 👨💻 **Auteur**
**SIEWE FORTUNE**
- 🌐 Website: [fortune-siewe.dev](https://fortune-siewe.dev)
- 📧 Email: fortune.siewe@example.com
- 💼 LinkedIn: [linkedin.com/in/fortune-siewe](https://linkedin.com/in/fortune-siewe)
- 🐦 Twitter: [@fortune_siewe](https://twitter.com/fortune_siewe)
## 🙏 **Remerciements**
- L'équipe **Y-Nkap** pour l'API robuste
- La communauté **Angular** pour les outils exceptionnels
- Les **contributeurs** qui améliorent continuellement ce module
- Les **développeurs** qui utilisent et font confiance à cette solution
<div align="center">
  <p><strong>Fait avec ❤️ pour la communauté des développeurs africains</strong></p>
  <p>
    <a href="https://y-nkap.com">🌐 Y-Nkap</a> •
    <a href="https://docs.y-nkap.com">📖 Documentation</a> •
    <a href="https://github.com/ynkap/angular-sdk">💻 GitHub</a> •
    <a href="https://discord.gg/ynkap">💬 Discord</a>
  </p>
</div>