# Abonnement Pro

> Les formules gratuite et Pro, leurs limites, comment s’abonner, gérer ou résilier, et comment un opérateur branche Stripe sur son déploiement.

Canonical: https://colis-docs.vercel.app/docs/abonnement · Markdown: https://colis-docs.vercel.app/docs/abonnement.md

Envoyer un fichier reste gratuit, sans compte. La formule Pro est un abonnement, rattaché à un
[compte](https://colis-docs.vercel.app/docs/compte), qui repousse les limites du service ouvert : des fichiers plus gros, des liens
qui durent plus longtemps, plus d’envois par heure. Le paiement passe par Stripe ; ni la page de
livraison ni son opérateur ne voient jamais un numéro de carte.

## Les deux formules

|                       | Gratuite                  | Pro                          |
| --------------------- | ------------------------- | ---------------------------- |
| Taille d’un fichier   | 100 Mo                    | 2 Go                         |
| Durée d’un lien       | 24 h                      | 30 jours                     |
| Envois par heure      | 20, par adresse ou compte | 200, par compte              |
| Prix (service public) | 0 €                       | 6 € par mois, ou 60 € par an |

Ce sont les valeurs par défaut, celles du service public ; un déploiement règle les siennes (voir
[plus bas](#sur-votre-déploiement)). Pas de période d’essai. TVA non applicable, article 293 B du CGI.

Le tableau de bord des envois et la page de livraison à vos couleurs ne font pas encore partie de
la formule.

## S’abonner

**Dans le navigateur.** Connectez-vous, cliquez sur votre adresse en haut de la page : c’est la
page **Mon compte** (`/compte`). Cochez la case qui confirme que vous avez lu les CGV et demandez
que le service commence tout de suite, puis **Passer Pro — 6 €/mois** ou **60 €/an**. Le paiement
se fait sur la page de Stripe ; au retour, la formule Pro s’active dans les secondes qui suivent,
le temps que Stripe prévienne le déploiement.

**Dans un terminal**, une fois connecté avec `colis connexion` :

```sh
colis compte pro            # mensuel
colis compte pro --annuel   # annuel
colis compte                # formule, limites, date de renouvellement
```

La page de paiement s’ouvre dans le navigateur, et son adresse s’affiche dans le terminal.

## Gérer, résilier

**Gérer mon abonnement**, sur la page Mon compte (ou `colis compte gerer`), ouvre l’espace client de
Stripe : changer de carte ou de période, télécharger les factures, résilier.

Une résiliation prend effet à la fin de la période payée : la formule Pro reste active jusque-là,
puis le compte repasse en formule gratuite. Les colis déjà envoyés gardent leur date d’expiration,
même au-delà de 24 h. Si un paiement échoue, Stripe réessaie pendant quelques jours, pendant lesquels
la formule reste Pro ; sans paiement au bout du compte, l’abonnement s’arrête.

## Ce que la formule change à un envoi

Les limites sont vérifiées par le serveur, à chaque envoi, selon la formule du compte qui envoie :
en une requête, au début d’un envoi en morceaux, et pour une nouvelle version. La page ne fait que
les afficher : connecté en Pro, le choix de durée va jusqu’à trente jours et la zone de dépôt
annonce 2 Go.

Sur un déploiement qui vend Pro, un envoi gratuit qui dépasse la taille ou la durée, mais que Pro
accepterait, est refusé en `403 PLAN_LIMIT` :

```json
{
  "error": {
    "code": "PLAN_LIMIT",
    "message": "Une durée de plus de 24 h est réservée à la formule Pro, qui garde un lien jusqu’à 30 jours.",
    "details": { "limit": "expiry", "max": 86400, "pro": 2592000 }
  }
}
```

Au-delà même des limites de Pro, rien ne change : un fichier trop gros reste `413 TOO_LARGE`, une
durée trop longue est ramenée à la plus longue permise. Depuis la CLI, `--expires-in` choisit la
durée d’un envoi vers un serveur, par exemple `colis envoyer ./rush.mov --expires-in 30d`.

## Sur votre déploiement

La formule Pro est facultative. Elle s’active avec quatre variables, en plus des
[comptes](https://colis-docs.vercel.app/docs/compte) (`RESEND_API_KEY` et `COLIS_MAIL_FROM`) : sans l’une d’elles, les routes
de paiement répondent `503 BILLING_DISABLED`, aucun bouton « Passer Pro » n’apparaît, et tout le
reste fonctionne comme avant.

| Variable                    | Rôle                                                                                    |
| --------------------------- | --------------------------------------------------------------------------------------- |
| `STRIPE_SECRET_KEY`         | La clé secrète Stripe, `sk_live_…` (ou `sk_test_…` pour essayer). Jamais dans le dépôt. |
| `STRIPE_WEBHOOK_SECRET`     | Le secret de signature du point de terminaison webhook, `whsec_…`.                      |
| `STRIPE_PRICE_MONTHLY`      | L’identifiant du prix mensuel, `price_…`.                                               |
| `STRIPE_PRICE_YEARLY`       | L’identifiant du prix annuel, `price_…`.                                                |
| `DROP_PRO_MAX_UPLOAD_MB`    | La taille maximale en Pro. `2048` par défaut.                                           |
| `DROP_PRO_MAX_EXPIRES_IN`   | La durée maximale en Pro, en secondes. `2592000` (trente jours) par défaut.             |
| `DROP_PRO_UPLOADS_PER_HOUR` | Les envois par heure et par compte en Pro. `200` par défaut.                            |
| `DROP_PRO_MONTHLY_LABEL`    | Le prix mensuel affiché, `6 €/mois` par défaut. Le montant réel est celui de Stripe.    |
| `DROP_PRO_YEARLY_LABEL`     | Le prix annuel affiché, `60 €/an` par défaut.                                           |
| `DROP_URL`                  | L’adresse publique : les retours de Stripe (`/compte?abonnement=…`) en partent.         |

Les limites de la formule gratuite restent celles du [mode ouvert](https://colis-docs.vercel.app/docs/configuration#le-mode-ouvert)
(`DROP_OPEN_MAX_UPLOAD_MB`, `DROP_OPEN_MAX_EXPIRES_IN`, `DROP_UPLOADS_PER_HOUR`). Les formules ne
jouent qu’en mode ouvert : avec un `DROP_PASSWORD`, les limites du déploiement valent pour tous.

<Callout type="warn">
  Des liens de trente jours demandent une règle de cycle de vie d’au moins 31 jours sur le préfixe des colis (`drop/`) :
  une règle d’un ou deux jours supprimerait des colis Pro encore valides.
</Callout>

### Brancher Stripe

1. **Le produit et ses prix.** Dans Stripe, **Catalogue de produits → Ajouter un produit** :
   « colis Pro », avec deux prix récurrents, 6 € par mois et 60 € par an, en EUR. Notez les deux
   identifiants `price_…` : ce sont `STRIPE_PRICE_MONTHLY` et `STRIPE_PRICE_YEARLY`. N’ajoutez pas
   de période d’essai.
2. **La clé.** **Développeurs → Clés API** : la clé secrète va dans `STRIPE_SECRET_KEY`, dans les
   variables d’environnement de Vercel, jamais dans le dépôt. Une clé restreinte suffit, avec
   l’écriture sur _Checkout Sessions_ et _Customer portal_, et la lecture sur _Subscriptions_.
3. **Le webhook.** **Développeurs → Webhooks → Ajouter un point de terminaison** :
   `https://votre-livraison.vercel.app/api/billing/webhook`, avec quatre événements —
   `checkout.session.completed`, `customer.subscription.created`, `customer.subscription.updated`
   et `customer.subscription.deleted`. Son secret de signature va dans `STRIPE_WEBHOOK_SECRET`.
4. **L’espace client.** **Paramètres → Facturation → Portail client** : activez-le, autorisez la
   résiliation **à la fin de la période de facturation**, la mise à jour du moyen de paiement,
   l’historique des factures, et le changement entre les deux prix du produit.
5. **Les factures.** **Paramètres → Facturation → Factures et reçus** : envoi des factures et des
   reçus par e-mail aux clients, et, dans le pied de page des factures, la mention
   « TVA non applicable, art. 293 B du CGI ». Renseignez aussi les coordonnées de l’entreprise
   (**Paramètres → Informations publiques**), et l’adresse des CGV (`/cgv`) si vous voulez que Stripe
   les affiche.
6. **Essayez en mode test** : des clés `sk_test_…` et un webhook de test sur un déploiement de
   prévisualisation, la carte `4242 4242 4242 4242`, puis `colis compte` pour voir la formule passer
   à Pro, et une résiliation depuis l’espace client pour la voir revenir.

### Comment la formule suit Stripe

- `POST /api/billing/checkout { interval }` ouvre une session Stripe Checkout en mode abonnement.
  Le compte y est inscrit (`client_reference_id` et métadonnées), le client Stripe du compte est
  réutilisé s’il existe, et les adresses de retour sont construites depuis `DROP_URL`, jamais depuis
  l’en-tête `Host`. Depuis le navigateur, la requête doit venir d’une page du déploiement (`Origin`) ;
  un terminal envoie sa session en `Bearer`. Un compte déjà Pro reçoit `409 ALREADY_PRO`.
- `POST /api/billing/portal` ouvre l’espace client Stripe du compte, ou `404 NO_SUBSCRIPTION`.
- `POST /api/billing/webhook` vérifie la signature `Stripe-Signature` sur le corps brut (HMAC-SHA256
  de `t.corps`, chaque `v1` comparé en temps constant, cinq minutes de tolérance) avant de lire quoi
  que ce soit. Puis, quel que soit l’événement, il relit chez Stripe les abonnements du client et en
  déduit la formule : Pro si l’un d’eux, sur l’un des deux prix, est `active`, `trialing` ou
  `past_due` ; gratuite sinon. Un événement reçu deux fois, ou après un plus récent, aboutit donc au
  même état : l’état actuel.
- Le lien entre un client Stripe et un compte s’écrit une fois pour toutes, en création seule, sous
  `accounts/by-customer/<client>` : aucun événement ne peut ensuite rattacher ce client à un autre
  compte. Une session Checkout qui n’a pas été ouverte par le déploiement (sans ses métadonnées,
  comme un lien de paiement) ne rattache rien.
- Le compte garde `plan`, `stripeCustomerId` et `subscription` (`status`, `interval`,
  `currentPeriodEnd`, `cancelAtPeriodEnd`), réécrits par écriture conditionnelle (`If-Match`).
  Au-delà de la fin de la période payée plus trois jours, un compte repasse en gratuit même si
  l’événement de fin s’est perdu.
