# -*- coding: utf-'8' "-*-" import hashlib import hmac import logging import time import urlparse from openerp import api, fields, models from openerp.addons.payment.models.payment_acquirer import ValidationError from openerp.addons.payment_authorize.controllers.main import AuthorizeController from openerp.tools.float_utils import float_compare _logger = logging.getLogger(__name__) class PaymentAcquirerAuthorize(models.Model): _inherit = 'payment.acquirer' def _get_authorize_urls(self, environment): """ Authorize URLs """ if environment == 'prod': return {'authorize_form_url': 'https://secure.authorize.net/gateway/transact.dll'} else: return {'authorize_form_url': 'https://test.authorize.net/gateway/transact.dll'} @api.model def _get_providers(self): providers = super(PaymentAcquirerAuthorize, self)._get_providers() providers.append(['authorize', 'Authorize.Net']) return providers authorize_login = fields.Char(string='API Login Id', required_if_provider='authorize', groups='base.group_user') authorize_transaction_key = fields.Char(string='API Transaction Key', required_if_provider='authorize', groups='base.group_user') def _authorize_generate_hashing(self, values): data = '^'.join([ values['x_login'], values['x_fp_sequence'], values['x_fp_timestamp'], values['x_amount'], values['x_currency_code']]) return hmac.new(str(values['x_trans_key']), data, hashlib.md5).hexdigest() @api.multi def authorize_form_generate_values(self, partner_values, tx_values): self.ensure_one() base_url = self.env['ir.config_parameter'].get_param('web.base.url') authorize_tx_values = dict(tx_values) temp_authorize_tx_values = { 'x_login': self.authorize_login, 'x_trans_key': self.authorize_transaction_key, 'x_amount': str(tx_values['amount']), 'x_show_form': 'PAYMENT_FORM', 'x_type': 'AUTH_CAPTURE', 'x_method': 'CC', 'x_fp_sequence': '%s%s' % (self.id, int(time.time())), 'x_version': '3.1', 'x_relay_response': 'TRUE', 'x_fp_timestamp': str(int(time.time())), 'x_relay_url': '%s' % urlparse.urljoin(base_url, AuthorizeController._return_url), 'x_cancel_url': '%s' % urlparse.urljoin(base_url, AuthorizeController._cancel_url), 'x_currency_code': tx_values['currency'] and tx_values['currency'].name or '', 'address': partner_values['address'], 'city': partner_values['city'], 'country': partner_values['country'] and partner_values['country'].name or '', 'email': partner_values['email'], 'zip': partner_values['zip'], 'first_name': partner_values['first_name'], 'last_name': partner_values['last_name'], 'phone': partner_values['phone'], 'state': partner_values.get('state') and partner_values['state'].name or '', } temp_authorize_tx_values['returndata'] = authorize_tx_values.pop('return_url', '') temp_authorize_tx_values['x_fp_hash'] = self._authorize_generate_hashing(temp_authorize_tx_values) authorize_tx_values.update(temp_authorize_tx_values) return partner_values, authorize_tx_values @api.multi def authorize_get_form_action_url(self): self.ensure_one() return self._get_authorize_urls(self.environment)['authorize_form_url'] class TxAuthorize(models.Model): _inherit = 'payment.transaction' authorize_txnid = fields.Char(string='Transaction ID') _authorize_valid_tx_status = 1 _authorize_pending_tx_status = 4 _authorize_cancel_tx_status = 2 # -------------------------------------------------- # FORM RELATED METHODS # -------------------------------------------------- @api.model def _authorize_form_get_tx_from_data(self, data): """ Given a data dict coming from authorize, verify it and find the related transaction record. """ reference, trans_id, fingerprint = data.get('x_invoice_num'), data.get('x_trans_id'), data.get('x_MD5_Hash') if not reference or not trans_id or not fingerprint: error_msg = 'Authorize: received data with missing reference (%s) or trans_id (%s) or fingerprint (%s)' % (reference, trans_id, fingerprint) _logger.error(error_msg) raise ValidationError(error_msg) tx = self.search([('reference', '=', reference)]) if not tx or len(tx) > 1: error_msg = 'Authorize: received data for reference %s' % (reference) if not tx: error_msg += '; no order found' else: error_msg += '; multiple order found' _logger.error(error_msg) raise ValidationError(error_msg) return tx[0] @api.model def _authorize_form_get_invalid_parameters(self, tx, data): invalid_parameters = [] if tx.authorize_txnid and data.get('x_trans_id') != tx.authorize_txnid: invalid_parameters.append(('Transaction Id', data.get('x_trans_id'), tx.authorize_txnid)) # check what is buyed if float_compare(float(data.get('x_amount', '0.0')), tx.amount, 2) != 0: invalid_parameters.append(('Amount', data.get('x_amount'), '%.2f' % tx.amount)) return invalid_parameters @api.model def _authorize_form_validate(self, tx, data): if tx.state == 'done': _logger.warning('Authorize: trying to validate an already validated tx (ref %s)' % tx.reference) return True status_code = int(data.get('x_response_code', '0')) if status_code == self._authorize_valid_tx_status: tx.write({ 'state': 'done', 'authorize_txnid': data.get('x_trans_id'), 'acquirer_reference': data['x_invoice_num'], }) return True elif status_code == self._authorize_pending_tx_status: tx.write({ 'state': 'pending', 'authorize_txnid': data.get('x_trans_id'), 'acquirer_reference': data['x_invoice_num'], }) return True elif status_code == self._authorize_cancel_tx_status: tx.write({ 'state': 'cancel', 'authorize_txnid': data.get('x_trans_id'), 'acquirer_reference': data['x_invoice_num'], }) return True else: error = data.get('x_response_reason_text') _logger.info(error) tx.write({ 'state': 'error', 'state_message': error, 'authorize_txnid': data.get('x_trans_id'), 'acquirer_reference': data['x_invoice_num'], }) return False