summaryrefslogtreecommitdiff
path: root/addons/payment_stripe/static/src/js/payment_form.js
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/payment_stripe/static/src/js/payment_form.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/payment_stripe/static/src/js/payment_form.js')
-rw-r--r--addons/payment_stripe/static/src/js/payment_form.js212
1 files changed, 212 insertions, 0 deletions
diff --git a/addons/payment_stripe/static/src/js/payment_form.js b/addons/payment_stripe/static/src/js/payment_form.js
new file mode 100644
index 00000000..4a11e289
--- /dev/null
+++ b/addons/payment_stripe/static/src/js/payment_form.js
@@ -0,0 +1,212 @@
+odoo.define('payment_stripe.payment_form', function (require) {
+"use strict";
+
+var ajax = require('web.ajax');
+var core = require('web.core');
+var Dialog = require('web.Dialog');
+var PaymentForm = require('payment.payment_form');
+
+var qweb = core.qweb;
+var _t = core._t;
+
+ajax.loadXML('/payment_stripe/static/src/xml/stripe_templates.xml', qweb);
+
+PaymentForm.include({
+
+ willStart: function () {
+ return this._super.apply(this, arguments).then(function () {
+ return ajax.loadJS("https://js.stripe.com/v3/");
+ })
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * called to create payment method object for credit card/debit card.
+ *
+ * @private
+ * @param {Object} stripe
+ * @param {Object} formData
+ * @param {Object} card
+ * @param {Boolean} addPmEvent
+ * @returns {Promise}
+ */
+ _createPaymentMethod: function (stripe, formData, card, addPmEvent) {
+ if (addPmEvent) {
+ return this._rpc({
+ route: '/payment/stripe/s2s/create_setup_intent',
+ params: {'acquirer_id': formData.acquirer_id}
+ }).then(function(intent_secret) {
+ return stripe.handleCardSetup(intent_secret, card);
+ });
+ } else {
+ return stripe.createPaymentMethod({
+ type: 'card',
+ card: card,
+ });
+ }
+ },
+
+ /**
+ * called when clicking on pay now or add payment event to create token for credit card/debit card.
+ *
+ * @private
+ * @param {Event} ev
+ * @param {DOMElement} checkedRadio
+ * @param {Boolean} addPmEvent
+ */
+ _createStripeToken: function (ev, $checkedRadio, addPmEvent) {
+ var self = this;
+ if (ev.type === 'submit') {
+ var button = $(ev.target).find('*[type="submit"]')[0]
+ } else {
+ var button = ev.target;
+ }
+ this.disableButton(button);
+ var acquirerID = this.getAcquirerIdFromRadio($checkedRadio);
+ var acquirerForm = this.$('#o_payment_add_token_acq_' + acquirerID);
+ var inputsForm = $('input', acquirerForm);
+ if (this.options.partnerId === undefined) {
+ console.warn('payment_form: unset partner_id when adding new token; things could go wrong');
+ }
+
+ var formData = self.getFormData(inputsForm);
+ var stripe = this.stripe;
+ var card = this.stripe_card_element;
+ if (card._invalid) {
+ return;
+ }
+ this._createPaymentMethod(stripe, formData, card, addPmEvent).then(function(result) {
+ if (result.error) {
+ return Promise.reject({"message": {"data": { "arguments": [result.error.message]}}});
+ } else {
+ const paymentMethod = addPmEvent ? result.setupIntent.payment_method : result.paymentMethod.id;
+ _.extend(formData, {"payment_method": paymentMethod});
+ return self._rpc({
+ route: formData.data_set,
+ params: formData,
+ });
+ }
+ }).then(function(result) {
+ if (addPmEvent) {
+ if (formData.return_url) {
+ window.location = formData.return_url;
+ } else {
+ window.location.reload();
+ }
+ } else {
+ $checkedRadio.val(result.id);
+ self.el.submit();
+ }
+ }).guardedCatch(function (error) {
+ // We don't want to open the Error dialog since
+ // we already have a container displaying the error
+ if (error.event) {
+ error.event.preventDefault();
+ }
+ // if the rpc fails, pretty obvious
+ self.enableButton(button);
+ self.displayError(
+ _t('Unable to save card'),
+ _t("We are not able to add your payment method at the moment. ") +
+ self._parseError(error)
+ );
+ });
+ },
+ /**
+ * called when clicking a Stripe radio if configured for s2s flow; instanciates the card and bind it to the widget.
+ *
+ * @private
+ * @param {DOMElement} checkedRadio
+ */
+ _bindStripeCard: function ($checkedRadio) {
+ var acquirerID = this.getAcquirerIdFromRadio($checkedRadio);
+ var acquirerForm = this.$('#o_payment_add_token_acq_' + acquirerID);
+ var inputsForm = $('input', acquirerForm);
+ var formData = this.getFormData(inputsForm);
+ var stripe = Stripe(formData.stripe_publishable_key);
+ var element = stripe.elements();
+ var card = element.create('card', {hidePostalCode: true});
+ card.mount('#card-element');
+ card.on('ready', function(ev) {
+ card.focus();
+ });
+ card.addEventListener('change', function (event) {
+ var displayError = document.getElementById('card-errors');
+ displayError.textContent = '';
+ if (event.error) {
+ displayError.textContent = event.error.message;
+ }
+ });
+ this.stripe = stripe;
+ this.stripe_card_element = card;
+ },
+ /**
+ * destroys the card element and any stripe instance linked to the widget.
+ *
+ * @private
+ */
+ _unbindStripeCard: function () {
+ if (this.stripe_card_element) {
+ this.stripe_card_element.destroy();
+ }
+ this.stripe = undefined;
+ this.stripe_card_element = undefined;
+ },
+ /**
+ * @override
+ */
+ updateNewPaymentDisplayStatus: function () {
+ var $checkedRadio = this.$('input[type="radio"]:checked');
+
+ if ($checkedRadio.length !== 1) {
+ return;
+ }
+ var provider = $checkedRadio.data('provider')
+ if (provider === 'stripe') {
+ // always re-init stripe (in case of multiple acquirers for stripe, make sure the stripe instance is using the right key)
+ this._unbindStripeCard();
+ if (this.isNewPaymentRadio($checkedRadio)) {
+ this._bindStripeCard($checkedRadio);
+ }
+ }
+ return this._super.apply(this, arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ */
+ payEvent: function (ev) {
+ ev.preventDefault();
+ var $checkedRadio = this.$('input[type="radio"]:checked');
+
+ // first we check that the user has selected a stripe as s2s payment method
+ if ($checkedRadio.length === 1 && this.isNewPaymentRadio($checkedRadio) && $checkedRadio.data('provider') === 'stripe') {
+ return this._createStripeToken(ev, $checkedRadio);
+ } else {
+ return this._super.apply(this, arguments);
+ }
+ },
+ /**
+ * @override
+ */
+ addPmEvent: function (ev) {
+ ev.stopPropagation();
+ ev.preventDefault();
+ var $checkedRadio = this.$('input[type="radio"]:checked');
+
+ // first we check that the user has selected a stripe as add payment method
+ if ($checkedRadio.length === 1 && this.isNewPaymentRadio($checkedRadio) && $checkedRadio.data('provider') === 'stripe') {
+ return this._createStripeToken(ev, $checkedRadio, true);
+ } else {
+ return this._super.apply(this, arguments);
+ }
+ },
+});
+});