diff --git a/addons/payment_acquirer/__init__.py b/addons/payment_acquirer/__init__.py index e5619fd9c83..0ce2de595b2 100644 --- a/addons/payment_acquirer/__init__.py +++ b/addons/payment_acquirer/__init__.py @@ -19,5 +19,4 @@ # ############################################################################## -import controllers import payment_acquirer diff --git a/addons/payment_acquirer/__openerp__.py b/addons/payment_acquirer/__openerp__.py index b4c5d552696..08b6e323281 100644 --- a/addons/payment_acquirer/__openerp__.py +++ b/addons/payment_acquirer/__openerp__.py @@ -30,6 +30,8 @@ 'data': [ 'views/acquirer_view.xml', 'payment_acquirer_data.xml', + 'security/ir.model.access.csv', + 'security/ir.rule.xml', ], 'installable': True, } diff --git a/addons/payment_acquirer/controllers/__init__.py b/addons/payment_acquirer/controllers/__init__.py deleted file mode 100644 index 8ee9bae18d9..00000000000 --- a/addons/payment_acquirer/controllers/__init__.py +++ /dev/null @@ -1 +0,0 @@ -import main diff --git a/addons/payment_acquirer/controllers/main.py b/addons/payment_acquirer/controllers/main.py deleted file mode 100644 index d8f7a7d8a98..00000000000 --- a/addons/payment_acquirer/controllers/main.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2013-Today OpenERP SA (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp import SUPERUSER_ID -from openerp.addons.web import http -from openerp.addons.web.http import request -from openerp.addons.website.models import website - - -class PaymentAcquirer(http.Controller): - - @website.route(['/payment_acquirer/'], type='json', auth="public") - def payment_acquirer(self, **post): - return False diff --git a/addons/payment_acquirer/payment_acquirer.py b/addons/payment_acquirer/payment_acquirer.py index 55a3cf6f023..71be65d9716 100644 --- a/addons/payment_acquirer/payment_acquirer.py +++ b/addons/payment_acquirer/payment_acquirer.py @@ -22,13 +22,66 @@ import openerp from openerp.osv import osv, fields from openerp.tools import float_repr +import urlparse +import requests +import logging +_logger = logging.getLogger(__name__) class type(osv.osv): _name = 'payment.acquirer.type' _columns = { 'name': fields.char('Name', required=True), } + def validate_payement(self, cr, uid, id, object, reference, currency, amount, context=None): + """ + return (payment, retry_time) + payment: "validated" or "refused" or "pending" + retry_time = False (don't retry validation) or int (seconds for retry validation) + """ + if isinstance(id, list): + id = id[0] + pay_type = self.browse(cr, uid, id, context=context) + method = getattr(self, '_validate_payement_%s' % pay_type.name) + return method(object, reference, currency, amount, context=context) + + def _validate_payement_virement(self, object, reference, currency, amount, context=None): + return ("pending", False) + + +class type_paypal(osv.osv): + _inherit = "payment.acquirer.type" + + def _validate_payement_paypal(self, object, reference, currency, amount, context=None): + parameters = {} + parameters.update( + cmd='_notify-validate', + business=object.company_id.paypal_account, + item_name="%s %s" % (object.company_id.name, reference), + item_number=reference, + amount=amount, + currency_code=currency.name + ) + paypal_url = "https://www.paypal.com/cgi-bin/webscr" + paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr" + response = urlparse.parse_qsl(requests.post(paypal_url, data=parameters)) + + # transaction's unique id + # response["txn_id"] + + if response["payment_status"] == "Voided": + raise "Paypal authorization has been voided." + elif response["payment_status"] in ("Completed", "Processed") and response["item_number"] == reference and response["mc_gross"] == amount: + return ("validated", False) + elif response["payment_status"] == "Expired": + _logger.warn("Paypal Validate Payement status: Expired") + return ("pending", 5) + elif response["payment_status"] == "Pending": + _logger.warn("Paypal Validate Payement status: Pending, reason: %s" % response["pending_reason"]) + return ("pending", 5) + + # Canceled_Reversal, Denied, Failed, Refunded, Reversed + return ("refused", False) class acquirer(osv.osv): @@ -46,10 +99,10 @@ class acquirer(osv.osv): 'visible': True, } - def render(self, cr, uid, ids, object, reference, currency, amount, context=None): + def render(self, cr, uid, id, object, reference, currency, amount, cancel_url=None, return_url=None, context=None): """ Renders the form template of the given acquirer as a qWeb template """ user = self.pool.get("res.users") - precision = self.pool.get("decimal.precision").precision_get(cr, uid, 'Account') + precision = self.pool.get("decimal.precision").precision_get(cr, openerp.SUPERUSER_ID, 'Account') if not context: context = {} @@ -62,31 +115,22 @@ class acquirer(osv.osv): amount=amount, amount_str=float_repr(amount, precision), user_id=user.browse(cr, uid, uid), - context=context + context=context, + cancel_url=cancel_url, + return_url=return_url ) - pays = self.browse(cr, uid, ids, context=context) - - if isinstance(ids, list): - res = [] - for pay in pays: - res[pay.id] = pay.form_template_id.render(qweb_context.copy(), engine='ir.qweb', context=context) - return res - else: - return pays.form_template_id.render(qweb_context, engine='ir.qweb', context=context) - - def validate_payement(self, cr, uid, ids, object, reference, currency, amount, context=None): - res = [] - for pay in self.browse(cr, uid, ids, context=context): - method = getattr(self, '_validate_payement_%s' % pay.type_id.name) - res[pay.id] = method(cr, uid, ids, object, reference, currency, amount, context=context) - return res - - def _validate_payement_paypal(self, cr, uid, ids, object, reference, currency, amount, context=None): - payment = "pending" # "validated" or "refused" or "pending" - retry_time = False + return self.browse(cr, uid, id, context=context) \ + .form_template_id.render(qweb_context, engine='ir.qweb', context=context) \ + .strip() + def validate_payement(self, cr, uid, id, object, reference, currency, amount, context=None): + """ return (payment, retry_time) - - def _validate_payement_virement(self, cr, uid, ids, object, reference, currency, amount, context=None): - return ("pending", False) + payment: "validated" or "refused" or "pending" + retry_time = False (don't retry validation) or int (seconds for retry validation) + """ + if isinstance(id, list): + id = id[0] + type_id = self.browse(cr, uid, id, context=context).type_id + return type_id.validate_payement(object, reference, currency, amount, context=context) diff --git a/addons/payment_acquirer/payment_acquirer_data.xml b/addons/payment_acquirer/payment_acquirer_data.xml index 62ba7a2530a..943b7a91673 100644 --- a/addons/payment_acquirer/payment_acquirer_data.xml +++ b/addons/payment_acquirer/payment_acquirer_data.xml @@ -8,12 +8,15 @@ @@ -36,6 +39,7 @@ Numero de compte: Communication: + Validate & Pay diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 32fb9d28ca9..8d31ff54159 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -613,31 +613,63 @@ class Ecommerce(http.Controller): return request.redirect("/shop/payment/") @website.route(['/shop/payment/'], type='http', auth="public", multilang=True) - def payment(self, **post): + def payment(self, payment_acquirer_id=None, **post): + payment_obj = request.registry.get('payment.acquirer') order = get_current_order() if not order or not order.order_line: - return self.mycart(**post) + return request.redirect("/shop/checkout/") values = { 'partner': False, + 'payment_acquirer_id': payment_acquirer_id, 'order': order } - payment_obj = request.registry.get('payment.acquirer') - payment_ids = payment_obj.search(request.cr, SUPERUSER_ID, [('visible', '=', True)], context=request.context) - values['payments'] = payment_obj.browse(request.cr, SUPERUSER_ID, payment_ids, request.context) - for payment in values['payments']: - content = payment_obj.render(request.cr, SUPERUSER_ID, payment.id, order, order.name, order.pricelist_id.currency_id, order.amount_total) - payment._content = content.strip() + if payment_acquirer_id: + values['validation'] = self.payment_validation(payment_acquirer_id) + if values['validation'][0] == "validated" or (values['validation'][0] == "pending" and values['validation'][1] == False): + return request.redirect("/shop/confirmation/") + elif values['validation'][0] == "refused": + values['payment_acquirer_id'] = None + + if not values['payment_acquirer_id']: + payment_ids = payment_obj.search(request.cr, SUPERUSER_ID, [('visible', '=', True)], context=request.context) + values['payments'] = payment_obj.browse(request.cr, request.uid, payment_ids, context=request.context) + for pay in values['payments']: + pay._content = payment_obj.render(request.cr, request.uid, pay.id, + object=order, + reference=order.name, + currency=order.pricelist_id.currency_id, + amount=order.amount_total, + cancel_url=request.httprequest.base_url, + return_url="%sshop/payment/?payment_acquirer_id=%s" % (request.httprequest.host_url, pay.id), + context=request.context) return request.website.render("website_sale.payment", values) - @website.route(['/shop/payment_validate/'], type='http', auth="public", multilang=True) - def payment_validate(self, **post): + @website.route(['/shop/payment_validation/'], type='json', auth="public", multilang=True) + def payment_validation(self, payment_acquirer_id=None): + payment_obj = request.registry.get('payment.acquirer') + order = get_current_order() + return payment_obj.validate_payement(request.cr, request.uid, int(payment_acquirer_id), + object=order, + reference=order.name, + currency=order.pricelist_id.currency_id, + amount=order.amount_total, + context=request.context) + + @website.route(['/shop/confirmation/'], type='http', auth="public", multilang=True) + def confirmation(self, **post): + order = get_current_order() + + if not order or not order.order_line: + return request.redirect("/shop/") + + res = request.website.render("website_sale.confirmation", {'order': order}) request.httprequest.session['ecommerce_order_id'] = False request.httprequest.session['ecommerce_pricelist'] = False - return request.redirect("/shop/") + return res @website.route(['/shop/change_sequence/'], type='json', auth="public") def change_sequence(self, id, top): diff --git a/addons/website_sale/models/product_attributes.py b/addons/website_sale/models/product_attributes.py index e89763946f8..57657968daa 100644 --- a/addons/website_sale/models/product_attributes.py +++ b/addons/website_sale/models/product_attributes.py @@ -35,8 +35,8 @@ class attributes(osv.Model): 'value_ids': fields.one2many('product.attribute.value', 'attribute_id', 'Values'), 'product_ids': fields.one2many('product.attribute.product', 'attribute_id', 'Products'), - 'float_max': fields.function(_get_float_max, type='float', string="Max", relation='product.attribute.product',store=True), - 'float_min': fields.function(_get_float_min, type='float', string="Min", relation='product.attribute.product',store=True), + 'float_max': fields.function(_get_float_max, type='float', string="Max", relation='product.attribute.product'), + 'float_min': fields.function(_get_float_min, type='float', string="Min", relation='product.attribute.product'), } _defaults = { 'type': 'distinct' diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index b7a053b2599..de8738cc610 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -789,7 +789,7 @@

Validate Order

-
+
@@ -869,7 +869,7 @@ -
+

Select your payment method:

@@ -881,9 +881,115 @@ +
+ Please wait, we validate your payment. +
+ +
+
+ +
+
+
+ + + + +