diff --git a/addons/payment/__openerp__.py b/addons/payment/__openerp__.py index a3843a872c1..071218f7b5d 100644 --- a/addons/payment/__openerp__.py +++ b/addons/payment/__openerp__.py @@ -11,6 +11,7 @@ 'data': [ 'views/payment_acquirer.xml', 'views/res_config_view.xml', + 'views/res_partner_view.xml', 'security/ir.model.access.csv', 'security/payment_security.xml', ], diff --git a/addons/payment/models/__init__.py b/addons/payment/models/__init__.py index cd7858767fc..02ea486041a 100644 --- a/addons/payment/models/__init__.py +++ b/addons/payment/models/__init__.py @@ -2,3 +2,4 @@ import payment_acquirer import res_config +import res_partner diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index d7e7e79e14e..33ce5482568 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -1,5 +1,4 @@ # -*- coding: utf-'8' "-*-" - import logging from openerp.osv import osv, fields @@ -64,13 +63,16 @@ class PaymentAcquirer(osv.Model): 'provider': fields.selection(_provider_selection, string='Provider', required=True), 'company_id': fields.many2one('res.company', 'Company', required=True), 'pre_msg': fields.html('Message', translate=True, - help='Message displayed to explain and help the payment process.'), + help='Message displayed to explain and help the payment process.'), 'post_msg': fields.html('Thanks Message', help='Message displayed after having done the payment process.'), 'validation': fields.selection( [('manual', 'Manual'), ('automatic', 'Automatic')], string='Process Method', help='Static payments are payments like transfer, that require manual steps.'), 'view_template_id': fields.many2one('ir.ui.view', 'Form Button Template', required=True), + 'registration_view_template_id': fields.many2one('ir.ui.view', 'S2S Form Template', + domain=[('type', '=', 'qweb')], + help="Template for method registration"), 'environment': fields.selection( [('test', 'Test'), ('prod', 'Production')], string='Environment', oldname='env'), @@ -273,11 +275,41 @@ class PaymentAcquirer(osv.Model): 'partner_values': partner_values, 'tx_values': tx_values, 'context': context, + 'type': tx_values.get('type') or 'form', } # because render accepts view ids but not qweb -> need to use the xml_id return self.pool['ir.ui.view'].render(cr, uid, acquirer.view_template_id.xml_id, qweb_context, engine='ir.qweb', context=context) + def _registration_render(self, cr, uid, id, partner_id, qweb_context=None, context=None): + acquirer = self.browse(cr, uid, id, context=context) + if qweb_context is None: + qweb_context = {} + qweb_context.update(id=id, partner_id=partner_id) + method_name = '_%s_registration_form_generate_values' % (acquirer.provider,) + if hasattr(self, method_name): + method = getattr(self, method_name) + qweb_context.update(method(cr, uid, id, qweb_context, context=context)) + return self.pool['ir.ui.view'].render(cr, uid, acquirer.registration_view_template_id.xml_id, qweb_context, engine='ir.qweb', context=context) + + def s2s_process(self, cr, uid, id, data, context=None): + acquirer = self.browse(cr, uid, id, context=context) + cust_method_name = '%s_s2s_form_process' % (acquirer.provider) + if not self.s2s_validate(cr, uid, id, data, context=context): + return False + if hasattr(self, cust_method_name): + method = getattr(self, cust_method_name) + return method(cr, uid, data, context=context) + return True + + def s2s_validate(self, cr, uid, id, data, context=None): + acquirer = self.browse(cr, uid, id, context=context) + cust_method_name = '%s_s2s_form_validate' % (acquirer.provider) + if hasattr(self, cust_method_name): + method = getattr(self, cust_method_name) + return method(cr, uid, id, data, context=context) + return True + def _wrap_payment_block(self, cr, uid, html_block, amount, currency_id, context=None): payment_header = _('Pay safely online') amount_str = float_repr(amount, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')) @@ -342,7 +374,7 @@ class PaymentTransaction(osv.Model): required=True, ), 'type': fields.selection( - [('server2server', 'Server To Server'), ('form', 'Form')], + [('server2server', 'Server To Server'), ('form', 'Form'), ('form_save', 'Form with credentials storage')], string='Type', required=True), 'state': fields.selection( [('draft', 'Draft'), ('pending', 'Pending'), @@ -377,6 +409,11 @@ class PaymentTransaction(osv.Model): 'partner_phone': fields.char('Phone'), 'partner_reference': fields.char('Partner Reference', help='Reference of the customer in the acquirer database'), + 'html_3ds': fields.char('3D Secure HTML'), + + 's2s_cb_eval': fields.char('S2S Callback', help="""\ + Will be safe_eval with `self` being the current transaction. i.e.: + self.env['my.model'].payment_validated(self)"""), } def _check_reference(self, cr, uid, ids, context=None): @@ -467,62 +504,16 @@ class PaymentTransaction(osv.Model): # -------------------------------------------------- # SERVER2SERVER RELATED METHODS # -------------------------------------------------- - def s2s_create(self, cr, uid, values, cc_values, context=None): tx_id, tx_result = self.s2s_send(cr, uid, values, cc_values, context=context) self.s2s_feedback(cr, uid, tx_id, tx_result, context=context) return tx_id - def s2s_send(self, cr, uid, values, cc_values, context=None): - """ Create and send server-to-server transaction. - - :param dict values: transaction values - :param dict cc_values: credit card values that are not stored into the - payment.transaction object. Acquirers should - handle receiving void or incorrect cc values. - Should contain : - - - holder_name - - number - - cvc - - expiry_date - - brand - - expiry_date_yy - - expiry_date_mm - """ - tx_id, result = None, None - - if values.get('acquirer_id'): - acquirer = self.pool['payment.acquirer'].browse(cr, uid, values.get('acquirer_id'), context=context) - custom_method_name = '_%s_s2s_send' % acquirer.provider - if hasattr(self, custom_method_name): - tx_id, result = getattr(self, custom_method_name)(cr, uid, values, cc_values, context=context) - - if tx_id is None and result is None: - tx_id = super(PaymentTransaction, self).create(cr, uid, values, context=context) - return (tx_id, result) - - def s2s_feedback(self, cr, uid, tx_id, data, context=None): - """ Handle the feedback of a server-to-server transaction. """ - tx = self.browse(cr, uid, tx_id, context=context) - invalid_parameters = None - - invalid_param_method_name = '_%s_s2s_get_invalid_parameters' % tx.acquirer_id.provider - if hasattr(self, invalid_param_method_name): - invalid_parameters = getattr(self, invalid_param_method_name)(cr, uid, tx, data, context=context) - - if invalid_parameters: - _error_message = '%s: incorrect tx data:\n' % (tx.acquirer_id.name) - for item in invalid_parameters: - _error_message += '\t%s: received %s instead of %s\n' % (item[0], item[1], item[2]) - _logger.error(_error_message) - return False - - feedback_method_name = '_%s_s2s_validate' % tx.acquirer_id.provider - if hasattr(self, feedback_method_name): - return getattr(self, feedback_method_name)(cr, uid, tx, data, context=context) - - return True + def s2s_do_transaction(self, cr, uid, id, context=None, **kwargs): + tx = self.browse(cr, uid, id, context=context) + custom_method_name = '%s_s2s_do_transaction' % tx.acquirer_id.provider + if hasattr(self, custom_method_name): + return getattr(self, custom_method_name)(cr, uid, id, context=context, **kwargs) def s2s_get_tx_status(self, cr, uid, tx_id, context=None): """ Get the tx status. """ @@ -533,3 +524,32 @@ class PaymentTransaction(osv.Model): return getattr(self, invalid_param_method_name)(cr, uid, tx, context=context) return True + + +class PaymentMethod(osv.Model): + _name = 'payment.method' + _order = 'partner_id' + + _columns = { + 'name': fields.char('Name', help='Name of the payment method'), + 'partner_id': fields.many2one('res.partner', 'Partner', required=True), + 'acquirer_id': fields.many2one('payment.acquirer', 'Acquirer Account', required=True), + 'acquirer_ref': fields.char('Acquirer Ref.', required=True), + 'active': fields.boolean('Active') + } + + _defaults = { + 'active': True + } + + def create(self, cr, uid, values, context=None): + # call custom create method if defined (i.e. ogone_create for ogone) + if values.get('acquirer_id'): + acquirer = self.pool['payment.acquirer'].browse(cr, uid, values.get('acquirer_id'), context=context) + + # custom create + custom_method_name = '%s_create' % acquirer.provider + if hasattr(self, custom_method_name): + values.update(getattr(self, custom_method_name)(cr, uid, values, context=context)) + + return super(PaymentMethod, self).create(cr, uid, values, context=context) diff --git a/addons/payment/models/res_partner.py b/addons/payment/models/res_partner.py new file mode 100644 index 00000000000..e688b89a4dd --- /dev/null +++ b/addons/payment/models/res_partner.py @@ -0,0 +1,9 @@ +from openerp.osv import fields, osv + + +class res_partner(osv.osv): + _name = 'res.partner' + _inherit = 'res.partner' + _columns = { + 'payment_method_ids': fields.one2many('payment.method', 'partner_id', 'Payment Methods'), + } diff --git a/addons/payment/security/ir.model.access.csv b/addons/payment/security/ir.model.access.csv index f52f9a44d4e..942718807d5 100644 --- a/addons/payment/security/ir.model.access.csv +++ b/addons/payment/security/ir.model.access.csv @@ -4,4 +4,8 @@ payment_acquirer_user,payment.acquirer.user,model_payment_acquirer,base.group_us payment_acquirer_system,payment.acquirer.system,model_payment_acquirer,base.group_system,1,1,1,1 payment_transaction_all,payment.transaction.all,model_payment_transaction,,1,0,0,0 payment_transaction_user,payment.transaction.user,model_payment_transaction,base.group_user,1,1,1,0 -payment_transaction_system,payment.transaction.system,model_payment_transaction,base.group_system,1,1,1,1 \ No newline at end of file +payment_transaction_system,payment.transaction.system,model_payment_transaction,base.group_system,1,1,1,1 +payment_method_all,payment.method.all,model_payment_method,,1,0,0,0 +payment_method_user,payment.method.user,model_payment_method,base.group_user,1,1,1,0 +payment_method_portal,payment.method.portal,model_payment_method,base.group_portal,1,1,1,0 +payment_method_system,payment.method.system,model_payment_method,base.group_system,1,1,1,1 diff --git a/addons/payment/security/payment_security.xml b/addons/payment/security/payment_security.xml index 7bae346c648..f2dedd5e6ee 100644 --- a/addons/payment/security/payment_security.xml +++ b/addons/payment/security/payment_security.xml @@ -20,5 +20,18 @@ + + Access own payment methods only + + [('partner_id','=',user.partner_id.id)] + + + + + Access every payment method + + + + diff --git a/addons/payment/views/payment_acquirer.xml b/addons/payment/views/payment_acquirer.xml index a83e475c1da..933a4fb6e3c 100644 --- a/addons/payment/views/payment_acquirer.xml +++ b/addons/payment/views/payment_acquirer.xml @@ -58,6 +58,7 @@ + @@ -189,5 +190,33 @@ parent='root_payment_menu' sequence='20' /> + + + payment.method.tree + payment.method + + + + + + + + + + + + + + Saved Payment Data + payment.method + form + tree + + + + diff --git a/addons/payment/views/res_partner_view.xml b/addons/payment/views/res_partner_view.xml new file mode 100644 index 00000000000..193018e74e1 --- /dev/null +++ b/addons/payment/views/res_partner_view.xml @@ -0,0 +1,25 @@ + + + + + + + view.res.partner.form.payment.defaultcreditcard + res.partner + + + + + + + + + + + + + + + + +