192 lines
8.1 KiB
Python
192 lines
8.1 KiB
Python
# -*- coding: utf-'8' "-*-"
|
|
from hashlib import sha1
|
|
import logging
|
|
import urlparse
|
|
|
|
from openerp.addons.payment.models.payment_acquirer import ValidationError
|
|
from openerp.addons.payment_buckaroo.controllers.main import BuckarooController
|
|
from openerp.osv import osv, fields
|
|
from openerp.tools.float_utils import float_compare
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AcquirerBuckaroo(osv.Model):
|
|
_inherit = 'payment.acquirer'
|
|
|
|
def _get_buckaroo_urls(self, cr, uid, environment, context=None):
|
|
""" Buckaroo URLs
|
|
"""
|
|
if environment == 'prod':
|
|
return {
|
|
'buckaroo_form_url': 'https://checkout.buckaroo.nl/html/',
|
|
}
|
|
else:
|
|
return {
|
|
'buckaroo_form_url': 'https://testcheckout.buckaroo.nl/html/',
|
|
}
|
|
|
|
def _get_providers(self, cr, uid, context=None):
|
|
providers = super(AcquirerBuckaroo, self)._get_providers(cr, uid, context=context)
|
|
providers.append(['buckaroo', 'Buckaroo'])
|
|
return providers
|
|
|
|
_columns = {
|
|
'brq_websitekey': fields.char('WebsiteKey', required_if_provider='buckaroo'),
|
|
'brq_secretkey': fields.char('SecretKey', required_if_provider='buckaroo'),
|
|
}
|
|
|
|
def _buckaroo_generate_digital_sign(self, acquirer, inout, values):
|
|
""" Generate the shasign for incoming or outgoing communications.
|
|
|
|
:param browse acquirer: the payment.acquirer browse record. It should
|
|
have a shakey in shaky out
|
|
:param string inout: 'in' (openerp contacting buckaroo) or 'out' (buckaroo
|
|
contacting openerp).
|
|
:param dict values: transaction values
|
|
|
|
:return string: shasign
|
|
"""
|
|
assert inout in ('in', 'out')
|
|
assert acquirer.provider == 'buckaroo'
|
|
|
|
keys = "add_returndata Brq_amount Brq_culture Brq_currency Brq_invoicenumber Brq_return Brq_returncancel Brq_returnerror Brq_returnreject brq_test Brq_websitekey".split()
|
|
|
|
def get_value(key):
|
|
if values.get(key):
|
|
return values[key]
|
|
return ''
|
|
|
|
if inout == 'out':
|
|
if 'BRQ_SIGNATURE' in values:
|
|
del values['BRQ_SIGNATURE']
|
|
items = sorted((k.upper(), v) for k, v in values.items())
|
|
sign = ''.join('%s=%s' % (k, v) for k, v in items)
|
|
else:
|
|
sign = ''.join('%s=%s' % (k,get_value(k)) for k in keys)
|
|
#Add the pre-shared secret key at the end of the signature
|
|
sign = sign + acquirer.brq_secretkey
|
|
if isinstance(sign, str):
|
|
sign = urlparse.parse_qsl(sign)
|
|
shasign = sha1(sign).hexdigest()
|
|
return shasign
|
|
|
|
|
|
def buckaroo_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None):
|
|
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
|
|
acquirer = self.browse(cr, uid, id, context=context)
|
|
buckaroo_tx_values = dict(tx_values)
|
|
buckaroo_tx_values.update({
|
|
'Brq_websitekey': acquirer.brq_websitekey,
|
|
'Brq_amount': tx_values['amount'],
|
|
'Brq_currency': tx_values['currency'] and tx_values['currency'].name or '',
|
|
'Brq_invoicenumber': tx_values['reference'],
|
|
'brq_test': acquirer.environment,
|
|
'Brq_return': '%s' % urlparse.urljoin(base_url, BuckarooController._return_url),
|
|
'Brq_returncancel': '%s' % urlparse.urljoin(base_url, BuckarooController._cancel_url),
|
|
'Brq_returnerror': '%s' % urlparse.urljoin(base_url, BuckarooController._exception_url),
|
|
'Brq_returnreject': '%s' % urlparse.urljoin(base_url, BuckarooController._reject_url),
|
|
'Brq_culture': partner_values.get('lang', 'en_US'),
|
|
})
|
|
if buckaroo_tx_values.get('return_url'):
|
|
buckaroo_tx_values['add_returndata'] = {'return_url': '%s' % buckaroo_tx_values.pop('return_url')}
|
|
else:
|
|
buckaroo_tx_values['add_returndata'] = ''
|
|
buckaroo_tx_values['Brq_signature'] = self._buckaroo_generate_digital_sign(acquirer, 'in', buckaroo_tx_values)
|
|
return partner_values, buckaroo_tx_values
|
|
|
|
def buckaroo_get_form_action_url(self, cr, uid, id, context=None):
|
|
acquirer = self.browse(cr, uid, id, context=context)
|
|
return self._get_buckaroo_urls(cr, uid, acquirer.environment, context=context)['buckaroo_form_url']
|
|
|
|
class TxBuckaroo(osv.Model):
|
|
_inherit = 'payment.transaction'
|
|
|
|
# buckaroo status
|
|
_buckaroo_valid_tx_status = [190]
|
|
_buckaroo_pending_tx_status = [790, 791, 792, 793]
|
|
_buckaroo_cancel_tx_status = [890, 891]
|
|
_buckaroo_error_tx_status = [490, 491, 492]
|
|
_buckaroo_reject_tx_status = [690]
|
|
|
|
_columns = {
|
|
'buckaroo_txnid': fields.char('Transaction ID'),
|
|
}
|
|
|
|
|
|
# --------------------------------------------------
|
|
# FORM RELATED METHODS
|
|
# --------------------------------------------------
|
|
|
|
def _buckaroo_form_get_tx_from_data(self, cr, uid, data, context=None):
|
|
""" Given a data dict coming from buckaroo, verify it and find the related
|
|
transaction record. """
|
|
reference, pay_id, shasign = data.get('BRQ_INVOICENUMBER'), data.get('BRQ_PAYMENT'), data.get('BRQ_SIGNATURE')
|
|
if not reference or not pay_id or not shasign:
|
|
error_msg = 'Buckaroo: received data with missing reference (%s) or pay_id (%s) or shashign (%s)' % (reference, pay_id, shasign)
|
|
_logger.error(error_msg)
|
|
raise ValidationError(error_msg)
|
|
|
|
tx_ids = self.search(cr, uid, [('reference', '=', reference)], context=context)
|
|
if not tx_ids or len(tx_ids) > 1:
|
|
error_msg = 'Buckaroo: received data for reference %s' % (reference)
|
|
if not tx_ids:
|
|
error_msg += '; no order found'
|
|
else:
|
|
error_msg += '; multiple order found'
|
|
_logger.error(error_msg)
|
|
raise ValidationError(error_msg)
|
|
tx = self.pool['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
|
|
|
|
#verify shasign
|
|
shasign_check = self.pool['payment.acquirer']._buckaroo_generate_digital_sign(tx.acquirer_id, 'out' ,data)
|
|
if shasign_check.upper() != shasign.upper():
|
|
error_msg = 'Buckaroo: invalid shasign, received %s, computed %s, for data %s' % (shasign, shasign_check, data)
|
|
_logger.error(error_msg)
|
|
raise ValidationError(error_msg)
|
|
|
|
return tx
|
|
|
|
def _buckaroo_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
|
|
invalid_parameters = []
|
|
|
|
if tx.acquirer_reference and data.get('BRQ_TRANSACTIONS') != tx.acquirer_reference:
|
|
invalid_parameters.append(('Transaction Id', data.get('BRQ_TRANSACTIONS'), tx.acquirer_reference))
|
|
# check what is buyed
|
|
if float_compare(float(data.get('BRQ_AMOUNT', '0.0')), tx.amount, 2) != 0:
|
|
invalid_parameters.append(('Amount', data.get('BRQ_AMOUNT'), '%.2f' % tx.amount))
|
|
if data.get('BRQ_CURRENCY') != tx.currency_id.name:
|
|
invalid_parameters.append(('Currency', data.get('BRQ_CURRENCY'), tx.currency_id.name))
|
|
|
|
return invalid_parameters
|
|
|
|
def _buckaroo_form_validate(self, cr, uid, tx, data, context=None):
|
|
status_code = int(data.get('BRQ_STATUSCODE','0'))
|
|
if status_code in self._buckaroo_valid_tx_status:
|
|
tx.write({
|
|
'state': 'done',
|
|
'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
|
|
})
|
|
return True
|
|
elif status_code in self._buckaroo_pending_tx_status:
|
|
tx.write({
|
|
'state': 'pending',
|
|
'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
|
|
})
|
|
return True
|
|
elif status_code in self._buckaroo_cancel_tx_status:
|
|
tx.write({
|
|
'state': 'cancel',
|
|
'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
|
|
})
|
|
return True
|
|
else:
|
|
error = 'Buckaroo: feedback error'
|
|
_logger.info(error)
|
|
tx.write({
|
|
'state': 'error',
|
|
'state_message': error,
|
|
'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
|
|
})
|
|
return False
|