[MIG] payment_ogone: new API
No functional change.
This commit is contained in:
committed by
Thibault Delavallée
parent
b6c5b3a6b7
commit
4ef937ed38
@@ -3,9 +3,9 @@ import logging
|
||||
import pprint
|
||||
import werkzeug
|
||||
|
||||
from openerp import http, SUPERUSER_ID
|
||||
from openerp.http import request
|
||||
from openerp.addons.payment.models.payment_acquirer import ValidationError
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
from odoo.addons.payment.models.payment_acquirer import ValidationError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -25,33 +25,24 @@ class OgoneController(http.Controller):
|
||||
def ogone_form_feedback(self, **post):
|
||||
""" Ogone contacts using GET, at least for accept """
|
||||
_logger.info('Ogone: entering form_feedback with post data %s', pprint.pformat(post)) # debug
|
||||
cr, uid, context = request.cr, SUPERUSER_ID, request.context
|
||||
request.registry['payment.transaction'].form_feedback(cr, uid, post, 'ogone', context=context)
|
||||
request.env['payment.transaction'].sudo().form_feedback(post, 'ogone')
|
||||
return werkzeug.utils.redirect(post.pop('return_url', '/'))
|
||||
|
||||
@http.route(['/payment/ogone/s2s/create_json'], type='json', auth='public', csrf=False)
|
||||
def ogone_s2s_create_json(self, **kwargs):
|
||||
data = kwargs
|
||||
acquirer_id = int(data.get('acquirer_id'))
|
||||
acquirer = request.env['payment.acquirer'].browse(acquirer_id)
|
||||
new_id = acquirer.s2s_process(data)
|
||||
new_id = request.env['payment.acquirer'].browse(int(kwargs.get('acquirer_id'))).s2s_process(kwargs)
|
||||
return new_id
|
||||
|
||||
@http.route(['/payment/ogone/s2s/create'], type='http', auth='public', methods=["POST"], csrf=False)
|
||||
def ogone_s2s_create(self, **post):
|
||||
acquirer_id = int(post.get('acquirer_id'))
|
||||
acquirer = request.env['payment.acquirer'].browse(acquirer_id)
|
||||
acquirer.s2s_process(post)
|
||||
request.env['payment.acquirer'].browse(int(post.get('acquirer_id'))).s2s_process(post)
|
||||
return werkzeug.utils.redirect(post.get('return_url', '/'))
|
||||
|
||||
@http.route(['/payment/ogone/s2s/feedback'], auth='none', csrf=False)
|
||||
def feedback(self, **kwargs):
|
||||
cr, uid, context = request.cr, SUPERUSER_ID, request.context
|
||||
payment = request.registry.get('payment.transaction')
|
||||
try:
|
||||
tx = payment._ogone_form_get_tx_from_data(cr, uid, kwargs, context=context)
|
||||
payment._ogone_s2s_validate(tx)
|
||||
tx = request.env['payment.transaction']._ogone_form_get_tx_from_data(kwargs)
|
||||
tx._ogone_s2s_validate()
|
||||
except ValidationError:
|
||||
return 'ko'
|
||||
|
||||
return 'ok'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="payment.payment_acquirer_ogone" model="payment.acquirer">
|
||||
@@ -20,4 +20,4 @@
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -1,39 +1,45 @@
|
||||
# coding: utf-8
|
||||
|
||||
import datetime
|
||||
from hashlib import sha1
|
||||
import logging
|
||||
from lxml import etree, objectify
|
||||
from openerp.tools.translate import _
|
||||
from pprint import pformat
|
||||
import time
|
||||
from unicodedata import normalize
|
||||
from urllib import urlencode
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import time
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.addons.payment.models.payment_acquirer import ValidationError
|
||||
from openerp.addons.payment_ogone.controllers.main import OgoneController
|
||||
from openerp.addons.payment_ogone.data import ogone
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools import float_round, DEFAULT_SERVER_DATE_FORMAT
|
||||
from openerp.tools.float_utils import float_compare, float_repr
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.addons.payment.models.payment_acquirer import ValidationError
|
||||
from odoo.addons.payment_ogone.controllers.main import OgoneController
|
||||
from odoo.addons.payment_ogone.data import ogone
|
||||
from odoo.tools import float_round, DEFAULT_SERVER_DATE_FORMAT
|
||||
from odoo.tools.float_utils import float_compare, float_repr
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PaymentAcquirerOgone(osv.Model):
|
||||
class PaymentAcquirerOgone(models.Model):
|
||||
_inherit = 'payment.acquirer'
|
||||
|
||||
def _get_ogone_urls(self, cr, uid, environment, context=None):
|
||||
provider = fields.Selection(selection_add=[('ogone', 'Ogone')])
|
||||
ogone_pspid = fields.Char('PSPID', required_if_provider='ogone')
|
||||
ogone_userid = fields.Char('API User ID', required_if_provider='ogone')
|
||||
ogone_password = fields.Char('API User Password', required_if_provider='ogone')
|
||||
ogone_shakey_in = fields.Char('SHA Key IN', size=32, required_if_provider='ogone')
|
||||
ogone_shakey_out = fields.Char('SHA Key OUT', size=32, required_if_provider='ogone')
|
||||
ogone_alias_usage = fields.Char('Alias Usage', help="""If you want to use Ogone Aliases,
|
||||
this default Alias Usage will be presented to
|
||||
the customer as the reason you want to
|
||||
keep his payment data""")
|
||||
|
||||
def _get_ogone_urls(self, environment):
|
||||
""" Ogone URLS:
|
||||
|
||||
- standard order: POST address for form-based
|
||||
|
||||
@TDETODO: complete me
|
||||
"""
|
||||
- standard order: POST address for form-based """
|
||||
return {
|
||||
'ogone_standard_order_url': 'https://secure.ogone.com/ncol/%s/orderstandard_utf8.asp' % (environment,),
|
||||
'ogone_direct_order_url': 'https://secure.ogone.com/ncol/%s/orderdirect_utf8.asp' % (environment,),
|
||||
@@ -41,38 +47,19 @@ class PaymentAcquirerOgone(osv.Model):
|
||||
'ogone_afu_agree_url': 'https://secure.ogone.com/ncol/%s/AFU_agree.asp' % (environment,),
|
||||
}
|
||||
|
||||
def _get_providers(self, cr, uid, context=None):
|
||||
providers = super(PaymentAcquirerOgone, self)._get_providers(cr, uid, context=context)
|
||||
providers.append(['ogone', 'Ogone'])
|
||||
return providers
|
||||
|
||||
_columns = {
|
||||
'ogone_pspid': fields.char('PSPID', required_if_provider='ogone'),
|
||||
'ogone_userid': fields.char('API User ID', required_if_provider='ogone'),
|
||||
'ogone_password': fields.char('API User Password', required_if_provider='ogone'),
|
||||
'ogone_shakey_in': fields.char('SHA Key IN', size=32, required_if_provider='ogone'),
|
||||
'ogone_shakey_out': fields.char('SHA Key OUT', size=32, required_if_provider='ogone'),
|
||||
'ogone_alias_usage': fields.char('Alias Usage', help="""If you want to use Ogone Aliases,
|
||||
this default Alias Usage will be presented to
|
||||
the customer as the reason you want to
|
||||
keep his payment data""")
|
||||
}
|
||||
|
||||
def _ogone_generate_shasign(self, acquirer, inout, values):
|
||||
def _ogone_generate_shasign(self, 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' (ogone
|
||||
contacting openerp). In this last case only some
|
||||
:param string inout: 'in' (odoo contacting ogone) or 'out' (ogone
|
||||
contacting odoo). 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.provider == 'ogone'
|
||||
key = getattr(acquirer, 'ogone_shakey_' + inout)
|
||||
assert self.provider == 'ogone'
|
||||
key = getattr(self, 'ogone_shakey_' + inout)
|
||||
|
||||
def filter_key(key):
|
||||
if inout == 'in':
|
||||
@@ -147,12 +134,11 @@ class PaymentAcquirerOgone(osv.Model):
|
||||
shasign = sha1(sign).hexdigest()
|
||||
return shasign
|
||||
|
||||
def ogone_form_generate_values(self, cr, uid, ids, values, context=None):
|
||||
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
|
||||
acquirer = self.browse(cr, uid, ids, context=context)[0]
|
||||
def ogone_form_generate_values(self, values):
|
||||
base_url = self.env['ir.config_parameter'].get_param('web.base.url')
|
||||
ogone_tx_values = dict(values)
|
||||
temp_ogone_tx_values = {
|
||||
'PSPID': acquirer.ogone_pspid,
|
||||
'PSPID': self.ogone_pspid,
|
||||
'ORDERID': values['reference'],
|
||||
'AMOUNT': float_repr(float_round(values['amount'], 2) * 100, 0),
|
||||
'CURRENCY': values['currency'] and values['currency'].name or '',
|
||||
@@ -173,20 +159,18 @@ class PaymentAcquirerOgone(osv.Model):
|
||||
if values.get('type') == 'form_save':
|
||||
temp_ogone_tx_values.update({
|
||||
'ALIAS': 'ODOO-NEW-ALIAS-%s' % time.time(), # something unique,
|
||||
'ALIASUSAGE': values.get('alias_usage') or acquirer.ogone_alias_usage,
|
||||
'ALIASUSAGE': values.get('alias_usage') or self.ogone_alias_usage,
|
||||
})
|
||||
shasign = self._ogone_generate_shasign(acquirer, 'in', temp_ogone_tx_values)
|
||||
shasign = self._ogone_generate_shasign('in', temp_ogone_tx_values)
|
||||
temp_ogone_tx_values['SHASIGN'] = shasign
|
||||
ogone_tx_values.update(temp_ogone_tx_values)
|
||||
return ogone_tx_values
|
||||
|
||||
def ogone_get_form_action_url(self, cr, uid, ids, context=None):
|
||||
acquirer = self.browse(cr, uid, ids, context=context)[0]
|
||||
return self._get_ogone_urls(cr, uid, acquirer.environment, context=context)['ogone_standard_order_url']
|
||||
def ogone_get_form_action_url(self):
|
||||
return self._get_ogone_urls(self.environment)['ogone_standard_order_url']
|
||||
|
||||
def ogone_s2s_form_validate(self, cr, uid, ids, data, context=None):
|
||||
def ogone_s2s_form_validate(self, data):
|
||||
error = dict()
|
||||
error_message = []
|
||||
|
||||
mandatory_fields = ["cc_number", "cc_cvc", "cc_holder_name", "cc_expiry", "cc_brand"]
|
||||
# Validation
|
||||
@@ -196,7 +180,7 @@ class PaymentAcquirerOgone(osv.Model):
|
||||
|
||||
return False if error else True
|
||||
|
||||
def ogone_s2s_form_process(self, cr, uid, data, context=None):
|
||||
def ogone_s2s_form_process(self, data):
|
||||
values = {
|
||||
'cc_number': data.get('cc_number'),
|
||||
'cc_cvc': int(data.get('cc_cvc')),
|
||||
@@ -206,11 +190,11 @@ class PaymentAcquirerOgone(osv.Model):
|
||||
'acquirer_id': int(data.get('acquirer_id')),
|
||||
'partner_id': int(data.get('partner_id'))
|
||||
}
|
||||
pm_id = self.pool['payment.token'].create(cr, SUPERUSER_ID, values, context=context)
|
||||
pm_id = self.env['payment.token'].sudo().create(values)
|
||||
return pm_id
|
||||
|
||||
|
||||
class PaymentTxOgone(osv.Model):
|
||||
class PaymentTxOgone(models.Model):
|
||||
_inherit = 'payment.transaction'
|
||||
# ogone status
|
||||
_ogone_valid_tx_status = [5, 9]
|
||||
@@ -222,7 +206,8 @@ class PaymentTxOgone(osv.Model):
|
||||
# FORM RELATED METHODS
|
||||
# --------------------------------------------------
|
||||
|
||||
def _ogone_form_get_tx_from_data(self, cr, uid, data, context=None):
|
||||
@api.model
|
||||
def _ogone_form_get_tx_from_data(self, data):
|
||||
""" Given a data dict coming from ogone, verify it and find the related
|
||||
transaction record. Create a payment token if an alias is returned."""
|
||||
reference, pay_id, shasign, alias = data.get('orderID'), data.get('PAYID'), data.get('SHASIGN'), data.get('ALIAS')
|
||||
@@ -232,19 +217,18 @@ class PaymentTxOgone(osv.Model):
|
||||
raise ValidationError(error_msg)
|
||||
|
||||
# find tx -> @TDENOTE use paytid ?
|
||||
tx_ids = self.search(cr, uid, [('reference', '=', reference)], context=context)
|
||||
if not tx_ids or len(tx_ids) > 1:
|
||||
tx = self.search([('reference', '=', reference)])
|
||||
if not tx or len(tx) > 1:
|
||||
error_msg = _('Ogone: received data for reference %s') % (reference)
|
||||
if not tx_ids:
|
||||
if not tx:
|
||||
error_msg += _('; no order found')
|
||||
else:
|
||||
error_msg += _('; multiple order found')
|
||||
_logger.info(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']._ogone_generate_shasign(tx.acquirer_id, 'out', data)
|
||||
shasign_check = tx.acquirer_id._ogone_generate_shasign('out', data)
|
||||
if shasign_check.upper() != shasign.upper():
|
||||
error_msg = _('Ogone: invalid shasign, received %s, computed %s, for data %s') % (shasign, shasign_check, data)
|
||||
_logger.info(error_msg)
|
||||
@@ -255,39 +239,36 @@ class PaymentTxOgone(osv.Model):
|
||||
|
||||
# alias was created on ogone server, store it
|
||||
if alias:
|
||||
method_obj = self.pool['payment.token']
|
||||
Method = self.env['payment.token']
|
||||
domain = [('acquirer_ref', '=', alias)]
|
||||
cardholder = data.get('CN')
|
||||
if not method_obj.search_count(cr, uid, domain, context=context):
|
||||
if not Method.search_count(domain):
|
||||
_logger.info('Ogone: saving alias %s for partner %s' % (data.get('CARDNO'), tx.partner_id))
|
||||
ref = method_obj.create(cr, uid, {'name': data.get('CARDNO') + (' - ' + cardholder if cardholder else ''),
|
||||
'partner_id': tx.partner_id.id,
|
||||
'acquirer_id': tx.acquirer_id.id,
|
||||
'acquirer_ref': alias
|
||||
})
|
||||
ref = Method.create({'name': data.get('CARDNO') + (' - ' + cardholder if cardholder else ''),
|
||||
'partner_id': tx.partner_id.id,
|
||||
'acquirer_id': tx.acquirer_id.id,
|
||||
'acquirer_ref': alias})
|
||||
tx.write({'payment_token_id': ref})
|
||||
|
||||
return tx
|
||||
|
||||
def _ogone_form_get_invalid_parameters(self, cr, uid, ids, data, context=None):
|
||||
tx = self.browse(cr, uid, ids, context=context)[0]
|
||||
def _ogone_form_get_invalid_parameters(self, data):
|
||||
invalid_parameters = []
|
||||
|
||||
# TODO: txn_id: should be false at draft, set afterwards, and verified with txn details
|
||||
if tx.acquirer_reference and data.get('PAYID') != tx.acquirer_reference:
|
||||
invalid_parameters.append(('PAYID', data.get('PAYID'), tx.acquirer_reference))
|
||||
if self.acquirer_reference and data.get('PAYID') != self.acquirer_reference:
|
||||
invalid_parameters.append(('PAYID', data.get('PAYID'), self.acquirer_reference))
|
||||
# check what is bought
|
||||
if float_compare(float(data.get('amount', '0.0')), tx.amount, 2) != 0:
|
||||
invalid_parameters.append(('amount', data.get('amount'), '%.2f' % tx.amount))
|
||||
if data.get('currency') != tx.currency_id.name:
|
||||
invalid_parameters.append(('currency', data.get('currency'), tx.currency_id.name))
|
||||
if float_compare(float(data.get('amount', '0.0')), self.amount, 2) != 0:
|
||||
invalid_parameters.append(('amount', data.get('amount'), '%.2f' % self.amount))
|
||||
if data.get('currency') != self.currency_id.name:
|
||||
invalid_parameters.append(('currency', data.get('currency'), self.currency_id.name))
|
||||
|
||||
return invalid_parameters
|
||||
|
||||
def _ogone_form_validate(self, cr, uid, ids, data, context=None):
|
||||
tx = self.browse(cr, uid, ids, context=context)[0]
|
||||
if tx.state == 'done':
|
||||
_logger.info('Ogone: trying to validate an already validated tx (ref %s)', tx.reference)
|
||||
def _ogone_form_validate(self, data):
|
||||
if self.state == 'done':
|
||||
_logger.info('Ogone: trying to validate an already validated tx (ref %s)', self.reference)
|
||||
return True
|
||||
|
||||
status = int(data.get('STATUS', '0'))
|
||||
@@ -297,25 +278,25 @@ class PaymentTxOgone(osv.Model):
|
||||
'date_validate': datetime.datetime.strptime(data['TRXDATE'], '%m/%d/%y').strftime(DEFAULT_SERVER_DATE_FORMAT),
|
||||
'acquirer_reference': data['PAYID'],
|
||||
}
|
||||
if data.get('ALIAS') and tx.partner_id and tx.type == 'form_save' and not tx.payment_token_id:
|
||||
pm_id = self.pool['payment.token'].create(cr, uid, {
|
||||
'partner_id': tx.partner_id.id,
|
||||
'acquirer_id': tx.acquirer_id.id,
|
||||
if data.get('ALIAS') and self.partner_id and self.type == 'form_save' and not self.payment_token_id:
|
||||
pm = self.env['payment.token'].create({
|
||||
'partner_id': self.partner_id.id,
|
||||
'acquirer_id': self.acquirer_id.id,
|
||||
'acquirer_ref': data.get('ALIAS'),
|
||||
'name': '%s - %s' % (data.get('CARDNO'), data.get('CN'))
|
||||
}, context=context)
|
||||
vals.update(payment_token_id=pm_id)
|
||||
tx.write(vals)
|
||||
if tx.callback_eval:
|
||||
safe_eval(tx.callback_eval, {'self': tx})
|
||||
})
|
||||
vals.update(payment_token_id=pm.id)
|
||||
self.write(vals)
|
||||
if self.callback_eval:
|
||||
safe_eval(self.callback_eval, {'self': self})
|
||||
return True
|
||||
elif status in self._ogone_cancel_tx_status:
|
||||
tx.write({
|
||||
self.write({
|
||||
'state': 'cancel',
|
||||
'acquirer_reference': data.get('PAYID'),
|
||||
})
|
||||
elif status in self._ogone_pending_tx_status or status in self._ogone_wait_tx_status:
|
||||
tx.write({
|
||||
self.write({
|
||||
'state': 'pending',
|
||||
'acquirer_reference': data.get('PAYID'),
|
||||
})
|
||||
@@ -326,7 +307,7 @@ class PaymentTxOgone(osv.Model):
|
||||
'error_msg': ogone.OGONE_ERROR_MAP.get(data.get('NCERROR')),
|
||||
}
|
||||
_logger.info(error)
|
||||
tx.write({
|
||||
self.write({
|
||||
'state': 'error',
|
||||
'state_message': error,
|
||||
'acquirer_reference': data.get('PAYID'),
|
||||
@@ -336,29 +317,29 @@ class PaymentTxOgone(osv.Model):
|
||||
# --------------------------------------------------
|
||||
# S2S RELATED METHODS
|
||||
# --------------------------------------------------
|
||||
def ogone_s2s_do_transaction(self, cr, uid, ids, context=None, **kwargs):
|
||||
|
||||
def ogone_s2s_do_transaction(self, **kwargs):
|
||||
# TODO: create tx with s2s type
|
||||
tx = self.browse(cr, uid, ids, context=context)[0]
|
||||
account = tx.acquirer_id
|
||||
reference = tx.reference or "ODOO-%s-%s" % (datetime.datetime.now().strftime('%y%m%d_%H%M%S'), tx.partner_id.id)
|
||||
account = self.acquirer_id
|
||||
reference = self.reference or "ODOO-%s-%s" % (datetime.datetime.now().strftime('%y%m%d_%H%M%S'), self.partner_id.id)
|
||||
|
||||
data = {
|
||||
'PSPID': account.ogone_pspid,
|
||||
'USERID': account.ogone_userid,
|
||||
'PSWD': account.ogone_password,
|
||||
'ORDERID': reference,
|
||||
'AMOUNT': long(tx.amount * 100),
|
||||
'CURRENCY': tx.currency_id.name,
|
||||
'AMOUNT': long(self.amount * 100),
|
||||
'CURRENCY': self.currency_id.name,
|
||||
'OPERATION': 'SAL',
|
||||
'ECI': 2, # Recurring (from MOTO)
|
||||
'ALIAS': tx.payment_token_id.acquirer_ref,
|
||||
'ALIAS': self.payment_token_id.acquirer_ref,
|
||||
'RTIMEOUT': 30,
|
||||
}
|
||||
|
||||
if kwargs.get('3d_secure'):
|
||||
data.update({
|
||||
'FLAG3D': 'Y',
|
||||
'LANGUAGE': tx.partner_id.lang or 'en_US',
|
||||
'LANGUAGE': self.partner_id.lang or 'en_US',
|
||||
})
|
||||
|
||||
for url in 'accept decline exception'.split():
|
||||
@@ -368,9 +349,9 @@ class PaymentTxOgone(osv.Model):
|
||||
key = '{0}URL'.format(url).upper()
|
||||
data[key] = val
|
||||
|
||||
data['SHASIGN'] = self.pool['payment.acquirer']._ogone_generate_shasign(tx.acquirer_id, 'in', data)
|
||||
data['SHASIGN'] = self.acquirer_id._ogone_generate_shasign('in', data)
|
||||
|
||||
direct_order_url = 'https://secure.ogone.com/ncol/%s/orderdirect.asp' % (tx.acquirer_id.environment)
|
||||
direct_order_url = 'https://secure.ogone.com/ncol/%s/orderdirect.asp' % (self.acquirer_id.environment)
|
||||
|
||||
_logger.debug("Ogone data %s", pformat(data))
|
||||
request = urllib2.Request(direct_order_url, urlencode(data))
|
||||
@@ -384,53 +365,51 @@ class PaymentTxOgone(osv.Model):
|
||||
_logger.exception('Invalid xml response from ogone')
|
||||
raise
|
||||
|
||||
return self._ogone_s2s_validate_tree(tx, tree)
|
||||
return self._ogone_s2s_validate_tree(tree)
|
||||
|
||||
def _ogone_s2s_validate(self, cr, uid, ids, context=None):
|
||||
tx = self.browse(cr, uid, ids, context=context)[0]
|
||||
tree = self._ogone_s2s_get_tx_status(tx)
|
||||
return self._ogone_s2s_validate_tree(tx, tree)
|
||||
def _ogone_s2s_validate(self):
|
||||
tree = self._ogone_s2s_get_tx_status()
|
||||
return self._ogone_s2s_validate_tree(tree)
|
||||
|
||||
def _ogone_s2s_validate_tree(self, cr, uid, ids, tree, tries=2, context=None):
|
||||
tx = self.browse(cr, uid, ids, context=context)[0]
|
||||
if tx.state not in ('draft', 'pending'):
|
||||
_logger.info('Ogone: trying to validate an already validated tx (ref %s)', tx.reference)
|
||||
def _ogone_s2s_validate_tree(self, tree, tries=2):
|
||||
if self.state not in ('draft', 'pending'):
|
||||
_logger.info('Ogone: trying to validate an already validated tx (ref %s)', self.reference)
|
||||
return True
|
||||
|
||||
status = int(tree.get('STATUS') or 0)
|
||||
if status in self._ogone_valid_tx_status:
|
||||
tx.write({
|
||||
self.write({
|
||||
'state': 'done',
|
||||
'date_validate': datetime.date.today().strftime(DEFAULT_SERVER_DATE_FORMAT),
|
||||
'acquirer_reference': tree.get('PAYID'),
|
||||
})
|
||||
if tree.get('ALIAS') and tx.partner_id and tx.type == 'form_save' and not tx.payment_token_id:
|
||||
pm = tx.env['payment.token'].create({
|
||||
'partner_id': tx.partner_id.id,
|
||||
'acquirer_id': tx.acquirer_id.id,
|
||||
if tree.get('ALIAS') and self.partner_id and self.type == 'form_save' and not self.payment_token_id:
|
||||
pm = self.env['payment.token'].create({
|
||||
'partner_id': self.partner_id.id,
|
||||
'acquirer_id': self.acquirer_id.id,
|
||||
'acquirer_ref': tree.get('ALIAS'),
|
||||
'name': tree.get('CARDNO'),
|
||||
})
|
||||
tx.write({'payment_token_id': pm.id})
|
||||
if tx.callback_eval:
|
||||
safe_eval(tx.callback_eval, {'self': tx})
|
||||
self.write({'payment_token_id': pm.id})
|
||||
if self.callback_eval:
|
||||
safe_eval(self.callback_eval, {'self': self})
|
||||
return True
|
||||
elif status in self._ogone_cancel_tx_status:
|
||||
tx.write({
|
||||
self.write({
|
||||
'state': 'cancel',
|
||||
'acquirer_reference': tree.get('PAYID'),
|
||||
})
|
||||
elif status in self._ogone_pending_tx_status:
|
||||
tx.write({
|
||||
self.write({
|
||||
'state': 'pending',
|
||||
'acquirer_reference': tree.get('PAYID'),
|
||||
'html_3ds': str(tree.HTML_ANSWER).decode('base64')
|
||||
})
|
||||
elif (not status or status in self._ogone_wait_tx_status) and tries > 0:
|
||||
time.sleep(500)
|
||||
tx.write({'acquirer_reference': tree.get('PAYID')})
|
||||
tree = self._ogone_s2s_get_tx_status(tx)
|
||||
return self._ogone_s2s_validate_tree(tx, tree, tries - 1)
|
||||
self.write({'acquirer_reference': tree.get('PAYID')})
|
||||
tree = self._ogone_s2s_get_tx_status(self)
|
||||
return self._ogone_s2s_validate_tree(self, tree, tries - 1)
|
||||
else:
|
||||
error = 'Ogone: feedback error: %(error_str)s\n\n%(error_code)s: %(error_msg)s' % {
|
||||
'error_str': tree.get('NCERRORPLUS'),
|
||||
@@ -438,26 +417,25 @@ class PaymentTxOgone(osv.Model):
|
||||
'error_msg': ogone.OGONE_ERROR_MAP.get(tree.get('NCERROR')),
|
||||
}
|
||||
_logger.info(error)
|
||||
tx.write({
|
||||
self.write({
|
||||
'state': 'error',
|
||||
'state_message': error,
|
||||
'acquirer_reference': tree.get('PAYID'),
|
||||
})
|
||||
return False
|
||||
|
||||
def _ogone_s2s_get_tx_status(self, cr, uid, ids, context=None):
|
||||
tx = self.browse(cr, uid, ids, context=context)[0]
|
||||
account = tx.acquirer_id
|
||||
def _ogone_s2s_get_tx_status(self):
|
||||
account = self.acquirer_id
|
||||
#reference = tx.reference or "ODOO-%s-%s" % (datetime.datetime.now().strftime('%Y%m%d_%H%M%S'), tx.partner_id.id)
|
||||
|
||||
data = {
|
||||
'PAYID': tx.acquirer_reference,
|
||||
'PAYID': self.acquirer_reference,
|
||||
'PSPID': account.ogone_pspid,
|
||||
'USERID': account.ogone_userid,
|
||||
'PSWD': account.ogone_password,
|
||||
}
|
||||
|
||||
query_direct_url = 'https://secure.ogone.com/ncol/%s/querydirect.asp' % (tx.acquirer_id.environment)
|
||||
query_direct_url = 'https://secure.ogone.com/ncol/%s/querydirect.asp' % (self.acquirer_id.environment)
|
||||
|
||||
_logger.debug("Ogone data %s", pformat(data))
|
||||
request = urllib2.Request(query_direct_url, urlencode(data))
|
||||
@@ -474,14 +452,14 @@ class PaymentTxOgone(osv.Model):
|
||||
return tree
|
||||
|
||||
|
||||
class PaymentToken(osv.Model):
|
||||
class PaymentToken(models.Model):
|
||||
_inherit = 'payment.token'
|
||||
|
||||
def ogone_create(self, cr, uid, values, context=None):
|
||||
def ogone_create(self, values):
|
||||
if values.get('cc_number'):
|
||||
# create a alias via batch
|
||||
values['cc_number'] = values['cc_number'].replace(' ', '')
|
||||
acquirer = self.pool['payment.acquirer'].browse(cr, uid, values['acquirer_id'])
|
||||
acquirer = self.env['payment.acquirer'].browse(values['acquirer_id'])
|
||||
alias = 'ODOO-NEW-ALIAS-%s' % time.time()
|
||||
|
||||
expiry = str(values['cc_expiry'][:2]) + str(values['cc_expiry'][-2:])
|
||||
|
||||
@@ -4,27 +4,23 @@ from lxml import objectify
|
||||
import time
|
||||
import urlparse
|
||||
|
||||
from openerp.addons.payment.models.payment_acquirer import ValidationError
|
||||
from openerp.addons.payment.tests.common import PaymentAcquirerCommon
|
||||
from openerp.addons.payment_ogone.controllers.main import OgoneController
|
||||
from openerp.tools import mute_logger
|
||||
from odoo.addons.payment.models.payment_acquirer import ValidationError
|
||||
from odoo.addons.payment.tests.common import PaymentAcquirerCommon
|
||||
from odoo.addons.payment_ogone.controllers.main import OgoneController
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
class OgonePayment(PaymentAcquirerCommon):
|
||||
|
||||
def setUp(self):
|
||||
super(OgonePayment, self).setUp()
|
||||
cr, uid = self.cr, self.uid
|
||||
self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
|
||||
|
||||
# get the adyen account
|
||||
model, self.ogone_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment', 'payment_acquirer_ogone')
|
||||
self.ogone = self.env.ref('payment.payment_acquirer_ogone')
|
||||
|
||||
def test_10_ogone_form_render(self):
|
||||
cr, uid, context = self.cr, self.uid, {}
|
||||
base_url = self.env['ir.config_parameter'].get_param('web.base.url')
|
||||
# be sure not to do stupid thing
|
||||
ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None)
|
||||
self.assertEqual(ogone.environment, 'test', 'test without test environment')
|
||||
self.assertEqual(self.ogone.environment, 'test', 'test without test environment')
|
||||
|
||||
# ----------------------------------------
|
||||
# Test: button direct rendering + shasign
|
||||
@@ -44,19 +40,17 @@ class OgonePayment(PaymentAcquirerCommon):
|
||||
'OWNERTOWN': 'Sin City',
|
||||
'OWNERTELNO': '0032 12 34 56 78',
|
||||
'SHASIGN': '815f67b8ff70d234ffcf437c13a9fa7f807044cc',
|
||||
'ACCEPTURL': '%s' % urlparse.urljoin(self.base_url, OgoneController._accept_url),
|
||||
'DECLINEURL': '%s' % urlparse.urljoin(self.base_url, OgoneController._decline_url),
|
||||
'EXCEPTIONURL': '%s' % urlparse.urljoin(self.base_url, OgoneController._exception_url),
|
||||
'CANCELURL': '%s' % urlparse.urljoin(self.base_url, OgoneController._cancel_url),
|
||||
'ACCEPTURL': '%s' % urlparse.urljoin(base_url, OgoneController._accept_url),
|
||||
'DECLINEURL': '%s' % urlparse.urljoin(base_url, OgoneController._decline_url),
|
||||
'EXCEPTIONURL': '%s' % urlparse.urljoin(base_url, OgoneController._exception_url),
|
||||
'CANCELURL': '%s' % urlparse.urljoin(base_url, OgoneController._cancel_url),
|
||||
}
|
||||
|
||||
# render the button
|
||||
res = self.payment_acquirer.render(
|
||||
cr, uid, self.ogone_id,
|
||||
'test_ref0', 0.01, self.currency_euro_id,
|
||||
res = self.ogone.render(
|
||||
'test_ref0', 0.01, self.currency_euro.id,
|
||||
partner_id=None,
|
||||
partner_values=self.buyer_values,
|
||||
context=context)
|
||||
partner_values=self.buyer_values)
|
||||
|
||||
# check form result
|
||||
tree = objectify.fromstring(res)
|
||||
@@ -75,23 +69,18 @@ class OgonePayment(PaymentAcquirerCommon):
|
||||
# ----------------------------------------
|
||||
|
||||
# create a new draft tx
|
||||
tx_id = self.payment_transaction.create(
|
||||
cr, uid, {
|
||||
'amount': 0.01,
|
||||
'acquirer_id': self.ogone_id,
|
||||
'currency_id': self.currency_euro_id,
|
||||
'reference': 'test_ref0',
|
||||
'partner_id': self.buyer_id,
|
||||
}, context=context
|
||||
)
|
||||
tx = self.env['payment.transaction'].create({
|
||||
'amount': 0.01,
|
||||
'acquirer_id': self.ogone.id,
|
||||
'currency_id': self.currency_euro.id,
|
||||
'reference': 'test_ref0',
|
||||
'partner_id': self.buyer_id})
|
||||
# render the button
|
||||
res = self.payment_acquirer.render(
|
||||
cr, uid, self.ogone_id,
|
||||
res = self.ogone.render(
|
||||
'should_be_erased', 0.01, self.currency_euro,
|
||||
tx_id=tx_id,
|
||||
tx_id=tx.id,
|
||||
partner_id=None,
|
||||
partner_values=self.buyer_values,
|
||||
context=context)
|
||||
partner_values=self.buyer_values)
|
||||
|
||||
# check form result
|
||||
tree = objectify.fromstring(res)
|
||||
@@ -105,12 +94,10 @@ class OgonePayment(PaymentAcquirerCommon):
|
||||
'ogone: wrong value for form input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
|
||||
)
|
||||
|
||||
@mute_logger('openerp.addons.payment_ogone.models.ogone', 'ValidationError')
|
||||
@mute_logger('openerp.addons.payment_ogone.models.payment', 'ValidationError')
|
||||
def test_20_ogone_form_management(self):
|
||||
cr, uid, context = self.cr, self.uid, {}
|
||||
# be sure not to do stupid thing
|
||||
ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None)
|
||||
self.assertEqual(ogone.environment, 'test', 'test without test environment')
|
||||
self.assertEqual(self.ogone.environment, 'test', 'test without test environment')
|
||||
|
||||
# typical data posted by ogone after client has successfully paid
|
||||
ogone_post_data = {
|
||||
@@ -133,23 +120,19 @@ class OgonePayment(PaymentAcquirerCommon):
|
||||
|
||||
# should raise error about unknown tx
|
||||
with self.assertRaises(ValidationError):
|
||||
self.payment_transaction.ogone_form_feedback(cr, uid, ogone_post_data, context=context)
|
||||
self.env['payment.transaction'].form_feedback(ogone_post_data)
|
||||
|
||||
# create tx
|
||||
tx_id = self.payment_transaction.create(
|
||||
cr, uid, {
|
||||
'amount': 1.95,
|
||||
'acquirer_id': self.ogone_id,
|
||||
'currency_id': self.currency_euro_id,
|
||||
'reference': 'test_ref_2',
|
||||
'partner_name': 'Norbert Buyer',
|
||||
'partner_country_id': self.country_france_id,
|
||||
}, context=context
|
||||
)
|
||||
tx = self.env['payment.transaction'].create({
|
||||
'amount': 1.95,
|
||||
'acquirer_id': self.ogone.id,
|
||||
'currency_id': self.currency_euro.id,
|
||||
'reference': 'test_ref_2',
|
||||
'partner_name': 'Norbert Buyer',
|
||||
'partner_country_id': self.country_france.id})
|
||||
# validate it
|
||||
self.payment_transaction.ogone_form_feedback(cr, uid, ogone_post_data, context=context)
|
||||
tx.form_feedback(ogone_post_data)
|
||||
# check state
|
||||
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
|
||||
self.assertEqual(tx.state, 'done', 'ogone: validation did not put tx into done state')
|
||||
self.assertEqual(tx.ogone_payid, ogone_post_data.get('PAYID'), 'ogone: validation did not update tx payid')
|
||||
|
||||
@@ -159,67 +142,39 @@ class OgonePayment(PaymentAcquirerCommon):
|
||||
# now ogone post is ok: try to modify the SHASIGN
|
||||
ogone_post_data['SHASIGN'] = 'a4c16bae286317b82edb49188d3399249a784691'
|
||||
with self.assertRaises(ValidationError):
|
||||
self.payment_transaction.ogone_form_feedback(cr, uid, ogone_post_data, context=context)
|
||||
tx.form_feedback(ogone_post_data)
|
||||
|
||||
# simulate an error
|
||||
ogone_post_data['STATUS'] = 2
|
||||
ogone_post_data['SHASIGN'] = 'a4c16bae286317b82edb49188d3399249a784691'
|
||||
self.payment_transaction.ogone_form_feedback(cr, uid, ogone_post_data, context=context)
|
||||
tx.form_feedback(ogone_post_data)
|
||||
# check state
|
||||
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
|
||||
self.assertEqual(tx.state, 'error', 'ogone: erroneous validation did not put tx into error state')
|
||||
|
||||
def test_30_ogone_s2s(self):
|
||||
test_ref = 'test_ref_%.15f' % time.time()
|
||||
cr, uid, context = self.cr, self.uid, {}
|
||||
# be sure not to do stupid thing
|
||||
ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None)
|
||||
self.assertEqual(ogone.environment, 'test', 'test without test environment')
|
||||
self.assertEqual(self.ogone.environment, 'test', 'test without test environment')
|
||||
|
||||
# create a new draft tx
|
||||
tx_id = self.payment_transaction.create(
|
||||
cr, uid, {
|
||||
'amount': 0.01,
|
||||
'acquirer_id': self.ogone_id,
|
||||
'currency_id': self.currency_euro_id,
|
||||
'reference': test_ref,
|
||||
'partner_id': self.buyer_id,
|
||||
'type': 'server2server',
|
||||
}, context=context
|
||||
)
|
||||
tx = self.env['payment.transaction'].create({
|
||||
'amount': 0.01,
|
||||
'acquirer_id': self.ogone.id,
|
||||
'currency_id': self.currency_euro.id,
|
||||
'reference': test_ref,
|
||||
'partner_id': self.buyer_id,
|
||||
'type': 'server2server',
|
||||
})
|
||||
|
||||
# create an alias
|
||||
res = self.payment_transaction.ogone_s2s_create_alias(
|
||||
cr, uid, tx_id, {
|
||||
'expiry_date_mm': '01',
|
||||
'expiry_date_yy': '2015',
|
||||
'holder_name': 'Norbert Poilu',
|
||||
'number': '4000000000000002',
|
||||
'brand': 'VISA',
|
||||
}, context=context)
|
||||
res = tx.ogone_s2s_create_alias({
|
||||
'expiry_date_mm': '01',
|
||||
'expiry_date_yy': '2015',
|
||||
'holder_name': 'Norbert Poilu',
|
||||
'number': '4000000000000002',
|
||||
'brand': 'VISA'})
|
||||
|
||||
# check an alias is set, containing at least OPENERP
|
||||
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
|
||||
self.assertIn('OPENERP', tx.partner_reference, 'ogone: wrong partner reference after creating an alias')
|
||||
|
||||
res = self.payment_transaction.ogone_s2s_execute(cr, uid, tx_id, {}, context=context)
|
||||
# print res
|
||||
|
||||
|
||||
# {
|
||||
# 'orderID': u'reference',
|
||||
# 'STATUS': u'9',
|
||||
# 'CARDNO': u'XXXXXXXXXXXX0002',
|
||||
# 'PAYID': u'24998692',
|
||||
# 'CN': u'Norbert Poilu',
|
||||
# 'NCERROR': u'0',
|
||||
# 'TRXDATE': u'11/05/13',
|
||||
# 'IP': u'85.201.233.72',
|
||||
# 'BRAND': u'VISA',
|
||||
# 'ACCEPTANCE': u'test123',
|
||||
# 'currency': u'EUR',
|
||||
# 'amount': u'1.95',
|
||||
# 'SHASIGN': u'EFDC56879EF7DE72CCF4B397076B5C9A844CB0FA',
|
||||
# 'ED': u'0314',
|
||||
# 'PM': u'CreditCard'
|
||||
# }
|
||||
res = tx.ogone_s2s_execute({})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<template id="ogone_acquirer_button">
|
||||
@@ -89,4 +89,4 @@
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="acquirer_form_ogone" model="ir.ui.view">
|
||||
@@ -22,4 +22,4 @@
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user