Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
372 changes: 372 additions & 0 deletions payment_payplug/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,372 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=========================
Payment Provider: Payplug
=========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8e9ac986b57d3094891d8dc40a31dccf61e1e548b335229055e03dd09c19c5db
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fe--commerce-lightgray.png?logo=github
:target: https://github.com/OCA/e-commerce/tree/19.0/payment_payplug
:alt: OCA/e-commerce
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/e-commerce-19-0/e-commerce-19-0-payment_payplug
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/e-commerce&target_branch=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

Ce module ajoute `Payplug <https://www.payplug.com/>`__ comme
fournisseur de paiement au cadre de paiement d'Odoo (module
``payment``).

Le client est redirigé vers la page de paiement hébergée par Payplug,
puis revient sur Odoo. Le module gère :

- le paiement en ligne sur le site web (panier et validation de
commande) ;
- le paiement des factures depuis le portail client et par lien de
paiement ;
- les notifications serveur de Payplug (paiements et remboursements) ;
- les remboursements totaux et partiels depuis Odoo, et ceux faits
depuis le portail Payplug ;
- les annulations, les échecs et les paiements expirés.

Payplug n'accepte que l'euro : le fournisseur n'est proposé que pour les
paiements en EUR.

Le module appelle directement l'API REST de Payplug avec ``requests`` ;
il ne demande aucune bibliothèque Python supplémentaire.

**Avertissement :** ce module est un développement indépendant. Il n'est
ni affilié à Payplug, ni approuvé par Payplug. « Payplug » est une
marque de son propriétaire.

**Table of contents**

.. contents::
:local:

Installation
============

Le module dépend des modules standard ``payment`` et ``account_payment``
(installés avec la Facturation ou le site e-commerce). Il ne demande
aucune bibliothèque Python supplémentaire.

1. Placez le dossier ``payment_payplug`` dans un chemin d'extensions
(``addons_path``) d'Odoo 19, ou installez le paquet Python construit
avec ``pyproject.toml``.
2. Redémarrez Odoo, mettez à jour la liste des applications, puis
installez *Payment Provider: Payplug*.

Le fournisseur *Payplug* est créé désactivé, pour chaque société.

À la désinstallation, comme pour les fournisseurs standard, Odoo refuse
de continuer si des paiements comptables ont été faits avec Payplug. Un
fournisseur qui n'a que des transactions sans paiement est conservé
(désactivé, sans code) pour garder ces transactions lisibles ; sinon il
est supprimé.

Configuration
=============

**Clés Payplug**

Le module accepte deux méthodes d'authentification, au choix dans le
champ *Authentification* de l'onglet *Identifiants* :

- **Clé API** (par défaut) : la clé secrète du compte est envoyée à
chaque requête ;
- **OAuth2** : Odoo échange un identifiant client (*client ID*) et un
secret client (*client secret*) contre des jetons d'accès valables 5
minutes, demandés et renouvelés automatiquement. Le secret ne circule
que vers le serveur d'autorisation de Payplug.

1. Dans le portail Payplug, à la rubrique des clés d'API, générez une
clé en environnement **Test** et, plus tard, une clé en environnement
**Live** :

- pour la méthode *Clé API*, une clé de type **API Key** (clé
secrète). Les clés actuelles sont des jetons JWT (``eyJ...``) ; les
anciennes clés ``sk_test_...`` et ``sk_live_...`` sont aussi
acceptées ;
- pour la méthode *OAuth2*, une clé de type **OAuth2**. Le portail
affiche son *client ID* et son *client secret* ; notez le secret
aussitôt, il n'est montré qu'une fois.

La clé publique n'est pas utilisée : le module ne passe que par la
page de paiement hébergée.

2. Dans Odoo, ouvrez *Facturation (ou Comptabilité) > Configuration >
Fournisseurs de paiement* et choisissez **Payplug**.

3. Dans l'onglet *Identifiants*, choisissez la méthode
d'authentification, puis collez la clé secrète (*Clé API*) ou le
*client ID* et le *client secret* (*OAuth2*). Seuls les
administrateurs (groupe *Paramètres*) peuvent les lire ou les
modifier.

4. Réglez l'état :

- **Mode test** avec une clé de l'environnement Test : aucun débit
réel ;
- **Activé** avec une clé de l'environnement Live : paiements réels.

Pour une ancienne clé ``sk_...``, Odoo refuse une clé de production
en mode test et une clé de test sur un fournisseur activé. Pour une
clé JWT, l'accord entre le mode et la clé est vérifié à chaque
paiement : un paiement dont le mode ne correspond pas est refusé. En
OAuth2, l'environnement du jeton (*scope* ``test``) est en plus
vérifié à chaque requête : en mode test, seul un jeton de
l'environnement Test est accepté ; sur un fournisseur activé, un
jeton de test est refusé.

