diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php index 593f1bd35806d975c41fba9806a6586c538a2950..91f23b64334cf2a2103e0f4e876ff584784a5aec 100644 --- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php +++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php @@ -139,4 +139,24 @@ class Sidebar extends AbstractCart { return $this->getLayout()->getBlock('checkout.cart.minicart.totals')->toHtml(); } + + /** + * Get customer register url + * + * @return string + */ + public function getCustomerRegisterUrlUrl() + { + return $this->getUrl('customer/account/create'); + } + + /** + * Get customer forgot password url + * + * @return string + */ + public function getCustomerForgotPasswordUrl() + { + return $this->getUrl('customer/account/forgotpassword'); + } } diff --git a/app/code/Magento/Checkout/Controller/Onepage/Index.php b/app/code/Magento/Checkout/Controller/Onepage/Index.php index 5e16fbd5f2f01e44e5a21d625aa72adc280a2d10..187054943b79c55a80cd40f7c0ece9a094927785 100644 --- a/app/code/Magento/Checkout/Controller/Onepage/Index.php +++ b/app/code/Magento/Checkout/Controller/Onepage/Index.php @@ -15,11 +15,19 @@ class Index extends \Magento\Checkout\Controller\Onepage */ public function execute() { - if (!$this->_objectManager->get('Magento\Checkout\Helper\Data')->canOnepageCheckout()) { + $checkoutHelper = $this->_objectManager->get('Magento\Checkout\Helper\Data'); + if (!$checkoutHelper->canOnepageCheckout()) { $this->messageManager->addError(__('The onepage checkout is disabled.')); return $this->resultRedirectFactory->create()->setPath('checkout/cart'); } + $quote = $this->getOnepage()->getQuote(); + + if (!$this->_customerSession->isLoggedIn() && !$checkoutHelper->isAllowedGuestCheckout($quote)) { + $this->messageManager->addError(__('Guest checkout is disabled.')); + return $this->resultRedirectFactory->create()->setPath('checkout/cart'); + } + if (!$quote->hasItems() || $quote->getHasError() || !$quote->validateMinimumAmount()) { return $this->resultRedirectFactory->create()->setPath('checkout/cart'); } diff --git a/app/code/Magento/Checkout/CustomerData/Cart.php b/app/code/Magento/Checkout/CustomerData/Cart.php index ae306dc9439a26fedb5282ced36980fd55476887..55fd454db8aeb8d42bb6674d6ad0336f9e45c1ff 100644 --- a/app/code/Magento/Checkout/CustomerData/Cart.php +++ b/app/code/Magento/Checkout/CustomerData/Cart.php @@ -94,6 +94,7 @@ class Cart extends \Magento\Framework\Object implements SectionSourceInterface 'possible_onepage_checkout' => $this->isPossibleOnepageCheckout(), 'items' => $this->getRecentItems(), 'extra_actions' => $this->layout->createBlock('Magento\Catalog\Block\ShortcutButtons')->toHtml(), + 'isGuestCheckoutAllowed' => $this->isGuestCheckoutAllowed(), ]; } @@ -173,4 +174,14 @@ class Cart extends \Magento\Framework\Object implements SectionSourceInterface } return $this->getQuote()->getAllVisibleItems(); } + + /** + * Check if guest checkout is allowed + * + * @return bool + */ + public function isGuestCheckoutAllowed() + { + return $this->checkoutHelper->isAllowedGuestCheckout($this->checkoutSession->getQuote()); + } } diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_cart_index.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_cart_index.xml index 3fce4aad4112a6476075eb0d26c2d20847eceeec..d0aeb1702d330c44a65833c0bfef597b5e09c6b0 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/checkout_cart_index.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_cart_index.xml @@ -42,7 +42,6 @@ <container name="checkout.cart.empty.widget" as="checkout_cart_empty_widget" label="Empty Shopping Cart Content Before"/> </container> </block> - <block class="Magento\Framework\View\Element\Template" name="cart.customer.signin" template="Magento_Checkout::sign-in.phtml" /> </referenceContainer> <block class="Magento\Checkout\Block\Cart\Additional\Info" name="additional.product.info" template="cart/additional/info.phtml"/> </body> diff --git a/app/code/Magento/Checkout/view/frontend/layout/default.xml b/app/code/Magento/Checkout/view/frontend/layout/default.xml index 2ac27890ca18a2a79b604c647abe24eb95f14625..da1007040f6a19ab02d2f794b2df8ac4e93df719 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/default.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/default.xml @@ -51,6 +51,19 @@ <item name="displayArea" xsi:type="string">promotion</item> </item> </item> + <item name="sign-in-popup" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/cart/authentication</item> + <item name="config" xsi:type="array"> + <item name="displayArea" xsi:type="string">sign-in-popup</item> + <item name="template" xsi:type="string">Magento_Checkout/cart/authentication</item> + </item> + <item name="children" xsi:type="array"> + <item name="messages" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/view/messages</item> + <item name="displayArea" xsi:type="string">messages</item> + </item> + </item> + </item> </item> </item> </item> diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml index d515d34169278ca83c7d361c5e43fcd51f9840ae..03322e3ab35958db5bbe99d179ad6f3fd5cec958 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml @@ -47,7 +47,9 @@ checkoutUrl: '<?=$block->getCheckoutUrl()?>', updateItemQtyUrl: '<?=$block->getUpdateItemQtyUrl()?>', removeItemUrl: '<?=$block->getRemoveItemUrl()?>', - imageTemplate: '<?= $block->getImageHtmlTemplate()?>' + imageTemplate: '<?= $block->getImageHtmlTemplate()?>', + customerRegisterUrl: '<?= $block->getCustomerRegisterUrlUrl()?>', + customerForgotPasswordUrl: '<?= $block->getCustomerForgotPasswordUrl()?>' }; </script> <script type="text/x-magento-init"> @@ -57,6 +59,13 @@ } } </script> + <script> + require([ + 'Magento_Ui/js/block-loader' + ], function(blockLoader) { + blockLoader("<?php echo $block->getViewFileUrl('images/loader-1.gif'); ?>"); + }) + </script> </div> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml index b7e34e07b15f160097a88d5071eed692072a822a..eea3462380412838de65c0ba3602f8459e60ff3d 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml @@ -5,20 +5,36 @@ */ // @codingStandardsIgnoreFile - -/** - * @deprecated - * @removeCandidate - */ ?> <?php if ($block->isPossibleOnepageCheckout()):?> <button type="button" + data-role="proceed-to-checkout" title="<?php echo __('Proceed to Checkout') ?>" class="action primary checkout<?php echo($block->isDisabled()) ? ' disabled' : ''; ?>" - <?php if ($block->isDisabled()):?>disabled="disabled"<?php endif; ?> - onclick="window.location='<?php echo $block->getCheckoutUrl() ?>';"> - <span><?php echo __('Proceed to Checkout') ?></span> + <?php if ($block->isDisabled()):?>disabled="disabled"<?php endif; ?>> + <span><?php echo __('Proceed to Checkout') ?></span> </button> - <!-- /Temp MAGETWO-36239 markup --> - <button type="button" class="action secondary proceed-to-checkout" href="#"><span><?php echo __('Sign in and Checkout') ?></span></button> + + <script> + require( + [ + 'jquery', + 'Magento_Checkout/js/model/cart/authentication-popup', + 'Magento_Customer/js/customer-data' + ], + function($, authenticationPopup, customerData) { + $('button[data-role="proceed-to-checkout"]').click(function(event) { + event.preventDefault(); + var cart = customerData.get('cart'), + customer = customerData.get('customer'); + + if (customer() == false && !cart().isGuestCheckoutAllowed) { + authenticationPopup.showModal(); + return false; + } + location.href = window.checkout.checkoutUrl; + }); + } + ); + </script> <?php endif?> diff --git a/app/code/Magento/Checkout/view/frontend/templates/sign-in.phtml b/app/code/Magento/Checkout/view/frontend/templates/sign-in.phtml deleted file mode 100644 index 6ac898aba4163797beade07bbd36ebb5e86fd629..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/sign-in.phtml +++ /dev/null @@ -1,77 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -?> -<!-- /Temp MAGETWO-36239 markup --> -<div class="block-authentication" - style="display: none" - data-mage-init='{ - "Magento_Ui/js/modal/modal":{ - "type": "popup", - "modalClass": "popup-authentication", - "responsive": true, - "innerScroll": true, - "trigger": ".proceed-to-checkout", - "buttons": [] - }}'> - <div class="block block-new-customer" - data-label="<?php echo __('or')?>"> - <div class="block-title"> - <strong id="block-new-customer-heading" role="heading" aria-level="2"><?php echo __('Checkout out as a new customer') ?></strong> - </div> - <div class="block-content" aria-labelledby="block-new-customer-heading"> - <p><?php echo __('Creating an account has many benefits:') ?></p> - <ul> - <li><?php echo __('See order and shipping status') ?></li> - <li><?php echo __('Track order history') ?></li> - <li><?php echo __('Check out faster') ?></li> - </ul> - <div class="actions-toolbar"> - <div class="primary"> - <a href="#" class="action action-register primary"><span><?php echo __('Create Account') ?></span></a> - </div> - </div> - </div> - </div> - <div class="block block-customer-login" - data-label="<?php echo __('or')?>"> - <div class="block-title"> - <strong id="block-customer-login-heading" role="heading" aria-level="2"><?php echo __('Checkout out using your account')?></strong> - </div> - <div class="block-content" aria-labelledby="block-customer-login-heading"> - <form class="form form-login" - method="post" - id="login-form" - data-mage-init='{"validation":{}}'> - <div class="fieldset login" data-hasrequired="<?php echo __('* Required Fields') ?>"> - <div class="field email required"> - <label class="label" for="email"><span><?php echo __('Email Address') ?></span></label> - <div class="control"> - <input name="login[username]" - id="email" - type="email" - class="input-text" - data-validate="{required:true, 'validate-email':true}"> - </div> - </div> - <div class="field password required"> - <label for="pass" class="label"><span><?php echo __('Password') ?></span></label> - <div class="control"> - <input name="login[password]" - type="password" - class="input-text" - id="pass" - data-validate="{required:true, 'validate-password':true}"> - </div> - </div> - <div class="actions-toolbar"> - <div class="primary"><button type="submit" class="action action-login secondary" name="send" id="send2"><span><?php echo __('Sign In') ?></span></button></div> - <div class="secondary"><a class="action" href="<?php echo $block->getForgotPasswordUrl() ?>"><span><?php echo __('Forgot Your Password?') ?></span></a></div> - </div> - </div> - </form> - </div> - </div> -</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js b/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js new file mode 100644 index 0000000000000000000000000000000000000000..e448a1c30b07da31ae1f26aaecb0477bade09b65 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js @@ -0,0 +1,37 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'Magento_Ui/js/modal/modal' + ], + function ($, modal) { + 'use strict'; + return { + modalWindow: null, + + /** Create popUp window for provided element */ + createPopUp: function(element) { + this.modalWindow = element; + var options = { + 'type': 'popup', + 'modalClass': 'popup-authentication', + 'responsive': true, + 'innerScroll': true, + 'trigger': '.proceed-to-checkout', + 'buttons': [] + }; + modal(options, $(this.modalWindow)); + }, + + /** Show login popup window */ + showModal: function() { + $(this.modalWindow).modal('openModal'); + } + } + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js index 2455c3932eabaeee72ba2ec5997a0ed9a35b5732..5f93022da11a9089f3ef90ebef20ef2057529a56 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js @@ -6,9 +6,11 @@ /*global confirm:true*/ define([ "jquery", + 'Magento_Checkout/js/model/cart/authentication-popup', + 'Magento_Customer/js/customer-data', "jquery/ui", "mage/decorate" -], function($){ +], function($, authenticationPopup, customerData){ $.widget('mage.sidebar', { options: { @@ -32,6 +34,13 @@ define([ }); $(this.options.button.checkout).on('click', $.proxy(function() { + var cart = customerData.get('cart'), + customer = customerData.get('customer'); + + if (customer() == false && !cart().isGuestCheckoutAllowed) { + authenticationPopup.showModal(); + return false; + } location.href = this.options.url.checkout; }, this)); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js b/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js index 51439dddc7af62e547994c908eb98374cc2392c2..b921592e718ca5fc134113209f8a39e2624f68d3 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js @@ -22,15 +22,7 @@ define( registerUrl: checkoutConfig.registerUrl, forgotPasswordUrl: checkoutConfig.forgotPasswordUrl, defaults: { - template: 'Magento_Checkout/authentication', - visible: false - }, - - /** Initialize observable properties */ - initObservable: function () { - this._super() - .observe('visible'); - return this; + template: 'Magento_Checkout/authentication' }, /** Is login form enabled for current customer */ @@ -38,11 +30,6 @@ define( return !customer.isLoggedIn(); }, - /** Toggle login form visibility */ - toggleForm: function() { - this.visible(!this.visible()); - }, - /** Provide login action */ login: function(loginForm) { var loginData = {}, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index f8f4f68a09e561e5bb69ed975b123cf6fbd920f8..d83bb9ed58e1723447516b40fbce3ff087ecf82a 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -60,6 +60,8 @@ define( addressOptions: addressOptions, + customerHasAddresses: addressOptions.length > 1, + addressOptionsText: function(address) { return address.getAddressInline(); }, @@ -82,6 +84,10 @@ define( this.source.trigger(this.dataScopePrefix + '.data.validate'); if (!this.source.get('params.invalid')) { var addressData = this.source.get(this.dataScopePrefix); + + if (this.isCustomerLoggedIn && !this.customerHasAddresses) { + this.saveInAddressBook = true; + } addressData.save_in_address_book = this.saveInAddressBook; // New address must be selected as a billing address diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js new file mode 100644 index 0000000000000000000000000000000000000000..0985d990a697bde35a780beb7d318895548e9103 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js @@ -0,0 +1,71 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'ko', + 'Magento_Ui/js/form/form', + 'Magento_Customer/js/action/login', + 'Magento_Customer/js/customer-data', + 'Magento_Checkout/js/model/cart/authentication-popup', + 'mage/translate', + 'mage/validation' + ], + function($, ko, Component, loginAction, customerData, authenticationPopup, $t) { + 'use strict'; + return Component.extend({ + registerUrl: window.checkout.customerRegisterUrl, + forgotPasswordUrl: window.checkout.customerForgotPasswordUrl, + modalWindow: null, + isLoading: ko.observable(false), + + initialize: function() { + var self = this; + this._super(); + loginAction.registerLoginCallback(function() { + self.isLoading(false); + }); + }, + + /** Init popup login window */ + setModalElement: function (element) { + authenticationPopup.createPopUp(element); + }, + + /** Is login form enabled for current customer */ + isActive: function() { + var customer = customerData.get('customer'); + return customer() == false; + }, + + /** Show login popup window */ + showModal: function() { + if (this.modalWindow) { + $(this.modalWindow).modal('openModal'); + } else { + alert($t('Guest checkout is disabled.')); + } + }, + + /** Provide login action */ + login: function(loginForm) { + var loginData = {}, + formDataArray = $(loginForm).serializeArray(); + formDataArray.forEach(function (entry) { + loginData[entry.name] = entry.value; + }); + + if($(loginForm).validation() + && $(loginForm).validation('isValid') + ) { + this.isLoading(true); + loginAction(loginData); + } + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html index c405d20229100c9502b77e5f01412242f8addbac..6c59936d60504f56b80a9bbd0f57e3121f8d1f2e 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html @@ -38,7 +38,7 @@ </div> <div class="block-content" aria-labelledby="block-customer-login-heading"> <form data-role="login" - data-bind="submit:login, mageInit: {'validation':{}}" + data-bind="submit:login" method="post"> <div class="fieldset" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}"> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html index ec88cbef634ca37aac501361d7179466908b8044..4174aa194d635afdd5220f2076a8ac71e985a0a7 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html @@ -13,7 +13,7 @@ <!-- ko foreach: getRegion('additional-fieldsets') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> - <!-- ko if: (isCustomerLoggedIn) --> + <!-- ko if: (isCustomerLoggedIn && customerHasAddresses) --> <div class="choice field"> <input type="checkbox" class="checkbox" id="billing-save-in-address-book" data-bind="checked: saveInAddressBook" /> <label class="label" for="billing-save-in-address-book"> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html new file mode 100644 index 0000000000000000000000000000000000000000..e7a7397371ef188f51c42847821af47185271104 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html @@ -0,0 +1,81 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<div class="block-authentication" + data-bind="afterRender: setModalElement, blockLoader: isLoading" + style="display: none"> + <div class="block block-new-customer" + data-label="or"> + <div class="block-title"> + <strong id="block-new-customer-heading" role="heading" aria-level="2" data-bind="text: $t('Checkout out as a new customer')"></strong> + </div> + <div class="block-content" aria-labelledby="block-new-customer-heading"> + <p data-bind="text: $t('Creating an account has many benefits:')"></p> + <ul> + <li data-bind="text: $t('See order and shipping status')"></li> + <li data-bind="text: $t('Track order history')"></li> + <li data-bind="text: $t('Check out faster')"></li> + </ul> + <div class="actions-toolbar"> + <div class="primary"> + <a class="action action-register primary" data-bind="attr: {href: registerUrl}"> + <span data-bind="text: $t('Create Account')"></span> + </a> + </div> + </div> + </div> + </div> + <div class="block block-customer-login" + data-label="or"> + <div class="block-title"> + <strong id="block-customer-login-heading" role="heading" aria-level="2" data-bind="text:$t('Checkout out using your account')"></strong> + </div> + <!-- ko foreach: getRegion('messages') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + <div class="block-content" aria-labelledby="block-customer-login-heading"> + <form class="form form-login" + method="post" + data-bind="submit:login" + id="login-form"> + <div class="fieldset login" data-hasrequired="* Required Fields"> + <div class="field email required"> + <label class="label" for="email"><span data-bind="text: $t('Email Address')"></span></label> + <div class="control"> + <input name="username" + id="email" + type="email" + class="input-text" + data-validate="{required:true, 'validate-email':true}"> + </div> + </div> + <div class="field password required"> + <label for="pass" class="label"><span data-bind="text: $t('Password')"></span></label> + <div class="control"> + <input name="password" + type="password" + class="input-text" + id="pass" + data-validate="{required:true, 'validate-password':true}"> + </div> + </div> + <div class="actions-toolbar"> + <div class="primary"> + <button type="submit" class="action action-login secondary" name="send" id="send2"> + <span data-bind="text: $t('Sign In')"></span> + </button> + </div> + <div class="secondary"> + <a class="action" data-bind="attr: {href: forgotPasswordUrl}"> + <span data-bind="text: $t('Forgot Your Password?')"></span> + </a> + </div> + </div> + </div> + </form> + </div> + </div> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html index 82475d90a25234b62a37c5e8c73fd01e5d0d61b8..a2fe08baaa52a4265d71b256b2d675514a380047 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html @@ -98,3 +98,6 @@ <!-- /ko --> </div> </div> +<!-- ko foreach: getRegion('sign-in-popup') --> +<!-- ko template: getTemplate() --><!-- /ko --> +<!-- /ko --> diff --git a/app/code/Magento/Customer/view/frontend/web/js/action/login.js b/app/code/Magento/Customer/view/frontend/web/js/action/login.js index 93aabf625bf6d58422f62327691ec63ff8ec0b75..743ec6d2f55c3b7d89dc9e2a170359ea7931963f 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/action/login.js +++ b/app/code/Magento/Customer/view/frontend/web/js/action/login.js @@ -7,14 +7,15 @@ define( [ 'jquery', 'mage/storage', - 'Magento_Ui/js/model/messageList' + 'Magento_Ui/js/model/messageList', + 'Magento_Customer/js/customer-data' ], - function($, storage, messageList) { + function($, storage, messageList, customerData) { 'use strict'; var callbacks = [], action = function(loginData, redirectUrl) { return storage.post( - 'customer/ajax/login', + '/customer/ajax/login', JSON.stringify(loginData) ).done(function (response) { if (response.errors) { @@ -26,6 +27,7 @@ define( callbacks.forEach(function(callback) { callback(loginData); }); + customerData.invalidate(['customer']); if (redirectUrl) { window.location.href = redirectUrl; } else { diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js new file mode 100644 index 0000000000000000000000000000000000000000..ef6dd82c179b4591a89a43987f72ca91ca974478 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js @@ -0,0 +1,19 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + return { + creditCard: null, + creditCardNumber: null, + expirationMonth: null, + expirationYear: null, + cvvCode: null + } + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..018c0cbb6b1d62c3be1f7317fc9a67ae1dbc0193 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js @@ -0,0 +1,72 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'mageUtils', + 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator', + 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type' + ], + function (utils, luhn10, creditCardTypes) { + 'use strict'; + + function result(card, isPotentiallyValid, isValid) { + return { + card: card, + isValid: isValid, + isPotentiallyValid: isPotentiallyValid + }; + } + + return function (value) { + var potentialTypes, + cardType, + valid, + i, + maxLength; + + if (utils.isEmpty(value)) { + return result(null, false, false); + } + + value = value.replace(/\-|\s/g, ''); + + if (!/^\d*$/.test(value)) { + return result(null, false, false); + } + + potentialTypes = creditCardTypes.getCardTypes(value); + + if (potentialTypes.length === 0) { + return result(null, false, false); + } else if (potentialTypes.length !== 1) { + return result(null, true, false); + } + + cardType = potentialTypes[0]; + + if (cardType.type === 'unionpay') { // UnionPay is not Luhn 10 compliant + valid = true; + } else { + valid = luhn10(value); + } + + for (i = 0; i < cardType.lengths.length; i++) { + if (cardType.lengths[i] === value.length) { + return result(cardType, valid, valid); + } + } + + maxLength = Math.max.apply(null, cardType.lengths); + + if (value.length < maxLength) { + return result(cardType, true, false); + } + + return result(cardType, false, false); + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js new file mode 100644 index 0000000000000000000000000000000000000000..7ace4e1594b796425b4d2788aa94a0a7dafc1f3d --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js @@ -0,0 +1,130 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'mageUtils' + ], + function ($, utils) { + 'use strict'; + var types = [ + { + niceType: 'Visa', + type: 'visa', + pattern: '^4\\d*$', + gaps: [4, 8, 12], + lengths: [16], + code: { + name: 'CVV', + size: 3 + } + }, + { + niceType: 'MasterCard', + type: 'master-card', + pattern: '^5([1-5]\\d*)?$', + gaps: [4, 8, 12], + lengths: [16], + code: { + name: 'CVC', + size: 3 + } + }, + { + niceType: 'American Express', + type: 'american-express', + pattern: '^3([47]\\d*)?$', + isAmex: true, + gaps: [4, 10], + lengths: [15], + code: { + name: 'CID', + size: 4 + } + }, + { + niceType: 'DinersClub', + type: 'diners-club', + pattern: '^3((0([0-5]\\d*)?)|[689]\\d*)?$', + gaps: [4, 10], + lengths: [14], + code: { + name: 'CVV', + size: 3 + } + }, + { + niceType: 'Discover', + type: 'discover', + pattern: '^6(0|01|011\\d*|5\\d*|4|4[4-9]\\d*)?$', + gaps: [4, 8, 12], + lengths: [16], + code: { + name: 'CID', + size: 3 + } + }, + { + niceType: 'JCB', + type: 'jcb', + pattern: '^((2|21|213|2131\\d*)|(1|18|180|1800\\d*)|(3|35\\d*))$', + gaps: [4, 8, 12], + lengths: [16], + code: { + name: 'CVV', + size: 3 + } + }, + { + niceType: 'UnionPay', + type: 'unionpay', + pattern: '^6(2\\d*)?$', + gaps: [4, 8, 12], + lengths: [16, 17, 18, 19], + code: { + name: 'CVN', + size: 3 + } + }, + { + niceType: 'Maestro', + type: 'maestro', + pattern: '^((5((0|[6-9])\\d*)?)|(6|6[37]\\d*))$', + gaps: [4, 8, 12], + lengths: [12, 13, 14, 15, 16, 17, 18, 19], + code: { + name: 'CVC', + size: 3 + } + } + ]; + + return { + getCardTypes: function (cardNumber) { + var i, value, + result = []; + + if (utils.isEmpty(cardNumber)) { + return result; + } + + if (cardNumber === '') { + return $.extend(true, {}, types); + } + + for (i = 0; i < types.length; i++) { + value = types[i]; + + if (new RegExp(value.pattern).test(cardNumber)) { + result.push($.extend(true, {}, value)); + } + } + return result; + } + } + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..22d5f8acdd93a33419abdf644dbbf4b563c853aa --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js @@ -0,0 +1,19 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + return function(a,b,c,d,e) { + for(d = +a[b = a.length-1], e=0; b--;) { + c = +a[b]; + d += ++e % 2 ? 2 * c % 10 + (c > 4) : c; + } + return !(d%10) + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..812ee62b363aa58e857db7df4a6c8e23be8e6471 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js @@ -0,0 +1,39 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + + function result(isValid, isPotentiallyValid) { + return { + isValid: isValid, + isPotentiallyValid: isPotentiallyValid + }; + } + + return function(value, maxLength) { + var DEFAULT_LENGTH = 3; + maxLength = maxLength || DEFAULT_LENGTH; + + if (!/^\d*$/.test(value)) { + return result(false, false); + } + if (value.length === maxLength) { + return result(true, true); + } + if (value.length < maxLength) { + return result(false, true); + } + if (value.length > maxLength) { + return result(false, false); + } + + return result(true, true); + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..1dda53d0721e1aa1b10dd022c2aa32c4e43553e8 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js @@ -0,0 +1,51 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'mageUtils', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator' + ], + function(utils, parseDate, expirationMonth, expirationYear) { + 'use strict'; + + function result(isValid, isPotentiallyValid, month, year) { + return { + isValid: isValid, + isPotentiallyValid: isPotentiallyValid, + month: month, + year: year + }; + } + + return function(value) { + var date, + monthValid, + yearValid; + + if (utils.isEmpty(value)) { + return result(false, false, null, null); + } + + value = value.replace(/^(\d\d) (\d\d(\d\d)?)$/, '$1/$2'); + date = parseDate(value); + monthValid = expirationMonth(date.month); + yearValid = expirationYear(date.year); + + if (monthValid.isValid && yearValid.isValid) { + return result(true, true, date.month, date.year); + } + + if (monthValid.isPotentiallyValid && yearValid.isPotentiallyValid) { + return result(false, true, null, null); + } + + return result(false, false, null, null); + } + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..d9f9729a7c6dd0d27e80af92f6864a4e29098a68 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js @@ -0,0 +1,41 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function () { + 'use strict'; + + function result(isValid, isPotentiallyValid) { + return { + isValid: isValid, + isPotentiallyValid: isPotentiallyValid + }; + } + + return function (value) { + var month, + monthValid; + + if ((value.replace(/\s/g, '') === '') || (value === '0')) { + return result(false, true); + } + + if (!/^\d*$/.test(value)) { + return result(false, false); + } + + if (isNaN(value)) { + return result(false, false); + } + + month = parseInt(value, 10); + monthValid = month > 0 && month < 13; + + return result(monthValid, monthValid); + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..5b0c1da544b57c717f5096c44a0a42702b2e4e68 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js @@ -0,0 +1,63 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + + function result(isValid, isPotentiallyValid) { + return { + isValid: isValid, + isPotentiallyValid: isPotentiallyValid + }; + } + + return function(value) { + var currentFirstTwo, + currentYear = new Date().getFullYear(), + firstTwo, + len = value.length, + twoDigitYear, + valid, + maxYear = 19; + + if (value.replace(/\s/g, '') === '') { + return result(false, true); + } + + if (!/^\d*$/.test(value)) { + return result(false, false); + } + + if (len < 2) { + return result(false, true); + } + + if (len === 3) { + // 20x === 20x + firstTwo = value.slice(0, 2); + currentFirstTwo = String(currentYear).slice(0, 2); + return result(false, firstTwo === currentFirstTwo); + } + + if (len > 4) { + return result(false, false); + } + + value = parseInt(value, 10); + twoDigitYear = Number(String(currentYear).substr(2, 2)); + + if (len === 2) { + valid = value >= twoDigitYear && value <= twoDigitYear + maxYear; + } else if (len === 4) { + valid = value >= currentYear && value <= currentYear + maxYear; + } + + return result(valid, valid); + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js new file mode 100644 index 0000000000000000000000000000000000000000..56c281a516e7af401a013b292107ccb1211e8932 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js @@ -0,0 +1,32 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + return function(value) { + var month, len; + + if (value.match('/')) { + value = value.split(/\s*\/\s*/g); + + return { + month: value[0], + year: value.slice(1).join() + }; + } + + len = value[0] === '0' || value.length > 5 || value.length === 4 || value.length === 3 ? 2 : 1; + month = value.substr(0, len); + + return { + month: month, + year: value.substr(month.length, 4) + }; + } + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js new file mode 100644 index 0000000000000000000000000000000000000000..dea84a03bdd04e7b5fed66678f704e553ad5a371 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js @@ -0,0 +1,61 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +(function (factory) { + if (typeof define === 'function' && define.amd) { + define([ + 'jquery', + 'Magento_Payment/js/model/credit-card-validation/cvv-validator', + 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator' + ], factory); + } else { + factory(jQuery); + } +}(function ($, cvvValidator, creditCardNumberValidator, expirationDateValidator, monthValidator) { + "use strict"; + + $.each({ + 'validate-card-number': [ + /** + * Validate credit card number based on mod 10 + * @param number - credit card number + * @return {boolean} + */ + function (number) { + return creditCardNumberValidator(number).isValid; + }, + 'Please enter a valid credit card number11.' + ], + 'validate-card-date': [ + /** + * Validate credit card number based on mod 10 + * @param date - month + * @return {boolean} + */ + function (date) { + return monthValidator(date).isValid; + }, + 'Incorrect credit card expiration date11.' + ], + 'validate-card-cvv': [ + /** + * Validate credit card number based on mod 10 + * @param cvv - month + * @return {boolean} + */ + function (cvv) { + return cvvValidator(cvv).isValid; + }, + 'Please enter a valid credit card verification number11.' + ] + + }, function (i, rule) { + rule.unshift(i); + $.validator.addMethod.apply($.validator, rule); + }); +})); \ No newline at end of file diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js index b8c738f6b3db6a27522d2eae1ca9d594d3ca111a..4e9c7b833327486c835a460e6cad78a18dc91aaf 100644 --- a/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js +++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js @@ -8,9 +8,10 @@ define( [ 'underscore', 'Magento_Checkout/js/view/payment/default', + 'Magento_Payment/js/model/credit-card-validation/credit-card-data', 'mage/translate' ], - function (_, Component, $t) { + function (_, Component, creditCardData, $t) { return Component.extend({ defaults: { creditCardType: '', @@ -34,6 +35,31 @@ define( ]); return this; }, + + initialize: function() { + this._super(); + + //Set credit card number to credit card data object + this.creditCardNumber.subscribe(function(value) { + console.log(value); + }); + + //Set expiration year to credit card data object + this.creditCardExpYear.subscribe(function(value) { + creditCardData.expirationYear = value; + }); + + //Set expiration month to credit card data object + this.creditCardExpMonth.subscribe(function(value) { + creditCardData.expirationYear = value; + }); + + //Set cvv code to credit card data object + this.creditCardVerificationNumber.subscribe(function(value) { + creditCardData.cvvCode = value; + }); + }, + getCode: function() { return 'cc'; }, diff --git a/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html b/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html index dcd12d8931523a68ba8d82348a61d2748bb45c9d..87dfe38b878d893a69ee54940ba2540bb11bc3f3 100644 --- a/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html +++ b/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html @@ -36,9 +36,10 @@ </label> <div class="control"> <input type="text" name="payment[cc_number]" class="input-text" value="" - data-bind="attr: {id: getCode() + '_cc_number', title: $t('Credit Card Number'), 'data-container': getCode() + '-cc-number', 'data-validate': JSON.stringify({'required-number':true, 'validate-cc-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})}, + data-bind="attr: {id: getCode() + '_cc_number', title: $t('Credit Card Number'), 'data-container': getCode() + '-cc-number', 'data-validate': JSON.stringify({'required-number':true, 'validate-card-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})}, enable: isActive($parents), - value: creditCardNumber"/> + value: creditCardNumber, + valueUpdate: 'keyup',"/> </div> </div> <div class="field date required" data-bind="attr: {id: getCode() + '_cc_type_exp_div'}"> @@ -51,7 +52,7 @@ <div class="control"> <select name="payment[cc_exp_month]" class="select select-month" - data-bind="attr: {id: getCode() + '_expiration', 'data-container': getCode() + '-cc-month', 'data-validate': JSON.stringify({required:true, 'validate-cc-exp':'#' + getCode() + '_expiration_yr'})}, + data-bind="attr: {id: getCode() + '_expiration', 'data-container': getCode() + '-cc-month', 'data-validate': JSON.stringify({required:true, 'validate-card-date':'#' + getCode() + '_expiration_yr'})}, enable: isActive($parents), options: getCcMonthsValues(), optionsValue: 'value', @@ -85,7 +86,7 @@ </label> <div class="control _with-tooltip"> <input type="text" class="input-text cvv" name="payment[cc_cid]" value="" - data-bind="attr: {id: getCode() + '_cc_cid', title: $t('Card Verification Number'), 'data-container': getCode() + '-cc-cvv', 'data-validate': JSON.stringify({'required-number':true, 'validate-cc-cvn':'#' + getCode() + '_cc_type'})}, + data-bind="attr: {id: getCode() + '_cc_cid', title: $t('Card Verification Number'), 'data-container': getCode() + '-cc-cvv', 'data-validate': JSON.stringify({'required-number':true, 'validate-card-cvv':'#' + getCode() + '_cc_type'})}, enable: isActive($parents), value: creditCardVerificationNumber"/> <div class="field-tooltip toggle"> diff --git a/app/code/Magento/Payment/view/frontend/web/transparent.js b/app/code/Magento/Payment/view/frontend/web/transparent.js index 7b2ba69366d0bedd69a931d32ce00ec667e57809..2060ca7c8ea5e5a344329c0e48ad935859f77f8a 100644 --- a/app/code/Magento/Payment/view/frontend/web/transparent.js +++ b/app/code/Magento/Payment/view/frontend/web/transparent.js @@ -6,9 +6,10 @@ define([ "jquery", "mage/template", - "jquery/ui" + "jquery/ui", + "Magento_Payment/js/model/credit-card-validation/validator" ], function($, mageTemplate){ - "use strict"; + 'use strict'; $.widget('mage.transparent', { options: {