Before this commit, the payment providers (e.g., Stripe, Adyen...)
available for payment were displayed on the payment forms. The customer
had to select one to process their payment. After that, the customer had
to select their preferred payment method (e.g., Credit Card,
Bancontact...) from a list of payment methods supported by the selected
provider over which the website administrator had close to no control.
This was making the payment forms confusing because the payment methods
were displayed sometimes more than once, if at all, in a non-controlled
order, and behind the selection of a payment provider that customers
should not have to deal with.
As the payment method was selected in an iframe or directly on the
provider's website, the information on the selection payment method was
not available in Odoo. This posed many problems, among which were the
impossibility of assessing whether a specific feature (e.g.,
tokenization, refunds, manual capture...) was available, not being able
to easily identify payment tokens through the payment method logo,
listing available payment methods on the website, sorting and
fine-grained configuration of the available payment method, subpar
payment method-specific display on the payment form (e.g., PayPal that
requires displaying a "Pay with PayPal" button), etc.
In this commit, the payment providers are thus replaced by the payment
methods on the payment forms. All contextually available (depending on
the country, currency, requested feature...) payment methods are
displayed one after the other on a single-level list and in the order
configured by the website administrator. Each payment method is
"powered by" (i.e., linked) to a single payment provider: the first one,
by model order, to support it. This allows, for example, offering the
PayPal payment method through Mollie, which charges low processing fees,
while also offering Klarna through Stripe, which supports more payment
methods but charges higher processing fees.
While doing so, the two different payment forms, "Checkout" and
"Manage", are also merged together in a new, configurable case-by-case,
payment form that is entirely redesigned to offer a better user
experience.
After payment, the information on the selected payment method is saved
on the transaction and eventual payment record and updated with the
information received from the provider.
task-2882677
closesodoo/odoo#120446
Related: odoo/upgrade#5103
Related: odoo/documentation#5717
Related: odoo/enterprise#40666
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Co-authored-by: Anita (anko) <anko@odoo.com>
Co-authored-by: Brieuc-brd <brd@odoo.com>
Co-authored-by: Valeriya (vchu) <vchu@odoo.com>
In V14, the cardholder name is send, but not in V16.
closesodoo/odoo#130545
X-original-commit: b8d7d1a619c76e3ce0a50e9fc9251a33fc8ca52b
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Prior to this commit, the generation of token aliases in Ogone relied
on the util function `singularize_reference_prefix`, which is intended
to make transaction references (and not token aliases!) more
distinguishable by suffixing a timestamp accurate to the second. That
util function does not guarantee the uniqueness of generated reference
prefixes, which is okay because the final reference is further suffixed
if the prefix happens to collide with an existing reference.
Using the util to generate Ogone's token aliases, however, poses a
problem because aliases *must* be unique. Otherwise, a customer saving a
payment token at the same second as another customer would end up
linking their payment method to the other customer's payment token.
This commit drops the use of the util method and replaces it with a UUID.
closesodoo/odoo#115580
X-original-commit: 61d833ffcd1562950126d3c87c92569fe35a8b08
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Before this commit the neutralize system introduced in v16 was using ORM
methods in order to change appropriate records. Although flexible, this approach
could lead to call some methods with side effects while neutralizing
(eg: overloads of write).
This patch converts the neutralize system to a safer "inert" SQL based approach
by migrating the generic method _neutralize to SQL files exposed in the
data folder.
Task id: 2961687closesodoo/odoo#102792
X-original-commit: e5dbded9bb363351feff7ca8a56c7f8a6860f492
Related: odoo/enterprise#32580
Signed-off-by: Fabien Meghazi <fme@odoo.com>
Changing the name of model payment.acquirer to payment.provider
and everything that it touches. It is technically incorrect to
use the term "acquirer" for systems that only provide a service
of payment.
After this commit the model payment.acquirer and all related to
it will be renamed to payment.provider.
Task - 2842088
closesodoo/odoo#90899
Related: odoo/upgrade#3542
Related: odoo/documentation#1981
Related: odoo/enterprise#27131
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Before this commit, tokens were prefixed with usually 12 X’s. To improve
readability, modernity and to shorten the length, this commit changes
token prefixes to a standard of •••• 1111.
task-2832669
closesodoo/odoo#94978
Related: odoo/upgrade#3738
Related: odoo/enterprise#29190
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Before this commit, zombie payment tokens (= tokens linked to disabled
acquirers) could still
1) be used by internal users and
2) reactivated when the acquirer’s state changed to ‘test’ or ‘enabled’.
This is not desirable because zombie tokens should neither be used,
nor reactivated.
After this commit, all tokens related to an acquirer are unassigned
from linked documents and archived as soon as the acquirer’s state is
changed to ‘disabled’. Creating a payment with an archived token is
prohibited. In addition, archived tokens cannot be un-archived anymore.
task-2649806
closesodoo/odoo#93774
Related: odoo/enterprise#28661
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Computing the fields instead of storing them allows to implement the
feature for each provider more easily, without needing a migration
script.
task-2841744
closesodoo/odoo#91961
Related: odoo/enterprise#27618
Related: odoo/upgrade#3535
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Since odoo/odoo#85759 we are allowed to use other hashing algorithm
with OGONE's payment acquierer.
The V15 fw-port of this PR missed to unlock the max key size.
The goal of this PR is to fix the issue where 32+ length key
were not accepted in V15 and later.
opw-2766648
closesodoo/odoo#90895
X-original-commit: 534d16a6000c603025897bae225e0955317f411f
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Before this commit, most acquirers needed to run several successive
searches for the transaction whose reference was received by a
controller in notification data. This is because the security checks
run on the notification data require access to the acquirer through the
transaction record which was immediately discarded.
Starting with this commit, all `*_feedback_data` method are no longer
decorated with `api.model` and can use the transaction record they're
called on if provided. They are also renamed to `*_notification_data`.
task-2737144
closesodoo/odoo#83850
Related: odoo/enterprise#23938
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
An overridable model method was added in a previous commit in order to
neutralize a database.
This commit introduce the implementation of this method for the payment
modules.
Also, a `_neutralize_fields` helper method is added on the
PaymentAcquirer model to simplify the neutralization of the various
payment modules.
Part-of: odoo/odoo#67825
Notification handling in some acquirers presents a subset of the
following issues:
1. The signature of synchronous notifications (redirect payloads) is not
checked. (Alipay, Authorize, Buckaroo, Mollie, PayU money, PayULatam)
2. When the signature check fails, we raise a ValidationError which
counts as an HTTP 200 for some providers (it's not the case if they
expect a specific string). (Adyen, Paypal, Sips, Stripe)
3. If a ValidationError is raised when processing the feedback data, it
is allowed to bubble up to the provider. (Alipay, Ogone)
The issues are respectively addressed as follows:
1. If the acquirer implements payments with redirection, make sure that
if either makes a request to the provider to validate the data or
that it verifies the signature. Verifying the origin of the request
is not enough: the payload must be checked too.
2. Instead of raising ValidationError's, raise an HTTP 403 FORBIDDEN
error if the signature check fails.
3. Wrap the call to `_handle_feedback_data` of the webhook method inside
a try/except clause to catch any ValidationError, log a warning, and
acknowledge the notification to avoid having the provider disable the
webhook because of too many failures.
task-2688139
task-2693293
closesodoo/odoo#81607
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Co-authored-by: Lucie Van Nieuwenhuyze <luvn@odoo.com>
Before this revision, when a payment was declined,
for instance because the authorization is declined by the bank,
or the credit card amount limit is exceeded,
the error was marked as
"Received data with invalid payment status: 2"
which is not very meaningful for the users.
This revision aims to set the reason why the payment
was declined with the meaningful error from ogone.
closesodoo/odoo#80742
X-original-commit: 758f94a173379ba7bd22813b2050e3a6f98210a9
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
The logs for payments contain the transaction reference whenever possible.
Before logs for transactions contained the reference or the id of the
transaction in an inconsitent way. No transactions are identified by
reference whenever possible.
The logs for payments for the same function on different acquirers should
have the same format. Same flow step for different acquirers had
information passed in different formats. Now at each step of a transaction
flow log messages have the same format regardless of the acquirer.
Overall the payment logs should have an uniform format. Hopefully
understanding log messages related to transactions should be easier, as
now log format is independent of the acquirer and transaction are easily
identified by reference.
Task - 2545450
closesodoo/odoo#79547
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Fix two issues:
The search of suitable payment token was searching on the journal_id
field of the payment acquirer that is no longer stored.
Change it to now search on the acquirer_id directly, since we have
this information.
The _inverse_journal_id method on payment acquirers would create
new payment line with the manual payment method when no provider
are given to an acquirer, or no payment method is existing for
a given provider. This would cause issues with the creation of
multiple line with the same name on a same journal, which would
trigger the constrains blocking that.
closesodoo/odoo#74990
X-original-commit: a3a2fcb0b299fafbf359ec9015da5c85cdb57b3a
Related: odoo/enterprise#20193
Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
Before this commit, the FlexCheckout API was used to process validation
operations only. It proved itself to be:
- unusable without making small payments with immediate refunds
- badly suited to PSD2 due to its Merchant Initiated Transactions (MIT)
- not worth the maintenance cost tied to its complexity given the simple
flow that it implements
- inconvenient to integrate to standard payment flows
- poorly customizable in regard to the hosted tokenization page
This commit thus removes it entirely and drops Ogone's support for
validation operations with it.
task-2494916
With commit 139dd9d, the Hosted Payment Page API of Ogone was entirely
replaced by the FlexCheckout API. This new API allows customers to
tokenize a payment method for a later use without the need of making a
purchase. However, it proved itself to be less convenient for regular
purchases as it offers less payment options than the HPP, and payments
are no longer cardholder-initiated transactions but merchant-initiated
transactions which have a higher chance of triggering an authentication
check. Furthermore, the payment flow itself is more complicated than
before.
This commit brings back the Hosted Payment Page API to work in parallel
with the FlexCheckout API and the other APIs that were left untouched.
It will be exclusively used for making online payments with a new card.
The validation flow is managed by the FlexCheckout API while the
DirectLink API manages the payment by token and offline payment flows.
task-2494916
closesodoo/odoo#72991
X-original-commit: 4fa7b772c71979f61eb098ff8d005deba834527c
Signed-off-by: Toufik Benjaa (tbe) <tbe@odoo.com>
Signed-off-by: Antoine Vandevenne (anv) <AntoineVDV@users.noreply.github.com>
Before this commit, the implementation of Ogone and PayU Latam's
requirements regarding the transaction reference was preventing the
computation of the reference prefix from being based on the related
document (invoice, SO).
This commit attempts to compute the reference based on the document if
no reference prefix is provided, before applying the said requirements.
task-2494916
closesodoo/odoo#72291
X-original-commit: f18a1d67b769ea69a07fb3c0343e092038df5c93
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
- Re-introduce the changes added by commit 783a8e22a9
- It seems like Ogone has a bug on their side. Even when configuring
the encoding to UTF-8 on their back office, when signing a request
containing non ISO characters the signature we send do not match
the one computed by Ogone.
By calling the URLs suffixed with `_utf8` the issue is fixed.
closesodoo/odoo#71672
X-original-commit: f435ad2d69c7910139cd3ea6a47576399fb4d882
Signed-off-by: Antoine Vandevenne (anv) <AntoineVDV@users.noreply.github.com>
Signed-off-by: Toufik Benjaa (tbe) <tbe@odoo.com>
Users may want to be able to have transactions coming from multiple
payment acquirers to be registered in the same journal.
This will allows that.
Task id #2414749closesodoo/odoo#67331
Related: odoo/upgrade#2500
Related: odoo/enterprise#17258
Signed-off-by: William André (wan) <wan@odoo.com>
In Ogone's backend, it is possible to remove `CARD.CARDNUMBER` from
Flexcheckout's feedback data (Configuration -> Technical information ->
Transaction feedback -> Alias gateway and Tokenization -> Dynamic
parameters). Since this is the configuration that was suggested to Odoo
customers migrating from a previous version, we must be able to process
feedback data when the card number is missing.
This commit creates an anonymous card number ('XXXX...') if one is not
provided by Ogone.
task-2494916
closesodoo/odoo#70896
X-original-commit: 272c4259624d88e2d061c6418109d4e0c2dbfb2d
Signed-off-by: Antoine Vandevenne (anv) <AntoineVDV@users.noreply.github.com>
The key that should be used to check the signature of incoming (Ogone to
Odoo) communication should be `ogone_shakey_out`. For an outgoing
communication, the signature should be generated with `ogone_shakey_in`.
This commit swaps the IN key with the OUT key in signature calculations
to use the appropriate key for a given communication.
The opportunity is also taken to go back to using SHA1 for signature
computation rather than SHA256 that was introduced with 61a02a73 in
order to ease the migration of existing users. Keeping SHA256 would have
required users to make the switch on Ogone's backend.
task-2494916
closesodoo/odoo#70280
X-original-commit: 91782fa29ce597d3985221b76a0d16993facb53e
Signed-off-by: Antoine Vandevenne (anv) <AntoineVDV@users.noreply.github.com>
In this commit, we take the opportunity to replace the previous unsecure
API with the new FlexCheckout API that implements payment methods
validation in a hosted page. Payment processing is still done with the
DirectLink API.
This commit also renames the module `payment_ingenico` to
`payment_ogone` as well as the referring strings ("Ogone" instead
of "Ingenico", ...).
A dedicated [MOV] commit is not used because neither the [MOV] commit
nor the adapted [REF] would be valid on its own.
See the merge commit for more details.
task-2333029
task-2313907
task-2334015
Co-authored-by: Antoine Vandevenne <anv@odoo.com>
The client IP and email are useful pieces of information for auditing
transactions, and are used by the Fraud Detection Module(s) of Ingenico.
closesodoo/odoo#32058
Signed-off-by: Toufik Benjaa (tbe) <tbe@odoo.com>
- When receiving a 3DS payment notification from Ingenico the payment
transaction should be set to "pending" and not in "done".
Then a second notification is send by Ingenico to set the
payment.transaction to "done".
This is the reason for accepting "pending" as a valid state on the
feedback validation.
It was very confusing for the user to distinct account.payment and payment.transaction. From now on, the transactions are
technical objects and, in the backend, we only refer to it in log messages (Front end will be adapted in the same fashion
later on). They are hidden in debug mode in accounting\configuration\payments as their purpose is now purely technical/log
This commit also aims to reduce the gap between the accounting app and the transactions: account.payment objects are
created/validated upon completion of transaction.
To ease the capture/voiding of pending transactions, the related buttons are now displayed directly on the SO/invoice
instead of the transactions.
Was task: https://www.odoo.com/web#id=35857&view_type=form&model=project.task&action=333&active_id=967&menu_id=4720
Was PR #24043
[FIX] add domain based on journal to payment tokens
Was opw: https://www.odoo.com/web?debug#id=1828206&view_type=form&model=project.task&menu_id=5200
Complements rev. 9b1009cd5a to fix the
handling of validation transactions for 3DS-enabled cards.
This handles a few issues:
- make sure to trigger the refund for validation transactions even if
the first feedback we get is the S2S feedback
- feedback URL called by the users' browser should not reset the payment
transaction to 'done' when the refund process has been initiated
- status 81 for "refund pending" should not end up with a transaction in
error. It may be that Ingenico will send a feedback transaction later
or not at all, but the refund is likely to succeed at that point.
Without this commit, validation transactions would never be refunded for
3DS cards.
Remaining issue: the return_url does not seem to be set for those
validation transactions, so the user ends up on the homepage after
completing the 3DS step.
The validation transactions introduced in
7d428c871b were not working properly for
Ogone, due to several problems:
- The refund requests when being sent via the orderdirect.asp API, which
does not support refunding previous transactions, according to the
Ingenico helpdesk. It only support creating independent refund
transactions, which is something that requires special pre-approval
from the payment acquirer, and generally not permitted.
In order to cancel/refund a previous transaction, the direct
maintenance API must be used instead[1].
- Maintenance requests to refund a previous transaction fully should use
the RFS code, as explained in the API documentation [1], and should
always mention the PAYID of the refunded transaction.
- Such maintenance requests must always be SHA-signed, as usual.
- The various transaction status codes for refunded transactions need to
be taken into account as well (typically those beginning with 8)
This commit fixes these various problems.
[1]
https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/directlink
(5.2 Direct Maintenance)
As of today, Ingenico platform 4.125 has non-uniform handling of the
PARAMPLUS parameters that can be passed as part of transaction metadata.
This parameter is documented as being parsed[1] as a series of
parameter-value pairs, to be passed as extra parameters to the feedback
transaction. Based on this, it seems that the PARAMPLUS value should not
be urlencoded globally, but each field value should be urlencoded, as
the Ingenico side will have to be able to parse and re-emit these
individual parameters.
In one case we were missing this urlencoding step, so this commit fixes
it.
Without this, the querydirect.asp API would return invalid XML data when
we retrieve the status of a transaction that used a PARAMPLUS value with
an '=' sign!
For example with PARAMPLUS passed as
return_url=/payment/confirm?tx_id=123
the value returned by querydirect.asp would contain the following:
(note the invalid extra quote character in the `return_url` param)
```
<?xml version="1.0"?>
<ncresponse
(...)
ED="1234"
return_url="/payment/confirm?tx_id="123"
SCORING=""
SCO_CATEGORY="G">
</ncresponse>
```
Url-encoding the value of the return_url in PARAMPLUS fixes this
nonsensical result.
However, the Ingenico API then fails to decode the parameter value when
passing it to the feedback URL, such as the ACCEPTURL we depend on.
As a workaround, since we only pass a single parameter inside
PARAMPLUS, we'll url-unquote it afterwards.
[1]
https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/e-commerce#feedbackparameters_variablefeedbackparameters
Now that we're closer to switching to P3 for good, these helpers have
outlived their usefulness, and mostly add noise.
All remaining dict.iter*() or dict.view*() must be converted to the
normal keys(), values() or items() calls.
Whenever the result is likely to be used for more than the scope of a
loop, or when the dict needs to be modified during iteration, the calls
must be wrapped in a ``list()``, to protect the new P3 semantics.
Those cases are very exceptional.
Also removed some dead code or improved the API to remove unnecessary
conversions.
* StringIO removed from stdlib, replace with io
* try to correctly handle BytesIO/StringIO (one is for bytes the other
is for text)
* fix base64: Python 3 removed bytes-encoding and bytes-bytes
codecs (via #encode) so replace all calls to str.encode('base64'),
also b64encode is a bytes->bytes conversion so attempt to properly
handle that
issue #8530
- When registering a payment token, validating it using a payment of a small amount (~1.50€) followed by a refund allows ensuring
that the payment method is valid (i.e. checksumming the card number simple ensure the number is valid but not that the card exists).
This commit introduces a generic approach that must be implemented for each acquirer that has tokenization support.
This commit also introduces a generic payment token registration/usage template that can be adapted according to one's need.
- Introducing a new payment form that handles payment, deletion and adding payment method (only for server2server for the moment).
- On /my/payment_method, changed strings 'Payment Acquirers' to 'Payment Methods' which is more clear.
- Stripe can now be used to pay subscriptions.
When registering a payment token, validating it using a payment of a small amount followed by a refund
allows ensuring that the method is valid (i.e. checksumming the card number simple ensure the number
is valid but not that the card exists). This commit introduces a generic approach that must be implemented
for each acquirer that has tokenization support. This commit also introduces a generic payment token registration/usage template that can be adapted according to one's need.
payment_ogone: add support for tokens validation
In Python 3, all of these were "consolidated" under urllib(.request,
.parse, .errors) which is inconvenient.
Since we already have hard dependencies on requests and
werkzeug(.urls, which is a backport of Python 3's unicode-aware
urllib.parse) migrate *everything* to that.
A sticking point is urllib2.URLError, those were (mostly) replaced by
the slightly more general IOError which URLError extends.
In Python 3:
* various builtins and dict methods were changed to return
view/iterable objects rather than lists
* and the separate Python 2 view/iterable builtins and methods were
removed altogether
This is problematic when using these items as list (which the happens
repeatedly in Odoo), but more viciously when iterating *multiple times*
over them (which also happens, which I've messed up multiple times while
writing this, and which is a pain to debug even when you've just created
the issue).
Convert all code using these to semantics-matching cross-version
helper functions to get the LCD behaviour between P2 and P3, and
forbid the builtins via lint.
issue #8530