Pour passer de Test à Live en OAuth2, remplacez le *client ID* et le
*client secret* par ceux de la clé Live en même temps que vous
activez le fournisseur.

5. Dans l'onglet *Configuration*, vérifiez le journal de paiement et les
moyens de paiement. Par défaut, seul *Carte* (CB, Visa, Mastercard)
est activé. Bancontact, iDEAL et MyBank sont proposés, mais ne les
activez qu'après les avoir fait ouvrir sur votre compte Payplug.

6. Publiez le fournisseur pour qu'il apparaisse sur le site web.

**Adresse de notification (webhook)**

Le module donne à Payplug, pour chaque paiement, l'adresse
``https://<votre-domaine>/payment/payplug/webhook``. Il n'y a rien à
saisir dans le portail Payplug, mais cette adresse doit être joignable
depuis Internet en HTTPS :

- ne la protégez pas par une authentification, un filtrage IP ou une
règle de pare-feu (WAF, fail2ban, Cloudflare…) qui bloquerait les
requêtes POST de Payplug ;
- vérifiez le paramètre système ``web.base.url`` (ou le domaine du site
web) : c'est lui qui sert à construire les adresses de retour et de
notification.

Les retours du client passent par ``/payment/payplug/return`` et
``/payment/payplug/cancel``.

**Jetons d'accès OAuth2**

Un jeton dure 5 minutes ; Odoo le garde en mémoire et en demande un
nouveau une minute avant son expiration. Les jetons ne sont jamais
écrits en base ni dans les journaux ; chaque processus (worker) d'Odoo
demande les siens. Si Payplug refuse un jeton (HTTP 401), Odoo l'oublie,
en demande un autre et renvoie la requête une seule fois. Après une
modification des identifiants, chaque processus demande un nouveau jeton
dès sa requête suivante ; après un changement d'état, le jeton en
mémoire est de nouveau confronté au mode du fournisseur.

**Paramètres système réservés aux tests**

Ils ne servent qu'à pointer vers un faux serveur de test ; ne les créez
pas en production.

