Module PrestaShop : Stripe Connect - Split Payment
Version : 1.0.3
Auteur : Webdevoo
Compatibilité : PrestaShop 1.7+ / 8.x
Pays supportés : FR, US, CA
Table des matières
- Vue d'ensemble
- Architecture du module
- Installation et configuration
- Variables de configuration
- Flux de paiement complet
- Contrôleurs Front-Office
- 6.1 payment.php
- 6.2 validation.php
- 6.3 webhook.php
- Gestion des affiliés
- Sécurité
- Base de données
- Hooks PrestaShop utilisés
- Dépannage
1. Vue d'ensemble
Le module Stripe Connect - Split Payment permet d'intégrer le paiement par carte bancaire via Stripe Connect dans une boutique PrestaShop. Il gère la répartition des fonds (split payment) entre la plateforme principale et des comptes affiliés connectés à Stripe.
Principe de fonctionnement
Client (Checkout) ──► API distante (create-checkout.php) ──► Stripe Checkout
│
▼
PrestaShop (webhook.php) ◄────────────────────────── Stripe (webhook)
│
▼
Création commande
Le module ne communique pas directement avec l'API Stripe depuis PrestaShop. Il passe par une API intermédiaire (plateforme distante) qui orchestre la création de la session Checkout Stripe et la répartition des fonds.
2. Architecture du module
stripeconnect/
├── stripeconnect.php # Classe principale du module
├── controllers/
│ └── front/
│ ├── payment.php # Initiation du paiement
│ ├── validation.php # Retour client post-paiement
│ └── webhook.php # Réception webhook Stripe
├── views/
│ └── templates/
│ ├── admin/
│ │ ├── configure.tpl # Template config Back-Office
│ │ └── product_tab.tpl # Onglet affilié sur fiche produit
│ └── front/
│ ├── payment_info.tpl # Infos additionnelles au checkout
│ └── error.tpl # Page d'erreur
3. Installation et configuration
Prérequis
- Extension PHP cURL activée sur le serveur
- Un compte Stripe avec Stripe Connect activé
- Une API distante déployée et accessible (endpoint
create-checkout.php)
Étapes d'installation
- Copier le dossier
stripeconnect/dans/modules/de votre PrestaShop - Installer le module via Back-Office > Modules > Module Manager
- Configurer les clés API dans la page de configuration du module
Configuration Back-Office
Accédez à la configuration via : Modules > Stripe Connect - Split Payment > Configurer
| Champ | Description |
|---|---|
| Stripe Publishable Key | Clé publique Stripe (pk_live_... ou pk_test_...) |
| Stripe Secret Key | Clé secrète Stripe (sk_live_... ou sk_test_...) |
| Stripe Client ID | Identifiant Client Stripe Connect (ca_...) |
| Stripe Webhook Secret | Secret du webhook Stripe (whsec_...) |
| URL de votre plateforme API | URL de base de l'API distante |
| Mode Production | Bascule entre mode test et production |
4. Variables de configuration
| Clé | Type | Description | Valeur par défaut |
|---|---|---|---|
STRIPECONNECT_LIVE_MODE |
bool |
Active le mode production | 0 (test) |
STRIPECONNECT_API_BASE_URL |
string |
URL de base de l'API distante | — |
STRIPECONNECT_PUBLIC_KEY |
string |
Clé publique Stripe | — |
STRIPECONNECT_SECRET_KEY |
string |
Clé secrète Stripe | — |
STRIPECONNECT_CLIENT_ID |
string |
Client ID Stripe Connect | — |
STRIPECONNECT_WEBHOOK_SECRET |
string |
Secret du webhook Stripe | — |
STRIPECONNECT_SHARED_SECRET |
string |
Secret partagé pour signer les appels à l'API distante | Auto-généré (32 chars) |
Note :
STRIPECONNECT_SHARED_SECRETest automatiquement généré à l'installation et sert à signer les requêtes vers l'API distante via HMAC-SHA256.
5. Flux de paiement complet
Le parcours de paiement se déroule en 5 étapes :
┌─────────────────────────────────────────────────────────────────────────┐
│ FLUX DE PAIEMENT │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Le client choisit "Payer par Carte Bancaire (Stripe Connect)" │
│ └──► hookPaymentOptions() affiche l'option │
│ │
│ 2. Redirection vers payment.php │
│ ├── Construit le payload (id_cart, amount, currency, affiliate_id) │
│ ├── Signe le payload avec HMAC-SHA256 (shared_secret) │
│ └── Envoie le payload à l'API distante (create-checkout.php) │
│ │
│ 3. L'API distante crée une Stripe Checkout Session │
│ └── Renvoie l'URL de checkout (checkout_url) │
│ │
│ 4. Le client paie sur la page Stripe Checkout │
│ ├── Succès ──► Redirigé vers validation.php (url_success) │
│ └── Annulation ──► Redirigé vers le panier (url_cancel) │
│ │
│ 5a. webhook.php reçoit l'événement Stripe (serveur à serveur) │
│ ├── Vérifie la signature Stripe (whsec_) │
│ ├── Crée la commande via validateOrder() │
│ └── Enregistre l'affilié si applicable │
│ │
│ 5b. validation.php attend que la commande existe (polling) │
│ ├── Tente 5 fois avec 2s d'intervalle (max 10s) │
│ ├── Commande trouvée ──► Redirection page confirmation │
│ └── Non trouvée ──► Redirection historique commandes │
│ │
└─────────────────────────────────────────────────────────────────────────┘
6. Contrôleurs Front-Office
6.1 payment.php — Initiation du paiement
Classe : StripeconnectPaymentModuleFrontController
URL : {base_url}/module/stripeconnect/payment
Responsabilité
Prépare et envoie les données du panier à l'API distante pour créer une session Stripe Checkout.
Payload envoyé à l'API
{
"id_cart": 12345,
"amount_total": 196.00,
"currency": "eur",
"affiliate_id": 1,
"url_success": "https://shop.com/module/stripeconnect/validation?id_cart=12345&key=abc123",
"url_cancel": "https://shop.com/commande?step=3"
}
Points importants
- Montant : Envoyé en format décimal (ex :
196.00), pas en centimes. L'API distante gère elle-même la conversion en centimes pour Stripe. - Signature : Le payload JSON est signé via
hash_hmac('sha256', $json_payload, $shared_secret)et envoyé dans le headerX-SHARED-TOKEN. - Affilié : L'ID affilié est récupéré depuis la table
stripeconnect_affiliate_producten se basant sur le premier produit du panier qui a un affilié associé. - SSL : La vérification SSL est désactivée (
CURLOPT_SSL_VERIFYPEER = false). A activer en production. - Timeout : 15 secondes pour la requête cURL.
Gestion d'erreurs
| Situation | Comportement |
|---|---|
| Panier vide ou invalide | Redirection vers la page de commande |
| Erreur cURL | Log via PrestaShopLogger + redirection panier |
| Erreur API (HTTP != 200) | Notification utilisateur + redirection panier |
6.2 validation.php — Retour client
Classe : StripeconnectValidationModuleFrontController
URL : {base_url}/module/stripeconnect/validation?id_cart={id}&key={secure_key}
Responsabilité
Gère le retour du client après le paiement sur Stripe. Attend que le webhook ait créé la commande, puis redirige.
Mécanisme de polling
La commande est créée de manière asynchrone par le webhook. Ce contrôleur implémente un système de polling :
Tentative 1 ──► Order::getOrderByCartId() ──► Non trouvée ──► sleep(2s)
Tentative 2 ──► Order::getOrderByCartId() ──► Non trouvée ──► sleep(2s)
Tentative 3 ──► Order::getOrderByCartId() ──► Trouvée ! ──► Redirection confirmation
- Maximum : 5 tentatives
- Intervalle : 2 secondes
- Durée totale max : ~10 secondes
Redirections
| Résultat | Destination |
|---|---|
| Commande trouvée | Page de confirmation (order-confirmation) |
| Commande non trouvée après 10s | Historique des commandes (history) |
| Paramètres manquants | Page de commande (order) |
| Secure key invalide | Template d'erreur du module |
6.3 webhook.php — Confirmation serveur-à-serveur
Classe : StripeconnectWebhookModuleFrontController
URL : {base_url}/module/stripeconnect/webhook
Responsabilité
Reçoit les événements webhook directement de Stripe, vérifie leur authenticité, et crée ou met à jour les commandes dans PrestaShop.
Flux de traitement
1. Réception du payload brut (php://input)
2. Vérification de la signature Stripe (Stripe\Webhook::constructEvent)
3. Décodage JSON et extraction des données
4. Validation des données minimales (id_cart, transaction_id, amount)
5. Chargement du panier PrestaShop
6. Création ou mise à jour de la commande
7. Enregistrement de l'affilié (si applicable)
Données extraites du webhook
| Champ | Source | Description |
|---|---|---|
id_cart |
metadata.id_cart |
ID du panier PrestaShop |
transaction_id |
id ou payment_intent |
Identifiant de transaction Stripe |
amount |
amount_total ou amount |
Montant (divisé par 100) |
currency_iso |
currency |
Code ISO de la devise |
affiliate_id |
metadata.affiliate_id |
ID de l'affilié |
Codes de réponse HTTP
| Code | Situation |
|---|---|
| 200 | Webhook traité avec succès |
| 400 | Payload invalide ou données incomplètes |
| 403 | Signature Stripe manquante ou invalide |
| 404 | Panier introuvable en base |
| 500 | Erreur interne lors de la création de commande |
Format de réponse
Succès :
{
"status": "success",
"id_order": 789,
"affiliate_tracked": true,
"message": "Webhook traité avec succès"
}
Erreur :
{
"status": "error",
"message": "Signature Stripe invalide. Vérifiez votre whsec_"
}
Événements Stripe gérés
| Événement | Comportement |
|---|---|
checkout.session.completed |
Création de la commande |
account.updated |
Accusé de réception simple (pas de commande) |
Note : Si une commande existe déjà pour le panier, le webhook met simplement à jour le statut vers
PS_OS_PAYMENT(paiement accepté).
7. Gestion des affiliés
Principe
Chaque produit peut être associé à un affilié via un onglet dédié dans la fiche produit du Back-Office. Lors du paiement, l'ID de l'affilié est transmis à l'API distante pour permettre le split payment via Stripe Connect.
Assignation produit-affilié
- Onglet Back-Office : Hook
displayAdminProductsExtraaffiche un sélecteur d'affilié sur chaque fiche produit - Sauvegarde : Hook
actionProductUpdateenregistre l'association dans la tablestripeconnect_affiliate_product
Logique de récupération
Lors du paiement, le module parcourt les produits du panier et utilise le premier affilié trouvé :
foreach ($products as $product) {
$id_affiliate = $this->module->getAffiliateIdByProduct($product['id_product']);
if ($id_affiliate) {
$affiliate_id = (int)$id_affiliate;
break; // Premier affilié trouvé = affilié utilisé
}
}
Limitation actuelle : Un seul affilié est pris en compte par panier, même si plusieurs produits sont associés à des affiliés différents.
Enregistrement post-commande
Après la création de la commande par le webhook, l'affiliate_id est enregistré directement dans la table orders :
UPDATE ps_orders SET affiliate_id = '{affiliate_id}' WHERE id_order = {id_order}
Prérequis : La colonne
affiliate_iddoit exister dans la tableps_orders.
8. Sécurité
Signature des requêtes vers l'API distante
Les appels depuis payment.php vers l'API distante sont signés avec HMAC-SHA256 :
$signature = hash_hmac('sha256', $json_payload, $shared_secret);
// Envoyé dans le header : X-SHARED-TOKEN
Le shared_secret est généré automatiquement à l'installation (32 caractères aléatoires) et doit être configuré de manière identique côté API distante.
Vérification des webhooks Stripe
Le webhook.php utilise la bibliothèque officielle Stripe PHP pour valider la signature :
\Stripe\Webhook::constructEvent($payload, $sig_header, $webhookSecret);
Cela garantit que seuls les événements provenant réellement de Stripe sont traités.
Vérification d'identité client
Le validation.php vérifie le secure_key du client PrestaShop pour empêcher l'accès non autorisé à la page de confirmation.
Points d'attention
| Risque | Statut | Recommandation |
|---|---|---|
| SSL Verify Peer désactivé | CURLOPT_SSL_VERIFYPEER = false |
Activer en production |
| Injection SQL (affiliate) | Protégé via pSQL() et (int) |
OK |
| CSRF sur webhook | Protégé via signature Stripe | OK |
| Shared Secret en clair | Stocké dans ps_configuration |
Acceptable |
9. Base de données
Table créée par le module
{prefix}stripeconnect_affiliate_product
| Colonne | Type | Description |
|---|---|---|
id_stripeconnect_affiliate_product |
INT(10) UNSIGNED AUTO_INCREMENT |
Clé primaire |
id_product |
INT(10) UNSIGNED |
ID du produit (unique) |
affiliate_id |
INT(10) UNSIGNED |
ID de l'affilié |
Index : UNIQUE KEY sur id_product (un produit ne peut avoir qu'un seul affilié).
Modification de table existante requise
La colonne affiliate_id doit être ajoutée manuellement à la table ps_orders :
ALTER TABLE `ps_orders` ADD `affiliate_id` VARCHAR(64) DEFAULT NULL;
10. Hooks PrestaShop utilisés
| Hook | Fichier | Description |
|---|---|---|
paymentOptions |
stripeconnect.php |
Affiche l'option de paiement Stripe Connect au checkout |
paymentReturn |
stripeconnect.php |
Enregistré mais non implémenté explicitement |
displayAdminProductsExtra |
stripeconnect.php |
Affiche l'onglet affilié sur la fiche produit admin |
actionProductUpdate |
stripeconnect.php |
Sauvegarde l'association produit-affilié |
11. Dépannage
Problèmes courants
Le paiement ne se lance pas
- Vérifier que la Publishable Key est renseignée (condition d'affichage du hook
paymentOptions) - Vérifier que l'URL de l'API est correcte et accessible
- Vérifier les logs PrestaShop pour des erreurs cURL
Erreur 403 sur le webhook
- Cause probable : Le
STRIPECONNECT_WEBHOOK_SECRET(whsec_...) ne correspond pas à celui configuré dans le Dashboard Stripe - Solution : Copier le secret depuis Stripe Dashboard > Developers > Webhooks et le coller dans la configuration du module
La commande n'est pas créée
- Vérifier que le webhook Stripe pointe vers :
{base_url}/module/stripeconnect/webhook - Vérifier que le serveur est accessible depuis Internet (pas de firewall bloquant)
- Vérifier les logs :
PrestaShopLoggerenregistre toutes les erreurs webhook
Le client voit la page "Historique des commandes" au lieu de la confirmation
- Cause : Le webhook n'a pas encore créé la commande dans les 10 secondes de polling
- Vérifications :
- Le webhook est-il bien configuré dans Stripe ?
- Y a-t-il des erreurs dans les logs du webhook ?
- Le serveur est-il lent (latence > 10s) ?
Montant incorrect
- Rappel : Le
payment.phpenvoie le montant en format décimal (ex :196.00), pas en centimes. L'API distante se charge de la conversion. - Le
webhook.phpreçoit le montant en centimes de Stripe et le divise par 100.
Logs
Toutes les erreurs sont enregistrées via PrestaShopLogger::addLog() avec un niveau de sévérité 3 (erreur) ou 2 (avertissement). Consultez-les via :
Back-Office > Paramètres avancés > Logs
Document généré le 09/02/2026 — Module Stripe Connect v1.0.3