# Stripe → Facture électronique (Factur-X / SUPER PDP)

Connecteur **PHP sans dépendance** qui rend vos factures Stripe (abonnements récurrents, factures ponctuelles, avoirs)
conformes à la réforme française de la facturation électronique, en passant par la plateforme agréée **SUPER PDP**.

```
Stripe (webhook) ──▶ connecteur (votre hébergement) ──▶ Factur-X (PDF/A-3 + XML EN 16931) ──▶ SUPER PDP ──▶ client / administration
                                   ▲                                                             │
                                   └──────────────── statuts, encaissements, factures reçues ◀────┘
```

* **Émission** : chaque facture finalisée dans Stripe est transformée en Factur-X (profil EN 16931, règles françaises
  BR-FR « Flux 2 »), archivée, puis transmise à SUPER PDP qui l'achemine au client (B2B) et à l'administration (e-reporting).
* **Encaissement** : quand Stripe confirme le paiement, le statut « Encaissée » (fr:212) est transmis — c'est ce qui sert
  à l'e-reporting des données de paiement (prestations de services).
* **Avoirs** : les avoirs Stripe sont émis en tant qu'avoirs électroniques (type 381) référençant la facture d'origine.
* **Réception** : les factures de vos fournisseurs arrivées sur SUPER PDP sont récupérées, archivées et notifiées par e-mail.
* **Tableau de bord** : suivi des statuts, relances, qualification des clients, factures reçues.

Vos abonnements et votre encaissement **restent dans Stripe** : rien ne change pour vos clients.

---

## 1. Prérequis

