From ffd527d0273197925102175feb95d4a6f4fcd8d5 Mon Sep 17 00:00:00 2001 From: Damien Bouvy Date: Thu, 1 Sep 2016 13:07:12 +0200 Subject: [PATCH] [IMP] payment, payment_*: add/improve tokenization support This commit improves the tokenization process, allowing users to set the acquirer to save payment data never, always or letting the customer decide (only implemented in ecommerce for now). Support for tokenization is improved for Ogone and Authorize.net This commits also factorizes advanced payment features support (authorization, tokenization, fees computation) in a generic method overriden by every provider to specifiy which features are supported. This process can be used in views to hide/show fields depending on feature support or in constraint checks. --- addons/payment/models/payment_acquirer.py | 43 ++++++++++++++-- addons/payment/views/payment_views.xml | 2 + .../models/authorize_request.py | 38 +++++++++++++- addons/payment_authorize/models/payment.py | 46 +++++++++++++++-- addons/payment_ogone/models/payment.py | 49 +++++++++++++------ .../views/payment_ogone_templates.xml | 2 +- addons/payment_paypal/models/payment.py | 15 ++++++ 7 files changed, 168 insertions(+), 27 deletions(-) diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index d0733c16fe3..d9442e0ae1c 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -101,8 +101,18 @@ class PaymentAcquirer(models.Model): 'Error Message', translate=True, default='Error, Please be aware that an error occurred during the transaction. The order has been confirmed but will not be paid. Do not hesitate to contact us if you have any questions on the status of your order.', help='Message displayed, if error is occur during the payment process.') + save_token = fields.Selection([ + ('none', 'Never'), + ('ask', 'Let the customer decide'), + ('always', 'Always')], + string='Store Card Data', default='none', + help="Determine if card data is saved as a token automatically or not. " + "Payment tokens allow your customer to reuse their cards in the e-commerce " + "or allow you to charge an invoice directly on a credit card. If set to " + "'let the customer decide', ecommerce customers will have a checkbox displayed on the payment page.") + token_implemented = fields.Boolean('Saving Card Data supported', compute='_compute_feature_support') - fees_implemented = fields.Boolean('Fees Computation Supported', compute='_compute_fees_implemented') + fees_implemented = fields.Boolean('Fees Computation Supported', compute='_compute_feature_support') fees_active = fields.Boolean('Add Extra Fees') fees_dom_fixed = fields.Float('Fixed domestic fees') fees_dom_var = fields.Float('Variable domestic fees (in percents)') @@ -127,9 +137,12 @@ class PaymentAcquirer(models.Model): "resized as a 64x64px image, with aspect ratio preserved. " "Use this field anywhere a small image is required.") - @api.one - def _compute_fees_implemented(self): - self.fees_implemented = hasattr(self, '%s_compute_fees' % self.provider) + @api.multi + def _compute_feature_support(self): + feature_support = self._get_feature_support() + for acquirer in self: + acquirer.fees_implemented = acquirer.provider in feature_support['fees'] + acquirer.token_implemented = acquirer.provider in feature_support['tokenize'] @api.multi def _check_required_if_provider(self): @@ -140,10 +153,30 @@ class PaymentAcquirer(models.Model): return False return True + @api.constrains('auto_confirm') + def _check_authorization_support(self): + for acquirer in self: + if acquirer.auto_confirm == 'authorize' and acquirer.provider not in self._get_feature_support()['authorize']: + raise ValidationError('Transaction Authorization is not supported by this payment provider.') + return True + _constraints = [ (_check_required_if_provider, 'Required fields not filled', []), ] + def _get_feature_support(self): + """Get advanced feature support by provider. + + Each provider should add its technical in the corresponding + key for the following features: + * fees: support payment fees computations + * authorize: support authorizing payment (separates + authorization and capture) + * tokenize: support saving payment data in a payment.tokenize + object + """ + return dict(authorize=[], tokenize=[], fees=[]) + @api.model def create(self, vals): image_resize_images(vals) @@ -370,7 +403,7 @@ class PaymentTransaction(models.Model): type = fields.Selection([ ('server2server', 'Server To Server'), ('form', 'Form'), - ('form_save', 'Form with credentials storage')], 'Type', + ('form_save', 'Form with tokenization')], 'Type', default='form', required=True) state = fields.Selection([ ('draft', 'Draft'), diff --git a/addons/payment/views/payment_views.xml b/addons/payment/views/payment_views.xml index 51bf831a719..a8677057aff 100644 --- a/addons/payment/views/payment_views.xml +++ b/addons/payment/views/payment_views.xml @@ -25,6 +25,7 @@
+ @@ -79,6 +80,7 @@ +