En vous promenant sur Beamreactor, nous stockons votre IP 48h pour des raisons de sécurité.

Markdown Reader

payment Documentation › PAYMENT_DOCUMENTATION_FR

Payment Documentation Fr

Plugin : Payment #

Page de retour de paiement (succès, annulation, attente). Réceptionne l'utilisateur après checkout Stripe / PayPal / virement / chèque, vérifie le statut, affiche la confirmation et envoie l'email récapitulatif.

Rôle

Le plugin payment n'initie aucun paiement — il reçoit les retours :

| Provider | URL de retour | Action |

|----------|---------------|--------|

| Stripe | ?obj=payment.php&order=NUM&session_id=cs_... | Vérification synchrone de la session, marque l'order paid si Stripe confirme |

| PayPal | ?obj=payment.php&order=NUM&token=... | Capture du paiement via Payment::handleCallback('paypal', …) |

| Virement | ?obj=payment.php&order=NUM | Affiche IBAN/BIC + référence commande |

| Chèque | ?obj=payment.php&order=NUM | Affiche l'adresse postale + libellé |

| Annulation | ?obj=payment.php&action=cancel&order=NUM | Restaure le panier, redirige vers products_checkout.php |

L'initiation des paiements est gérée en amont par products_checkout (panier classique), abo_checkout (premier abonnement) et reabo_checkout (réabonnement).

Architecture HT / TTC

| Couche | Format |

|--------|--------|

| products.price, products.subscription_price (DB) | HT |

| order_items.unit_price_ht, unit_price_recurring_ht (DB) | HT |

| Affichage utilisateur (panier, fiche, paiement) | TTC |

| API Stripe/PayPal unit_amount (cents) | TTC (calculé via vat_rate) |

| Saisie admin éditeur | TTC via toggle (mais stocké HT) |

| B2B VIES zero-rated | passer vat_rate=0 au moment du checkout |

Tous les montants envoyés aux providers sont calculés via bcmul(number_format(HT × (1 + vat/100), 2, '.', ''), '100', 0) pour éviter les arrondis flottants.

Flux Stripe — vérification synchrone au retour

Stripe redirige sur success_url avant que le webhook n'ait toujours fini de traiter. Sans vérification synchrone, l'utilisateur voyait "paiement en cours de traitement" alors que tout était OK.

text
Stripe Checkout → success_url (payment.php?session_id=...)
        ↓
payment.php : Payment::verifySession('stripe', $sessionId, $orderId)
        ↓
PaymentStripe::verifySession()
   GET /v1/checkout/sessions/{id}
   Vérifie : status='complete' ET payment_status IN ('paid','no_payment_required')
        ↓
Si OK → Payment::updateStatus($orderId, 'paid', $paymentIntent, 'Stripe session verified on return')
        ↓
Affichage de la confirmation

Le webhook reste la source de vérité de secours (idempotent grâce à Payment::updateStatus). Si la vérification synchrone échoue (réseau, Stripe lent), le webhook prendra le relais et l'utilisateur verra "en cours de traitement" puis pourra rafraîchir.

Affichage du total avec abonnement

Pour les commandes mixtes (produits one-time + abonnement), orders.total_ttc ne contient que la part one-time. Le premier versement de l'abonnement est facturé par Stripe via une line_item séparée.

L'affichage calcule donc :

php
$paidTodayTtc = (float)$order['total_ttc'] + $recurringTtc;

avec $recurringTtc = Σ (unit_price_recurring_ht × (1 + vat_rate/100) × quantity) sur les order_itemsis_subscription = 1.

Trois lignes affichées :

  • Total payé aujourd'hui : $paidTodayTtc
  • Dont produits : $order['total_ttc']
  • Dont premier versement abonnement : $recurringTtc
  • Puis : $recurringTtc / mois (récurrence)

Email de confirmation

Envoyé une seule fois par commande (flag orders.email_sent). Contient :

  • Récapitulatif lignes (nom, qty, ligne TTC)
  • Sous-total HT + TVA + total TTC
  • Adresses facturation/livraison
  • Instructions virement/chèque si applicable
  • Référence transaction Stripe/PayPal si applicable

Expédition via mail() natif PHP, expéditeur $cfg[34]['headoffice_name'] <$cfg[11]['commercial']>.

Annulation

Si ?action=cancel ET payment_status='unpaid' :

1. Récupère les order_items de l'order

2. Vide le panier courant (Panier::vider())

3. Réinjecte les items (Panier::ajouterProduit(productId, quantity))

4. Marque l'order failed via Payment::updateStatus(..., 'failed', ..., 'Payment cancelled by user')

5. Redirige vers products_checkout.php

Même logique si l'utilisateur revient sur payment.php avec un order déjà en failed (recovery panier).

Webhook — `handlers/payment.mod.php`

Endpoint : ?obj=payment.mod.php&method=stripe (ou paypal)

text
POST raw payload
  ↓
$rawPayload = file_get_contents('php://input')
$method     = $_GET['method']
  ↓
Payment::handleCallback($method, ['_raw'=>…, '_headers'=>…, 'event'=>…])
  ↓
Provider vérifie signature + traite l'event
  ↓
HTTP 200 {status:ok} | 400 {status:error}

Stripe et PayPal doivent être configurés dans leurs dashboards respectifs avec ces URLs :

  • https://shop.example.com/index.php?obj=payment.mod.php&method=stripe
  • https://shop.example.com/index.php?obj=payment.mod.php&method=paypal

Configuration `cog.php`

| Indice | Rôle |

|--------|------|

| $cfg[34] | Coordonnées société (nom, adresse, SIRET) — utilisées dans l'email |

| $cfg[35] | IBAN / BIC pour les virements |

| $cfg[36] | Stripe : public_key, secret_key, webhook_secret, mode |

| $cfg[37] | PayPal : client_id, client_secret, webhook_id, mode |

| $cfg[38] | Chèque : order_to (destinataire du chèque) |

| $cfg[11]['commercial'] | Email expéditeur des confirmations |

Dépendances

  • Beamreactor\Database\SQL
  • Beamreactor\Payment\Payment — façade publique (processSubscription, verifySession, handleCallback, updateStatus, getInstructions)
  • Beamreactor\Payment\PaymentStripe, PaymentPaypal, PaymentVirement, PaymentCheque — handlers concrets, autoloadés par Payment::loadHandler() (include explicite, pas par namespace)
  • Beamreactor\Shop\Panier — restauration panier sur annulation/échec
  • Beamreactor\Sanitizer\Parser — sanitize des paramètres GET
  • Fonction PHP mail() pour l'envoi de l'email

⚠️ Ne jamais instancier PaymentStripe directement par new \Beamreactor\Payment\PaymentStripe() — la classe n'est pas autoloadée par namespace. Toujours passer par les méthodes statiques de Payment::.

Tables SQL

  • orders : commande principale (payment_status, total_ttc, payment_method, email_sent, …)
  • order_items : lignes commande, dont colonnes abonnement (is_subscription, unit_price_recurring_ht, subscription_billing_anchor, subscription_interval)
  • payment_subscriptions : abonnements actifs Stripe/PayPal (alimentée par les webhooks)

Installation

Déposer le répertoire payment/ dans /plugins/. Aucune migration spécifique. Les tables orders / order_items sont gérées par le module shop principal.

de en fr