diff options
| -rw-r--r-- | .tx/config | 5 | ||||
| -rw-r--r-- | addons/payment_payumoney/__init__.py | 5 | ||||
| -rw-r--r-- | addons/payment_payumoney/__openerp__.py | 20 | ||||
| -rw-r--r-- | addons/payment_payumoney/controllers/__init__.py | 4 | ||||
| -rw-r--r-- | addons/payment_payumoney/controllers/main.py | 24 | ||||
| -rw-r--r-- | addons/payment_payumoney/data/payment_payumoney_data.xml | 28 | ||||
| -rw-r--r-- | addons/payment_payumoney/i18n/payment_payumoney.pot | 97 | ||||
| -rw-r--r-- | addons/payment_payumoney/models/__init__.py | 5 | ||||
| -rw-r--r-- | addons/payment_payumoney/models/payment_acquirer.py | 78 | ||||
| -rw-r--r-- | addons/payment_payumoney/models/payment_transaction.py | 86 | ||||
| -rw-r--r-- | addons/payment_payumoney/static/description/icon.png | bin | 0 -> 60598 bytes | |||
| -rw-r--r-- | addons/payment_payumoney/static/src/img/payumoney_icon.png | bin | 0 -> 5538 bytes | |||
| -rw-r--r-- | addons/payment_payumoney/views/payment_acquirer.xml | 16 | ||||
| -rw-r--r-- | addons/payment_payumoney/views/payumoney.xml | 25 |
14 files changed, 393 insertions, 0 deletions
diff --git a/.tx/config b/.tx/config index 8acbd627c7d..f73f83a49f3 100644 --- a/.tx/config +++ b/.tx/config @@ -642,6 +642,11 @@ file_filter = addons/payment_paypal/i18n/<lang>.po source_file = addons/payment_paypal/i18n/payment_paypal.pot source_lang = en +[odoo-9.payment_payumoney] +file_filter = addons/payment_payumoney/i18n/<lang>.po +source_file = addons/payment_payumoney/i18n/payment_payumoney.pot +source_lang = en + [odoo-9.payment_sips] file_filter = addons/payment_sips/i18n/<lang>.po source_file = addons/payment_sips/i18n/payment_sips.pot diff --git a/addons/payment_payumoney/__init__.py b/addons/payment_payumoney/__init__.py new file mode 100644 index 00000000000..5efbd253ebb --- /dev/null +++ b/addons/payment_payumoney/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import models +import controllers diff --git a/addons/payment_payumoney/__openerp__.py b/addons/payment_payumoney/__openerp__.py new file mode 100644 index 00000000000..62e92bb78d8 --- /dev/null +++ b/addons/payment_payumoney/__openerp__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'PayuMoney Payment Acquirer', + 'category': 'Payment Acquirer', + 'summary': 'Payment Acquirer: PayuMoney Implementation', + 'description': """ + PayuMoney Payment Acquirer for India. + + PayUmoney payment gateway supports only INR currency. + """, + 'depends': ['payment'], + 'data': [ + 'views/payumoney.xml', + 'views/payment_acquirer.xml', + 'data/payment_payumoney_data.xml', + ], + 'license': 'OEEL-1', +} diff --git a/addons/payment_payumoney/controllers/__init__.py b/addons/payment_payumoney/controllers/__init__.py new file mode 100644 index 00000000000..f48716d3a69 --- /dev/null +++ b/addons/payment_payumoney/controllers/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import main diff --git a/addons/payment_payumoney/controllers/main.py b/addons/payment_payumoney/controllers/main.py new file mode 100644 index 00000000000..78bc73dfe2d --- /dev/null +++ b/addons/payment_payumoney/controllers/main.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import logging +import pprint +import werkzeug + +from odoo import http +from odoo.http import request + +_logger = logging.getLogger(__name__) + + +class PayuMoneyController(http.Controller): + @http.route(['/payment/payumoney/return', '/payment/payumoney/cancel', '/payment/payumoney/error'], type='http', auth='public', csrf=False) + def payu_return(self, **post): + """ PayUmoney.""" + _logger.info( + 'PayUmoney: entering form_feedback with post data %s', pprint.pformat(post)) + return_url = '/' + if post: + request.env['payment.transaction'].sudo().form_feedback(post, 'payumoney') + return_url = post.get('udf1') + return werkzeug.utils.redirect(return_url) diff --git a/addons/payment_payumoney/data/payment_payumoney_data.xml b/addons/payment_payumoney/data/payment_payumoney_data.xml new file mode 100644 index 00000000000..2bbff8f9470 --- /dev/null +++ b/addons/payment_payumoney/data/payment_payumoney_data.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data noupdate="1"> + <record id="payment_acquirer_payumoney" model="payment.acquirer"> + <field name="name">PayUmoney</field> + <field name="image" type="base64" file="payment_payumoney/static/description/icon.png"/> + <field name="provider">payumoney</field> + <field name="company_id" ref="base.main_company"/> + <field name="view_template_id" ref="payumoney_acquirer_button"/> + <field name="environment">test</field> + <field name="pre_msg"><![CDATA[ + <p>You will be redirected to the PayUmoney website after clicking on the payment button.</p>]]> + </field> + <field name="payumoney_merchant_key">dummy</field> + <field name="payumoney_merchant_salt">dummy</field> + <field name="description" type="html"> + <p> + PayU India is an online payments solutions company serving the Indian market. + </p> + <ul> + <li><i class="fa fa-check"/>eCommerce</li> + <li><i class="fa fa-check"/>Subscription</li> + <li><i class="fa fa-check"/>Pay button in emails</li> + </ul> + </field> + </record> + </data> +</odoo> diff --git a/addons/payment_payumoney/i18n/payment_payumoney.pot b/addons/payment_payumoney/i18n/payment_payumoney.pot new file mode 100644 index 00000000000..b4de2907c04 --- /dev/null +++ b/addons/payment_payumoney/i18n/payment_payumoney.pot @@ -0,0 +1,97 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * payment_payumoney +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0alpha1e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-03-17 08:19+0000\n" +"PO-Revision-Date: 2016-03-17 08:19+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: payment_payumoney +#: model:payment.acquirer,cancel_msg:payment_payumoney.payment_acquirer_payumoney +msgid "<span><i>Cancel,</i> Your payment has been cancelled.</span>" +msgstr "" + +#. module: payment_payumoney +#: model:payment.acquirer,done_msg:payment_payumoney.payment_acquirer_payumoney +msgid "<span><i>Done,</i> Your online payment has been successfully processed. Thank you for your order.</span>" +msgstr "" + +#. module: payment_payumoney +#: model:payment.acquirer,error_msg:payment_payumoney.payment_acquirer_payumoney +msgid "<span><i>Error,</i> Please be aware that an error occurred during the transaction. The order has been confirmed but won't be paid. Don't hesitate to contact us if you have any questions on the status of your order.</span>" +msgstr "" + +#. module: payment_payumoney +#: model:payment.acquirer,pending_msg:payment_payumoney.payment_acquirer_payumoney +msgid "<span><i>Pending,</i> Your online payment has been successfully processed. But your order is not validated yet.</span>" +msgstr "" + +#. module: payment_payumoney +#: model:ir.model.fields,field_description:payment_payumoney.field_payment_acquirer_payumoney_merchant_key +msgid "Merchant Key" +msgstr "" + +#. module: payment_payumoney +#: model:ir.model.fields,field_description:payment_payumoney.field_payment_acquirer_payumoney_merchant_salt +msgid "Merchant Salt" +msgstr "" + +#. module: payment_payumoney +#: model:payment.acquirer,name:payment_payumoney.payment_acquirer_payumoney +msgid "PayUmoney" +msgstr "" + +#. module: payment_payumoney +#: code:addons/payment_payumoney/models/payment_transaction.py:77 +#, python-format +msgid "PayUmoney: feedback error" +msgstr "" + +#. module: payment_payumoney +#: code:addons/payment_payumoney/models/payment_transaction.py:39 +#, python-format +msgid "PayUmoney: invalid shasign, received %s, computed %s, for data %s" +msgstr "" + +#. module: payment_payumoney +#: code:addons/payment_payumoney/models/payment_transaction.py:33 +#, python-format +msgid "PayUmoney: received data for reference %s; multiple orders found" +msgstr "" + +#. module: payment_payumoney +#: code:addons/payment_payumoney/models/payment_transaction.py:30 +#, python-format +msgid "PayUmoney: received data for reference %s; no order found" +msgstr "" + +#. module: payment_payumoney +#: code:addons/payment_payumoney/models/payment_transaction.py:25 +#, python-format +msgid "PayUmoney: received data with missing reference (%s) or pay_id (%s) or shashign (%s)" +msgstr "" + +#. module: payment_payumoney +#: model:ir.model,name:payment_payumoney.model_payment_acquirer +msgid "Payment Acquirer" +msgstr "" + +#. module: payment_payumoney +#: model:ir.model,name:payment_payumoney.model_payment_transaction +msgid "Payment Transaction" +msgstr "" + +#. module: payment_payumoney +#: model:payment.acquirer,pre_msg:payment_payumoney.payment_acquirer_payumoney +msgid "You will be redirected to the PayUmoney website after clicking on the payment button." +msgstr "" + diff --git a/addons/payment_payumoney/models/__init__.py b/addons/payment_payumoney/models/__init__.py new file mode 100644 index 00000000000..29abdbcb773 --- /dev/null +++ b/addons/payment_payumoney/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import payment_acquirer +import payment_transaction diff --git a/addons/payment_payumoney/models/payment_acquirer.py b/addons/payment_payumoney/models/payment_acquirer.py new file mode 100644 index 00000000000..0abe333e73d --- /dev/null +++ b/addons/payment_payumoney/models/payment_acquirer.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import hashlib +import urlparse + +from odoo import api, fields, models, _ + + +class PaymentAcquirerPayumoney(models.Model): + _inherit = 'payment.acquirer' + + payumoney_merchant_key = fields.Char(string='Merchant Key', required_if_provider='payumoney') + payumoney_merchant_salt = fields.Char(string='Merchant Salt', required_if_provider='payumoney') + + def _get_payumoney_urls(self, environment): + """ PayUmoney URLs""" + if environment == 'prod': + return {'payumoney_form_url': 'https://secure.payu.in/_payment'} + else: + return {'payumoney_form_url': 'https://test.payu.in/_payment'} + + @api.model + def _get_providers(self): + providers = super(PaymentAcquirerPayumoney, self)._get_providers() + providers.append(['payumoney', 'PayUmoney']) + return providers + + def _payumoney_generate_sign(self, inout, values): + """ Generate the shasign for incoming or outgoing communications. + :param self: the self browse record. It should have a shakey in shakey out + :param string inout: 'in' (odoo contacting payumoney) or 'out' (payumoney + contacting odoo). + :param dict values: transaction values + + :return string: shasign + """ + if inout not in ('in', 'out'): + raise Exception("Type must be 'in' or 'out'") + + if inout == 'in': + keys = "key|txnid|amount|productinfo|firstname|email|udf1|||||||||".split('|') + sign = ''.join('%s|' % (values.get(k) or '') for k in keys) + sign += self.payumoney_merchant_salt or '' + else: + keys = "|status||||||||||udf1|email|firstname|productinfo|amount|txnid".split('|') + sign = ''.join('%s|' % (values.get(k) or '') for k in keys) + sign = self.payumoney_merchant_salt + sign + self.payumoney_merchant_key + + shasign = hashlib.sha512(sign).hexdigest() + return shasign + + @api.multi + def payumoney_form_generate_values(self, values): + self.ensure_one() + base_url = self.env['ir.config_parameter'].get_param('web.base.url') + payumoney_values = dict(values, + key=self.payumoney_merchant_key, + txnid=values['reference'], + amount=values['amount'], + productinfo=values['reference'], + firstname=values.get('partner_name'), + email=values.get('partner_email'), + phone=values.get('partner_phone'), + service_provider='payu_paisa', + surl='%s' % urlparse.urljoin(base_url, '/payment/payumoney/return'), + furl='%s' % urlparse.urljoin(base_url, '/payment/payumoney/error'), + curl='%s' % urlparse.urljoin(base_url, '/payment/payumoney/cancel') + ) + + payumoney_values['udf1'] = payumoney_values.pop('return_url', '/') + payumoney_values['hash'] = self._payumoney_generate_sign('in', payumoney_values) + return payumoney_values + + @api.multi + def payumoney_get_form_action_url(self): + self.ensure_one() + return self._get_payumoney_urls(self.environment)['payumoney_form_url'] diff --git a/addons/payment_payumoney/models/payment_transaction.py b/addons/payment_payumoney/models/payment_transaction.py new file mode 100644 index 00000000000..b502307b467 --- /dev/null +++ b/addons/payment_payumoney/models/payment_transaction.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import logging + +from odoo import api, fields, models, _ +from odoo.addons.payment.models.payment_acquirer import ValidationError +from odoo.tools.float_utils import float_compare + + +_logger = logging.getLogger(__name__) + + +class PaymentTransactionPayumoney(models.Model): + _inherit = 'payment.transaction' + + @api.model + def _payumoney_form_get_tx_from_data(self, data): + """ Given a data dict coming from payumoney, verify it and find the related + transaction record. """ + reference = data.get('txnid') + pay_id = data.get('mihpayid') + shasign = data.get('hash') + if not reference or not pay_id or not shasign: + raise ValidationError(_('PayUmoney: received data with missing reference (%s) or pay_id (%s) or shashign (%s)') % (reference, pay_id, shasign)) + + transaction = self.search([('reference', '=', reference)]) + + if not transaction: + error_msg = (_('PayUmoney: received data for reference %s; no order found') % (reference)) + raise ValidationError(error_msg) + elif len(transaction) > 1: + error_msg = (_('PayUmoney: received data for reference %s; multiple orders found') % (reference)) + raise ValidationError(error_msg) + + #verify shasign + shasign_check = transaction.acquirer_id._payumoney_generate_sign('out', data) + if shasign_check.upper() != shasign.upper(): + raise ValidationError(_('PayUmoney: invalid shasign, received %s, computed %s, for data %s') % (shasign, shasign_check, data)) + return transaction + + @api.model + def _payumoney_form_get_invalid_parameters(self, transaction, data): + invalid_parameters = [] + + if transaction.acquirer_reference and data.get('mihpayid') != transaction.acquirer_reference: + invalid_parameters.append( + ('Transaction Id', data.get('mihpayid'), transaction.acquirer_reference)) + #check what is buyed + if float_compare(float(data.get('amount', '0.0')), transaction.amount, 2) != 0: + invalid_parameters.append( + ('Amount', data.get('amount'), '%.2f' % transaction.amount)) + + return invalid_parameters + + @api.model + def _payumoney_form_validate(self, transaction, data): + status = data.get('status') + transaction_status = { + 'success': { + 'state': 'done', + 'acquirer_reference': data.get('payuMoneyId'), + 'date_validate': fields.Datetime.now(), + }, + 'pending': { + 'state': 'pending', + 'acquirer_reference': data.get('payuMoneyId'), + 'date_validate': fields.Datetime.now(), + }, + 'failure': { + 'state': 'cancel', + 'acquirer_reference': data.get('payuMoneyId'), + 'date_validate': fields.Datetime.now(), + }, + 'error': { + 'state': 'error', + 'state_message': data.get('error_Message') or _('PayUmoney: feedback error'), + 'acquirer_reference': data.get('payuMoneyId'), + 'date_validate': fields.Datetime.now(), + } + } + vals = transaction_status.get(status, False) + if not vals: + vals = transaction_status['error'] + _logger.info(vals['state_message']) + return transaction.write(vals) diff --git a/addons/payment_payumoney/static/description/icon.png b/addons/payment_payumoney/static/description/icon.png Binary files differnew file mode 100644 index 00000000000..9b467f8416c --- /dev/null +++ b/addons/payment_payumoney/static/description/icon.png diff --git a/addons/payment_payumoney/static/src/img/payumoney_icon.png b/addons/payment_payumoney/static/src/img/payumoney_icon.png Binary files differnew file mode 100644 index 00000000000..4055c624801 --- /dev/null +++ b/addons/payment_payumoney/static/src/img/payumoney_icon.png diff --git a/addons/payment_payumoney/views/payment_acquirer.xml b/addons/payment_payumoney/views/payment_acquirer.xml new file mode 100644 index 00000000000..406aab52dbc --- /dev/null +++ b/addons/payment_payumoney/views/payment_acquirer.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <record id="payment_acquirer_form_payumoney" model="ir.ui.view"> + <field name="name">payment.acquirer.form.inherit</field> + <field name="model">payment.acquirer</field> + <field name="inherit_id" ref="payment.acquirer_form"/> + <field name="arch" type="xml"> + <xpath expr='//group[@name="acquirer"]' position='after'> + <group attrs="{'invisible': [('provider', '!=', 'payumoney')]}"> + <field name="payumoney_merchant_key"/> + <field name="payumoney_merchant_salt" password="True"/> + </group> + </xpath> + </field> + </record> +</odoo> diff --git a/addons/payment_payumoney/views/payumoney.xml b/addons/payment_payumoney/views/payumoney.xml new file mode 100644 index 00000000000..3fd3ca8c254 --- /dev/null +++ b/addons/payment_payumoney/views/payumoney.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <template id="payumoney_acquirer_button"> + <form t-if="acquirer.payumoney_merchant_key" t-att-action="tx_url" method="post" target="_self"> + <input type="hidden" name="key" t-att-value='key' /> + <input type="hidden" name="txnid" t-att-value='txnid' /> + <input type="hidden" name="amount" t-att-value='amount' /> + <input type="hidden" name="productinfo" t-att-value='productinfo' /> + <input type="hidden" name="firstname" t-att-value='firstname' /> + <input type="hidden" name="email" t-att-value='email' /> + <input type="hidden" name="phone" t-att-value='phone'/> + <input type="hidden" name="service_provider" t-att-value='service_provider' /> + <input type="hidden" name="hash" t-att-value='hash' /> + <input type="hidden" name="surl" t-att-value='surl' /> + <input type="hidden" name="furl" t-att-value='furl' /> + <input type="hidden" name="curl" t-att-value='curl' /> + <input type="hidden" name="udf1" t-att-value='udf1'/> + <!-- submit --> + <button type="submit" width="100px" t-att-class="submit_class"> + <img t-if="not submit_txt" src="/payment_payumoney/static/src/img/payumoney_icon.png"/> + <span t-if="submit_txt"><t t-esc="submit_txt"/> <span class="fa fa-long-arrow-right"/></span> + </button> + </form> + </template> +</odoo> |