- ``payment_payplug.api_base_url`` remplace l'adresse de l'API Payplug
(``https://api.payplug.com/v1/`` par défaut) ;
- ``payment_payplug.token_url`` remplace l'adresse du point d'obtention
des jetons OAuth2 (par défaut ``/oauth2/token`` sur l'hôte de l'API,
soit ``https://api.payplug.com/oauth2/token``) ;
- ``payment_payplug.token_audience`` remplace l'audience demandée pour
les jetons (``https://www.payplug.com`` par défaut).

Usage
=====

**Paiement sur le site web ou depuis le portail**

Le client choisit *Carte* (ou un autre moyen activé), est redirigé vers
la page Payplug, paie, puis revient sur la page d'état du paiement
d'Odoo. La commande ou la facture est confirmée dès qu'Odoo a relu le
paiement auprès de Payplug, soit au retour du client, soit à la
réception de la notification.

Si le client clique sur *Annuler* sur la page Payplug, le paiement est
abandonné chez Payplug et la transaction passe à l'état *Annulée*. Un
paiement refusé passe à l'état *Erreur* avec le motif donné par Payplug
; un paiement jamais terminé est annulé quand Payplug signale son
expiration (environ 15 minutes).

**Remboursement**

Depuis le paiement (*Comptabilité > Clients > Paiements*), ou depuis la
facture via son paiement, cliquez sur *Rembourser* et indiquez le
montant (total ou partiel). Odoo demande le remboursement à Payplug,
crée une transaction de remboursement liée à la transaction d'origine,
puis le paiement comptable négatif correspondant.

Un remboursement fait directement dans le portail Payplug est aussi
enregistré dans Odoo, à la réception de sa notification.

Payplug n'accepte pas de remboursement inférieur à 0,10 €.

**Vérifier une transaction**

Sur une transaction Payplug en attente ou en erreur, le bouton *Vérifier
le statut sur Payplug* relit le paiement auprès de Payplug et met la
transaction à jour (utile si une notification n'a pas pu arriver).

Development
===========

Les tests automatiques (``--test-tags /payment_payplug``) n'appellent
jamais l'API Payplug : ils démarrent un faux serveur Payplug local
(``tests/fake_payplug.py``) et y font pointer le module par le paramètre
système ``payment_payplug.api_base_url``.

Le même faux serveur sert aux essais manuels de bout en bout, avec une
page de paiement factice (boutons *Payer*, *Refuser*, *Annuler*) et
l'envoi des notifications :

.. code:: shell

python3 payment_payplug/tests/fake_payplug.py --host 127.0.0.1 --port 8765

Sur une base de test, créez alors le paramètre système
``payment_payplug.api_base_url`` avec la valeur
``http://127.0.0.1:8765/v1/``, et saisissez une clé quelconque
commençant par ``sk_test_``. ``POST /_control/refund/<id du paiement>``
(corps ``{"amount": 1000}``) simule un remboursement fait depuis le
portail Payplug.

Pour essayer la méthode OAuth2, le faux serveur répond aussi sur
``POST /oauth2/token`` (authentification *Basic*,
``grant_type=client_credentials``, audience ``https://www.payplug.com``)
avec deux clients factices : ``fake_client_test`` /
``fake_client_secret_test`` (jetons de test) et ``fake_client_live`` /
``fake_client_secret_live`` (jetons Live). L'adresse du point de jeton
se déduit de ``payment_payplug.api_base_url`` ; il n'y a rien d'autre à
régler.

Known issues / Roadmap
======================

- Connexion « avec son compte Payplug » (OAuth2 *authorization code* +
PKCE, chemin ``/oauth2/auth``) : hors périmètre. Ce flux demande un
client enregistré par Payplug avec une adresse de rappel ; le module
se limite au flux *client credentials* avec une clé OAuth2 créée dans
le portail.
- Prévu pour une version 3 : paiement en un clic (carte enregistrée),
paiement fractionné, paiement différé, Apple Pay et paiement intégré.
- Paiement en plusieurs fois (Oney 3x/4x) : non pris en charge. Il
demande le panier détaillé (``payment_context``), une autorisation
puis une capture, et des montants entre 100 € et 3 000 €.
- Enregistrement de la carte (jetons) et paiements récurrents : non pris
en charge.
- Capture différée (autorisation puis capture manuelle) : non prise en
charge.
- Apple Pay et le paiement intégré (*Integrated Payment*, champs de
carte dans la page Odoo) : non pris en charge ; seule la page hébergée
est utilisée.
- Les marques de carte renvoyées par Payplug (``card.brand``) ne sont
connues que par la documentation ; à vérifier avec de vraies
transactions de test.
- Satispay, Scalapay et Wero n'ont pas de moyen de paiement
correspondant dans Odoo 19 : ils ne sont pas proposés.

À vérifier avec de vraies clés de test Payplug (non vérifié, faute de
compte) :

- le format exact des notifications (paiement et remboursement), en
particulier la présence de ``payment_id`` dans celles des
remboursements ;
- le code HTTP attendu par Payplug en réponse aux notifications, et s'il
les renvoie après une erreur (le module répond 503 quand il ne peut
pas relire le paiement) ;
- l'acceptation des champs ``billing`` / ``shipping`` envoyés (langue,
téléphone, pays) ;
- l'abandon (``aborted``) d'un paiement quand le client clique sur
*Annuler* ;
- les valeurs de ``card.brand`` (Visa, Mastercard, CB…) ;
- Bancontact, iDEAL et MyBank, qui demandent une activation sur le
compte Payplug ;
- en OAuth2 : la valeur du *scope* des jetons de l'environnement Live
(``live`` est supposé ; une autre valeur est tolérée sur un
fournisseur activé, le mode de chaque paiement restant vérifié).

Changelog
=========

19.0.1.1.0 (2026-10-24)
-----------------------

- Authentification OAuth2 (*client credentials*) au choix, à côté de la
clé API : jetons d'accès de 5 minutes gardés en mémoire et renouvelés
automatiquement, nouvelle demande et renvoi unique de la requête si
Payplug refuse le jeton, contrôle de l'environnement (Test ou Live) du
jeton.

19.0.1.0.0 (2026-10-24)
-----------------------

- Première version : paiement par la page hébergée Payplug,
notifications, remboursements totaux et partiels, paiement des
factures.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/e-commerce/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/e-commerce/issues/new?body=module:%20payment_payplug%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Sébastien Berger (sbinfo67)

Contributors
------------

- Sébastien Berger <contact@sbinfo.pro>

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-sbinfo67| image:: https://github.com/sbinfo67.png?size=40px
:target: https://github.com/sbinfo67
:alt: sbinfo67

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-sbinfo67|

This module is part of the `OCA/e-commerce <https://github.com/OCA/e-commerce/tree/19.0/payment_payplug>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
6 changes: 6 additions & 0 deletions payment_payplug/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright 2026 Sébastien Berger (sbinfo67)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0).

from . import controllers
from . import models
from .hooks import post_init_hook, uninstall_hook
Loading
Loading