123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- /*browser:true*/
- /*global define*/
- define([
- 'jquery',
- 'uiComponent',
- 'Magento_Ui/js/modal/alert',
- 'Magento_Ui/js/lib/view/utils/dom-observer',
- 'mage/translate',
- 'Magento_Braintree/js/validator'
- ], function ($, Class, alert, domObserver, $t, validator) {
- 'use strict';
- return Class.extend({
- defaults: {
- $selector: null,
- selector: 'edit_form',
- container: 'payment_form_braintree',
- active: false,
- scriptLoaded: false,
- braintree: null,
- selectedCardType: null,
- checkout: null,
- imports: {
- onActiveChange: 'active'
- }
- },
- /**
- * Set list of observable attributes
- * @returns {exports.initObservable}
- */
- initObservable: function () {
- var self = this;
- validator.setConfig(this);
- self.$selector = $('#' + self.selector);
- this._super()
- .observe([
- 'active',
- 'scriptLoaded',
- 'selectedCardType'
- ]);
- // re-init payment method events
- self.$selector.off('changePaymentMethod.' + this.code)
- .on('changePaymentMethod.' + this.code, this.changePaymentMethod.bind(this));
- // listen block changes
- domObserver.get('#' + self.container, function () {
- if (self.scriptLoaded()) {
- self.$selector.off('submit');
- self.initBraintree();
- }
- });
- return this;
- },
- /**
- * Enable/disable current payment method
- * @param {Object} event
- * @param {String} method
- * @returns {exports.changePaymentMethod}
- */
- changePaymentMethod: function (event, method) {
- this.active(method === this.code);
- return this;
- },
- /**
- * Triggered when payment changed
- * @param {Boolean} isActive
- */
- onActiveChange: function (isActive) {
- if (!isActive) {
- this.$selector.off('submitOrder.braintree');
- return;
- }
- this.disableEventListeners();
- window.order.addExcludedPaymentMethod(this.code);
- if (!this.clientToken) {
- this.error($.mage.__('This payment is not available'));
- return;
- }
- this.enableEventListeners();
- if (!this.scriptLoaded()) {
- this.loadScript();
- }
- },
- /**
- * Load external Braintree SDK
- */
- loadScript: function () {
- var self = this,
- state = self.scriptLoaded;
- $('body').trigger('processStart');
- require([this.sdkUrl], function (braintree) {
- state(true);
- self.braintree = braintree;
- self.initBraintree();
- $('body').trigger('processStop');
- });
- },
- /**
- * Retrieves client token and setup Braintree SDK
- */
- initBraintree: function () {
- var self = this;
- try {
- $('body').trigger('processStart');
- $.getJSON(self.clientTokenUrl).done(function (response) {
- self.clientToken = response.clientToken;
- self._initBraintree();
- }).fail(function (response) {
- var failed = JSON.parse(response.responseText);
- $('body').trigger('processStop');
- self.error(failed.message);
- });
- } catch (e) {
- $('body').trigger('processStop');
- self.error(e.message);
- }
- },
- /**
- * Setup Braintree SDK
- */
- _initBraintree: function () {
- var self = this;
- this.disableEventListeners();
- if (self.checkout) {
- self.checkout.teardown(function () {
- self.checkout = null;
- });
- }
- self.braintree.setup(self.clientToken, 'custom', {
- id: self.selector,
- hostedFields: self.getHostedFields(),
- /**
- * Triggered when sdk was loaded
- */
- onReady: function (checkout) {
- self.checkout = checkout;
- $('body').trigger('processStop');
- self.enableEventListeners();
- },
- /**
- * Callback for success response
- * @param {Object} response
- */
- onPaymentMethodReceived: function (response) {
- if (self.validateCardType()) {
- self.setPaymentDetails(response.nonce);
- self.placeOrder();
- }
- },
- /**
- * Error callback
- * @param {Object} response
- */
- onError: function (response) {
- self.error(response.message);
- }
- });
- },
- /**
- * Get hosted fields configuration
- * @returns {Object}
- */
- getHostedFields: function () {
- var self = this,
- fields = {
- number: {
- selector: self.getSelector('cc_number')
- },
- expirationMonth: {
- selector: self.getSelector('cc_exp_month'),
- placeholder: $t('MM')
- },
- expirationYear: {
- selector: self.getSelector('cc_exp_year'),
- placeholder: $t('YY')
- },
- /**
- * Triggered when hosted field is changed
- * @param {Object} event
- */
- onFieldEvent: function (event) {
- return self.fieldEventHandler(event);
- }
- };
- if (self.useCvv) {
- fields.cvv = {
- selector: self.getSelector('cc_cid')
- };
- }
- return fields;
- },
- /**
- * Function to handle hosted fields events
- * @param {Object} event
- * @returns {Boolean}
- */
- fieldEventHandler: function (event) {
- var self = this,
- $cardType = $('#' + self.container).find('.icon-type');
- if (event.isEmpty === false) {
- self.validateCardType();
- }
- if (event.type !== 'fieldStateChange') {
- return false;
- }
- // Handle a change in validation or card type
- if (event.target.fieldKey === 'number') {
- self.selectedCardType(null);
- }
- // remove previously set classes
- $cardType.attr('class', 'icon-type');
- if (event.card) {
- $cardType.addClass('icon-type-' + event.card.type);
- self.selectedCardType(
- validator.getMageCardType(event.card.type, self.getCcAvailableTypes())
- );
- }
- },
- /**
- * Show alert message
- * @param {String} message
- */
- error: function (message) {
- alert({
- content: message
- });
- },
- /**
- * Enable form event listeners
- */
- enableEventListeners: function () {
- this.$selector.on('submitOrder.braintree', this.submitOrder.bind(this));
- },
- /**
- * Disable form event listeners
- */
- disableEventListeners: function () {
- this.$selector.off('submitOrder');
- this.$selector.off('submit');
- },
- /**
- * Store payment details
- * @param {String} nonce
- */
- setPaymentDetails: function (nonce) {
- var $container = $('#' + this.container);
- $container.find('[name="payment[payment_method_nonce]"]').val(nonce);
- },
- /**
- * Trigger order submit
- */
- submitOrder: function () {
- this.$selector.validate().form();
- this.$selector.trigger('afterValidate.beforeSubmit');
- $('body').trigger('processStop');
- // validate parent form
- if (this.$selector.validate().errorList.length) {
- return false;
- }
- $('#' + this.container).find('[type="submit"]').trigger('click');
- },
- /**
- * Place order
- */
- placeOrder: function () {
- $('#' + this.selector).trigger('realOrder');
- },
- /**
- * Get list of currently available card types
- * @returns {Array}
- */
- getCcAvailableTypes: function () {
- var types = [],
- $options = $(this.getSelector('cc_type')).find('option');
- $.map($options, function (option) {
- types.push($(option).val());
- });
- return types;
- },
- /**
- * Validate current entered card type
- * @returns {Boolean}
- */
- validateCardType: function () {
- var $input = $(this.getSelector('cc_number'));
- $input.removeClass('braintree-hosted-fields-invalid');
- if (!this.selectedCardType()) {
- $input.addClass('braintree-hosted-fields-invalid');
- return false;
- }
- $(this.getSelector('cc_type')).val(this.selectedCardType());
- return true;
- },
- /**
- * Get jQuery selector
- * @param {String} field
- * @returns {String}
- */
- getSelector: function (field) {
- return '#' + this.code + '_' + field;
- }
- });
- });
|