summaryrefslogtreecommitdiff
path: root/addons/payment_adyen/models
diff options
context:
space:
mode:
authorThibault Delavallée <tde@openerp.com>2014-01-22 18:57:02 +0100
committerThibault Delavallée <tde@openerp.com>2014-01-22 18:57:02 +0100
commit0b69bad9968ce2650f6dffd7df703cd33e7f38af (patch)
tree947ae3933f8b4f382bf090031d1ea15e53e88155 /addons/payment_adyen/models
parentf70e54255641f4d3d61777501b20b0f8c7a1fb77 (diff)
[RENAME] payment_acquirer_* -> payment_ *
bzr revid: tde@openerp.com-20140122175702-1h1e51z4njt4s70w
Diffstat (limited to 'addons/payment_adyen/models')
-rw-r--r--addons/payment_adyen/models/__init__.py3
-rw-r--r--addons/payment_adyen/models/adyen.py180
2 files changed, 183 insertions, 0 deletions
diff --git a/addons/payment_adyen/models/__init__.py b/addons/payment_adyen/models/__init__.py
new file mode 100644
index 00000000000..fdc540ef04d
--- /dev/null
+++ b/addons/payment_adyen/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+import adyen
diff --git a/addons/payment_adyen/models/adyen.py b/addons/payment_adyen/models/adyen.py
new file mode 100644
index 00000000000..80103f50dae
--- /dev/null
+++ b/addons/payment_adyen/models/adyen.py
@@ -0,0 +1,180 @@
+# -*- coding: utf-'8' "-*-"
+
+import base64
+try:
+ import simplejson as json
+except ImportError:
+ import json
+from hashlib import sha1
+import hmac
+import logging
+import urlparse
+
+from openerp.addons.payment.models.payment_acquirer import ValidationError
+from openerp.addons.payment_adyen.controllers.main import AdyenController
+from openerp.osv import osv, fields
+from openerp.tools import float_round
+
+_logger = logging.getLogger(__name__)
+
+
+class AcquirerAdyen(osv.Model):
+ _inherit = 'payment.acquirer'
+
+ def _get_adyen_urls(self, cr, uid, env, context=None):
+ """ Adyen URLs
+
+ - yhpp: hosted payment page: pay.shtml for single, select.shtml for multiple
+ """
+ if env == 'prod':
+ return {
+ 'adyen_form_url': 'https://prod.adyen.com/hpp/pay.shtml',
+ }
+ else:
+ return {
+ 'adyen_form_url': 'https://test.adyen.com/hpp/pay.shtml',
+ }
+
+ _columns = {
+ 'adyen_merchant_account': fields.char('Merchant Account', required_if_provider='adyen'),
+ 'adyen_skin_code': fields.char('Skin Code', required_if_provider='adyen'),
+ 'adyen_skin_hmac_key': fields.char('Skin HMAC Key', required_if_provider='adyen'),
+ }
+
+ def _adyen_generate_merchant_sig(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 ogone) or 'out' (adyen
+ contacting openerp). In this last case only some
+ fields should be contained (see e-Commerce basic)
+ :param dict values: transaction values
+
+ :return string: shasign
+ """
+ assert inout in ('in', 'out')
+ assert acquirer.name == 'adyen'
+
+ if inout == 'in':
+ keys = "paymentAmount currencyCode shipBeforeDate merchantReference skinCode merchantAccount sessionValidity shopperEmail shopperReference recurringContract allowedMethods blockedMethods shopperStatement merchantReturnData billingAddressType deliveryAddressType offset".split()
+ else:
+ keys = "authResult pspReference merchantReference skinCode paymentMethod shopperLocale merchantReturnData".split()
+
+ def get_value(key):
+ if values.get(key):
+ return values[key]
+ return ''
+
+ sign = ''.join('%s' % get_value(k) for k in keys).encode('ascii')
+ key = acquirer.adyen_skin_hmac_key.encode('ascii')
+ return base64.b64encode(hmac.new(key, sign, sha1).digest())
+
+ def adyen_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)
+ # tmp
+ import datetime
+ from dateutil import relativedelta
+ tmp_date = datetime.date.today() + relativedelta.relativedelta(days=1)
+
+ adyen_tx_values = dict(tx_values)
+ adyen_tx_values.update({
+ 'merchantReference': tx_values['reference'],
+ 'paymentAmount': '%d' % int(float_round(tx_values['amount'], 2) * 100),
+ 'currencyCode': tx_values['currency'] and tx_values['currency'].name or '',
+ 'shipBeforeDate': tmp_date,
+ 'skinCode': acquirer.adyen_skin_code,
+ 'merchantAccount': acquirer.adyen_merchant_account,
+ 'shopperLocale': partner_values['lang'],
+ 'sessionValidity': tmp_date,
+ 'resURL': '%s' % urlparse.urljoin(base_url, AdyenController._return_url),
+ })
+ if adyen_tx_values.get('return_url'):
+ adyen_tx_values['merchantReturnData'] = json.dumps({'return_url': '%s' % adyen_tx_values.pop('return_url')})
+ adyen_tx_values['merchantSig'] = self._adyen_generate_merchant_sig(acquirer, 'in', adyen_tx_values)
+ return partner_values, adyen_tx_values
+
+ def adyen_get_form_action_url(self, cr, uid, id, context=None):
+ acquirer = self.browse(cr, uid, id, context=context)
+ return self._get_adyen_urls(cr, uid, acquirer.env, context=context)['adyen_form_url']
+
+
+class TxAdyen(osv.Model):
+ _inherit = 'payment.transaction'
+
+ _columns = {
+ 'adyen_psp_reference': fields.char('Adyen PSP Reference'),
+ }
+
+ # --------------------------------------------------
+ # FORM RELATED METHODS
+ # --------------------------------------------------
+
+ def _adyen_form_get_tx_from_data(self, cr, uid, data, context=None):
+ reference, pspReference = data.get('merchantReference'), data.get('pspReference')
+ if not reference or not pspReference:
+ error_msg = 'Adyen: received data with missing reference (%s) or missing pspReference (%s)' % (reference, pspReference)
+ _logger.error(error_msg)
+ raise ValidationError(error_msg)
+
+ # find tx -> @TDENOTE use pspReference ?
+ tx_ids = self.pool['payment.transaction'].search(cr, uid, [('reference', '=', reference)], context=context)
+ if not tx_ids or len(tx_ids) > 1:
+ error_msg = 'Adyen: 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']._adyen_generate_merchant_sig(tx.acquirer_id, 'out', data)
+ if shasign_check != data.get('merchantSig'):
+ error_msg = 'Adyen: invalid merchantSig, received %s, computed %s' % (data.get('merchantSig'), shasign_check)
+ _logger.warning(error_msg)
+ # raise ValidationError(error_msg)
+
+ return tx
+
+ def _adyen_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
+ invalid_parameters = []
+
+ # reference at acquirer: pspReference
+ if tx.acquirer_reference and data.get('pspReference') != tx.acquirer_reference:
+ invalid_parameters.append(('pspReference', data.get('pspReference'), tx.acquirer_reference))
+ # seller
+ if data.get('skinCode') != tx.acquirer_id.adyen_skin_code:
+ invalid_parameters.append(('skinCode', data.get('skinCode'), tx.acquirer_id.adyen_skin_code))
+ # result
+ if not data.get('authResult'):
+ invalid_parameters.append(('authResult', data.get('authResult'), 'something'))
+
+ return invalid_parameters
+
+ def _adyen_form_validate(self, cr, uid, tx, data, context=None):
+ status = data.get('authResult', 'PENDING')
+ if status == 'AUTHORISED':
+ tx.write({
+ 'state': 'done',
+ 'adyen_psp_reference': data.get('pspReference'),
+ # 'date_validate': data.get('payment_date', fields.datetime.now()),
+ # 'paypal_txn_type': data.get('express_checkout')
+ })
+ return True
+ elif status == 'PENDING':
+ tx.write({
+ 'state': 'pending',
+ 'adyen_psp_reference': data.get('pspReference'),
+ })
+ return True
+ else:
+ error = 'Paypal: feedback error'
+ _logger.info(error)
+ tx.write({
+ 'state': 'error',
+ 'state_message': error
+ })
+ return False