Your IP : 216.73.216.43


Current Path : /home/rtorresani/www/vendor/stripe/module-payments/view/frontend/web/js/
Upload File :
Current File : //home/rtorresani/www/vendor/stripe/module-payments/view/frontend/web/js/stripe_payments_express.js

/*global define*/
define(
    [
        'jquery',
        'mage/url',
        'mage/storage',
        'Magento_Ui/js/modal/alert',
        'mage/translate',
        'Magento_Customer/js/customer-data',
        'StripeIntegration_Payments/js/stripe'
    ],
    function (
        jQuery,
        urlBuilder,
        storage,
        alert,
        $t,
        customerData,
        stripe
    ) {
        'use strict';

        return {
            shippingAddress: [],
            shippingMethod: null,
            onPaymentSupportedCallbacks: [],
            PRAPIEvent: null,
            paymentRequest: null,

            getApplePayParams: function(type, callback)
            {
                var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/get_prapi_params', {}),
                    payload = {type: type},
                    self = this;

                return storage.post(
                    serviceUrl,
                    JSON.stringify(payload),
                    false
                )
                .fail(function (xhr, textStatus, errorThrown)
                {
                    console.error("Could not retrieve initialization params for Apple Pay");
                })
                .done(function (response)
                {
                    if (typeof response === 'string') {
                        response = JSON.parse(response);
                    }

                    callback(response);
                });
            },

            /**
             * Init Stripe Express
             * @param elementId
             * @param apiKey
             * @param paramsType
             * @param settings
             * @param callback
             */
            initStripeExpress: function (elementId, stripeParams, paramsType, settings, callback)
            {
                var self = this;

                this.getApplePayParams(paramsType, function(params)
                {
                    if (!params || params.length == 0)
                        return;

                    if (params.total.amount == 0 && params.displayItems.length == 0)
                        return;

                    stripe.initStripe(stripeParams, function (err)
                    {
                        if (err)
                        {
                            self.showError(self.maskError(err));
                            return;
                        }
                        self.initPaymentRequestButton(elementId, stripeParams.locale, params, settings, callback);
                    });
                });
            },

            maskError: function(err)
            {
                var errLowercase = err.toLowerCase();
                var pos1 = errLowercase.indexOf("Invalid API key provided".toLowerCase());
                var pos2 = errLowercase.indexOf("No API key provided".toLowerCase());
                if (pos1 === 0 || pos2 === 0)
                    return 'Invalid Stripe API key provided.';

                return err;
            },

            initPaymentRequestButton: function(elementId, locale, params, settings, callback)
            {
                // Init Payment Request
                var paymentRequest,
                    paymentRequestButton = jQuery(elementId),
                    self = this,
                    prButton = null;

                try {
                    if (typeof settings === 'string')
                        settings = JSON.parse(settings);

                    if (!params.country)
                        throw { message: 'Cannot display Wallet Button because there is no Country Code. You can set a default one from Magento Admin > Stores > Configuration > General > Country Options > Default Country.'};

                    this.paymentRequest = paymentRequest = stripe.stripeJs.paymentRequest(params);
                    var elements = stripe.stripeJs.elements({
                        locale: locale
                    });
                    prButton = elements.create('paymentRequestButton', {
                        paymentRequest: paymentRequest,
                        style: {
                            paymentRequestButton: settings
                        }
                    });
                }
                catch (e)
                {
                    console.warn(e.message);
                    return;
                }

                paymentRequest.canMakePayment().then(function(result)
                {
                    stripe.canMakePaymentResult = result;
                    if (result)
                    {
                        // The mini cart may be empty
                        if (document.getElementById(elementId.substr(1)))
                        {
                            prButton.mount(elementId);

                            for (var i = 0; i < self.onPaymentSupportedCallbacks.length; i++)
                                self.onPaymentSupportedCallbacks[i]();
                        }
                    }
                    else {
                        paymentRequestButton.hide();
                    }
                });

                prButton.on('ready', function () {
                    callback(paymentRequestButton, paymentRequest, params, prButton);
                });
            },

            getClientSecretFromResponse: function(response)
            {
                if (typeof response != "string")
                {
                    return null;
                }

                if (response.indexOf("Authentication Required: ") >= 0)
                {
                    return response.substring("Authentication Required: ".length);
                }

                return null;
            },

            /**
             * Place Order
             * @param result
             * @param callback
             */
            placeOrder: function (result, location, callback) {
                var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/place_order', {}),
                    payload = {
                        result: result,
                        location: location
                    },
                    self = this;

                return storage.post(
                    serviceUrl,
                    JSON.stringify(payload),
                    false
                ).fail(function (xhr, textStatus, errorThrown)
                {
                    try
                    {
                        var response = JSON.parse(xhr.responseText);

                        var clientSecret = self.getClientSecretFromResponse(response.message);

                        if (clientSecret)
                        {
                            self.closePaysheet("success");

                            return stripe.authenticateCustomer(clientSecret, function(err)
                            {
                                if (err)
                                    return callback(err, { message: err }, result);

                                self.placeOrder(result, location, callback);
                            });
                        }
                        else
                            callback(response.message, response, result);
                    }
                    catch (e)
                    {
                        return self.showError(xhr.responseText);
                    }
                }).done(function (response) { // @todo - this should be success, we dont want to callback() on failure
                    if (typeof response === 'string')
                    {
                        try
                        {
                            response = JSON.parse(response);
                        }
                        catch (e)
                        {
                            return self.showError(response);
                        }
                    }

                    callback(null, response, result);
                });
            },

            /**
             * Add Item to Cart
             * @param request
             * @param shipping_id
             * @param callback
             */
            addToCart: function(request, shipping_id, callback)
            {
                var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/addtocart', {}),
                    payload = {request: request, shipping_id: shipping_id},
                    self = this;

                return storage.post(
                    serviceUrl,
                    JSON.stringify(payload),
                    false
                ).fail(function (xhr, textStatus, errorThrown)
                {
                    self.parseFailedResponse.apply(self, [ xhr.responseText, callback ]);
                }
                ).done(function (response) {
                    customerData.invalidate(['cart']);
                    customerData.reload(['cart'], true);
                    self.processResponseWithPaymentIntent(response, callback);
                });
            },

            /**
             * Get Cart Contents
             * @param callback
             * @returns {*}
             */
            getCart: function(callback) {
                var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/get_cart', {}),
                    self = this;

                return storage.get(
                    serviceUrl,
                    null,
                    false
                ).fail(function (xhr, textStatus, errorThrown)
                {
                    self.parseFailedResponse.apply(self, [ xhr.responseText, callback ]);
                }
                ).done(function (response) {
                    if (typeof response === 'string') {
                        response = JSON.parse(response);
                    }

                    callback(null, response);
                });
            },

            getShippingAddressFrom: function(prapiShippingAddress)
            {
                if (!prapiShippingAddress)
                    return null;

                // For some countries like Japan, the PRAPI does not set the City, only the region
                if (prapiShippingAddress.city.length == 0 && prapiShippingAddress.region.length > 0)
                    prapiShippingAddress.city = prapiShippingAddress.region;

                return prapiShippingAddress;
            },

            /**
             * Estimate Shipping for Cart
             * @param address
             * @param callback
             * @returns {*}
             */
            estimateShippingCart: function(address, callback) {
                var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/estimate_cart', {}),
                    payload = {address: address},
                    self = this;

                return storage.post(
                    serviceUrl,
                    JSON.stringify(payload),
                    false
                ).fail(function (xhr, textStatus, errorThrown)
                {
                    self.parseFailedResponse.apply(self, [ xhr.responseText, callback ]);
                }
                ).done(function (response) {
                    self.processResponseWithPaymentIntent(response, callback);
                });
            },

            parseFailedResponse: function(responseText, callback)
            {
                try
                {
                    var response = JSON.parse(responseText);
                    callback(response.message);
                }
                catch (e)
                {
                    callback(responseText);
                }
            },

            /**
             * Apply Shipping and Return Totals
             * @param address
             * @param shipping_id
             * @param callback
             * @returns {*}
             */
            applyShipping: function(address, shipping_id, callback) {
                var serviceUrl = urlBuilder.build('/rest/V1/stripe/payments/apply_shipping', {}),
                    payload = {address: address, shipping_id: shipping_id},
                    self = this;

                return storage.post(
                    serviceUrl,
                    JSON.stringify(payload),
                    false
                ).fail(function (xhr, textStatus, errorThrown)
                {
                    self.parseFailedResponse.apply(self, [ xhr.responseText, callback ]);
                }
                ).done(function (response) {
                    self.processResponseWithPaymentIntent(response, callback);
                });
            },

            processResponseWithPaymentIntent: function(response, callback)
            {
                try
                {
                    if (typeof response === 'string') {
                        response = JSON.parse(response);
                    }

                    callback(null, response.results);
                }
                catch (e)
                {
                    callback(e.message, response);
                }
            },

            onShippingAddressChange: function(ev)
            {
                var self = this;

                this.shippingAddress = this.getShippingAddressFrom(ev.shippingAddress);
                this.estimateShippingCart(this.shippingAddress, function (err, shippingOptions)
                {
                    if (err)
                        return self.showError(err);

                    if (shippingOptions.length < 1) {
                        ev.updateWith({status: 'invalid_shipping_address'});
                        return;
                    }

                    self.shippingMethod = null;
                    if (shippingOptions.length > 0) {
                        // Apply first shipping method
                        var shippingOption = shippingOptions[0];
                        self.shippingMethod = shippingOption.hasOwnProperty('id') ? shippingOption.id : null;
                    }

                    self.applyShipping(self.shippingAddress, self.shippingMethod, function (err, response)
                    {
                        if (err)
                            return self.showError(err);

                        // Update order lines
                        var result = Object.assign({status: 'success', shippingOptions: shippingOptions}, response);
                        ev.updateWith(result);
                    });
                });
            },

            onShippingOptionChange: function(ev)
            {
                var shippingMethod = ev.shippingOption.hasOwnProperty('id') ? ev.shippingOption.id : null;
                this.applyShipping(this.shippingAddress, shippingMethod, function (err, response)
                {
                    if (err) {
                        ev.updateWith({status: 'fail'});
                        return;
                    }

                    // Update order lines
                    var result = Object.assign({status: 'success'}, response);
                    ev.updateWith(result);
                });
            },

            onPaymentMethod: function(paymentRequestButton, location, result)
            {
                this.onPaymentRequestPaymentMethod.call(this, result, paymentRequestButton, location);
            },

            initCheckoutWidget: function (paymentRequestButton, paymentRequest, prButton, onClick)
            {
                prButton.on('click', onClick);
                paymentRequest.on('shippingaddresschange', this.onShippingAddressChange.bind(this));
                paymentRequest.on('shippingoptionchange', this.onShippingOptionChange.bind(this));
                paymentRequest.on('paymentmethod', this.onPaymentMethod.bind(this, paymentRequestButton, 'checkout'));
            },

            /**
             * Init Widget for Cart Page
             * @param paymentRequestButton
             * @param paymentRequest
             * @param params
             * @param prButton
             */
            initCartWidget: function (paymentRequestButton, paymentRequest, params, prButton)
            {
                paymentRequest.on('shippingaddresschange', this.onShippingAddressChange.bind(this));
                paymentRequest.on('shippingoptionchange', this.onShippingOptionChange.bind(this));
                paymentRequest.on('paymentmethod', this.onPaymentMethod.bind(this, paymentRequestButton, 'cart'));
            },

            /**
             * Init Widget for Mini cart
             * @param paymentRequestButton
             * @param paymentRequest
             * @param params
             * @param prButton
             */
            initMiniCartWidget: function (paymentRequestButton, paymentRequest, params, prButton)
            {
                var self = this;

                prButton.on('click', function(ev) {
                    // ev.preventDefault();

                    paymentRequestButton.addClass('disabled');
                    self.getCart(function (err, result)
                    {
                        paymentRequestButton.removeClass('disabled');
                        if (err)
                            return self.showError(err);

                        // ev.updateWith(result);
                    });
                });

                paymentRequest.on('shippingaddresschange', this.onShippingAddressChange.bind(this));
                paymentRequest.on('shippingoptionchange', this.onShippingOptionChange.bind(this));
                paymentRequest.on('paymentmethod', this.onPaymentMethod.bind(this, paymentRequestButton, 'minicart'));
            },

            /**
             * Init Widget for Single Product Page
             * @param paymentRequestButton
             * @param paymentRequest
             * @param params
             * @param prButton
             */
            initProductWidget: function (paymentRequestButton, paymentRequest, params, prButton) {
                var self = this,
                    form = jQuery('#product_addtocart_form'),
                    request = [];

                prButton.on('click', function(ev)
                {
                    var validator = form.validation({radioCheckboxClosest: '.nested'});

                    if (!validator.valid())
                    {
                        ev.preventDefault();
                        return;
                    }

                    // We don't want to preventDefault for applePay because we cannot use
                    // paymentRequest.show() with applePay. Expecting Stripe to fix this.
                    if (!stripe.canMakePaymentResult.applePay)
                        ev.preventDefault();

                    // Add to Cart
                    request = form.serialize();
                    paymentRequestButton.addClass('disabled');
                    self.addToCart(request, self.shippingMethod, function (err, result) {
                        paymentRequestButton.removeClass('disabled');
                        if (err)
                            return self.showError(err);

                        try
                        {
                            paymentRequest.update(result);
                            paymentRequest.show();
                        }
                        catch (e)
                        {
                            console.warn(e.message);
                        }
                    });
                });

                paymentRequest.on('shippingaddresschange', this.onShippingAddressChange.bind(this));
                paymentRequest.on('shippingoptionchange', this.onShippingOptionChange.bind(this));
                paymentRequest.on('paymentmethod', this.onPaymentMethod.bind(this, paymentRequestButton, 'product'));
            },

            onPaymentRequestPaymentMethod: function(result, paymentRequestButton, location)
            {
                this.PRAPIEvent = result;
                var success = this.onPaymentPlaced.bind(this, result, paymentRequestButton, location);
                var error = this.showError.bind(this);

                return success();
            },

            closePaysheet: function(withResult)
            {
                try
                {
                    if (this.PRAPIEvent)
                        this.PRAPIEvent.complete(withResult);
                    else if (this.paymentRequest)
                        this.paymentRequest.abort();
                }
                catch (e)
                {
                    // Will get here if we already closed it
                }
            },

            showError: function(message)
            {
                this.closePaysheet('success'); // Simply hide the modal

                alert({
                    title: $t('Error'),
                    content: message,
                    actions: {
                        always: function (){}
                    }
                });
            },

            onPaymentPlaced: function(result, paymentRequestButton, location)
            {
                var self = this;
                paymentRequestButton.addClass('disabled');
                result.shippingAddress = this.getShippingAddressFrom(result.shippingAddress);
                this.placeOrder(result, location, function (err, response, result)
                {
                    if (err)
                    {
                        paymentRequestButton.removeClass('disabled');
                        self.showError(response.message);
                    }
                    else if (response.hasOwnProperty('redirect'))
                    {
                        customerData.invalidate(['cart']);
                        window.location = response.redirect;
                    }
                });
            },

            bindConfigurableProductOptions: function(elementId, stripeParams, productId, buttonConfig)
            {
                var self = this;
                var options = jQuery("#product-options-wrapper .configurable select.super-attribute-select");
                var params = {
                    elementId: elementId,
                    stripeParams: stripeParams,
                    buttonConfig: buttonConfig,
                    productId: productId
                };

                options.each(function(index)
                {
                    var onConfigurableProductChanged = self.onConfigurableProductChanged.bind(self, this, params);
                    jQuery(this).change(onConfigurableProductChanged);
                });
            },

            onConfigurableProductChanged: function(element, params)
            {
                var self = this;

                if (element.value)
                {
                    var apiParams = 'product:' + params.productId + ':' + element.value;
                    this.initStripeExpress(params.elementId, params.stripeParams, apiParams, params.buttonConfig,
                        function(paymentRequestButton, paymentRequest, params, prButton) {
                            self.initProductWidget(paymentRequestButton, paymentRequest, params, prButton);
                        }
                    );
                }
            }
        };
    }
);