# Flow de paiement Stripe Tap to Pay

## Vue d'ensemble

Ce document décrit le flow complet pour les paiements Stripe Tap to Pay dans l'application GeoSector, depuis la création du compte Stripe Connect jusqu'au paiement final.

---

## 🏢 PRÉALABLE : Création d'un compte Amicale Stripe Connect

Avant de pouvoir utiliser les paiements Stripe, chaque amicale doit créer son compte Stripe Connect.

### 📋 Flow de création du compte

#### 1. Initiation depuis l'application web admin

**Endpoint :** `POST /api/stripe/accounts/create`

**Requête :**
```json
{
  "amicale_id": 45,
  "type": "express",  // Type de compte Stripe Connect
  "country": "FR",
  "email": "contact@amicale-pompiers-paris.fr",
  "business_profile": {
    "name": "Amicale des Pompiers de Paris",
    "product_description": "Vente de calendriers des pompiers",
    "mcc": "8398",  // Code activité : organisations civiques
    "url": "https://www.amicale-pompiers-paris.fr"
  }
}
```

#### 2. Création du compte Stripe

**Actions API :**
1. Appel Stripe API pour créer un compte Express
2. Génération d'un lien d'onboarding personnalisé
3. Sauvegarde en base de données

**Réponse :**
```json
{
  "success": true,
  "stripe_account_id": "acct_1O3ABC456DEF789",
  "onboarding_url": "https://connect.stripe.com/express/oauth/authorize?...",
  "status": "pending"
}
```

#### 3. Processus d'onboarding Stripe

**Actions utilisateur (dirigeant amicale) :**
1. Clic sur le lien d'onboarding
2. Connexion/création compte Stripe
3. Saisie des informations légales :
   - **Entité** : Association loi 1901
   - **SIRET** de l'amicale
   - **RIB** pour les virements
   - **Pièce d'identité** du représentant légal
4. Validation des conditions d'utilisation

#### 4. Vérification et activation

**Webhook Stripe → API :**
```json
POST /api/stripe/webhooks
{
  "type": "account.updated",
  "data": {
    "object": {
      "id": "acct_1O3ABC456DEF789",
      "charges_enabled": true,
      "payouts_enabled": true,
      "details_submitted": true
    }
  }
}
```

**Actions API :**
1. Mise à jour du statut en base
2. Notification email à l'amicale
3. Activation des fonctionnalités de paiement

#### 5. Structure en base de données

**Table `stripe_accounts` :**
```sql
CREATE TABLE `stripe_accounts` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `fk_entite` int(10) unsigned NOT NULL,
  `stripe_account_id` varchar(50) NOT NULL,
  `account_type` enum('express','standard','custom') DEFAULT 'express',
  `charges_enabled` tinyint(1) DEFAULT 0,
  `payouts_enabled` tinyint(1) DEFAULT 0,
  `details_submitted` tinyint(1) DEFAULT 0,
  `country` varchar(2) DEFAULT 'FR',
  `default_currency` varchar(3) DEFAULT 'eur',
  `business_name` varchar(255) DEFAULT NULL,
  `support_email` varchar(255) DEFAULT NULL,
  `onboarding_completed_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `stripe_account_id` (`stripe_account_id`),
  KEY `fk_entite` (`fk_entite`),
  CONSTRAINT `stripe_accounts_ibfk_1` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`)
);
```

### 🔐 Sécurité et validation

#### Prérequis pour créer un compte :
- ✅ Utilisateur administrateur de l'amicale
- ✅ Amicale active avec statut validé
- ✅ Email de contact vérifié
- ✅ Informations légales complètes (SIRET, adresse)

#### Validation avant paiements :
- ✅ `charges_enabled = 1` (peut recevoir des paiements)
- ✅ `payouts_enabled = 1` (peut recevoir des virements)
- ✅ `details_submitted = 1` (onboarding terminé)

### 📊 États du compte Stripe

| État | Description | Actions possibles |
|------|-------------|-------------------|
| `pending` | Compte créé, onboarding en cours | Compléter l'onboarding |
| `restricted` | Informations manquantes | Fournir documents manquants |
| `restricted_soon` | Vérification en cours | Attendre validation Stripe |
| `active` | Compte opérationnel | Recevoir des paiements ✅ |
| `rejected` | Compte refusé par Stripe | Contacter support |

### 🚨 Gestion des erreurs

#### Erreurs courantes lors de la création :
- **400** : Données manquantes ou invalides
- **409** : Compte Stripe déjà existant pour cette amicale
- **403** : Utilisateur non autorisé

#### Erreurs durant l'onboarding :
- Documents manquants ou invalides
- Informations bancaires incorrectes
- Activité non autorisée par Stripe

### 📞 Support et résolution

#### Pour les amicales :
1. **Email support** : support@geosector.fr
2. **Documentation** : Guides d'onboarding disponibles
3. **Assistance téléphonique** : Disponible aux heures ouvrables

#### Pour les développeurs :
1. **Stripe Dashboard** : Accès aux comptes et statuts
2. **Logs API** : Traçabilité complète des opérations
3. **Webhook monitoring** : Suivi des événements Stripe

---

## 🚨 IMPORTANT : Nouveau Flow (v2)

**Le passage est TOUJOURS créé/modifié EN PREMIER** pour obtenir un ID réel, PUIS le PaymentIntent est créé avec cet ID.

## Flow détaillé

### 1. Sauvegarde du passage EN PREMIER

L'application crée ou modifie d'abord le passage pour obtenir un ID réel :

```
POST /api/passages/create  // Nouveau passage
PUT /api/passages/456      // Mise à jour passage existant
```

**Réponse avec l'ID réel :**
```json
{
  "status": "success",
  "passage_id": 456  // ID RÉEL du passage créé/modifié
}
```