| Élément | Détail |
|---|---|
| PHP | **8.1 ou plus**, extensions `curl`, `dom`, `libxml`, `pdo_sqlite`, `mbstring`, `openssl`, `json`, `zlib` (standard chez tous les hébergeurs) |
| Hébergement | un domaine en HTTPS, une tâche cron (toutes les 5 à 15 min), ~50 Mo d'espace + vos archives PDF (~0,5 Mo par facture) |
| Stripe | une **clé secrète restreinte** (lecture : factures, clients, avoirs, taux de taxe, produits/prix, abonnements, PaymentIntents/moyens de paiement ; écriture *clients* facultative pour qualifier un client depuis le tableau de bord) et un **webhook** |
| SUPER PDP | un compte ([superpdp.tech](https://www.superpdp.tech)), l'entreprise vérifiée (KYB), une **application** (client_id / client_secret) et une ligne d'annuaire pour recevoir |

Aucune installation Composer : téléversez les fichiers, c'est tout.

## 2. Installation

1. **Copier les fichiers** sur votre hébergement, de préférence **hors de la racine web**, en n'exposant que le dossier `public/` :

   ```
   /home/monsite/einvoice/          ← l'application (src/, bin/, config/, storage/, resources/…)
   /home/monsite/www/einvoice/      ← contenu de public/ (stripe-webhook.php, admin/)
   ```
   Si vous ne pouvez exposer qu'un seul dossier, déposez tout sous le web : les `.htaccess` fournis interdisent l'accès
   direct à `storage/`, `config/`, `src/`, `bin/`, `tests/`, `resources/` (Apache). Adaptez pour nginx le cas échéant.

2. **Configurer** : copiez `config/config.example.php` en `config/config.php` et renseignez au minimum :
   * `seller.*` : raison sociale, **SIREN**, n° de TVA, adresse, e-mail, mentions légales ;
   * `stripe.secret_key` et `stripe.webhook_secret` ;
   * `superpdp.client_id` / `superpdp.client_secret` ;
   * `mail.to` / `mail.from` (notifications) ;
   * `admin.password_hash` : `php -r "echo password_hash('votre-mot-de-passe', PASSWORD_DEFAULT);"`.

   Si vous déplacez `public/`, ajustez dans les deux fichiers `public/stripe-webhook.php` et `public/admin/index.php`
   la ligne `require dirname(__DIR__) . '/src/bootstrap.php';` vers le bon chemin.

3. **Droits** : `storage/` doit être accessible en écriture par PHP (`chmod 770` ou 750 selon l'hébergeur).

4. **Vérifier** :
   ```bash
   php bin/check-setup.php
   ```
   Tout doit être `[OK]` (le statut SUPER PDP doit être `verified`).

5. **Webhook Stripe** : Dashboard → Développeurs → Webhooks → *Ajouter un point de terminaison* :
   * URL : `https://votre-domaine/einvoice/stripe-webhook.php`
   * Événements : `invoice.finalized`, `invoice.paid`, `invoice.voided`, `invoice.marked_uncollectible`,
     `credit_note.created`, `credit_note.voided`
   * Copiez le **secret de signature** (`whsec_…`) dans `stripe.webhook_secret`.

6. **Cron** (indispensable : traitement de la file, statuts, factures reçues) :
   ```
   */10 * * * *  /usr/bin/php /home/monsite/einvoice/bin/cron.php >> /home/monsite/einvoice/storage/logs/cron.log 2>&1
   ```

7. **Tableau de bord** : `https://votre-domaine/einvoice/admin/` (identifiant `admin.user`, mot de passe choisi).

## 3. Tester avant la production (bac à sable)

SUPER PDP fournit un environnement de test avec des entreprises fictives ; Stripe a son mode test.

```bash
php tests/run.php                      # tests hors ligne du connecteur (aucun réseau)
php bin/preview.php --demo             # génère un Factur-X de démonstration (XML + PDF) sans rien envoyer
php bin/validate-file.php /tmp/einvoice-preview/DIGI-2026-0042.pdf   # validateur officiel SUPER PDP (schematrons)
php bin/send-invoice.php in_XXXX --dry-run   # génère la facture Stripe in_XXXX sans l'envoyer (storage/out)
php bin/send-invoice.php in_XXXX             # émission réelle (dans l'environnement configuré)
```

Parcours conseillé : compte SUPER PDP en bac à sable + clé Stripe **test** → finalisez une facture d'abonnement
test → vérifiez dans le tableau de bord et sur SUPER PDP → basculez les identifiants en production.

## 4. Comment sont qualifiés vos clients

Le connecteur détermine pour chaque facture le **traitement** (note `BAR`) attendu par la réforme :

| Traitement | Quand | Adresse électronique (BT-49) |
|---|---|---|
| **B2B** – pro français | SIREN trouvé : métadonnée `siren`, ou n° de TVA FR (`eu_vat`) sur le client/la facture | SIREN, schéma `0225` (annuaire) |
| **B2BINT** – pro étranger | pays ≠ FR et n° de TVA étranger, ou métadonnée | e-mail (`EM`) |
| **B2C** – particulier | métadonnée `einvoice_kind=B2C` (ou réglage `outbound.default_kind_without_ids=B2C`) | e-mail (`EM`) |
| **REVIEW** | aucun identifiant : la facture est mise **en attente** (tableau de bord + e-mail) | — |

Métadonnées Stripe reconnues (sur le **client**, ou sur la facture qui prime) :

* `einvoice_kind` = `B2B`, `B2C`, `B2BINT` ou `SKIP` (ne pas émettre)
* `siren` (9 chiffres) — ou `siret`, ou `vat_number`
* `einvoice_address` / `einvoice_address_scheme` : adresse d'annuaire spécifique (ex. `853322915_COMPTA`)
* `buyer_reference` (BT-10), `purchase_order` (BT-13), `legal_name`

Conseil : renseignez une fois pour toutes sur chaque client Stripe son **n° de TVA** (champ « ID fiscal », type TVA UE)
ou la métadonnée `siren` ; les particuliers reçoivent `einvoice_kind=B2C`. Les associations **non assujetties** à la TVA
se traitent comme des particuliers (`B2C`) : elles n'ont pas de plateforme de réception.
Le tableau de bord permet de qualifier un client directement (écrit la métadonnée dans Stripe).

## 5. Ce qui est généré

* **XML CII** au profil Factur-X EN 16931 (`urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:en16931`), avec les
  spécificités françaises : cadre de facturation BT-23 (`S1` prestations de services — modifiable), SIREN vendeur/acheteur
  (schéma `0002`), adresses électroniques (`0225`), mentions obligatoires PMT / PMD / AAB (frais de recouvrement,
  pénalités, escompte), note `BAR`, mention `TXD` en cas d'exonération, taux de TVA admis (BR-FR-16).
* **PDF/A-3b** lisible (mise en page française, polices embarquées, profil ICC sRGB) avec le XML `factur-x.xml`
  attaché (`AFRelationship /Data`) et les métadonnées XMP Factur-X — ou XML seul (`outbound.format = 'cii'`).
* Les fichiers sont archivés dans `storage/out/AAAA/MM/` (facture-N°.pdf / .xml) ; les factures reçues dans `storage/in/`.

Montants : le connecteur recalcule les totaux EN 16931 à partir des lignes Stripe (remises → remises de ligne BT-136,
TVA par taux, arrondi BT-114) et **refuse d'émettre** si le total s'écarte de celui de Stripe (facture mise en révision).
Facture déjà payée à l'émission : elle est émise normalement (cadre S1) puis le statut « Encaissée » suit aussitôt —
c'est le fonctionnement recommandé par SUPER PDP.

## 6. Exploitation au quotidien

* **Tableau de bord › Émises** : statut de chaque document (transmise, acceptée, rejetée, à vérifier…), dernier statut
  de cycle de vie reçu, PDF/XML, actions : ré-émettre, déclarer l'encaissement, qualifier le client, créer l'avoir d'annulation.
* **Reçues** : factures fournisseurs (PDF lisible, original, JSON), envoi des statuts acheteur (prise en charge, approuvée,
  paiement transmis, refusée avec motif).
* **File** : travaux en attente / en erreur, relance ou annulation. Les erreurs temporaires sont rejouées
  automatiquement (5 min, 10, 20 … jusqu'à 24 h, 8 tentatives) ; les refus définitifs (4xx) passent en révision avec le message.
* **Système** : compteurs, derniers identifiants synchronisés, journal du jour (`storage/logs/app-AAAA-MM-JJ.log`).
* **Facture annulée dans Stripe après transmission** : une facture électronique transmise ne s'annule pas — le tableau
  de bord propose de générer un **avoir d'annulation** intégral (n° `FACTURE-AV1`) référençant la facture.
* **Notifications e-mail** : facture en attente de qualification, document refusé/rejeté, nouvelle facture reçue,
  annulation après transmission.

## 7. Scripts

| Commande | Rôle |
|---|---|
| `php bin/cron.php` | file d'émission + synchronisation des statuts et des factures reçues (à planifier) |
| `php bin/check-setup.php [--offline]` | diagnostic complet |
| `php bin/send-invoice.php in_… [--dry-run] [--force] [--payment] [--cancel]` | émission manuelle / test / encaissement / avoir d'annulation |
| `php bin/preview.php <json> \| --demo [dossier]` | aperçu XML + PDF hors ligne |
| `php bin/validate-file.php <pdf\|xml> [--local]` | validation XSD locale et validateur officiel SUPER PDP |
| `php tests/run.php` | suite de tests (33 scénarios, sans réseau) |

## 8. Sécurité

* Le webhook vérifie la **signature Stripe** (HMAC, tolérance 5 min) et ignore les doublons.
* Le tableau de bord est protégé par mot de passe (HTTP Basic) + jeton anti-CSRF ; servez-le en HTTPS et, si possible,
  restreignez-le par IP.
* Les secrets sont dans `config/config.php` (hors racine web ou protégé par `.htaccess`).
* Utilisez une clé Stripe **restreinte** en lecture. Le jeton d'accès SUPER PDP (valable 30 min) est mis en cache dans
  la base SQLite locale (`storage/db/`) : protégez ce dossier comme la configuration.

## 9. Limites connues et points d'attention

* Une seule catégorie / un seul taux de TVA par ligne Stripe (cas standard). Les prix « TVA incluse » sont gérés par
  recalcul, mais les prix **hors taxes** restent recommandés.
* Taux de TVA étrangers (OSS, ventes à des particuliers de l'UE) : signalés et mis en révision (hors champ du Flux 2).
* Le e-reporting des **achats** internationaux (B2Bi achats) et des ventes sans facture (caisse) n'est pas géré :
  ils se déclarent directement sur SUPER PDP.
* Les règles métier complètes (schematrons EN 16931 + BR-FR) sont vérifiées en partie localement et **intégralement par
  le validateur SUPER PDP** (`bin/validate-file.php`) : faites-le sur quelques factures avant la mise en production.
* Les textes des mentions légales (pénalités, indemnité de 40 €, escompte, exonérations) sont ceux de votre
  configuration : adaptez-les à vos CGV et faites-les relire par votre expert-comptable.
* Le connecteur épingle la version d'API Stripe `2025-02-24.acacia` pour une structure de facture stable ; les objets
  `invoice`/`credit_note` plus récents (structure « basil ») sont gérés en lecture directe mais moins testés.

## 10. Arborescence

```
bin/            scripts CLI (cron, diagnostic, émission manuelle, aperçu, validation)
config/         config.example.php → config.php
public/         stripe-webhook.php, admin/index.php  (seul dossier à exposer)
resources/      XSD Factur-X EN 16931, polices Liberation (OFL), profil ICC sRGB
src/            code (Stripe, Mapping, FacturX, SuperPdp, Services)
storage/        base SQLite, factures émises/reçues, journaux, verrous (écriture requise, non exposé)
tests/          suite de tests + fixtures + doublures
```

---

*Ce connecteur vous a été généré sur mesure ; le code vous appartient. Polices Liberation sous licence SIL OFL 1.1
(resources/fonts/LICENSE-Liberation.txt), profil sRGB du domaine public.*
