Architecture · Stripe · Salesforce

Stripe et Salesforce : architecture d’un middleware de paiement

Stripe maître du paiement, Salesforce de la relation client : identifiants croisés, objets Abonnement et Paiement, sens des flux et ce qui ne doit jamais entrer dans le CRM.

Le besoin

Fil rouge de la série : Acme Assurances, compagnie fictive, vend des contrats à cotisation mensuelle. Les conseillers travaillent dans Salesforce (org acme-demo) ; les paiements et les prélèvements récurrents passent par Stripe.

Sans intégration, chaque paiement se ressaisit à la main dans le CRM, un impayé se découvre trop tard et deux équipes regardent deux vérités différentes. Le but : le conseiller déclenche un paiement depuis Salesforce et y voit, à jour, l’état de chaque abonnement et de chaque facture, sans jamais manipuler une donnée de carte.

Qui est maître de quoi

La règle qui évite la plupart des incohérences : chaque donnée a un seul système maître, les autres n’en détiennent qu’une copie.

DonnéeMaîtreCopie
Client, contrat, conseillerSalesforceStripe (nom, e-mail, métadonnées)
Moyen de paiementStripeAucune (au plus la marque et les 4 derniers chiffres)
Abonnement, échéances, montant prélevéStripeSalesforce (lecture seule)
Facture, paiement, remboursementStripeSalesforce (lecture seule)

Conséquence directe : on ne modifie jamais un statut de paiement dans Salesforce. Un conseiller qui veut résilier ou rembourser déclenche une action qui passe par Stripe, et le nouveau statut revient par webhook.

Le modèle de données croisé

Chaque objet porte l’identifiant de son équivalent dans l’autre système. Côté Salesforce, les identifiants Stripe sont des champs External ID uniques : ils servent de clé d’upsert et rendent chaque écriture rejouable.

StripeSalesforce (fictif)Clé de liaison
Customer cus_…AccountStripe_Customer_Id__c ; métadonnée Stripe sf_account_id
Subscription sub_…Abonnement__cStripe_Subscription_Id__c ; métadonnée sf_contrat_id
Invoice in_…Paiement__cStripe_Invoice_Id__c
Price price_…Product2 / PricebookEntryStripe_Price_Id__c

Les metadata Stripe (paires clé–valeur libres) portent l’identifiant Salesforce : à la réception d’un événement, le middleware sait à quel compte ou contrat le rattacher sans recherche floue par e-mail.

Les flux

                     ┌──────────────── middleware Symfony ────────────────┐
Salesforce ──(1)──►  │ POST /api/paiements/checkout   → API Stripe        │  ──►  Stripe
(conseiller)         │                                                    │       (paiement,
                     │ POST /webhooks/stripe  ◄── événements signés ──────│  ◄──   abonnement,
Salesforce ◄──(3)──  │ file Messenger → upsert Salesforce (REST / Bulk)   │        facture)
                     └────────────────────────────────────────────────────┘
(1) demande de paiement   (2) le client paie sur la page Stripe   (3) statut écrit dans le CRM
  • Salesforce → Stripe, synchrone et rare : créer un client, ouvrir une session de paiement, résilier. Salesforce appelle le middleware, qui appelle Stripe (article Déclencher un paiement Stripe depuis Salesforce).
  • Stripe → Salesforce, asynchrone et fréquent : chaque changement d’abonnement, chaque facture payée ou en échec arrive en webhook, passe par une file et finit en upsert (articles webhooks et abonnements).
  • Contrôle, chaque nuit : un rapprochement compare les deux côtés et rattrape les événements perdus (article rapprochement).

Pourquoi un middleware plutôt qu’un appel direct de Stripe vers Salesforce ? Stripe ne sait pas s’authentifier en OAuth auprès d’une org, les webhooks doivent être vérifiés et dédoublonnés, et la traduction du modèle Stripe vers le modèle Salesforce a besoin d’un code versionné et testé. C’est le rôle du middleware Symfony décrit dans la série précédente.

Ce qui n’entre jamais dans Salesforce

Le numéro de carte, la date d’expiration, le cryptogramme et l’IBAN complet restent chez Stripe. Le client les saisit sur une page hébergée par Stripe (Checkout) ou dans un composant Stripe Elements : ni Salesforce ni le middleware ne les voient passer, ce qui les maintient hors du périmètre le plus lourd de la norme PCI DSS.

Salesforce reçoit au plus des données d’affichage : marque de la carte, quatre derniers chiffres, date d’expiration pour anticiper un renouvellement. Les notes et commentaires libres des conseillers ne doivent pas non plus recueillir de numéro dicté par téléphone.

Les composants Symfony

  • SDK stripe/stripe-php : client unique déclaré comme service, version d’API figée.
  • Contrôleur de webhook : vérifie la signature et publie un message, rien de plus.
  • Messenger : file dédiée, reprises, transport d’échec.
  • Client Salesforce : jeton OAuth JWT Bearer, upsert par External ID, Bulk API pour le rapprochement.
  • Une petite table locale : événements Stripe déjà traités, pour le dédoublonnage.
# .env — secrets fournis par l'hébergement, jamais committés
STRIPE_SECRET_KEY=sk_test_...          # clé restreinte en production (droits minimaux)
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_API_VERSION=2025-03-31.basil    # exemple ; figée : un changement de version est un chantier testé
# config/services.yaml
services:
    Stripe\StripeClient:
        arguments:
            - api_key: '%env(STRIPE_SECRET_KEY)%'
              stripe_version: '%env(STRIPE_API_VERSION)%'

Bonnes pratiques

  • Deux environnements étanches : clés de test Stripe avec une sandbox Salesforce, clés live avec la production ; jamais de croisement.
  • Clé restreinte : en production, une clé Stripe limitée aux ressources utilisées par le middleware.
  • Montants en centimes : Stripe exprime les montants dans la plus petite unité (4590 = 45,90 €) ; la conversion se fait à un seul endroit.
  • Métadonnées systématiques : tout objet créé par le middleware porte l’identifiant Salesforce correspondant.
  • Pas de logique métier dupliquée : le calcul d’un prorata ou d’une relance reste à Stripe ; Salesforce l’affiche.
🍪 Gestion des cookies
Ce site utilise des cookies pour mesurer l'audience (Google Analytics) et lire des vidéos (YouTube). Vous pouvez personnaliser votre choix.
Mentions légales
Réglages des cookies
Essentiels Nécessaires au fonctionnement du site — ne peuvent pas être désactivés.
Google Analytics Analyse d'audience (pages vues, sources de trafic). Aucune donnée personnelle identifiante.
YouTube Permet de lire les vidéos YouTube intégrées sur cette page.