### 2. Création du PaymentIntent AVEC l'ID réel

Ensuite seulement, création du PaymentIntent avec le `passage_id` réel :

```
POST /api/stripe/payments/create-intent
```

```json
{
  "amount": 2500,  // En centimes (25€)
  "passage_id": 456,  // ID RÉEL du passage (JAMAIS 0)
  "payment_method_types": ["card_present"],  // Tap to Pay
  "location_id": "tml_xxx",  // Terminal reader location
  "amicale_id": 45,
  "member_id": 67,
  "stripe_account": "acct_xxx"
}
```

#### Réponse

```json
{
  "status": "success",
  "data": {
    "client_secret": "pi_3QaXYZ_secret_xyz",
    "payment_intent_id": "pi_3QaXYZ123ABC456",
    "amount": 2500,
    "currency": "eur",
    "passage_id": 789,  // 0 pour nouveau passage
    "type": "tap_to_pay"
  }
}
```

### 2. Traitement du paiement côté client

L'application utilise le SDK Stripe pour traiter le paiement via NFC :

```dart
// Flutter - Utilisation du client_secret
final paymentResult = await stripe.collectPaymentMethod(
  clientSecret: response['client_secret'],
  // ... configuration Tap to Pay
);
```

### 3. Traitement du paiement Tap to Pay

L'application utilise le SDK Stripe Terminal avec le `client_secret` pour collecter le paiement via NFC.

### 4. Mise à jour du passage avec stripe_payment_id

Après succès du paiement, l'app met à jour le passage avec le `stripe_payment_id` :

```json
PUT /api/passages/456
{
  "stripe_payment_id": "pi_3QaXYZ123ABC456",  // ← LIEN AVEC STRIPE
  // ... autres champs si nécessaire
}
```

## Points clés du nouveau flow

### ✅ Avantages

1. **Passage toujours existant** : Le passage existe toujours avec un ID réel avant le paiement
2. **Traçabilité garantie** : Le `passage_id` dans Stripe est toujours valide
3. **Gestion d'erreur robuste** : Si le paiement échoue, le passage existe déjà
4. **Cohérence des données** : Pas de passage "orphelin" ou de paiement sans passage

### ❌ Ce qui n'est plus supporté

1. **passage_id=0** : Plus jamais utilisé dans `/create-intent`
2. **operation_id** : Plus nécessaire car le passage existe déjà
3. **Création conditionnelle** : Le passage est toujours créé avant

## Schéma de séquence (Nouveau Flow v2)

```
┌─────────┐     ┌─────────┐     ┌────────┐     ┌────────────┐
│   App   │     │   API   │     │ Stripe │     │  ope_pass  │
└────┬────┘     └────┬────┘     └────┬───┘     └─────┬──────┘
     │               │                │                │
     │ 1. CREATE/UPDATE passage       │                │
     ├──────────────>│                │                │
     │               ├────────────────┼───────────────>│
     │               │                │   INSERT/UPDATE │
     │               │                │                │
     │ 2. passage_id: 456 (réel)      │                │
     │<──────────────│                │                │
     │               │                │                │
     │ 3. create-intent (id=456)      │                │
     ├──────────────>│                │                │
     │               │                │                │
     │               │ 4. Create PI   │                │
     │               ├───────────────>│                │
     │               │                │                │
     │               │ 5. PI created  │                │
     │               │<───────────────│                │
     │               │                │                │
     │               │ 6. UPDATE      │                │
     │               ├────────────────┼───────────────>│
     │               │ stripe_payment_id = pi_xxx      │
     │               │                │                │
     │ 7. client_secret + pi_id       │                │
     │<──────────────│                │                │
     │               │                │                │
     │ 8. Tap to Pay │                │                │
     ├───────────────┼───────────────>│                │
     │   avec SDK    │                │                │
     │               │                │                │
     │ 9. Payment OK │                │                │
     │<──────────────┼────────────────│                │
     │               │                │                │
     │ 10. UPDATE passage (optionnel) │                │
     ├──────────────>│                │                │
     │               ├────────────────┼───────────────>│
     │               │ Confirmer stripe_payment_id     │
     │               │                │                │
     │ 11. Success   │                │                │
     │<──────────────│                │                │
     │               │                │                │
```

## Points importants (Nouveau Flow v2)

1. **Passage créé en premier** : Le passage est TOUJOURS créé/modifié AVANT le PaymentIntent
2. **ID réel obligatoire** : Le `passage_id` ne peut jamais être 0 dans `/create-intent`
3. **Lien Stripe automatique** : Le `stripe_payment_id` est ajouté automatiquement lors de la création du PaymentIntent
4. **Idempotence** : Un passage ne peut avoir qu'un seul `stripe_payment_id`
5. **Validation stricte** : Vérification du montant, propriété et existence du passage

## Erreurs possibles

- **400** :
  - `passage_id` manquant ou ≤ 0
  - Montant invalide (< 1€ ou > 999€)
  - Passage déjà payé par Stripe
  - Montant ne correspond pas au passage
- **401** : Non authentifié
- **403** : Passage non autorisé (pas le bon utilisateur)
- **404** : Passage non trouvé

## Migration base de données

La colonne `stripe_payment_id VARCHAR(50)` a été ajoutée via :
```sql
ALTER TABLE `ope_pass` ADD COLUMN `stripe_payment_id` VARCHAR(50) DEFAULT NULL;
ALTER TABLE `ope_pass` ADD INDEX `idx_stripe_payment` (`stripe_payment_id`);
```

## Environnements

- **DEV** : dva-geo sur IN3 - Base mise à jour ✅
- **REC** : rca-geo sur IN3 - Base mise à jour ✅
- **PROD** : pra-geo sur IN4 - À mettre à jour