[CLEAN] payment_acquirer and acquirer implementation: cleaned code, removing duplicate code for managing transaction and partner values. Also removed dependency towards requests library. Updated acquirers data, not in no update.

bzr revid: tde@openerp.com-20131203142501-4cibxmcuvyp8uof9
This commit is contained in:
Thibault Delavallée
2013-12-03 15:25:01 +01:00
parent 9a54529ff4
commit 382829686d
13 changed files with 253 additions and 315 deletions
@@ -1,9 +1,9 @@
# -*- coding: utf-'8' "-*-"
from openerp.osv import osv, fields
import logging
from openerp.osv import osv, fields
_logger = logging.getLogger(__name__)
@@ -22,8 +22,9 @@ class ValidationError(ValueError):
class PaymentAcquirer(osv.Model):
""" Acquirer Model. Each specific acquirer can extend the model by adding
its own fields. Using the required_if_provider='<name>' attribute on fields
it is possible to have required fields that depend on a specific acquirer.
its own fields, using the acquirer_name as a prefix for the new fields.
Using the required_if_provider='<name>' attribute on fields it is possible
to have required fields that depend on a specific acquirer.
Each acquirer has a link to an ir.ui.view record that is a template of
a button used to display the payment form. See examples in ``payment_acquirer_ogone``
@@ -36,7 +37,10 @@ class PaymentAcquirer(osv.Model):
method that generates the values used to render the form button template.
- ``<name>_get_form_action_url(self, cr, uid, id, context=None):``: method
that returns the url of the button form. It is used for example in
ecommerce application, if you want to repost some data to the acquirer.
ecommerce application, if you want to post some data to the acquirer.
- ``<name>_compute_fees(self, cr, uid, id, amount, currency_id, country_id,
context=None)``: computed the fees of the acquirer, using generic fields
defined on the acquirer model (see fields definition).
Each acquirer should also define controllers to handle communication between
OpenERP and the acquirer. It generally consists in return urls given to the
@@ -54,8 +58,9 @@ class PaymentAcquirer(osv.Model):
'env': fields.selection(
[('test', 'Test'), ('prod', 'Production')],
string='Environment'),
'portal_published': fields.boolean('Visible in Portal',
help="Make this payment acquirer available (Customer invoices, etc.)"),
'portal_published': fields.boolean(
'Visible in Portal',
help="Make this payment acquirer available (Customer invoices, etc.)"),
# Fees
'fees_active': fields.boolean('Compute fees'),
'fees_dom_fixed': fields.float('Fixed domestic fees'),
@@ -89,27 +94,81 @@ class PaymentAcquirer(osv.Model):
return getattr(self, '%s_get_form_action_url' % acquirer.name)(cr, uid, id, context=context)
return False
def form_preprocess_values(self, cr, uid, id, reference, amount, currency_id, tx_id, partner_id, partner_values, tx_custom_values, context=None):
acquirer = self.browse(cr, uid, id, context=context)
tx_values = tx_custom_values
def form_preprocess_values(self, cr, uid, id, reference, amount, currency_id, tx_id, partner_id, partner_values, tx_values, context=None):
""" Pre process values before giving them to the acquirer-specific render
methods. Those methods will receive:
# compute country
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
tx_values['country_id'] = partner.country_id.id
elif partner_values and partner_values.get('country_name'):
country_ids = self.pool['res.country'].search(cr, uid, [('name', '=', partner_values.get('country_name'))], context=context)
tx_values['country_id'] = country_ids and country_ids[0] or None
- partner_values: will contain name, lang, email, zip, address, city,
country_id (int or False), country (browse or False), phone, reference
- tx_values: will contain refernece, amount, currency_id (int or False),
currency (browse or False), partner (browse or False)
"""
acquirer = self.browse(cr, uid, id, context=context)
if tx_id:
tx = self.browse(cr, uid, id, context=context)
tx_data = {
'reference': tx.reference,
'amount': tx.amount,
'currency_id': tx.currency_id.id,
'currency': tx.currency_id,
'partner': tx.partner_id,
}
partner_data = {
'name': tx.partner_name,
'lang': tx.partner_lang,
'email': tx.partner_email,
'zip': tx.partner_zip,
'address': tx.partner_address,
'city': tx.partner_city,
'country_id': tx.partner_country_id.id,
'country': tx.partner_country_id,
'phone': tx.partner_phone,
'reference': tx.partner_reference,
}
else:
tx_values['country_id'] = False
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
partner_data = self.pool['payment.transaction'].on_change_partner_id(cr, uid, None, partner_id, context=context)['values']
else:
partner, partner_data = False, {}
partner_data.update(partner_values)
if currency_id:
currency = self.pool['res.currency'].browse(cr, uid, currency_id, context=context)
else:
currency = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.currency_id
tx_data = {
'reference': reference,
'amount': amount,
'currency_id': currency.id,
'currency': currency,
'partner': partner,
}
# update tx values
tx_data.update(tx_values)
# update partner values
if not partner_data.get('address'):
partner_data['address'] = _partner_format_address(partner_data.get('street', ''), partner_data.get('street2', ''))
if not partner_data.get('country') and partner_data.get('country_id'):
partner_data['country'] = self.pool['res.country'].browse(cr, uid, partner_data.get('country_id'), context=context)
partner_data.update({
'first_name': _partner_split_name(partner_data['name'])[0],
'last_name': _partner_split_name(partner_data['name'])[1],
})
# compute fees
if hasattr(self, '%s_compute_fees' % acquirer.name):
tx_values['fees'] = getattr(self, '%s_compute_fees' % acquirer.name)(cr, uid, id, amount, currency_id, tx_values.get('country_id'), context=None)
fees_method_name = '%s_compute_fees' % acquirer.name
if hasattr(self, fees_method_name):
tx_data['fees'] = getattr(self, fees_method_name)(
cr, uid, id, tx_data['amount'], tx_data['currency_id'],
partner_data['country_id'], context=None)
return tx_values
return (partner_data, tx_data)
def render(self, cr, uid, id, reference, amount, currency_id, tx_id=None, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
def render(self, cr, uid, id, reference, amount, currency_id, tx_id=None, partner_id=False, partner_values=None, tx_values=None, context=None):
""" Renders the form template of the given acquirer as a qWeb template.
All templates will receive:
@@ -120,9 +179,9 @@ class PaymentAcquirer(osv.Model):
- reference: reference of the transaction
- partner: the current partner browse record, if any (not necessarily set)
- partner_values: a dictionary of partner-related values
- tx_custom_values: a dictionary of transaction related values that depends
on the acquirer. Some specific keys should be managed
in each provider, depending on the features it offers:
- tx_values: a dictionary of transaction related values that depends on
the acquirer. Some specific keys should be managed in each
provider, depending on the features it offers:
- 'feedback_url': feedback URL, controler that manage answer of the acquirer
(without base url) -> FIXME
@@ -147,38 +206,36 @@ class PaymentAcquirer(osv.Model):
"""
if context is None:
context = {}
if tx_custom_values is None:
tx_custom_values = {}
partner = None
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
if tx_values is None:
tx_values = {}
if partner_values is None:
partner_values = {}
acquirer = self.browse(cr, uid, id, context=context)
currency = self.pool['res.currency'].browse(cr, uid, currency_id, context=context)
# pre-process values
tx_values = self.form_preprocess_values(cr, uid, id, reference, amount, currency, tx_id, partner_id, partner_values, tx_custom_values, context=context)
partner_values, tx_values = self.form_preprocess_values(
cr, uid, id, reference, amount, currency_id, tx_id, partner_id,
partner_values, tx_values, context=context)
# call <name>_form_generate_values to update the tx dict with acqurier specific values
cust_method_name = '%s_form_generate_values' % (acquirer.name)
if tx_id and hasattr(self.pool['payment.transaction'], cust_method_name):
method = getattr(self.pool['payment.transaction'], cust_method_name)
tx_values = method(cr, uid, tx_id, tx_values, context=context)
elif hasattr(self, cust_method_name):
if hasattr(self, cust_method_name):
method = getattr(self, cust_method_name)
tx_values = method(cr, uid, id, reference, amount, currency, partner_id, partner_values, tx_values, context=context)
partner_values, tx_values = method(cr, uid, id, partner_values, tx_values, context=context)
qweb_context = {
'acquirer': acquirer,
'user': self.pool.get("res.users").browse(cr, uid, uid, context=context),
'reference': reference,
'amount': amount,
'currency': currency,
'partner': partner,
'reference': tx_values['reference'],
'amount': tx_values['amount'],
'currency': tx_values['currency'],
'partner': tx_values.get('partner'),
'partner_values': partner_values,
'tx_values': tx_values,
'context': context,
}
# because render accepts view ids but not qweb -> need to find the xml_id
# 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)
@@ -186,12 +243,6 @@ class PaymentTransaction(osv.Model):
""" Transaction Model. Each specific acquirer can extend the model by adding
its own fields.
Methods that should be added in an acquirer-specific implementation:
- ``<name>_form_generate_values(self, cr, uid, id, tx_custom_values=None,
context=None)``: method that generates the values used to render the
form button template.
Methods that can be added in an acquirer-specific implementation:
- ``<name>_create``: method receiving values used when creating a new
@@ -243,7 +294,7 @@ class PaymentTransaction(osv.Model):
'partner_zip': fields.char('Zip'),
'partner_address': fields.char('Address'),
'partner_city': fields.char('City'),
'partner_country_id': fields.many2one('res.country', 'Country'),
'partner_country_id': fields.many2one('res.country', 'Country', required=True),
'partner_phone': fields.char('Phone'),
'partner_reference': fields.char('Buyer Reference'),
}
@@ -283,30 +334,19 @@ class PaymentTransaction(osv.Model):
return super(PaymentTransaction, self).create(cr, uid, values, context=context)
def on_change_partner_id(self, cr, uid, ids, partner_id, context=None):
partner = None
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
values = {
'partner_name': partner.name,
'partner_lang': partner.lang,
'partner_email': partner.email,
'partner_zip': partner.zip,
'partner_address': _partner_format_address(partner.street, partner.street2),
'partner_city': partner.city,
'partner_country_id': partner.country_id.id,
'partner_phone': partner.phone,
}
else:
values = {
'partner_name': False,
'partner_lang': 'en_US',
'partner_email': False,
'partner_zip': False,
'partner_address': False,
'partner_city': False,
'partner_country_id': False,
'partner_phone': False,
}
return {'values': values}
return {'values': {
'partner_name': partner and partner.name or False,
'partner_lang': partner and partner.lang or 'en_US',
'partner_email': partner and partner.email or False,
'partner_zip': partner and partner.zip or False,
'partner_address': _partner_format_address(partner.street, partner.street2),
'partner_city': partner and partner.city or False,
'partner_country_id': partner and partner.country_id.id or False,
'partner_phone': partner and partner.phone or False,
}}
# --------------------------------------------------
# FORM RELATED METHODS
+5 -3
View File
@@ -14,8 +14,10 @@ class PaymentAcquirerCommon(common.TransactionCase):
self.cr, self.uid, [('name', '=', 'EUR')], limit=1)[0]
self.currency_euro = self.registry('res.currency').browse(
self.cr, self.uid, self.currency_euro_id)
country_belgium_id = self.registry('res.country').search(
self.country_belgium_id = self.registry('res.country').search(
self.cr, self.uid, [('code', 'like', 'BE')], limit=1)[0]
self.country_france_id = self.registry('res.country').search(
self.cr, self.uid, [('code', 'like', 'FR')], limit=1)[0]
# dict partner values
self.buyer_values = {
@@ -27,7 +29,7 @@ class PaymentAcquirerCommon(common.TransactionCase):
'phone': '0032 12 34 56 78',
'city': 'Sin City',
'zip': '1000',
'country_id': country_belgium_id,
'country_id': self.country_belgium_id,
'country_name': 'Belgium',
}
@@ -42,6 +44,6 @@ class PaymentAcquirerCommon(common.TransactionCase):
'phone': '0032 12 34 56 78',
'city': 'Sin City',
'zip': '1000',
'country_id': country_belgium_id,
'country_id': self.country_belgium_id,
}
)
+4 -4
View File
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<data noupdate="1">
<record id="payment_acquirer_adyen" model="payment.acquirer">
<field name="name">adyen</field>
<field name="view_template_id" ref="adyen_acquirer_button"/>
<field name="env">test</field>
<field name="adyen_merchant_account">OpenERPCOM</field>
<field name="adyen_skin_code">cbqYWvVL</field>
<field name="adyen_skin_hmac_key">cbqYWvVL</field>
<field name="adyen_merchant_account">dummy</field>
<field name="adyen_skin_code">dummy</field>
<field name="adyen_skin_hmac_key">dummy</field>
</record>
</data>
+12 -34
View File
@@ -72,9 +72,7 @@ class AcquirerAdyen(osv.Model):
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, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
if partner_values is None:
partner_values = {}
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
@@ -82,27 +80,22 @@ class AcquirerAdyen(osv.Model):
from dateutil import relativedelta
tmp_date = datetime.date.today() + relativedelta.relativedelta(days=1)
partner = None
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
tx_values = {
'merchantReference': reference,
'paymentAmount': '%d' % int(float_round(amount, 2) * 100),
'currencyCode': currency and currency.name or 'EUR',
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 and partner.lang or partner_values.get('lang', 'en_US'),
'shopperLocale': partner_values['lang'],
'sessionValidity': tmp_date,
'merchantSig': 'oij',
'resURL': '%s' % urlparse.urljoin(base_url, AdyenController._return_url),
}
if tx_custom_values and tx_custom_values.get('return_url'):
tx_values['merchantReturnData'] = json.dumps({'return_url': '%s' % tx_custom_values.pop('return_url')})
if tx_custom_values:
tx_values.update(tx_custom_values)
tx_values['merchantSig'] = self._adyen_generate_merchant_sig(acquirer, 'in', tx_values)
return tx_values
})
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)
@@ -120,21 +113,6 @@ class TxAdyen(osv.Model):
# FORM RELATED METHODS
# --------------------------------------------------
def adyen_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None):
tx = self.browse(cr, uid, id, context=context)
tx_data = {
'shopperLocale': tx.partner_lang,
}
if tx_custom_values:
tx_data.update(tx_custom_values)
return self.pool['payment.acquirer'].paypal_form_generate_values(
cr, uid, tx.acquirer_id.id,
tx.reference, tx.amount, tx.currency_id,
tx_custom_values=tx_data,
context=context
)
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:
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from . import test_adyen
# from . import test_adyen
checks = [
test_adyen,
# test_adyen,
]
@@ -1,34 +1,24 @@
# -*- coding: utf-8 -*-
from lxml import objectify
import urlparse
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.addons.payment_acquirer.tests.common import PaymentAcquirerCommon
from openerp.addons.payment_acquirer_adyen.controllers.main import AdyenController
from openerp.osv.orm import except_orm
from openerp.tools import mute_logger
from lxml import objectify
import urlparse
class AdyenCommon(PaymentAcquirerCommon):
def setUp(self):
super(AdyenCommon, self).setUp()
cr, uid = self.cr, self.uid
self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
model, self.paypal_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_adyen', 'adyen_acquirer_button')
# create a new ogone account
self.adyen_id = self.payment_acquirer.create(
cr, uid, {
'name': 'adyen',
'env': 'test',
'view_template_id': self.paypal_view_id,
'adyen_merchant_account': 'OpenERPCOM',
'adyen_skin_code': 'cbqYWvVL',
'adyen_skin_hmac_key': 'cbqYWvVL',
})
# get the adyen account
model, self.adyen_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_adyen', 'payment_acquirer_adyen')
# some CC (always use expiration date 06 / 2016, cvc 737, cid 7373 (amex))
self.amex = (('370000000000002', '7373'))
@@ -57,6 +47,9 @@ class AdyenForm(AdyenCommon):
def test_10_adyen_form_render(self):
cr, uid, context = self.cr, self.uid, {}
# be sure not to do stupid things
adyen = self.payment_acquirer.browse(self.cr, self.uid, self.adyen_id, None)
self.assertEqual(adyen.env, 'test', 'test without test env')
# ----------------------------------------
# Test: button direct rendering
@@ -74,7 +67,7 @@ class AdyenForm(AdyenCommon):
# render the button
res = self.payment_acquirer.render(
cr, uid, self.adyen_id,
'test_ref0', 0.01, self.currency_euro,
'test_ref0', 0.01, self.currency_euro_id,
partner_id=None,
partner_values=self.buyer_values,
context=context)
@@ -88,12 +81,15 @@ class AdyenForm(AdyenCommon):
self.assertEqual(
form_input.get('value'),
form_values[form_input.get('name')],
'adyen: wrong value for form: received %s instead of %s' % (form_input.get('value'), form_values[form_input.get('name')])
'adyen: wrong value for 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_acquirer_paypal.models.paypal', 'ValidationError')
def test_20_paypal_form_management(self):
cr, uid, context = self.cr, self.uid, {}
# be sure not to do stupid things
adyen = self.payment_acquirer.browse(self.cr, self.uid, self.adyen_id, None)
self.assertEqual(adyen.env, 'test', 'test without test env')
# {'authResult': u'AUTHORISED',
# 'merchantReference': u'SO014',
+3 -3
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<data noupdate="1">
<record id="payment_acquirer_ogone" model="payment.acquirer">
<field name="name">ogone</field>
@@ -9,8 +9,8 @@
<field name='ogone_pspid'>dummy</field>
<field name='ogone_userid'>dummy</field>
<field name='ogone_password'>dummy</field>
<field name="ogone_shakey_in">tINY4Yv14789gUix1130</field>
<field name="ogone_shakey_out">tINYj885Tfvd4P471464</field>
<field name="ogone_shakey_in">dummy</field>
<field name="ogone_shakey_out">dummy</field>
</record>
</data>
+24 -49
View File
@@ -1,6 +1,10 @@
# -*- coding: utf-'8' "-*-"
from hashlib import sha1
try:
import simplejson as json
except ImportError:
import json
import logging
from lxml import etree, objectify
from pprint import pformat
@@ -93,39 +97,34 @@ class PaymentAcquirerOgone(osv.Model):
shasign = sha1(sign).hexdigest()
return shasign
def ogone_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
if partner_values is None:
partner_values = {}
def ogone_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)
partner = None
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
tx_values = {
ogone_tx_values = dict(tx_values)
ogone_tx_values.update({
'PSPID': acquirer.ogone_pspid,
'ORDERID': reference,
'AMOUNT': '%d' % int(float_round(amount, 2) * 100),
'CURRENCY': currency and currency.name or 'EUR',
'LANGUAGE': partner and partner.lang or partner_values.get('lang', ''),
'CN': partner and partner.name or partner_values.get('name', ''),
'EMAIL': partner and partner.email or partner_values.get('email', ''),
'OWNERZIP': partner and partner.zip or partner_values.get('zip', ''),
'OWNERADDRESS': partner and ' '.join((partner.street or '', partner.street2 or '')).strip() or ' '.join((partner_values.get('street', ''), partner_values.get('street2', ''))).strip(),
'OWNERTOWN': partner and partner.city or partner_values.get('city', ''),
'OWNERCTY': partner and partner.country_id and partner.country_id.name or partner_values.get('country_name', ''),
'OWNERTELNO': partner and partner.phone or partner_values.get('phone', ''),
'ORDERID': tx_values['reference'],
'AMOUNT': '%d' % int(float_round(tx_values['amount'], 2) * 100),
'CURRENCY': tx_values['currency'] and tx_values['currency'].name or '',
'LANGUAGE': partner_values['lang'],
'CN': partner_values['name'],
'EMAIL': partner_values['email'],
'OWNERZIP': partner_values['zip'],
'OWNERADDRESS': partner_values['address'],
'OWNERTOWN': partner_values['city'],
'OWNERCTY': partner_values['country'] and partner_values['country'].name or '',
'OWNERTELNO': partner_values['phone'],
'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),
}
if tx_custom_values and tx_custom_values.get('return_url'):
tx_values['PARAMPLUS'] = 'return_url=%s' % tx_custom_values.pop('return_url')
if tx_custom_values:
tx_values.update(tx_custom_values)
})
if ogone_tx_values.get('return_url'):
ogone_tx_values['PARAMPLUS'] = json.dumps('{"return_url": %s}' % ogone_tx_values.pop('return_url'))
shasign = self._ogone_generate_shasign(acquirer, 'in', tx_values)
tx_values['SHASIGN'] = shasign
return tx_values
ogone_tx_values['SHASIGN'] = shasign
return partner_values, ogone_tx_values
def ogone_get_form_action_url(self, cr, uid, id, context=None):
acquirer = self.browse(cr, uid, id, context=context)
@@ -153,30 +152,6 @@ class PaymentTxOgone(osv.Model):
# FORM RELATED METHODS
# --------------------------------------------------
def ogone_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None):
""" Ogone-specific value generation for rendering a transaction-based
form button. """
tx = self.browse(cr, uid, id, context=context)
tx_data = {
'LANGUAGE': tx.partner_lang,
'CN': tx.partner_name,
'EMAIL': tx.partner_email,
'OWNERZIP': tx.partner_zip,
'OWNERADDRESS': tx.partner_address,
'OWNERTOWN': tx.partner_city,
'OWNERCTY': tx.partner_country_id and tx.partner_country_id.name or '',
'OWNERTELNO': tx.partner_phone,
}
if tx_custom_values:
tx_data.update(tx_custom_values)
return self.pool['payment.acquirer'].ogone_form_generate_values(
cr, uid, tx.acquirer_id.id,
tx.reference, tx.amount, tx.currency_id,
tx_custom_values=tx_data,
context=context
)
def _ogone_form_get_tx_from_data(self, cr, uid, data, context=None):
""" Given a data dict coming from ogone, verify it and find the related
transaction record. """
@@ -1,45 +1,30 @@
# -*- coding: utf-8 -*-
from lxml import objectify
import time
import urlparse
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.addons.payment_acquirer.tests.common import PaymentAcquirerCommon
from openerp.addons.payment_acquirer_ogone.controllers.main import OgoneController
from openerp.tools import mute_logger
from lxml import objectify
# import requests
import time
import urlparse
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')
model, self.ogone_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_ogone', 'ogone_acquirer_button')
# create a new ogone account
self.ogone_id = self.payment_acquirer.create(
cr, uid, {
'name': 'ogone',
'env': 'test',
'view_template_id': self.ogone_view_id,
'ogone_pspid': 'dummy',
'ogone_userid': 'dummy',
'ogone_password': 'dummy',
'ogone_shakey_in': 'tINY4Yv14789gUix1130',
'ogone_shakey_out': 'tINYj885Tfvd4P471464',
})
self.ogone_url = self.payment_acquirer._get_ogone_urls(cr, uid, [self.ogone_id], None, None)[self.ogone_id]['ogone_standard_order_url']
def test_00_ogone_acquirer(self):
ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None)
self.assertEqual(ogone.env, 'test', 'test without test env')
# get the adyen account
model, self.ogone_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_ogone', 'payment_acquirer_ogone')
def test_10_ogone_form_render(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.env, 'test', 'test without test env')
# ----------------------------------------
# Test: button direct rendering + shasign
@@ -68,7 +53,7 @@ class OgonePayment(PaymentAcquirerCommon):
# render the button
res = self.payment_acquirer.render(
cr, uid, self.ogone_id,
'test_ref0', 0.01, self.currency_euro,
'test_ref0', 0.01, self.currency_euro_id,
partner_id=None,
partner_values=self.buyer_values,
context=context)
@@ -82,7 +67,7 @@ class OgonePayment(PaymentAcquirerCommon):
self.assertEqual(
form_input.get('value'),
form_values[form_input.get('name')],
'ogone: wrong value for form: received %s instead of %s' % (form_input.get('value'), form_values[form_input.get('name')])
'ogone: wrong value for input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
)
# ----------------------------------------
@@ -123,6 +108,9 @@ class OgonePayment(PaymentAcquirerCommon):
@mute_logger('openerp.addons.payment_acquirer_ogone.models.ogone', '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.env, 'test', 'test without test env')
# typical data posted by ogone after client has successfully paid
ogone_post_data = {
@@ -155,6 +143,7 @@ class OgonePayment(PaymentAcquirerCommon):
'currency_id': self.currency_euro_id,
'reference': 'test_ref_2',
'partner_name': 'Norbert Buyer',
'partner_country_id': self.country_france_id,
}, context=context
)
# validate it
@@ -183,6 +172,9 @@ class OgonePayment(PaymentAcquirerCommon):
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.env, 'test', 'test without test env')
# create a new draft tx
tx_id = self.payment_transaction.create(
@@ -1,17 +1,17 @@
# -*- coding: utf-8 -*-
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
try:
import simplejson as json
except ImportError:
import json
import logging
import pprint
import requests
from urllib import urlencode
import urllib
import urllib2
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
_logger = logging.getLogger(__name__)
@@ -32,9 +32,10 @@ class PaypalController(http.Controller):
Once data is validated, process it. """
res = False
paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"
post_url = '%s?cmd=_notify-validate&%s' % (paypal_url, urlencode(post))
resp = requests.post(post_url)
new_post = dict(post, cmd='_notify-validate')
urequest = urllib2.Request("https://www.sandbox.paypal.com/cgi-bin/webscr", urllib.urlencode(new_post))
uopen = urllib2.urlopen(urequest)
resp = uopen.read()
if resp.text == 'VERIFIED':
_logger.info('Paypal: validated data')
cr, uid, context = request.cr, request.uid, request.context
+24 -53
View File
@@ -1,11 +1,5 @@
# -*- coding: utf-'8' "-*-"
from openerp.addons.payment_acquirer.models import payment_acquirer
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.addons.payment_acquirer_paypal.controllers.main import PaypalController
from openerp.osv import osv, fields
from openerp.tools.float_utils import float_compare
import base64
try:
import simplejson as json
@@ -16,6 +10,11 @@ import urlparse
import urllib
import urllib2
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.addons.payment_acquirer_paypal.controllers.main import PaypalController
from openerp.osv import osv, fields
from openerp.tools.float_utils import float_compare
_logger = logging.getLogger(__name__)
@@ -65,40 +64,34 @@ class AcquirerPaypal(osv.Model):
fees = amount * (1 + acquirer.fees_int_var / 100.0) + acquirer.fees_int_fixed - amount
return fees
def paypal_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
if partner_values is None:
partner_values = {}
def paypal_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)
partner = None
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
tx_values = {
paypal_tx_values = dict(tx_values)
paypal_tx_values.update({
'cmd': '_xclick',
'business': acquirer.paypal_email_id,
'item_name': reference,
'item_number': reference,
'amount': amount,
'currency_code': currency and currency.name or 'EUR',
'address1': payment_acquirer._partner_format_address(partner and partner.street or partner_values.get('street', ''), partner and partner.street2 or partner_values.get('street2', '')),
'city': partner and partner.city or partner_values.get('city', ''),
'country': partner and partner.country_id and partner.country_id.name or partner_values.get('country_name', ''),
'email': partner and partner.email or partner_values.get('email', ''),
'zip': partner and partner.zip or partner_values.get('zip', ''),
'first_name': payment_acquirer._partner_split_name(partner and partner.name or partner_values.get('name', ''))[0],
'last_name': payment_acquirer._partner_split_name(partner and partner.name or partner_values.get('name', ''))[1],
'item_name': tx_values['reference'],
'item_number': tx_values['reference'],
'amount': tx_values['amount'],
'currency_code': tx_values['currency'] and tx_values['currency'].name or '',
'address1': 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'],
'return': '%s' % urlparse.urljoin(base_url, PaypalController._return_url),
'notify_url': '%s' % urlparse.urljoin(base_url, PaypalController._notify_url),
'cancel_return': '%s' % urlparse.urljoin(base_url, PaypalController._cancel_url),
}
})
if acquirer.fees_active:
tx_values['handling'] = '%.2f' % tx_custom_values.pop('fees', 0.0)
if tx_custom_values and tx_custom_values.get('return_url'):
tx_values['custom'] = json.dumps({'return_url': '%s' % tx_custom_values.pop('return_url')})
if tx_custom_values:
tx_values.update(tx_custom_values)
return tx_values
paypal_tx_values['handling'] = '%.2f' % paypal_tx_values.pop('fees', 0.0)
if paypal_tx_values.get('return_url'):
paypal_tx_values['custom'] = json.dumps({'return_url': '%s' % paypal_tx_values.pop('return_url')})
return partner_values, paypal_tx_values
def paypal_get_form_action_url(self, cr, uid, id, context=None):
acquirer = self.browse(cr, uid, id, context=context)
@@ -144,28 +137,6 @@ class TxPaypal(osv.Model):
# FORM RELATED METHODS
# --------------------------------------------------
def paypal_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None):
tx = self.browse(cr, uid, id, context=context)
tx_data = {
'item_name': tx.name,
'first_name': payment_acquirer._partner_split_name(tx.partner_name)[0],
'last_name': payment_acquirer._partner_split_name(tx.partner_name)[0],
'email': tx.partner_email,
'zip': tx.partner_zip,
'address1': tx.partner_address,
'city': tx.partner_city,
'country': tx.partner_country_id and tx.partner_country_id.name or '',
}
if tx_custom_values:
tx_data.update(tx_custom_values)
return self.pool['payment.acquirer'].paypal_form_generate_values(
cr, uid, tx.acquirer_id.id,
tx.reference, tx.amount, tx.currency_id,
tx_custom_values=tx_data,
context=context
)
def _paypal_form_get_tx_from_data(self, cr, uid, data, context=None):
reference, txn_id = data.get('item_number'), data.get('txn_id')
if not reference or not txn_id:
@@ -15,22 +15,10 @@ class PaypalCommon(PaymentAcquirerCommon):
def setUp(self):
super(PaypalCommon, self).setUp()
cr, uid = self.cr, self.uid
self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
model, self.paypal_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_paypal', 'paypal_acquirer_button')
# create a new ogone account
self.paypal_id = self.payment_acquirer.create(
cr, uid, {
'name': 'paypal',
'env': 'test',
'view_template_id': self.paypal_view_id,
'paypal_email_id': 'dummy',
'paypal_username': 'dummy',
'paypal_api_enabled': True,
'paypal_api_username': 'dummy',
'paypal_api_password': 'dummy',
})
# get the paypal account
model, self.paypal_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_paypal', 'payment_acquirer_paypal')
# tde+seller@openerp.com - tde+buyer@openerp.com - tde+buyer-it@openerp.com
# some CC
@@ -50,6 +38,9 @@ class PaypalServer2Server(PaypalCommon):
def test_00_tx_management(self):
cr, uid, context = self.cr, self.uid, {}
# be sure not to do stupid things
paypal = self.payment_acquirer.browse(self.cr, self.uid, self.paypal_id, None)
self.assertEqual(paypal.env, 'test', 'test without test env')
res = self.payment_acquirer._paypal_s2s_get_access_token(cr, uid, [self.paypal_id], context=context)
self.assertTrue(res[self.paypal_id] is not False, 'paypal: did not generate access token')
@@ -78,24 +69,10 @@ class PaypalServer2Server(PaypalCommon):
class PaypalForm(PaypalCommon):
def test_00_paypal_acquirer(self):
cr, uid, context = self.cr, self.uid, {}
# forgot some mandatory fields: should crash
with self.assertRaises(except_orm):
self.payment_acquirer.create(
cr, uid, {
'name': 'paypal',
'env': 'test',
'view_template_id': self.paypal_view_id,
'paypal_email_id': 'tde+paypal-facilitator@openerp.com',
}, context=context)
paypal = self.payment_acquirer.browse(self.cr, self.uid, self.paypal_id, None)
self.assertEqual(paypal.env, 'test', 'test without test env')
def test_10_paypal_form_render(self):
cr, uid, context = self.cr, self.uid, {}
# be sure not to do stupid things
self.payment_acquirer.write(cr, uid, self.paypal_id, {'fees_active': False}, context)
paypal = self.payment_acquirer.browse(cr, uid, self.paypal_id, context)
self.assertEqual(paypal.env, 'test', 'test without test env')
@@ -103,6 +80,14 @@ class PaypalForm(PaypalCommon):
# Test: button direct rendering
# ----------------------------------------
# render the button
res = self.payment_acquirer.render(
cr, uid, self.paypal_id,
'test_ref0', 0.01, self.currency_euro_id,
partner_id=None,
partner_values=self.buyer_values,
context=context)
form_values = {
'cmd': '_xclick',
'business': 'tde+paypal-facilitator@openerp.com',
@@ -122,14 +107,6 @@ class PaypalForm(PaypalCommon):
'cancel_return': '%s' % urlparse.urljoin(self.base_url, PaypalController._cancel_url),
}
# render the button
res = self.payment_acquirer.render(
cr, uid, self.paypal_id,
'test_ref0', 0.01, self.currency_euro,
partner_id=None,
partner_values=self.buyer_values,
context=context)
# check form result
tree = objectify.fromstring(res)
self.assertEqual(tree.get('action'), 'https://www.sandbox.paypal.com/cgi-bin/webscr', 'paypal: wrong form POST url')
@@ -139,19 +116,24 @@ class PaypalForm(PaypalCommon):
self.assertEqual(
form_input.get('value'),
form_values[form_input.get('name')],
'paypal: wrong value for form: received %s instead of %s' % (form_input.get('value'), form_values[form_input.get('name')])
'paypal: wrong value for input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
)
def test_11_paypal_form_with_fees(self):
cr, uid, context = self.cr, self.uid, {}
self.payment_acquirer.write(cr, uid, self.paypal_id, {
'fees_active': True,
}, context)
# be sure not to do stupid things
paypal = self.payment_acquirer.browse(self.cr, self.uid, self.paypal_id, None)
self.assertEqual(paypal.env, 'test', 'test without test env')
# update acquirer: compute fees
self.payment_acquirer.write(cr, uid, self.paypal_id, {
'fees_active': True,
'fees_dom_fixed': 1.0,
'fees_dom_var': 0.35,
'fees_int_fixed': 1.5,
'fees_int_var': 0.50,
}, context)
# render the button
res = self.payment_acquirer.render(
cr, uid, self.paypal_id,
@@ -167,7 +149,7 @@ class PaypalForm(PaypalCommon):
for form_input in tree.input:
if form_input.get('name') in ['handling']:
handling_found = True
self.assertEqual(form_input.get('value'), '0.84', 'paypal: wrong computed fees')
self.assertEqual(form_input.get('value'), '1.56', 'paypal: wrong computed fees')
self.assertTrue(handling_found, 'paypal: fees_active did not add handling input in rendered form')
@mute_logger('openerp.addons.payment_acquirer_paypal.models.paypal', 'ValidationError')
@@ -233,6 +215,7 @@ class PaypalForm(PaypalCommon):
'currency_id': self.currency_euro_id,
'reference': 'test_ref_2',
'partner_name': 'Norbert Buyer',
'partner_country_id': self.country_france_id,
}, context=context
)
# validate it
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<data noupdate="1">
<record id="payment_acquirer_transfer" model="payment.acquirer">
<field name="name">transfer</field>