- Mise à jour VERSION vers 3.3.4 - Optimisations et révisions architecture API (deploy-api.sh, scripts de migration) - Ajout documentation Stripe Tap to Pay complète - Migration vers polices Inter Variable pour Flutter - Optimisations build Android et nettoyage fichiers temporaires - Amélioration système de déploiement avec gestion backups - Ajout scripts CRON et migrations base de données 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
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 :
{
"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 :
- Appel Stripe API pour créer un compte Express
- Génération d'un lien d'onboarding personnalisé
- Sauvegarde en base de données
Réponse :
{
"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) :
- Clic sur le lien d'onboarding
- Connexion/création compte Stripe
- 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
- Validation des conditions d'utilisation
4. Vérification et activation
Webhook Stripe → API :
POST /api/stripe/webhooks
{
"type": "account.updated",
"data": {
"object": {
"id": "acct_1O3ABC456DEF789",
"charges_enabled": true,
"payouts_enabled": true,
"details_submitted": true
}
}
}
Actions API :
- Mise à jour du statut en base
- Notification email à l'amicale
- Activation des fonctionnalités de paiement
5. Structure en base de données
Table stripe_accounts :
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 :
- Email support : support@geosector.fr
- Documentation : Guides d'onboarding disponibles
- Assistance téléphonique : Disponible aux heures ouvrables
Pour les développeurs :
- Stripe Dashboard : Accès aux comptes et statuts
- Logs API : Traçabilité complète des opérations
- 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 :
{
"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
{
"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
{
"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 :
// 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 :
PUT /api/passages/456
{
"stripe_payment_id": "pi_3QaXYZ123ABC456", // ← LIEN AVEC STRIPE
// ... autres champs si nécessaire
}
Points clés du nouveau flow
✅ Avantages
- Passage toujours existant : Le passage existe toujours avec un ID réel avant le paiement
- Traçabilité garantie : Le
passage_iddans Stripe est toujours valide - Gestion d'erreur robuste : Si le paiement échoue, le passage existe déjà
- Cohérence des données : Pas de passage "orphelin" ou de paiement sans passage
❌ Ce qui n'est plus supporté
- passage_id=0 : Plus jamais utilisé dans
/create-intent - operation_id : Plus nécessaire car le passage existe déjà
- 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)
- Passage créé en premier : Le passage est TOUJOURS créé/modifié AVANT le PaymentIntent
- ID réel obligatoire : Le
passage_idne peut jamais être 0 dans/create-intent - Lien Stripe automatique : Le
stripe_payment_idest ajouté automatiquement lors de la création du PaymentIntent - Idempotence : Un passage ne peut avoir qu'un seul
stripe_payment_id - Validation stricte : Vérification du montant, propriété et existence du passage
Erreurs possibles
- 400 :
passage_idmanquant 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 :
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