Merge lp:~openerp-dev/openobject-addons/trunk-payment-buckaroo-dka into lp:openobject-addons

Proposed by Thibault Delavallée (OpenERP)
Status: Needs review
Proposed branch: lp:~openerp-dev/openobject-addons/trunk-payment-buckaroo-dka
Merge into: lp:openobject-addons
Diff against target: 744 lines (+579/-19)
15 files modified
payment/models/res_config.py (+3/-0)
payment/views/res_config_view.xml (+4/-0)
payment_buckaroo/__init__.py (+23/-0)
payment_buckaroo/__openerp__.py (+17/-0)
payment_buckaroo/controllers/__init__.py (+3/-0)
payment_buckaroo/controllers/main.py (+38/-0)
payment_buckaroo/data/buckaroo.xml (+18/-0)
payment_buckaroo/models/__init__.py (+3/-0)
payment_buckaroo/models/buckaroo.py (+191/-0)
payment_buckaroo/tests/__init__.py (+7/-0)
payment_buckaroo/tests/test_buckaroo.py (+178/-0)
payment_buckaroo/views/buckaroo.xml (+34/-0)
payment_buckaroo/views/payment_acquirer.xml (+35/-0)
website_sale/controllers/main.py (+15/-19)
website_sale/static/src/js/website_sale_payment.js (+10/-0)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/trunk-payment-buckaroo-dka
Reviewer Review Type Date Requested Status
Thibault Delavallée (OpenERP) (community) technical Needs Fixing
Review via email: mp+208589@code.launchpad.net

Description of the change

[ADD] New payment acquirer: Buckaroo.

To post a comment you must log in.
9087. By Niko (OpenERP)

[IMP] Add some video to manisfest ( website, website_blog, website_event, website_ecommerce)

9184. By Darshan Kalola(OpenERP)

[IMP]remove unnecessary code.

9185. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9186. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9187. By Darshan Kalola(OpenERP)

[ADD]payment_buckaroo: added websitekey.

9188. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo:added secretkey and improved digital signature.

9189. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo: added buckaroo_return method in controller to handel return url and added _buckaroo_form_get_tx_from_data method in payment transaction.

9190. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9191. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo:improved method name.

9192. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo: added _buckaroo_form_validate method.

9193. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo: added _buckaroo_form_get_invalid_parameters method.

9194. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo: Removed unnecessary field.

9195. By Darshan Kalola(OpenERP)

[IMP]website_sale : improved payment_transaction method to send post request to payment getway and added exception url and reject url in buckaroo parameter and removed unnecessary code.

9196. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9197. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9198. By Darshan Kalola(OpenERP)

[IMP]removed unnecessary code and typo.

9199. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo:improved code and image.

9200. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9201. By Darshan Kalola(OpenERP)

[IMP]improved typo.

9202. By Darshan Kalola(OpenERP)

[IMP]pyment_buckaroo: inherited selection to add ('buckaroo','Buckaroo')in provider list , changed code accordinglly and rename file.

9203. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9204. By Darshan Kalola(OpenERP)

[IMP]pyament_buckaroo: added separate variable for buckarro status code.

9205. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9206. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9207. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9208. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9209. By Darshan Kalola(OpenERP)

[IMP]verify the digital signature comming from buckaroo.

9210. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9211. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9212. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo: rename fields name env to environment.

Revision history for this message
Thibault Delavallée (OpenERP) (tde-openerp) wrote :

Hello,

At first sight seems quite correct. But could you write tests like the one present in paypal or ogone ? They should be disabled by default because there is no valid data in the module; but test them locally using the credentials you have.

Best regards,

9213. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo:added test case to check the module correctly work or not.

9214. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9215. By Darshan Kalola(OpenERP)

[IMP]disabled test case.

9216. By Darshan Kalola(OpenERP)

[IMP]improved spacing.

9217. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9218. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9219. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9220. By Thibault Delavallée (OpenERP)

[MERGE] Sync with upstream (trunk)

Revision history for this message
Thibault Delavallée (OpenERP) (tde-openerp) wrote :

Hello,

Some remarks :
- remove credentials from data now that the branch is about to be merged (set dummy / dummy)
- lint the module (some unused imports, space errors, ...)

One thing to add :
- management of tx_values['return_url'] (see in paypal / adyen / ...). Using custom variables (see chapter about custom variables in buckaroo documentation), put the return url of the shop like other providers, and get it back in the controller instead of having an hardcoded redirection to "/shop/payment/validate/" .

Best regards,

Thibault.

review: Needs Fixing (technical)
9221. By Darshan Kalola(OpenERP)

[IMP]remove credential information and remove unneccessary import.

9222. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo:added custome variable for return_url.

9223. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9224. By Darshan Kalola(OpenERP)

[IMP]remove unnecessary import.

9225. By Thibault Delavallée (OpenERP)

[MERGE] Sync with trunk

9226. By Thibault Delavallée (OpenERP)

[CLEAN] payment_buckaroo: cleaned a bit the file for the tests, according
to new tests specifications in post-saas-4.

9227. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo:improved digital signature in test case.

9228. By Thibault Delavallée (OpenERP)

[MERGE] Sync with trunk

9229. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9230. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9231. By Darshan Kalola(OpenERP)

[MERGE]merged lp:~openerp-dev/openobject-addons/trunk-ecommerce-post-tde and removed unnecessary code which handle the post request as got better solution in trunk-ecommerce-post-tde branch.

