Unverified Commit 1fdb10f0 authored by Damien Bouvy's avatar Damien Bouvy
Browse files

[MERGE] payments: Add new payment form to e-commerce & online quote

- The generic form now support form & s2s payments.
- The generic form is now implemented to pay on e-commerce and online
quotation.
- Added icons of supported credit cards for each payment acquirers.
- Replaced e-commerce footer that was displaying payment acquirers by
supported credit cards icons.
- The payment form doesn't render s2s forms in python anymore.
- The payment form now display an error when credit cards credentials
are not filled.
- Fixed a bug where paying with a registered token on e-commerce would
crash.
- Fixed errors not displaying on the payment form.
parents d8970d05 26eaac4e
Showing with 337 additions and 145 deletions
+337 -145
......@@ -9,6 +9,7 @@
'depends': ['account'],
'data': [
'data/account_data.xml',
'data/payment_icon_data.xml',
'data/payment_acquirer_data.xml',
'views/payment_views.xml',
'views/account_payment_views.xml',
......
......@@ -8,17 +8,18 @@ from odoo.http import request
class WebsitePayment(http.Controller):
@http.route(['/my/payment_method'], type='http', auth="user", website=True)
def payment_method(self, **kwargs):
acquirers = list(request.env['payment.acquirer'].search([('website_published', '=', True), ('registration_view_template_id', '!=', False)]))
acquirers = list(request.env['payment.acquirer'].search([('website_published', '=', True), ('registration_view_template_id', '!=', False), ('payment_flow', '=', 's2s')]))
partner = request.env.user.partner_id
payment_tokens = partner.payment_token_ids
payment_tokens |= partner.commercial_partner_id.sudo().payment_token_ids
return_url = request.params.get('redirect', '/my/payment_method')
values = {
'pms': payment_tokens,
'acquirers': acquirers
'acquirers': acquirers,
'return_url': return_url,
'bootstrap_formatting': True,
'partner_id': partner.id
}
return_url = request.params.get('redirect', '/my/payment_method')
for acquirer in acquirers:
acquirer.form = acquirer.sudo()._registration_render(request.env.user.partner_id.id, {'error': {}, 'error_message': [], 'return_url': return_url, 'json': False, 'bootstrap_formatting': True})
return request.render("payment.pay_methods", values)
@http.route(['/website_payment/pay'], type='http', auth='public', website=True)
......
......@@ -2,20 +2,14 @@
<odoo noupdate="1">
<template id="default_acquirer_button">
<form t-if="acquirer" t-att-action="tx_url" method="post" target="_self">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<t t-if="return_url">
<input type="hidden" name="return_url" t-att-value="return_url"/>
</t>
<input type="hidden" name="reference" t-att-value="reference"/>
<input type="hidden" name="amount" t-att-value="amount"/>
<input type="hidden" name="currency" t-att-value="currency.name"/>
<!-- submit -->
<button type="submit" width="100px" t-att-class="submit_class">
<img t-if="not submit_txt" src="/payment_transfer/static/src/img/transfer_icon.png"/>
<span t-if="submit_txt"><t t-esc="submit_txt"/> <span class="fa fa-long-arrow-right"/></span>
</button>
</form>
<input type="hidden" name="data_set" t-att-data-action-url="tx_url"/>
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<t t-if="return_url">
<input type="hidden" name="return_url" t-att-value="return_url"/>
</t>
<input type="hidden" name="reference" t-att-value="reference"/>
<input type="hidden" name="amount" t-att-value="amount"/>
<input type="hidden" name="currency" t-att-value="currency.name"/>
</template>
<record id="payment_acquirer_buckaroo" model="payment.acquirer">
......@@ -32,6 +26,12 @@
<li><i class="fa fa-check"/>Payment Status Tracking</li>
</ul>
</field>
<!-- https://www.buckaroo-payments.com/products/payment-methods/ -->
<field name="payment_icon_ids" eval='[(6, 0, [ref("payment.payment_icon_cc_bancontact"),
ref("payment.payment_icon_cc_maestro"),
ref("payment.payment_icon_cc_mastercard"),
ref("payment.payment_icon_cc_visa"),
ref("payment.payment_icon_cc_american_express")])]'/>
</record>
<record id="payment_acquirer_ogone" model="payment.acquirer">
......@@ -51,6 +51,11 @@
<li><i class="fa fa-check"/>Save Cards</li>
</ul>
</field>
<!-- https://payment-services.ingenico.com/~/media/files/130806_product_sheet_ingenico_collect_en.ashx?la=en -->
<field name="payment_icon_ids" eval='[(6, 0, [ref("payment.payment_icon_cc_bancontact"),
ref("payment.payment_icon_cc_maestro"),
ref("payment.payment_icon_cc_mastercard"),
ref("payment.payment_icon_cc_visa")])]'/>
</record>
<record id="payment_acquirer_adyen" model="payment.acquirer">
......@@ -67,6 +72,15 @@
<li><i class="fa fa-check"/>Payment Status Tracking</li>
</ul>
</field>
<!-- https://www.adyen.com/payment-methods -->
<field name="payment_icon_ids" eval='[(6, 0, [ref("payment.payment_icon_cc_bancontact"),
ref("payment.payment_icon_cc_maestro"),
ref("payment.payment_icon_cc_mastercard"),
ref("payment.payment_icon_cc_visa"),
ref("payment.payment_icon_cc_discover"),
ref("payment.payment_icon_cc_diners_club_intl"),
ref("payment.payment_icon_cc_jcb"),
ref("payment.payment_icon_cc_unionpay")])]'/>
</record>
<record id="payment_acquirer_authorize" model="payment.acquirer">
......@@ -87,6 +101,13 @@
<li><i class="fa fa-check"/>Manual Capture</li>
</ul>
</field>
<!-- https://www.authorize.net/solutions/merchantsolutions/onlinemerchantaccount/ -->
<field name="payment_icon_ids" eval='[(6, 0, [ref("payment.payment_icon_cc_maestro"),
ref("payment.payment_icon_cc_mastercard"),
ref("payment.payment_icon_cc_discover"),
ref("payment.payment_icon_cc_diners_club_intl"),
ref("payment.payment_icon_cc_jcb"),
ref("payment.payment_icon_cc_visa")])]'/>
</record>
<record id="payment_acquirer_transfer" model="payment.acquirer">
......@@ -117,6 +138,16 @@
<li><i class="fa fa-check"/>Payment Status Tracking</li>
</ul>
</field>
<!-- http://sips.worldline.com/en-us/home/features/payment-types-and-acquirers.html -->
<field name="payment_icon_ids" eval='[(6, 0, [ref("payment.payment_icon_cc_maestro"),
ref("payment.payment_icon_cc_mastercard"),
ref("payment.payment_icon_cc_discover"),
ref("payment.payment_icon_cc_diners_club_intl"),
ref("payment.payment_icon_cc_jcb"),
ref("payment.payment_icon_cc_american_express"),
ref("payment.payment_icon_cc_bancontact"),
ref("payment.payment_icon_cc_unionpay"),
ref("payment.payment_icon_cc_visa")])]'/>
</record>
<record id="payment_acquirer_paypal" model="payment.acquirer">
......@@ -134,6 +165,15 @@
<li><i class="fa fa-check"/>Payment Status Tracking</li>
</ul>
</field>
<!-- https://www.paypal.com/us/selfhelp/article/Which-credit-cards-can-I-accept-with-PayPal-Merchant-Services-FAQ1525#business -->
<field name="payment_icon_ids" eval='[(6, 0, [ref("payment.payment_icon_cc_maestro"),
ref("payment.payment_icon_cc_mastercard"),
ref("payment.payment_icon_cc_discover"),
ref("payment.payment_icon_cc_diners_club_intl"),
ref("payment.payment_icon_cc_jcb"),
ref("payment.payment_icon_cc_american_express"),
ref("payment.payment_icon_cc_unionpay"),
ref("payment.payment_icon_cc_visa")])]'/>
</record>
<record id="payment_acquirer_stripe" model="payment.acquirer">
......@@ -150,7 +190,17 @@
<li><i class="fa fa-check"/>Payment Status Tracking</li>
</ul>
</field>
<!--
https://stripe.com/payments/payment-methods-guide
https://support.goteamup.com/hc/en-us/articles/115002089349-Which-cards-and-payment-types-can-I-accept-with-Stripe-
-->
<field name="payment_icon_ids" eval='[(6, 0, [ref("payment.payment_icon_cc_maestro"),
ref("payment.payment_icon_cc_mastercard"),
ref("payment.payment_icon_cc_discover"),
ref("payment.payment_icon_cc_diners_club_intl"),
ref("payment.payment_icon_cc_jcb"),
ref("payment.payment_icon_cc_american_express"),
ref("payment.payment_icon_cc_visa")])]'/>
</record>
<record id="payment_acquirer_custom" model="payment.acquirer">
......@@ -182,6 +232,13 @@
<li><i class="fa fa-check"/>Payment Status Tracking</li>
</ul>
</field>
<!-- https://www.payumoney.com/selfcare.html?userType=seller
> Banks & Cards > What options do you have in the Credit Card payment?
-->
<field name="payment_icon_ids" eval='[(6, 0, [ref("payment.payment_icon_cc_maestro"),
ref("payment.payment_icon_cc_mastercard"),
ref("payment.payment_icon_cc_american_express"),
ref("payment.payment_icon_cc_visa")])]'/>
</record>
</odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment_icon_cc_visa" model="payment.icon">
<field name="name">VISA</field>
<field name="image" type="base64" file="payment/static/img/visa.png"/>
</record>
<record id="payment_icon_cc_american_express" model="payment.icon">
<field name="name">American Express</field>
<field name="image" type="base64" file="payment/static/img/american_express.png"/>
</record>
<record id="payment_icon_cc_cirrus" model="payment.icon">
<field name="name">Cirrus</field>
<field name="image" type="base64" file="payment/static/img/cirrus.png"/>
</record>
<record id="payment_icon_cc_diners_club_intl" model="payment.icon">
<field name="name">Diners Club International</field>
<field name="image" type="base64" file="payment/static/img/diners_club_intl.png"/>
</record>
<record id="payment_icon_cc_diners_club_intl" model="payment.icon">
<field name="name">Diners Club International</field>
<field name="image" type="base64" file="payment/static/img/diners_club_intl.png"/>
</record>
<record id="payment_icon_cc_discover" model="payment.icon">
<field name="name">Discover</field>
<field name="image" type="base64" file="payment/static/img/discover.png"/>
</record>
<record id="payment_icon_cc_jcb" model="payment.icon">
<field name="name">JCB</field>
<field name="image" type="base64" file="payment/static/img/jcb.png"/>
</record>
<record id="payment_icon_cc_maestro" model="payment.icon">
<field name="name">Maestro</field>
<field name="image" type="base64" file="payment/static/img/maestro.png"/>
</record>
<record id="payment_icon_cc_mastercard" model="payment.icon">
<field name="name">MasterCard</field>
<field name="image" type="base64" file="payment/static/img/mastercard.png"/>
</record>
<record id="payment_icon_cc_unionpay" model="payment.icon">
<field name="name">UnionPay</field>
<field name="image" type="base64" file="payment/static/img/unionpay.png"/>
</record>
<record id="payment_icon_cc_bancontact" model="payment.icon">
<field name="name">Bancontact</field>
<field name="image" type="base64" file="payment/static/img/bancontact.png"/>
</record>
</odoo>
\ No newline at end of file
......@@ -5,7 +5,7 @@ import logging
import datetime
from odoo import api, exceptions, fields, models, _
from odoo.tools import consteq, float_round, image_resize_images, ustr
from odoo.tools import consteq, float_round, image_resize_images, image_resize_image, ustr
from odoo.addons.base.module import module
from odoo.exceptions import ValidationError
......@@ -117,8 +117,8 @@ class PaymentAcquirer(models.Model):
help='Message displayed, if error is occur during the payment process.')
save_token = fields.Selection([
('none', 'Never'),
('ask', 'Let the customer decide (recommended for eCommerce)'),
('always', 'Always (recommended for Subscriptions)')],
('ask', 'Let the customer decide'),
('always', 'Always')],
string='Save Cards', default='none',
help="This option allows customers to save their credit card as a payment token and to reuse it for a later purchase."
"If you manage subscriptions (recurring invoicing), you need it to automatically charge the customer when you "
......@@ -150,6 +150,12 @@ class PaymentAcquirer(models.Model):
"resized as a 64x64px image, with aspect ratio preserved. "
"Use this field anywhere a small image is required.")
payment_icon_ids = fields.Many2many('payment.icon', string='Supported Payment Icons')
payment_flow = fields.Selection(selection=[('s2s','The customer encode his payment details on the website.'),
('form', 'The customer is redirected to the website of the acquirer.')],
default='form', required=True, string='Payment flow',
help="""Note: Subscriptions does not take this field in account, it uses server to server by default.""")
def _search_is_tokenized(self, operator, value):
tokenized = self._get_feature_support()['tokenize']
if (operator, value) in [('=', True), ('!=', False)]:
......@@ -344,16 +350,11 @@ class PaymentAcquirer(models.Model):
return self.view_template_id.render(values, engine='ir.qweb')
@api.multi
def _registration_render(self, partner_id, qweb_context=None):
if qweb_context is None:
qweb_context = {}
qweb_context.update(id=self.ids[0], partner_id=partner_id)
method_name = '_%s_registration_form_generate_values' % (self.provider,)
if hasattr(self, method_name):
method = getattr(self, method_name)
qweb_context.update(method(qweb_context))
return self.registration_view_template_id.render(qweb_context, engine='ir.qweb')
def get_s2s_form_xml_id(self):
if self.registration_view_template_id:
model_data = self.env['ir.model.data'].search([('model', '=', 'ir.ui.view'), ('res_id', '=', self.registration_view_template_id.id)])
return ('%s.%s') % (model_data.module, model_data.name)
return False
@api.multi
def s2s_process(self, data):
......@@ -394,6 +395,32 @@ class PaymentAcquirer(models.Model):
'context': context,
}
class PaymentIcon(models.Model):
_name = 'payment.icon'
_description = 'Payment Icon'
name = fields.Char(string='Name')
acquirer_ids = fields.Many2many('payment.acquirer', string="Acquirers", help="List of Acquirers supporting this payment icon.")
image = fields.Binary(
"Image", attachment=True,
help="This field holds the image used for this payment icon, limited to 1024x1024px")
image_payment_form = fields.Binary(
"Image displayed on the payment form", attachment=True)
@api.model
def create(self, vals):
if 'image' in vals:
vals['image_payment_form'] = image_resize_image(vals['image'], size=(45,30))
vals['image'] = image_resize_image(vals['image'], size=(64,64))
return super(PaymentIcon, self).create(vals)
@api.multi
def write(self, vals):
if 'image' in vals:
vals['image_payment_form'] = image_resize_image(vals['image'], size=(45,30))
vals['image'] = image_resize_image(vals['image'], size=(64,64))
return super(PaymentIcon, self).write(vals)
class PaymentTransaction(models.Model):
""" Transaction Model. Each specific acquirer can extend the model by adding
......
......@@ -9,3 +9,6 @@ payment_method_all,payment.token.all,model_payment_token,,1,0,0,0
payment_method_user,payment.token.user,model_payment_token,base.group_user,1,1,1,1
payment_method_portal,payment.token.portal,model_payment_token,base.group_portal,1,1,1,1
payment_method_system,payment.token.system,model_payment_token,base.group_system,1,1,1,1
payment_icon_all,payment.icon.all,model_payment_icon,,1,0,0,0
payment_icon_user,payment.icon.user,model_payment_icon,base.group_user,1,1,1,0
payment_icon_system,payment.icon.system,model_payment_icon,base.group_system,1,1,1,1
\ No newline at end of file
addons/payment/static/img/american_express.png

6.99 KB

addons/payment/static/img/bancontact.png

6.91 KB

addons/payment/static/img/cirrus.png

6.63 KB

addons/payment/static/img/diners_club_intl.png

8.7 KB

addons/payment/static/img/discover.png

5.74 KB

addons/payment/static/img/jcb.png

4 KB

addons/payment/static/img/maestro.png

7.83 KB

addons/payment/static/img/mastercard.png

8.75 KB

addons/payment/static/img/unionpay.png

9.31 KB

addons/payment/static/img/visa.png

4.79 KB

......@@ -18,7 +18,6 @@ odoo.define('payment.payment_form', function (require){
},
payEvent: function(ev) {
ev.stopPropagation();
ev.preventDefault();
var form = this.el;
var checked_radio = this.$('input[type="radio"]:checked');
......@@ -33,8 +32,28 @@ odoo.define('payment.payment_form', function (require){
var acquirer_id = this.getAcquirerIdFromRadio(checked_radio);
var acquirer_form = this.$('#o_payment_add_token_acq_' + acquirer_id);
// we retrieve all the input inside the acquirer form and 'serialize' them to an indexed array
var form_data = this.getFormData($('input', acquirer_form));
var inputs_form = $('input', acquirer_form);
var form_data = this.getFormData(inputs_form);
var ds = $('input[name="data_set"]', acquirer_form)[0];
var empty_inputs = false;
inputs_form.toArray().forEach(function(element) {
if(element.dataset.isRequired) {
if (element.value.length === 0) {
$(element).closest('div.form-group').addClass('has-error');
}
else {
$(element).closest('div.form-group').removeClass('has-error');
}
empty_inputs = true;
}
});
if(empty_inputs) {
this.error(_t('Missing values'), _t('<p>Please fill all the inputs required.</p>'));
return;
}
$(button).attr('disabled', true);
$(button).prepend('<span class="o_loader"><i class="fa fa-refresh fa-spin"></i>&nbsp;</span>');
......@@ -59,7 +78,7 @@ odoo.define('payment.payment_form', function (require){
}
// if the server has returned false, we display an error
else {
self.error(_t('Error'),
self.error(_t('Server Error'),
_t("<p>We are not able to add your payment method at the moment.</p>"));
}
// here we remove the 'processing' icon from the 'add a new payment' button
......@@ -70,10 +89,62 @@ odoo.define('payment.payment_form', function (require){
$(button).attr('disabled', false);
$(button).find('span.o_loader').remove();
self.error(_t('Error'),
self.error(_t('Server Error'),
_t("<p>We are not able to add your payment method at the moment.</p>") + (core.debug ? data.data.message : ''));
});
}
// if the user is going to pay with a form payment, then
else if(this.isFormPaymentRadio(checked_radio))
{
var self = this;
// we retrieve the acquirer id and its form
var acquirer_id = this.getAcquirerIdFromRadio(checked_radio);
var acquirer_form = this.$('#o_payment_form_acq_' + acquirer_id);
var inputs_form = $('input', acquirer_form);
var ds = $('input[name="data_set"]', acquirer_form)[0];
var form_save_token = false;
var $tx_url = this.$el.find('input[name="prepare_tx_url"]');
// if neither the dataset or the action url is defined, then we just stop the execution of the function
if(!ds || !ds.dataset.actionUrl)
return;
// if there's a prepare tx url set
if($tx_url.length == 1)
{
// if the user wants to save his credit card info
form_save_token = $('input[name="o_payment_form_save_token"]').checked === true;
// then we call the route to prepare the transaction
ajax.jsonRpc($tx_url[0].value, 'call', {
'acquirer_id': parseInt(acquirer_id),
'save_token': form_save_token
}).then(function(result){
if(result) {
// if the server sent us the html form, we create a form element
var newForm = document.createElement('form');
newForm.setAttribute("method", "post"); // set it to post
newForm.setAttribute("action", ds.dataset.actionUrl); // set the action url
newForm.hidden = true; // hide it
newForm.innerHTML = result; // put the html sent by the server inside the form
document.getElementsByTagName('body')[0].appendChild(newForm); // append the form to the body
$(newForm).find('input[data-remove-me]').remove(); // remove all the input that should be removed
newForm.submit(); // and finally submit the form
}
else {
self.error(_t('Server Error'),
_t("<p>We are not able to redirect you to the payment form.</p>"));
}
}).fail(function(message, data){
self.error(_t('Server Error'),
_t("<p>We are not able to redirect you to the payment form.</p>") + (core.debug ? data.data.message : ''));
});
}
else
{
// we append the form to the body and send it.
this.error(_t("Cannot set-up the payment"), _t("<p>We're unable to process your payment.</p>"));
}
}
// if the user is using an old payment
else {
// then we just submit the form
......@@ -81,8 +152,8 @@ odoo.define('payment.payment_form', function (require){
}
}
else {
this.error(_t('Error'),
_t('<p>Please select a payment method</p>'));
this.error(_t('No payment method selected'),
_t('<p>Please select a payment method.</p>'));
}
},
// event handler when clicking on the button to add a new payment method
......@@ -96,16 +167,35 @@ odoo.define('payment.payment_form', function (require){
// we check if the user has selected a 'add a new payment' option
if(checked_radio.length == 1 && this.isNewPaymentRadio(checked_radio[0])) {
// then we add a 'processing' icon into the 'add a new payment' button
$(button).attr('disabled', true);
$(button).prepend('<span class="o_loader"><i class="fa fa-refresh fa-spin"></i>&nbsp;</span>');
// we retrieve which acquirer is used
checked_radio = checked_radio[0];
var acquirer_id = this.getAcquirerIdFromRadio(checked_radio);
var acquirer_form = this.$('#o_payment_add_token_acq_' + acquirer_id);
// we retrieve all the input inside the acquirer form and 'serialize' them to an indexed array
var form_data = this.getFormData($('input', acquirer_form));
var inputs_form = $('input', acquirer_form);
var form_data = this.getFormData(inputs_form);
var ds = $('input[name="data_set"]', acquirer_form)[0];
var empty_inputs = false;
inputs_form.toArray().forEach(function(element) {
if(element.dataset.isRequired) {
if (element.value.length === 0) {
$(element).closest('div.form-group').addClass('has-error');
}
else {
$(element).closest('div.form-group').removeClass('has-error');
}
empty_inputs = true;
}
});
if(empty_inputs) {
this.error(_t('Missing values'), _t('<p>Please fill all the inputs required.</p>'));
return;
}
// We add a 'processing' icon into the 'add a new payment' button
$(button).attr('disabled', true);
$(button).prepend('<span class="o_loader"><i class="fa fa-refresh fa-spin"></i>&nbsp;</span>');
// we force the check when adding a card trough here
form_data.verify_validity = true;
......@@ -132,7 +222,7 @@ odoo.define('payment.payment_form', function (require){
}
// if the server has returned false, we display an error
else {
self.error(_t('Error'),
self.error(_t('Server Error'),
_t("<p>We are not able to add your payment method at the moment.</p>"));
}
// here we remove the 'processing' icon from the 'add a new payment' button
......@@ -143,13 +233,13 @@ odoo.define('payment.payment_form', function (require){
$(button).attr('disabled', false);
$(button).find('span.o_loader').remove();
self.error(_t('Error'),
self.error(_t('Server error'),
_t("<p>We are not able to add your payment method at the moment.</p>") + (core.debug ? data.data.message : ''));
});
}
else {
this.error(_t('Error'),
_t('<p>Please select the option to add a new payment method</p>'));
this.error(_t('No payment method selected'),
_t('<p>Please select the option to add a new payment method.</p>'));
}
},
// event handler when clicking on a button to delete a payment method
......@@ -170,7 +260,7 @@ odoo.define('payment.payment_form', function (require){
ev.target.closest('div').remove();
}
},function(type,err){
self.error(_t('Error'),
self.error(_t('Server Error'),
_t("<p>We are not able to delete your payment method at the moment.</p>"));
});
};
......@@ -202,7 +292,7 @@ odoo.define('payment.payment_form', function (require){
Delete();
}
}, function(type, err){
self.error(_t('Error'),
self.error(_t('Server Error'),
_t("<p>We are not able to delete your payment method at the moment.</p>") + (core.debug ? err.data.message : ''));
});
},
......@@ -215,28 +305,43 @@ odoo.define('payment.payment_form', function (require){
var checked_radio = this.$('input[type="radio"]:checked');
// we hide all the acquirers form
this.$('[id*="o_payment_add_token_acq_"]').addClass('hidden');
this.$('[id*="o_payment_form_acq_"]').addClass('hidden');
if(checked_radio.length != 1) {
return;
}
checked_radio = checked_radio[0];
// if we clicked on an add new payment radio
if(checked_radio.length == 1 && this.isNewPaymentRadio(checked_radio[0]))
if(this.isNewPaymentRadio(checked_radio))
{
// then we retrieve the acquirer name
var acquirer_id = this.getAcquirerIdFromRadio(checked_radio[0]);
var acquirer_id = this.getAcquirerIdFromRadio(checked_radio);
// and display its form
this.$('#o_payment_add_token_acq_' + acquirer_id).removeClass('hidden');
}
else if(this.isFormPaymentRadio(checked_radio))
{
// then we retrieve the acquirer name
var acquirer_id = this.getAcquirerIdFromRadio(checked_radio);
// and display its form
this.$('#o_payment_form_acq_' + acquirer_id).removeClass('hidden');
}
},
isNewPaymentRadio: function(element) {
return $(element).data('acquirer-id') !== undefined;
return $(element).data('s2s-payment') === 'True';
},
isFormPaymentRadio: function(element) {
return $(element).data('form-payment') === 'True';
},
getAcquirerIdFromRadio: function(element) {
return $(element).data('acquirer-id');
},
error: function(title, message, url) {
return new Dialog(null, {
title: title || "",
$content: $(core.qweb.render('website.error_dialog', {
message: message || "",
})),
}).open();
title: _t('Error: ') + title,
size: 'medium',
$content: message || "",
buttons: [
{text: _t('Ok'), close: true}]}).open();
},
getFormData: function($form){
var unindexed_array = $form.serializeArray();
......@@ -249,13 +354,18 @@ odoo.define('payment.payment_form', function (require){
},
start: function() {
this.updateNewPaymentDisplayStatus();
$('[data-toggle="tooltip"]').tooltip();
},
});
$(document).ready(function (){
var form = new PaymentForm();
form.attachTo($('.o_payment_form'));
});
require('web.dom_ready'); // only start this when dom is ready
if (!$('.o_payment_form').length) {
return $.Deferred().reject("DOM doesn't contain '.o_payment_form'");
}
var form = new PaymentForm();
form.attachTo($('.o_payment_form'));
});
odoo.define('payment.transaction', function (require) {
"use strict";
var ajax = require('web.ajax');
$(document).ready(function () {
// When choosing an acquirer, display its Pay Now button
var $payment = $("#payment_method");
$payment.on("click", "input[name='acquirer'], a.btn_payment_token", function (ev) {
var ico_off = 'fa-circle-o';
var ico_on = 'fa-dot-circle-o';
var payment_id = $(ev.currentTarget).val() || $(this).data('acquirer');
var token = $(ev.currentTarget).data('token') || '';
$("div.o_payment_acquirer_button[data-id='"+payment_id+"']", $payment).attr('data-token', token);
$("div.js_payment a.list-group-item").removeClass("list-group-item-info");
$('span.js_radio').switchClass(ico_on, ico_off, 0);
if (token) {
$("div.o_payment_acquirer_button div.token_hide").hide();
$(ev.currentTarget).find('span.js_radio').switchClass(ico_off, ico_on, 0);
$(ev.currentTarget).parents('li').find('input').prop("checked", true);
$(ev.currentTarget).addClass("list-group-item-info");
}
else{
$("div.o_payment_acquirer_button div.token_hide").show();
}
$("div.o_payment_acquirer_button[data-id]", $payment).addClass("hidden");
$("div.o_payment_acquirer_button[data-id='"+payment_id+"']", $payment).removeClass("hidden");
})
.find("input[name='acquirer']:checked").click();
// When clicking on payment button: create the tx using json then continue to the acquirer
$payment.on("click", 'button[type="submit"], button[name="submit"]', function (ev) {
ev.preventDefault();
ev.stopPropagation();
var $form = $(ev.currentTarget).parents('form');
var acquirer = $(ev.currentTarget).parents('div.o_payment_acquirer_button').first();
var tx_data = acquirer.data();
if (! tx_data.id || ! tx_data.callUrl) {
return false;
}
var params = {"tx_type": tx_data.txType || acquirer.find('input[name="odoo_save_token"]').is(':checked') ? 'form_save': 'form'};
var acquirer_token = acquirer.attr('data-token'); // !=data
if (acquirer_token) {
params.token = acquirer_token;
}
if (tx_data.access_token) {
params.access_token = tx_data.access_token;
}
$form.off('submit');
ajax.jsonRpc(tx_data.callUrl, 'call', params).then(function (data) {
$(data).appendTo('body').submit();
});
return false;
});
$('div.oe_pay_token').on('click', 'a.js_btn_valid_tx', function() {
$('div.js_token_load').toggle();
var $form = $(this).parents('form');
ajax.jsonRpc($form.attr('action'), 'call', $.deparam($form.serialize())).then(function (data) {
if (data.url) {
window.location = data.url;
}
else {
$('div.js_token_load').toggle();
if (!data.success && data.error) {
$('div.oe_pay_token div.panel-body p').html(data.error + "<br/><br/>" + _('Retry ? '));
$('div.oe_pay_token div.panel-body').parents('div').removeClass('panel-info').addClass('panel-danger');
}
}
});
});
});
});
.o_payment_form {
label > input[type="radio"]{
label > input[type="radio"], input[type="checkbox"]{
vertical-align: bottom;
margin-right: 5px;
}
label {
.payment_option_name {
font-size: 14px;
font-weight: normal !important;
font-family: Helvetica Neue, sans-serif;
......@@ -12,6 +12,10 @@
color: #4d4d4d;
}
label {
font-weight: normal;
}
.panel-body:first-child {
border-top: 0px;
}
......@@ -29,4 +33,18 @@
border-top: 1px solid #ddd;
padding: 1.14em !important;
}
.payment_icon_list {
li {
padding-left: 5px !important;
padding-right: 0px !important;
}
.more_option {
font-size:10px;
}
margin-top: 0px !important;
margin-bottom: -5px !important;
}
}
\ No newline at end of file
......@@ -4,7 +4,6 @@
<xpath expr="." position="inside">
<link rel='stylesheet' href='/payment/static/src/css/portal_payment.css'/>
<script type="text/javascript" src="/payment/static/lib/jquery.payment/jquery.payment.js"></script>
<script type="text/javascript" src="/payment/static/src/js/payment_transaction.js"></script>
<script type="text/javascript" src="/payment/static/src/js/payment_portal.js"></script>
<script type="text/javascript" src="/payment/static/src/js/payment_transaction_portal.js"></script>
<script type="text/javascript" src="/payment/static/src/js/payment_form.js"></script>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment