> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aftersell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Exiger l'acceptation des conditions avant le paiement

> Un cas d'usage du Cart SDK qui ajoute une case à cocher de conditions générales à Aftersell Cart et bloque le paiement jusqu'à ce que le client accepte.

Ajoutez une case à cocher sous le bouton de paiement et empêchez le client de continuer tant qu'il ne l'a pas cochée. Utile pour l'acceptation des conditions, les contrôles d'âge et les confirmations de fabrication sur commande.

<Warning>
  **L'événement `checkout` ne peut pas annuler le paiement.** Il se déclenche comme une notification juste avant que le navigateur ne navigue, donc renvoyer `false` ou appeler `preventDefault` ne fait rien. La seule façon de conditionner le paiement est d'empêcher le bouton de répondre aux clics *avant* qu'il ne soit pressé, ce que montre cette page.

  Considérez cela comme un frein d'interface, pas comme une garantie juridique. Un client déterminé peut toujours atteindre le paiement directement.
</Warning>

<div id="how-it-works">
  ## Fonctionnement
</div>

Trois éléments :

1. Un **bloc de code personnalisé** sous le bouton de paiement affiche la case à cocher.
2. Tant que la case n'est pas cochée, le bloc ajoute une classe aux boutons de paiement et de paiement express du panier via le [shadow root](/fr/aftersell/cart/sdk-overview#shadowroot).
3. Le **CSS personnalisé** fait en sorte que cette classe désactive les clics.

<div id="step-1-add-the-checkbox-block">
  ## Étape 1 : Ajouter le bloc de case à cocher
</div>

Ajoutez un [bloc de code personnalisé](/fr/aftersell/cart/custom-code-blocks) sous votre bloc de bouton Checkout, passez-le en mode **React component**, et collez :

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  const [accepted, setAccepted] = useState(false);

  useEffect(() => {
    const root = window.aftersell?.cart?.shadowRoot;
    if (!root) return;

    const targets = root.querySelectorAll(
      '.cart-external-checkout-button, .cart-external-express-buttons'
    );
    targets.forEach((el) => el.classList.toggle('checkout-gated', !accepted));
  }, [accepted, props.cart]);

  return (
    <div style={{ width: '100%', fontSize: '14px', textAlign: 'center' }}>
      <label style={{ display: 'flex', gap: '6px', justifyContent: 'center', alignItems: 'center' }}>
        <input
          type="checkbox"
          checked={accepted}
          onChange={(e) => setAccepted(e.target.checked)}
        />
        <span>
          I accept the{' '}
          <a href="https://yourstore.com/terms" target="_blank" rel="noopener noreferrer">
            Terms &amp; Conditions
          </a>
        </span>
      </label>
      {!accepted && (
        <div style={{ color: '#c00', fontWeight: 600, marginTop: '6px' }}>
          Please accept the terms above to continue.
        </div>
      )}
    </div>
  );
}
```

Cliquez sur **Compile**, puis activez **"Use custom template"**. Le bloc n'affiche rien tant que vous ne le faites pas.

La dépendance `props.cart` est importante : elle réapplique la classe après un nouveau rendu du panier, qui l'effacerait sinon.

<div id="step-2-add-the-css">
  ## Étape 2 : Ajouter le CSS
</div>

Dans **Cart settings → Custom CSS** :

```css theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
.checkout-gated {
  pointer-events: none !important;
  opacity: 0.5 !important;
}
```

`pointer-events: none` est ce qui bloque réellement le clic ; l'opacité montre simplement au client pourquoi.

<div id="step-3-test-it">
  ## Étape 3 : Tester
</div>

Dans l'[aperçu](/fr/aftersell/cart/previewing-carts), confirmez que :

* Le bouton de paiement est grisé et ne répond pas aux clics au chargement.
* Cocher la case l'active ; la décocher désactive à nouveau le bouton.
* Les boutons de paiement express sont également conditionnés.
* Ajouter ou retirer un article ne réactive pas le bouton tant que la case n'est pas cochée.

Ce dernier point est l'échec le plus courant. Si le bouton se réactive après un changement du panier, l'effet ne se réexécute pas. Vérifiez que `props.cart` figure dans le tableau de dépendances.

<div id="tracking-who-accepted">
  ## Suivre qui a accepté
</div>

La case à cocher est un état limité au navigateur ; elle n'atteint jamais la commande. Pour enregistrer l'acceptation, apposez-la sur chaque ligne comme propriété au moment de l'ajout au panier :

```html theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
<input type="hidden" name="properties[_terms_version]" value="2026-01">
```

Ajoutez ceci à votre formulaire produit dans le thème. Shopify lit `properties[...]` directement depuis le formulaire, donc la valeur parvient à la commande quel que soit celui qui effectue l'ajout : Aftersell, le thème ou une autre application.

Une propriété préfixée par `_` reste invisible sur la ligne côté acheteur mais atteint quand même Shopify, elle apparaît donc sur la commande. Cela enregistre *quelle* version des conditions était en vigueur, pas que le client a coché la case.

<div id="things-to-get-right">
  ## Points à ne pas manquer
</div>

* **Ne ciblez que les classes `cart-external-*`.** Les jumelles `cart-internal-*` sont la tuyauterie interne du panier, pas une prise pour votre code. Voir [CSS personnalisé](/fr/aftersell/cart/custom-css).
* **Vérifiez que `shadowRoot` existe** avant de l'utiliser. Il vaut `undefined` jusqu'au démarrage du panier.
* **Le bloc n'affiche rien tant que le panier n'est pas chargé**, donc le bouton de paiement n'est jamais brièvement actif avant l'application du verrou.
* **Un bloc React qui lève une exception n'affiche rien** et le reste du panier continue, ce qui signifie ici un bouton de paiement non protégé. Testez dans l'aperçu avant de publier.

<div id="where-to-go-next">
  ## Où aller ensuite
</div>

* **[Blocs de code personnalisés](/fr/aftersell/cart/custom-code-blocks)** : le mode React et ses props.
* **[CSS personnalisé](/fr/aftersell/cart/custom-css)** : la convention de classes publiques.
* **[Événements](/fr/aftersell/cart/sdk-events#checkout)** : ce que l'événement `checkout` peut faire et ne pas faire.