9232. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk and resolve conflicts from website_sale controller/ in payment_transaction method.

9233. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

Unmerged revisions

9233. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9232. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk and resolve conflicts from website_sale controller/ in payment_transaction method.

9231. By Darshan Kalola(OpenERP)

[MERGE]merged lp:~openerp-dev/openobject-addons/trunk-ecommerce-post-tde and removed unnecessary code which handle the post request as got better solution in trunk-ecommerce-post-tde branch.

9230. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9229. By Darshan Kalola(OpenERP)

[MERGE]sync with trunk.

9228. By Thibault Delavallée (OpenERP)

[MERGE] Sync with trunk

9227. By Darshan Kalola(OpenERP)

[IMP]payment_buckaroo:improved digital signature in test case.

9226. By Thibault Delavallée (OpenERP)

[CLEAN] payment_buckaroo: cleaned a bit the file for the tests, according
to new tests specifications in post-saas-4.

9225. By Thibault Delavallée (OpenERP)

[MERGE] Sync with trunk

9224. By Darshan Kalola(OpenERP)

[IMP]remove unnecessary import.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'payment/models/res_config.py'
2--- payment/models/res_config.py 2014-03-05 16:37:37 +0000
3+++ payment/models/res_config.py 2014-05-21 05:25:49 +0000
4@@ -16,4 +16,7 @@
5 'module_payment_adyen': fields.boolean(
6 'Manage Payments Using Adyen',
7 help='-It installs the module payment_adyen.'),
8+ 'module_payment_buckaroo': fields.boolean(
9+ 'Manage Payments Using Buckaroo',
10+ help='-It installs the module payment_buckaroo.'),
11 }
12
13=== modified file 'payment/views/res_config_view.xml'
14--- payment/views/res_config_view.xml 2014-01-23 15:01:35 +0000
15+++ payment/views/res_config_view.xml 2014-05-21 05:25:49 +0000
16@@ -20,6 +20,10 @@
17 <field name="module_payment_adyen" class="oe_inline"/>
18 <label for="module_payment_adyen"/>
19 </div>
20+ <div>
21+ <field name="module_payment_buckaroo" class="oe_inline"/>
22+ <label for="module_payment_buckaroo"/>
23+ </div>
24 </xpath>
25 </field>
26 </record>
27
28=== added directory 'payment_buckaroo'
29=== added file 'payment_buckaroo/__init__.py'
30--- payment_buckaroo/__init__.py 1970-01-01 00:00:00 +0000
31+++ payment_buckaroo/__init__.py 2014-05-21 05:25:49 +0000
32@@ -0,0 +1,23 @@
33+# -*- coding: utf-8 -*-
34+##############################################################################
35+#
36+# OpenERP, Open Source Management Solution
37+# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
38+#
39+# This program is free software: you can redistribute it and/or modify
40+# it under the terms of the GNU Affero General Public License as
41+# published by the Free Software Foundation, either version 3 of the
42+# License, or (at your option) any later version.
43+#
44+# This program is distributed in the hope that it will be useful,
45+# but WITHOUT ANY WARRANTY; without even the implied warranty of
46+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47+# GNU Affero General Public License for more details.
48+#
49+# You should have received a copy of the GNU Affero General Public License
50+# along with this program. If not, see <http://www.gnu.org/licenses/>.
51+#
52+##############################################################################
53+
54+import models
55+import controllers
56
57=== added file 'payment_buckaroo/__openerp__.py'
58--- payment_buckaroo/__openerp__.py 1970-01-01 00:00:00 +0000
59+++ payment_buckaroo/__openerp__.py 2014-05-21 05:25:49 +0000
60@@ -0,0 +1,17 @@
61+# -*- coding: utf-8 -*-
62+
63+{
64+ 'name': 'Payment Buckaroo',
65+ 'category': 'Hidden',
66+ 'summary': 'Payment Acquirer: Buckaroo Implementation',
67+ 'version': '1.0',
68+ 'description': """Payment Buckaroo""",
69+ 'author': 'OpenERP SA',
70+ 'depends': ['payment'],
71+ 'data': [
72+ 'views/buckaroo.xml',
73+ 'views/payment_acquirer.xml',
74+ 'data/buckaroo.xml',
75+ ],
76+ 'installable': True,
77+}
78
79=== added directory 'payment_buckaroo/controllers'
80=== added file 'payment_buckaroo/controllers/__init__.py'
81--- payment_buckaroo/controllers/__init__.py 1970-01-01 00:00:00 +0000
82+++ payment_buckaroo/controllers/__init__.py 2014-05-21 05:25:49 +0000
83@@ -0,0 +1,3 @@
84+# -*- coding: utf-8 -*-
85+
86+import main
87
88=== added file 'payment_buckaroo/controllers/main.py'
89--- payment_buckaroo/controllers/main.py 1970-01-01 00:00:00 +0000
90+++ payment_buckaroo/controllers/main.py 2014-05-21 05:25:49 +0000
91@@ -0,0 +1,38 @@
92+# -*- coding: utf-8 -*-
93+try:
94+ import simplejson as json
95+except ImportError:
96+ import json
97+
98+import logging
99+import pprint
100+import werkzeug
101+
102+from openerp import http, SUPERUSER_ID
103+from openerp.http import request
104+
105+_logger = logging.getLogger(__name__)
106+
107+
108+class BuckarooController(http.Controller):
109+ _return_url = '/payment/buckaroo/return'
110+ _cancel_url = '/payment/buckaroo/cancel'
111+ _exception_url = '/payment/buckaroo/error'
112+ _reject_url = '/payment/buckaroo/reject'
113+
114+ @http.route([
115+ '/payment/buckaroo/return',
116+ '/payment/buckaroo/cancel',
117+ '/payment/buckaroo/error',
118+ '/payment/buckaroo/reject',
119+ ], type='http', auth='none')
120+ def buckaroo_return(self, **post):
121+ """ Buckaroo."""
122+ _logger.info('Buckaroo: entering form_feedback with post data %s', pprint.pformat(post)) # debug
123+ request.registry['payment.transaction'].form_feedback(request.cr, SUPERUSER_ID, post, 'buckaroo', context=request.context)
124+ return_url = post.pop('return_url', '')
125+ if not return_url:
126+ data ='' + post.pop('ADD_RETURNDATA', '{}').replace("'", "\"")
127+ custom = json.loads(data)
128+ return_url = custom.pop('return_url', '/')
129+ return werkzeug.utils.redirect(return_url)
130
131=== added directory 'payment_buckaroo/data'
132=== added file 'payment_buckaroo/data/buckaroo.xml'
133--- payment_buckaroo/data/buckaroo.xml 1970-01-01 00:00:00 +0000
134+++ payment_buckaroo/data/buckaroo.xml 2014-05-21 05:25:49 +0000
135@@ -0,0 +1,18 @@
136+<?xml version="1.0" encoding="utf-8"?>
137+<openerp>
138+ <data noupdate="1">
139+
140+ <record id="payment_acquirer_buckaroo" model="payment.acquirer">
141+ <field name="name">Buckarro</field>
142+ <field name="provider">buckaroo</field>
143+ <field name="company_id" ref="base.main_company"/>
144+ <field name="view_template_id" ref="buckaroo_acquirer_button"/>
145+ <field name="environment">test</field>
146+ <field name="pre_msg"><![CDATA[
147+<p>You will be redirected to the Buckaroo website after cliking on the payment button.</p>]]></field>
148+ <field name="brq_websitekey">dummy</field>
149+ <field name="brq_secretkey">dummy</field>
150+ </record>
151+
152+ </data>
153+</openerp>
154
155=== added directory 'payment_buckaroo/models'
156=== added file 'payment_buckaroo/models/__init__.py'
157--- payment_buckaroo/models/__init__.py 1970-01-01 00:00:00 +0000
158+++ payment_buckaroo/models/__init__.py 2014-05-21 05:25:49 +0000
159@@ -0,0 +1,3 @@
160+# -*- coding: utf-8 -*-
161+
162+import buckaroo
163
164=== added file 'payment_buckaroo/models/buckaroo.py'
165--- payment_buckaroo/models/buckaroo.py 1970-01-01 00:00:00 +0000
166+++ payment_buckaroo/models/buckaroo.py 2014-05-21 05:25:49 +0000
167@@ -0,0 +1,191 @@
168+# -*- coding: utf-'8' "-*-"
169+from hashlib import sha1
170+import logging
171+import urlparse
172+
173+from openerp.addons.payment.models.payment_acquirer import ValidationError
174+from openerp.addons.payment_buckaroo.controllers.main import BuckarooController
175+from openerp.osv import osv, fields
176+from openerp.tools.float_utils import float_compare
177+
178+_logger = logging.getLogger(__name__)
179+
180+
181+class AcquirerBuckaroo(osv.Model):
182+ _inherit = 'payment.acquirer'
183+
184+ def _get_buckaroo_urls(self, cr, uid, environment, context=None):
185+ """ Buckaroo URLs
186+ """
187+ if environment == 'prod':
188+ return {
189+ 'buckaroo_form_url': 'https://checkout.buckaroo.nl/html/',
190+ }
191+ else:
192+ return {
193+ 'buckaroo_form_url': 'https://testcheckout.buckaroo.nl/html/',
194+ }
195+
196+ def _get_providers(self, cr, uid, context=None):
197+ providers = super(AcquirerBuckaroo, self)._get_providers(cr, uid, context=context)
198+ providers.append(['buckaroo', 'Buckaroo'])
199+ return providers
200+
201+ _columns = {
202+ 'brq_websitekey': fields.char('WebsiteKey', required_if_provider='buckaroo'),
203+ 'brq_secretkey': fields.char('SecretKey', required_if_provider='buckaroo'),
204+ }
205+
206+ def _buckaroo_generate_digital_sign(self, acquirer, inout, values):
207+ """ Generate the shasign for incoming or outgoing communications.
208+
209+ :param browse acquirer: the payment.acquirer browse record. It should
210+ have a shakey in shaky out
211+ :param string inout: 'in' (openerp contacting buckaroo) or 'out' (buckaroo
212+ contacting openerp).
213+ :param dict values: transaction values
214+
215+ :return string: shasign
216+ """
217+ assert inout in ('in', 'out')
218+ assert acquirer.provider == 'buckaroo'
219+
220+ keys = "add_returndata Brq_amount Brq_culture Brq_currency Brq_invoicenumber Brq_return Brq_returncancel Brq_returnerror Brq_returnreject brq_test Brq_websitekey".split()
221+
222+ def get_value(key):
223+ if values.get(key):
224+ return values[key]
225+ return ''
226+
227+ if inout == 'out':
228+ if 'BRQ_SIGNATURE' in values:
229+ del values['BRQ_SIGNATURE']
230+ items = sorted((k.upper(), v) for k, v in values.items())
231+ sign = ''.join('%s=%s' % (k, v) for k, v in items)
232+ else:
233+ sign = ''.join('%s=%s' % (k,get_value(k)) for k in keys)
234+ #Add the pre-shared secret key at the end of the signature
235+ sign = sign + acquirer.brq_secretkey
236+ if isinstance(sign, str):
237+ sign = urlparse.parse_qsl(sign)
238+ shasign = sha1(sign).hexdigest()
239+ return shasign
240+
241+
242+ def buckaroo_form_generate_values(self, cr, uid, id, partner_values, tx_values, context=None):
243+ base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
244+ acquirer = self.browse(cr, uid, id, context=context)
245+ buckaroo_tx_values = dict(tx_values)
246+ buckaroo_tx_values.update({
247+ 'Brq_websitekey': acquirer.brq_websitekey,
248+ 'Brq_amount': tx_values['amount'],
249+ 'Brq_currency': tx_values['currency'] and tx_values['currency'].name or '',
250+ 'Brq_invoicenumber': tx_values['reference'],
251+ 'brq_test' : True,
252+ 'Brq_return': '%s' % urlparse.urljoin(base_url, BuckarooController._return_url),
253+ 'Brq_returncancel': '%s' % urlparse.urljoin(base_url, BuckarooController._cancel_url),
254+ 'Brq_returnerror': '%s' % urlparse.urljoin(base_url, BuckarooController._exception_url),
255+ 'Brq_returnreject': '%s' % urlparse.urljoin(base_url, BuckarooController._reject_url),
256+ 'Brq_culture': 'en-US',
257+ })
258+ if buckaroo_tx_values.get('return_url'):
259+ buckaroo_tx_values['add_returndata'] = {'return_url': '%s' % buckaroo_tx_values.pop('return_url')}
260+ else:
261+ buckaroo_tx_values['add_returndata'] = ''
262+ buckaroo_tx_values['Brq_signature'] = self._buckaroo_generate_digital_sign(acquirer, 'in', buckaroo_tx_values)
263+ return partner_values, buckaroo_tx_values
264+
265+ def buckaroo_get_form_action_url(self, cr, uid, id, context=None):
266+ acquirer = self.browse(cr, uid, id, context=context)
267+ return self._get_buckaroo_urls(cr, uid, acquirer.environment, context=context)['buckaroo_form_url']
268+
269+class TxBuckaroo(osv.Model):
270+ _inherit = 'payment.transaction'
271+
272+ # buckaroo status
273+ _buckaroo_valid_tx_status = [190]
274+ _buckaroo_pending_tx_status = [790, 791, 792, 793]
275+ _buckaroo_cancel_tx_status = [890, 891]
276+ _buckaroo_error_tx_status = [490, 491, 492]
277+ _buckaroo_reject_tx_status = [690]
278+
279+ _columns = {
280+ 'buckaroo_txnid': fields.char('Transaction ID'),
281+ }
282+
283+
284+ # --------------------------------------------------
285+ # FORM RELATED METHODS
286+ # --------------------------------------------------
287+
288+ def _buckaroo_form_get_tx_from_data(self, cr, uid, data, context=None):
289+ """ Given a data dict coming from buckaroo, verify it and find the related
290+ transaction record. """
291+ reference, pay_id, shasign = data.get('BRQ_INVOICENUMBER'), data.get('BRQ_PAYMENT'), data.get('BRQ_SIGNATURE')
292+ if not reference or not pay_id or not shasign:
293+ error_msg = 'Buckaroo: received data with missing reference (%s) or pay_id (%s) or shashign (%s)' % (reference, pay_id, shasign)
294+ _logger.error(error_msg)
295+ raise ValidationError(error_msg)
296+
297+ tx_ids = self.search(cr, uid, [('reference', '=', reference)], context=context)
298+ if not tx_ids or len(tx_ids) > 1:
299+ error_msg = 'Buckaroo: received data for reference %s' % (reference)
300+ if not tx_ids:
301+ error_msg += '; no order found'
302+ else:
303+ error_msg += '; multiple order found'
304+ _logger.error(error_msg)
305+ raise ValidationError(error_msg)
306+ tx = self.pool['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
307+
308+ #verify shasign
309+ shasign_check = self.pool['payment.acquirer']._buckaroo_generate_digital_sign(tx.acquirer_id, 'out' ,data)
310+ if shasign_check.upper() != shasign.upper():
311+ error_msg = 'Buckaroo: invalid shasign, received %s, computed %s, for data %s' % (shasign, shasign_check, data)
312+ _logger.error(error_msg)
313+ raise ValidationError(error_msg)
314+
315+ return tx
316+
317+ def _buckaroo_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
318+ invalid_parameters = []
319+
320+ if tx.acquirer_reference and data.get('BRQ_TRANSACTIONS') != tx.acquirer_reference:
321+ invalid_parameters.append(('Transaction Id', data.get('BRQ_TRANSACTIONS'), tx.acquirer_reference))
322+ # check what is buyed
323+ if float_compare(float(data.get('BRQ_AMOUNT', '0.0')), tx.amount, 2) != 0:
324+ invalid_parameters.append(('Amount', data.get('BRQ_AMOUNT'), '%.2f' % tx.amount))
325+ if data.get('BRQ_CURRENCY') != tx.currency_id.name:
326+ invalid_parameters.append(('Currency', data.get('BRQ_CURRENCY'), tx.currency_id.name))
327+
328+ return invalid_parameters
329+
330+ def _buckaroo_form_validate(self, cr, uid, tx, data, context=None):
331+ status_code = int(data.get('BRQ_STATUSCODE','0'))
332+ if status_code in self._buckaroo_valid_tx_status:
333+ tx.write({
334+ 'state': 'done',
335+ 'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
336+ })
337+ return True
338+ elif status_code in self._buckaroo_pending_tx_status:
339+ tx.write({
340+ 'state': 'pending',
341+ 'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
342+ })
343+ return True
344+ elif status_code in self._buckaroo_cancel_tx_status:
345+ tx.write({
346+ 'state': 'cancel',
347+ 'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
348+ })
349+ return True
350+ else:
351+ error = 'Buckaroo: feedback error'
352+ _logger.info(error)
353+ tx.write({
354+ 'state': 'error',
355+ 'state_message': error,
356+ 'buckaroo_txnid': data.get('BRQ_TRANSACTIONS'),
357+ })
358+ return False
359
360=== added directory 'payment_buckaroo/static'
361=== added directory 'payment_buckaroo/static/description'
362=== added file 'payment_buckaroo/static/description/icon.png'
363Binary files payment_buckaroo/static/description/icon.png 1970-01-01 00:00:00 +0000 and payment_buckaroo/static/description/icon.png 2014-05-21 05:25:49 +0000 differ
364=== added directory 'payment_buckaroo/static/src'
365=== added directory 'payment_buckaroo/static/src/img'
366=== added file 'payment_buckaroo/static/src/img/buckaroo_icon.png'
367Binary files payment_buckaroo/static/src/img/buckaroo_icon.png 1970-01-01 00:00:00 +0000 and payment_buckaroo/static/src/img/buckaroo_icon.png 2014-05-21 05:25:49 +0000 differ
368=== added file 'payment_buckaroo/static/src/img/logo.png'
369Binary files payment_buckaroo/static/src/img/logo.png 1970-01-01 00:00:00 +0000 and payment_buckaroo/static/src/img/logo.png 2014-05-21 05:25:49 +0000 differ
370=== added directory 'payment_buckaroo/tests'
371=== added file 'payment_buckaroo/tests/__init__.py'
372--- payment_buckaroo/tests/__init__.py 1970-01-01 00:00:00 +0000
373+++ payment_buckaroo/tests/__init__.py 2014-05-21 05:25:49 +0000
374@@ -0,0 +1,7 @@
375+# -*- coding: utf-8 -*-
376+
377+from openerp.addons.payment_buckaroo.tests import test_buckaroo
378+
379+checks = [
380+ test_buckaroo,
381+]
382
383=== added file 'payment_buckaroo/tests/test_buckaroo.py'
384--- payment_buckaroo/tests/test_buckaroo.py 1970-01-01 00:00:00 +0000
385+++ payment_buckaroo/tests/test_buckaroo.py 2014-05-21 05:25:49 +0000
386@@ -0,0 +1,178 @@
387+# -*- coding: utf-8 -*-
388+
389+from lxml import objectify
390+import urlparse
391+
392+import openerp
393+from openerp.addons.payment.models.payment_acquirer import ValidationError
394+from openerp.addons.payment.tests.common import PaymentAcquirerCommon
395+from openerp.addons.payment_buckaroo.controllers.main import BuckarooController
396+from openerp.tools import mute_logger
397+
398+
399+@openerp.tests.common.at_install(False)
400+@openerp.tests.common.post_install(False)
401+class BuckarooCommon(PaymentAcquirerCommon):
402+
403+ def setUp(self):
404+ super(BuckarooCommon, self).setUp()
405+ cr, uid = self.cr, self.uid
406+ self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
407+
408+ # get the buckaroo account
409+ model, self.buckaroo_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_buckaroo', 'payment_acquirer_buckaroo')
410+
411+
412+@openerp.tests.common.at_install(False)
413+@openerp.tests.common.post_install(False)
414+class BuckarooForm(BuckarooCommon):
415+
416+ def test_10_Buckaroo_form_render(self):
417+ cr, uid, context = self.cr, self.uid, {}
418+ # be sure not to do stupid things
419+ buckaroo = self.payment_acquirer.browse(self.cr, self.uid, self.buckaroo_id, None)
420+ self.assertEqual(buckaroo.environment, 'test', 'test without test environment')
421+
422+ # ----------------------------------------
423+ # Test: button direct rendering
424+ # ----------------------------------------
425+
426+ form_values = {
427+ 'add_returndata': None,
428+ 'Brq_websitekey': buckaroo.brq_websitekey,
429+ 'Brq_amount': '2240.0',
430+ 'Brq_currency': 'EUR',
431+ 'Brq_invoicenumber': 'SO004',
432+ 'Brq_signature': '1b8c10074c622d965272a91a9e88b5b3777d2474', # update me
433+ 'brq_test': 'True',
434+ 'Brq_return': '%s' % urlparse.urljoin(self.base_url, BuckarooController._return_url),
435+ 'Brq_returncancel': '%s' % urlparse.urljoin(self.base_url, BuckarooController._cancel_url),
436+ 'Brq_returnerror': '%s' % urlparse.urljoin(self.base_url, BuckarooController._exception_url),
437+ 'Brq_returnreject': '%s' % urlparse.urljoin(self.base_url, BuckarooController._reject_url),
438+ 'Brq_culture': 'en-US',
439+ }
440+
441+ # render the button
442+ res = self.payment_acquirer.render(
443+ cr, uid, self.buckaroo_id,
444+ 'SO004', 2240.0, self.currency_euro_id,
445+ partner_id=None,
446+ partner_values=self.buyer_values,
447+ context=context)
448+
449+ # check form result
450+ tree = objectify.fromstring(res)
451+ self.assertEqual(tree.get('action'), 'https://testcheckout.buckaroo.nl/html/', 'Buckaroo: wrong form POST url')
452+ for form_input in tree.input:
453+ if form_input.get('name') in ['submit']:
454+ continue
455+ self.assertEqual(
456+ form_input.get('value'),
457+ form_values[form_input.get('name')],
458+ 'Buckaroo: wrong value for input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
459+ )
460+
461+ # ----------------------------------------
462+ # Test2: button using tx + validation
463+ # ----------------------------------------
464+
465+ # create a new draft tx
466+ tx_id = self.payment_transaction.create(
467+ cr, uid, {
468+ 'amount': 2240.0,
469+ 'acquirer_id': self.buckaroo_id,
470+ 'currency_id': self.currency_euro_id,
471+ 'reference': 'SO004',
472+ 'partner_id': self.buyer_id,
473+ }, context=context
474+ )
475+
476+ # render the button
477+ res = self.payment_acquirer.render(
478+ cr, uid, self.buckaroo_id,
479+ 'should_be_erased', 2240.0, self.currency_euro,
480+ tx_id=tx_id,
481+ partner_id=None,
482+ partner_values=self.buyer_values,
483+ context=context)
484+
485+ # check form result
486+ tree = objectify.fromstring(res)
487+ self.assertEqual(tree.get('action'), 'https://testcheckout.buckaroo.nl/html/', 'Buckaroo: wrong form POST url')
488+ for form_input in tree.input:
489+ if form_input.get('name') in ['submit']:
490+ continue
491+ self.assertEqual(
492+ form_input.get('value'),
493+ form_values[form_input.get('name')],
494+ 'Buckaroo: 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')])
495+ )
496+
497+ @mute_logger('openerp.addons.payment_buckaroo.models.buckaroo', 'ValidationError')
498+ def test_20_buckaroo_form_management(self):
499+ cr, uid, context = self.cr, self.uid, {}
500+ # be sure not to do stupid thing
501+ buckaroo = self.payment_acquirer.browse(self.cr, self.uid, self.buckaroo_id, None)
502+ self.assertEqual(buckaroo.environment, 'test', 'test without test environment')
503+
504+ # typical data posted by buckaroo after client has successfully paid
505+ buckaroo_post_data = {
506+ 'BRQ_RETURNDATA': u'',
507+ 'BRQ_AMOUNT': u'2240.00',
508+ 'BRQ_CURRENCY': u'EUR',
509+ 'BRQ_CUSTOMER_NAME': u'Jan de Tester',
510+ 'BRQ_INVOICENUMBER': u'SO004',
511+ 'BRQ_PAYMENT': u'573311D081B04069BD6336001611DBD4',
512+ 'BRQ_PAYMENT_METHOD': u'paypal',
513+ 'BRQ_SERVICE_PAYPAL_PAYERCOUNTRY': u'NL',
514+ 'BRQ_SERVICE_PAYPAL_PAYEREMAIL': u'fhe@openerp.com',
515+ 'BRQ_SERVICE_PAYPAL_PAYERFIRSTNAME': u'Jan',
516+ 'BRQ_SERVICE_PAYPAL_PAYERLASTNAME': u'Tester',
517+ 'BRQ_SERVICE_PAYPAL_PAYERMIDDLENAME': u'de',
518+ 'BRQ_SERVICE_PAYPAL_PAYERSTATUS': u'verified',
519+ 'BRQ_SIGNATURE': u'175d82dd53a02bad393fee32cb1eafa3b6fbbd91',
520+ 'BRQ_STATUSCODE': u'190',
521+ 'BRQ_STATUSCODE_DETAIL': u'S001',
522+ 'BRQ_STATUSMESSAGE': u'Transaction successfully processed',
523+ 'BRQ_TEST': u'true',
524+ 'BRQ_TIMESTAMP': u'2014-05-08 12:41:21',
525+ 'BRQ_TRANSACTIONS': u'D6106678E1D54EEB8093F5B3AC42EA7B',
526+ 'BRQ_WEBSITEKEY': u'5xTGyGyPyl',
527+ }
528+
529+ # should raise error about unknown tx
530+ with self.assertRaises(ValidationError):
531+ self.payment_transaction.form_feedback(cr, uid, buckaroo_post_data, 'buckaroo', context=context)
532+
533+ tx_id = self.payment_transaction.create(
534+ cr, uid, {
535+ 'amount': 2240.0,
536+ 'acquirer_id': self.buckaroo_id,
537+ 'currency_id': self.currency_euro_id,
538+ 'reference': 'SO004',
539+ 'partner_name': 'Norbert Buyer',
540+ 'partner_country_id': self.country_france_id,
541+ }, context=context
542+ )
543+ # validate it
544+ self.payment_transaction.form_feedback(cr, uid, buckaroo_post_data, 'buckaroo', context=context)
545+ # check state
546+ tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
547+ self.assertEqual(tx.state, 'done', 'Buckaroo: validation did not put tx into done state')
548+ self.assertEqual(tx.buckaroo_txnid, buckaroo_post_data.get('BRQ_TRANSACTIONS'), 'Buckaroo: validation did not update tx payid')
549+
550+ # reset tx
551+ tx.write({'state': 'draft', 'date_validate': False, 'buckaroo_txnid': False})
552+
553+ # now buckaroo post is ok: try to modify the SHASIGN
554+ buckaroo_post_data['BRQ_SIGNATURE'] = '54d928810e343acf5fb0c3ee75fd747ff159ef7a'
555+ with self.assertRaises(ValidationError):
556+ self.payment_transaction.form_feedback(cr, uid, buckaroo_post_data, 'buckaroo', context=context)
557+
558+ # simulate an error
559+ buckaroo_post_data['BRQ_STATUSCODE'] = 2
560+ buckaroo_post_data['BRQ_SIGNATURE'] = '4164b52adb1e6a2221d3d8a39d8c3e18a9ecb90b'
561+ self.payment_transaction.form_feedback(cr, uid, buckaroo_post_data, 'buckaroo', context=context)
562+ # check state
563+ tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
564+ self.assertEqual(tx.state, 'error', 'Buckaroo: erroneous validation did not put tx into error state')
565
566=== added directory 'payment_buckaroo/views'
567=== added file 'payment_buckaroo/views/buckaroo.xml'
568--- payment_buckaroo/views/buckaroo.xml 1970-01-01 00:00:00 +0000
569+++ payment_buckaroo/views/buckaroo.xml 2014-05-21 05:25:49 +0000
570@@ -0,0 +1,34 @@
571+<?xml version="1.0" encoding="utf-8"?>
572+<openerp>
573+ <data noupdate="1">
574+
575+ <template id="buckaroo_acquirer_button">
576+ <form t-if="acquirer.brq_websitekey" t-att-action="tx_url" method="post" target="_self">
577+ <input type="hidden" name="Brq_websitekey" t-att-value="tx_values['Brq_websitekey']"/>
578+ <input type="hidden" name="Brq_amount" t-att-value="tx_values['Brq_amount'] or '0.0'"/>
579+ <input type="hidden" name="Brq_currency" t-att-value="tx_values['Brq_currency']"/>
580+ <input type="hidden" name="Brq_invoicenumber" t-att-value="tx_values['Brq_invoicenumber']"/>
581+ <input type="hidden" name="Brq_signature" t-att-value="tx_values['Brq_signature']"/>
582+ <input type="hidden" name="brq_test" t-att-value="tx_values['brq_test']"/>
583+ <input type="hidden" name="Brq_culture" t-att-value="tx_values['Brq_culture']"/>
584+ <!-- URLs -->
585+ <input t-if="tx_values.get('Brq_return')" type='hidden' name='Brq_return'
586+ t-att-value="tx_values.get('Brq_return')"/>
587+ <input t-if="tx_values.get('Brq_returncancel')" type='hidden' name='Brq_returncancel'
588+ t-att-value="tx_values.get('Brq_returncancel')"/>
589+ <input t-if="tx_values.get('Brq_returnerror')" type='hidden' name='Brq_returnerror'
590+ t-att-value="tx_values.get('Brq_returnerror')"/>
591+ <input t-if="tx_values.get('Brq_returnreject')" type='hidden' name='Brq_returnreject'
592+ t-att-value="tx_values.get('Brq_returnreject')"/>
593+ <input type='hidden' name='add_returndata' t-att-value="tx_values.get('add_returndata')"/>
594+ <!-- submit -->
595+ <button type="image" name="submit" width="100px"
596+ t-att-class="submit_class">
597+ <img t-if="not submit_txt" src="/payment_buckaroo/static/src/img/buckaroo_icon.png"/>
598+ <span t-if="submit_txt"><t t-esc="submit_txt"/> <span class="fa fa-long-arrow-right"/></span>
599+ </button>
600+ </form>
601+ </template>
602+
603+ </data>
604+</openerp>
605
606=== added file 'payment_buckaroo/views/payment_acquirer.xml'
607--- payment_buckaroo/views/payment_acquirer.xml 1970-01-01 00:00:00 +0000
608+++ payment_buckaroo/views/payment_acquirer.xml 2014-05-21 05:25:49 +0000
609@@ -0,0 +1,35 @@
610+<?xml version="1.0" encoding="utf-8"?>
611+<openerp>
612+ <data>
613+
614+ <record id="acquirer_form_buckaroo" model="ir.ui.view">
615+ <field name="name">acquirer.form.buckaroo</field>
616+ <field name="model">payment.acquirer</field>
617+ <field name="inherit_id" ref="payment.acquirer_form"/>
618+ <field name="arch" type="xml">
619+ <xpath expr='//group[@name="acquirer_display"]' position='after'>
620+ <group attrs="{'invisible': [('provider', '!=', 'buckaroo')]}">
621+ <field name="brq_websitekey"/>
622+ <field name="brq_secretkey"/>
623+ </group>
624+ </xpath>
625+ </field>
626+ </record>
627+
628+ <record id="transaction_form_buckaroo" model="ir.ui.view">
629+ <field name="name">acquirer.transaction.form.buckaroo</field>
630+ <field name="model">payment.transaction</field>
631+ <field name="inherit_id" ref="payment.transaction_form"/>
632+ <field name="arch" type="xml">
633+ <xpath expr='//notebook' position='inside'>
634+ <page string="Buckaroo TX Details">
635+ <group>
636+ <field name="buckaroo_txnid"/>
637+ </group>
638+ </page>
639+ </xpath>
640+ </field>
641+ </record>
642+
643+ </data>
644+</openerp>
645
646=== modified file 'website_sale/controllers/main.py'
647--- website_sale/controllers/main.py 2014-05-19 10:12:46 +0000
648+++ website_sale/controllers/main.py 2014-05-21 05:25:49 +0000
649@@ -489,7 +489,6 @@
650 values['acquirers'] = payment_obj.browse(cr, uid, acquirer_ids, context=context)
651 render_ctx = dict(context, submit_class='btn btn-primary', submit_txt='Pay Now')
652 for acquirer in values['acquirers']:
653- render_ctx['tx_url'] = '/shop/payment/transaction/%s' % acquirer.id
654 acquirer.button = payment_obj.render(
655 cr, SUPERUSER_ID, acquirer.id,
656 order.name,
657@@ -503,32 +502,35 @@
658
659 return request.website.render("website_sale.payment", values)
660
661- @http.route(['/shop/payment/transaction/<int:acquirer_id>'], type='http', methods=['POST'], auth="public", website=True)
662- def payment_transaction(self, acquirer_id, **post):
663- """ Hook method that creates a payment.transaction and redirect to the
664- acquirer, using post values to re-create the post action.
665+ @http.route(['/shop/payment/transaction/<int:acquirer_id>'], type='json', auth="public", website=True)
666+ def payment_transaction(self, acquirer_id):
667+ """ Json method that creates a payment.transaction, used to create a
668+ transaction when the user clicks on 'pay now' button. After having
669+ created the transaction, the event continues and the user is redirected
670+ to the acquirer website.
671
672 :param int acquirer_id: id of a payment.acquirer record. If not set the
673 user is redirected to the checkout page
674- :param dict post: should coutain all post data for the acquirer
675 """
676- # @TDEFIXME: don't know why we received those data, but should not be send to the acquirer
677- post.pop('submit.x', None)
678- post.pop('submit.y', None)
679 cr, uid, context = request.cr, request.uid, request.context
680- payment_obj = request.registry.get('payment.acquirer')
681 transaction_obj = request.registry.get('payment.transaction')
682 sale_order_obj = request.registry['sale.order']
683 order = request.website.sale_get_order(context=context)
684
685 if not order or not order.order_line or acquirer_id is None:
686- return request.redirect("/shop/checkout")
687+ return False
688
689 assert order.partner_id.id != request.website.partner_id.id
690
691 # find an already existing transaction
692 tx = request.website.sale_get_transaction()
693- if not tx:
694+ if tx:
695+ if tx.state == 'draft': # button cliked but no more info -> rewrite on tx or create a new one ?
696+ tx.write({
697+ 'acquirer_id': acquirer_id,
698+ })
699+ tx_id = tx.id
700+ else:
701 tx_id = transaction_obj.create(cr, SUPERUSER_ID, {
702 'acquirer_id': acquirer_id,
703 'type': 'form',
704@@ -540,10 +542,6 @@
705 'sale_order_id': order.id,
706 }, context=context)
707 request.session['sale_transaction_id'] = tx_id
708- elif tx and tx.state == 'draft': # button cliked but no more info -> rewrite on tx or create a new one ?
709- tx.write({
710- 'acquirer_id': acquirer_id,
711- })
712
713 # update quotation
714 sale_order_obj.write(
715@@ -554,9 +552,7 @@
716 # confirm the quotation
717 sale_order_obj.action_button_confirm(cr, SUPERUSER_ID, [order.id], context=request.context)
718
719- acquirer_form_post_url = payment_obj.get_form_action_url(cr, uid, acquirer_id, context=context)
720- acquirer_total_url = '%s?%s' % (acquirer_form_post_url, werkzeug.url_encode(post))
721- return request.redirect(acquirer_total_url)
722+ return tx_id
723
724 @http.route('/shop/payment/get_status/<int:sale_order_id>', type='json', auth="public", website=True)
725 def payment_get_status(self, sale_order_id, **post):
726
727=== modified file 'website_sale/static/src/js/website_sale_payment.js'
728--- website_sale/static/src/js/website_sale_payment.js 2014-01-24 11:42:24 +0000
729+++ website_sale/static/src/js/website_sale_payment.js 2014-05-21 05:25:49 +0000
730@@ -9,4 +9,14 @@
731 })
732 .find("input[name='acquirer']:checked").click();
733
734+ // When clicking on payment button: create the tx using json then continue to the acquirer
735+ $payment.on("click", "button[name='submit']", function (ev) {
736+ var acquirer_id = $(ev.currentTarget).parents('div.oe_sale_acquirer_button').first().data('id');
737+ if (! acquirer_id) {
738+ return false;
739+ }
740+ return openerp.jsonRpc('/shop/payment/transaction/' + acquirer_id, 'call', {}).then(function (data) {
741+ return true;
742+ });
743+ });
744 });

Subscribers

People subscribed via source and target branches

to all changes: