diff --git a/app/code/Magento/Authorizenet/Model/Directpost.php b/app/code/Magento/Authorizenet/Model/Directpost.php
index d755cc71cce2b932f471e5148639b6e2b355db58..c4261e9581b82c92fec3505aae4180a1fe30011f 100644
--- a/app/code/Magento/Authorizenet/Model/Directpost.php
+++ b/app/code/Magento/Authorizenet/Model/Directpost.php
@@ -119,6 +119,11 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
      */
     protected $transactionRepository;
 
+    /**
+     * @var \Psr\Log\LoggerInterface
+     */
+    private $psrLogger;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
@@ -761,7 +766,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
     {
         try {
             $transactionId = $this->getResponse()->getXTransId();
-            $data = $payment->getMethodInstance()->getTransactionDetails($transactionId);
+            $data = $this->transactionService->getTransactionDetails($this, $transactionId);
             $transactionStatus = (string)$data->transaction->transactionStatus;
             $fdsFilterAction = (string)$data->transaction->FDSFilterAction;
 
@@ -779,6 +784,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
                 $payment->getOrder()->addStatusHistoryComment($message);
             }
         } catch (\Exception $e) {
+            $this->getPsrLogger()->critical($e);
             //this request is optional
         }
         return $this;
@@ -805,7 +811,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
             $order->registerCancellation($message)->save();
         } catch (\Exception $e) {
             //quiet decline
-            $this->logger->critical($e);
+            $this->getPsrLogger()->critical($e);
         }
     }
 
@@ -973,4 +979,18 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
 
         return $response;
     }
+
+    /**
+     * @return \Psr\Log\LoggerInterface
+     *
+     * @deprecated
+     */
+    private function getPsrLogger()
+    {
+        if (null === $this->psrLogger) {
+            $this->psrLogger = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get(\Psr\Log\LoggerInterface::class);
+        }
+        return $this->psrLogger;
+    }
 }
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js b/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js
index f88b11bf87a43e7b2feb4ec95fb3eafb6f69d056..2d142417ac099b023d2e715cbac026cfdada14e9 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js
@@ -6,48 +6,31 @@ define(
     [
         'Magento_Checkout/js/model/quote',
         'Magento_Checkout/js/model/url-builder',
-        'mage/storage',
-        'Magento_Checkout/js/model/error-processor',
         'Magento_Customer/js/model/customer',
-        'Magento_Checkout/js/model/full-screen-loader'
+        'Magento_Checkout/js/model/place-order'
     ],
-    function (quote, urlBuilder, storage, errorProcessor, customer, fullScreenLoader) {
+    function (quote, urlBuilder, customer, placeOrderService) {
         'use strict';
 
         return function (paymentData, messageContainer) {
-            var serviceUrl,
-                payload;
+            var serviceUrl, payload;
 
-            /** Checkout for guest and registered customer. */
-            if (!customer.isLoggedIn()) {
+            payload = {
+                cartId: quote.getQuoteId(),
+                billingAddress: quote.billingAddress(),
+                paymentMethod: paymentData
+            };
+
+            if (customer.isLoggedIn()) {
+                serviceUrl = urlBuilder.createUrl('/carts/mine/payment-information', {});
+            } else {
                 serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/payment-information', {
                     quoteId: quote.getQuoteId()
                 });
-                payload = {
-                    cartId: quote.getQuoteId(),
-                    email: quote.guestEmail,
-                    paymentMethod: paymentData,
-                    billingAddress: quote.billingAddress()
-                };
-            } else {
-                serviceUrl = urlBuilder.createUrl('/carts/mine/payment-information', {});
-                payload = {
-                    cartId: quote.getQuoteId(),
-                    paymentMethod: paymentData,
-                    billingAddress: quote.billingAddress()
-                };
+                payload.email = quote.guestEmail;
             }
 
-            fullScreenLoader.startLoader();
-
-            return storage.post(
-                serviceUrl, JSON.stringify(payload)
-            ).fail(
-                function (response) {
-                    errorProcessor.process(response, messageContainer);
-                    fullScreenLoader.stopLoader();
-                }
-            );
+            return placeOrderService(serviceUrl, payload, messageContainer);
         };
     }
 );
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
index 8b079d1fd5d15fecb0a8a63ec7e1c7d9e27d29a7..ab46c78c6f6e74f62a8c798c4c2b039b2eaf4876 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
@@ -4,18 +4,19 @@
  */
 /*jshint browser:true jquery:true*/
 /*global alert*/
-define([], function() {
+define([], function () {
     /**
-     * @param addressData
+     * @param {Object} addressData
      * Returns new address object
      */
     return function (addressData) {
         var identifier = Date.now();
+
         return {
             email: addressData.email,
             countryId: (addressData.country_id) ? addressData.country_id : window.checkoutConfig.defaultCountryId,
-            regionId: (addressData.region && addressData.region.region_id)
-                ? addressData.region.region_id
+            regionId: (addressData.region && addressData.region.region_id) ?
+                addressData.region.region_id
                 : window.checkoutConfig.defaultRegionId,
             regionCode: (addressData.region) ? addressData.region.region_code : null,
             region: (addressData.region) ? addressData.region.region : null,
@@ -33,25 +34,26 @@ define([], function() {
             suffix: addressData.suffix,
             vatId: addressData.vat_id,
             saveInAddressBook: addressData.save_in_address_book,
-            isDefaultShipping: function() {
+            customAttributes: addressData.custom_attributes,
+            isDefaultShipping: function () {
                 return addressData.default_shipping;
             },
-            isDefaultBilling: function() {
+            isDefaultBilling: function () {
                 return addressData.default_billing;
             },
-            getType: function() {
+            getType: function () {
                 return 'new-customer-address';
             },
-            getKey: function() {
+            getKey: function () {
                 return this.getType();
             },
-            getCacheKey: function() {
+            getCacheKey: function () {
                 return this.getType() + identifier;
             },
-            isEditable: function() {
+            isEditable: function () {
                 return true;
             },
-            canUseForBilling: function() {
+            canUseForBilling: function () {
                 return true;
             }
         }
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/place-order.js b/app/code/Magento/Checkout/view/frontend/web/js/model/place-order.js
new file mode 100644
index 0000000000000000000000000000000000000000..68548cb1b28d3e2a4abe66c8be13c9dd48b73ec2
--- /dev/null
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/place-order.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+define(
+    [
+        'mage/storage',
+        'Magento_Checkout/js/model/error-processor',
+        'Magento_Checkout/js/model/full-screen-loader'
+    ],
+    function (storage, errorProcessor, fullScreenLoader) {
+        'use strict';
+
+        return function (serviceUrl, payload, messageContainer) {
+            fullScreenLoader.startLoader();
+
+            return storage.post(
+                serviceUrl, JSON.stringify(payload)
+            ).fail(
+                function (response) {
+                    errorProcessor.process(response, messageContainer);
+                    fullScreenLoader.stopLoader();
+                }
+            );
+        };
+    }
+);
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js b/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js
index eb950d1e6f9a3d7d484c2379026a1cfd3a03d809..6f86ecedd1af3f5f85909c338ccd00e6cf390dc2 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js
@@ -44,7 +44,7 @@ define(
                 return totals;
             },
             setTotals: function(totalsData) {
-                if (_.isObject(totalsData.extension_attributes)) {
+                if (_.isObject(totalsData) && _.isObject(totalsData.extension_attributes)) {
                     _.each(totalsData.extension_attributes, function(element, index) {
                         totalsData[index] = element;
                     });
diff --git a/app/code/Magento/Customer/Model/Address.php b/app/code/Magento/Customer/Model/Address.php
index 54eeaf09f1ff76ef87522cccb5f2cc3d77107281..0d7638a37196a9062f05cc34e7ef9b2d983176c6 100644
--- a/app/code/Magento/Customer/Model/Address.php
+++ b/app/code/Magento/Customer/Model/Address.php
@@ -47,6 +47,11 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress
      */
     protected $indexerRegistry;
 
+    /**
+     * @var \Magento\Customer\Model\Address\CustomAttributeListInterface
+     */
+    private $attributeList;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
@@ -347,4 +352,27 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress
         $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
         $indexer->reindexRow($this->getCustomerId());
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getCustomAttributesCodes()
+    {
+        return array_keys($this->getAttributeList()->getAttributes());
+    }
+
+    /**
+     * Get new AttributeList dependency for application code.
+     * @return \Magento\Customer\Model\Address\CustomAttributeListInterface
+     * @deprecated
+     */
+    private function getAttributeList()
+    {
+        if (!$this->attributeList) {
+            $this->attributeList = \Magento\Framework\App\ObjectManager::getInstance()->get(
+                \Magento\Customer\Model\Address\CustomAttributeListInterface::class
+            );
+        }
+        return $this->attributeList;
+    }
 }
diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php
index 6855eb242e6e5f1e9b476a175dadc841d2b9fbf6..1851f858b992f2acfdd8285aeaca897682b24792 100644
--- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php
+++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php
@@ -263,7 +263,7 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt
     {
         if (is_array($key)) {
             $key = $this->_implodeArrayField($key);
-        } elseif (is_array($value) && $this->isAddressMultilineAttribute($key)) {
+        } elseif (is_array($value) && !empty($value) && $this->isAddressMultilineAttribute($key)) {
             $value = $this->_implodeArrayValues($value);
         }
         return parent::setData($key, $value);
diff --git a/app/code/Magento/Customer/Model/Address/CustomAttributeList.php b/app/code/Magento/Customer/Model/Address/CustomAttributeList.php
new file mode 100644
index 0000000000000000000000000000000000000000..f83b37c2a814debcc5d6b0c1ccd6a429cb3a755a
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Address/CustomAttributeList.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Address;
+
+class CustomAttributeList implements CustomAttributeListInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getAttributes()
+    {
+        return [];
+    }
+}
diff --git a/app/code/Magento/Customer/Model/Address/CustomAttributeListInterface.php b/app/code/Magento/Customer/Model/Address/CustomAttributeListInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..c04cfe16f49183e0e27ab8362068b75a83951d3c
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Address/CustomAttributeListInterface.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Customer\Model\Address;
+
+interface CustomAttributeListInterface
+{
+    /**
+     * Retrieve list of customer addresses custom attributes
+     *
+     * @return array
+     */
+    public function getAttributes();
+}
diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml
index 647ec87efca25a1e583df18d3d469f586996b2c2..1e5f0ce0677ecf699b12b540bb9805d8129d053e 100644
--- a/app/code/Magento/Customer/etc/di.xml
+++ b/app/code/Magento/Customer/etc/di.xml
@@ -49,6 +49,8 @@
                 type="Magento\Customer\Model\EmailNotification" />
     <preference for="Magento\Customer\Api\CustomerNameGenerationInterface"
                 type="Magento\Customer\Helper\View" />
+    <preference for="Magento\Customer\Model\Address\CustomAttributeListInterface"
+                type="Magento\Customer\Model\Address\CustomAttributeList" />
     <type name="Magento\Customer\Model\Session">
         <arguments>
             <argument name="configShare" xsi:type="object">Magento\Customer\Model\Config\Share\Proxy</argument>
diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js
index e81016145c705e9d99d86265fb6f0dfd284f9d19..30fbef98fd39ab15db1c7971e3e86ad82e367253 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js
@@ -32,6 +32,7 @@ define([], function() {
             vatId: addressData.vat_id,
             sameAsBilling: addressData.same_as_billing,
             saveInAddressBook: addressData.save_in_address_book,
+            customAttributes: addressData.custom_attributes,
             isDefaultShipping: function() {
                 return addressData.default_shipping;
             },
diff --git a/app/code/Magento/Dhl/Model/Carrier.php b/app/code/Magento/Dhl/Model/Carrier.php
index b9725a98209599aac6fe187ded298d03a8070e97..8a626dd2d42b8cdd5af810d3dd64ef58d7055834 100644
--- a/app/code/Magento/Dhl/Model/Carrier.php
+++ b/app/code/Magento/Dhl/Model/Carrier.php
@@ -1123,9 +1123,8 @@ class Carrier extends \Magento\Dhl\Model\AbstractDhl implements \Magento\Shippin
                     throw new \Magento\Framework\Exception\LocalizedException($responseError);
                 }
                 $this->debugErrors($this->_errors);
-
-                return false;
             }
+            $result->append($this->getErrorMessage());
         }
 
         return $result;
diff --git a/app/code/Magento/Fedex/Model/Carrier.php b/app/code/Magento/Fedex/Model/Carrier.php
index c03d89e480c355c2e6abe3f1d9d1585e66a793a4..4cd95cb5b4ba9d3c433d311440b509ee93c6dd3e 100644
--- a/app/code/Magento/Fedex/Model/Carrier.php
+++ b/app/code/Magento/Fedex/Model/Carrier.php
@@ -501,7 +501,10 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
         // make general request for all methods
         $response = $this->_doRatesRequest(self::RATE_REQUEST_GENERAL);
         $preparedGeneral = $this->_prepareRateResponse($response);
-        if (!$preparedGeneral->getError() || $this->_result->getError() && $preparedGeneral->getError()) {
+        if (!$preparedGeneral->getError()
+            || $this->_result->getError() && $preparedGeneral->getError()
+            || empty($this->_result->getAllRates())
+        ) {
             $this->_result->append($preparedGeneral);
         }
 
diff --git a/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php b/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php
index a824adbd2bf82ed733841813ba42d72622bfdf39..04e149cae270e1ff5077e55ce0283f9a51066e82 100644
--- a/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php
+++ b/app/code/Magento/Paypal/Controller/Express/AbstractExpress/PlaceOrder.php
@@ -62,15 +62,21 @@ class PlaceOrder extends \Magento\Paypal\Controller\Express\AbstractExpress
      */
     public function execute()
     {
-        try {
-            if ($this->isValidationRequired() &&
-                !$this->agreementsValidator->isValid(array_keys($this->getRequest()->getPost('agreement', [])))
-            ) {
-                throw new \Magento\Framework\Exception\LocalizedException(
-                    __('Please agree to all the terms and conditions before placing the order.')
-                );
-            }
+        if ($this->isValidationRequired() &&
+            !$this->agreementsValidator->isValid(array_keys($this->getRequest()->getPost('agreement', [])))
+        ) {
+            $e = new \Magento\Framework\Exception\LocalizedException(
+                __('Please agree to all the terms and conditions before placing the order.')
+            );
+            $this->messageManager->addExceptionMessage(
+                $e,
+                $e->getMessage()
+            );
+            $this->_redirect('*/*/review');
+            return;
+        }
 
+        try {
             $this->_initCheckout();
             $this->_checkout->place($this->_initToken());
 
@@ -108,12 +114,6 @@ class PlaceOrder extends \Magento\Paypal\Controller\Express\AbstractExpress
             return;
         } catch (ApiProcessableException $e) {
             $this->_processPaypalApiError($e);
-        } catch (\Magento\Framework\Exception\LocalizedException $e) {
-            $this->messageManager->addExceptionMessage(
-                $e,
-                $e->getMessage()
-            );
-            $this->_redirect('*/*/review');
         } catch (\Exception $e) {
             $this->messageManager->addExceptionMessage(
                 $e,
@@ -141,6 +141,9 @@ class PlaceOrder extends \Magento\Paypal\Controller\Express\AbstractExpress
             case ApiProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL:
                 $this->_redirectSameToken();
                 break;
+            case ApiProcessableException::API_ADDRESS_MATCH_FAIL:
+                $this->redirectToOrderReviewPageAndShowError($exception->getUserMessage());
+                break;
             case ApiProcessableException::API_UNABLE_TRANSACTION_COMPLETE:
                 if ($this->_config->getPaymentAction() == \Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER) {
                     $paypalTransactionData = $this->_getCheckoutSession()->getPaypalTransactionData();
@@ -182,6 +185,18 @@ class PlaceOrder extends \Magento\Paypal\Controller\Express\AbstractExpress
         $this->_redirect('checkout/cart');
     }
 
+    /**
+     * Redirect customer to the paypal order review page and show error message
+     *
+     * @param string $errorMessage
+     * @return void
+     */
+    private function redirectToOrderReviewPageAndShowError($errorMessage)
+    {
+        $this->messageManager->addErrorMessage($errorMessage);
+        $this->_redirect('*/*/review');
+    }
+
     /**
      * Return true if agreements validation required
      *
diff --git a/app/code/Magento/Paypal/Controller/Express/AbstractExpress/Start.php b/app/code/Magento/Paypal/Controller/Express/AbstractExpress/Start.php
index 20c9b5f7fb08fbcd78fc46cfa7c2e8ebce3436a1..aef1f4aa87920d3dc1a801ff5ee47b2c33ff84c5 100644
--- a/app/code/Magento/Paypal/Controller/Express/AbstractExpress/Start.php
+++ b/app/code/Magento/Paypal/Controller/Express/AbstractExpress/Start.php
@@ -21,7 +21,6 @@ class Start extends GetToken
     public function execute()
     {
         try {
-
             $token = $this->getToken();
             if ($token === null) {
 
diff --git a/app/code/Magento/Paypal/Controller/Express/GetToken.php b/app/code/Magento/Paypal/Controller/Express/GetToken.php
index c96cdb420bb3aca6bacfe83a9eb281a574e37c39..a7c00bf1f38322c811422f3e4b26f84934ed8bfd 100644
--- a/app/code/Magento/Paypal/Controller/Express/GetToken.php
+++ b/app/code/Magento/Paypal/Controller/Express/GetToken.php
@@ -53,8 +53,9 @@ class GetToken extends AbstractExpress
             if ($token === null) {
                 $token = false;
             }
+            $url = $this->_checkout->getRedirectUrl();
             $this->_initToken($token);
-            $controllerResult->setData(['token' => $token]);
+            $controllerResult->setData(['url' => $url]);
         } catch (LocalizedException $exception) {
             $this->messageManager->addExceptionMessage(
                 $exception,
diff --git a/app/code/Magento/Paypal/Model/Api/Nvp.php b/app/code/Magento/Paypal/Model/Api/Nvp.php
index 521887b6c3c524e4f82fb348bfcc47d63f2db99e..d1cc47a06ff8ff89d4f1b0d95748184ad0244e4d 100644
--- a/app/code/Magento/Paypal/Model/Api/Nvp.php
+++ b/app/code/Magento/Paypal/Model/Api/Nvp.php
@@ -1288,9 +1288,10 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi
         $exceptionPhrase = __('PayPal gateway has rejected request. %1', $errorMessages);
 
         /** @var \Magento\Framework\Exception\LocalizedException $exception */
-        $exception = count($errors) == 1 && $this->_isProcessableError($errors[0]['code'])
+        $firstError = $errors[0]['code'];
+        $exception = $this->_isProcessableError($firstError)
             ? $this->_processableExceptionFactory->create(
-                ['phrase' => $exceptionPhrase, 'code' => $errors[0]['code']]
+                ['phrase' => $exceptionPhrase, 'code' => $firstError]
             )
             : $this->_frameworkExceptionFactory->create(
                 ['phrase' => $exceptionPhrase]
diff --git a/app/code/Magento/Paypal/Model/Api/ProcessableException.php b/app/code/Magento/Paypal/Model/Api/ProcessableException.php
index a44e9ae5f3e753ef8c8a2e99a1bf768de8f16bfb..2a7ce0f104203c1a2803e1d77314f3c04cefbf0e 100644
--- a/app/code/Magento/Paypal/Model/Api/ProcessableException.php
+++ b/app/code/Magento/Paypal/Model/Api/ProcessableException.php
@@ -25,6 +25,7 @@ class ProcessableException extends LocalizedException
     const API_COUNTRY_FILTER_DECLINE = 10537;
     const API_MAXIMUM_AMOUNT_FILTER_DECLINE = 10538;
     const API_OTHER_FILTER_DECLINE = 10539;
+    const API_ADDRESS_MATCH_FAIL = 10736;
     /**#@-*/
 
     /**
@@ -61,8 +62,13 @@ class ProcessableException extends LocalizedException
                     'I\'m sorry - but we are not able to complete your transaction. Please contact us so we can assist you.'
                 );
                 break;
+            case self::API_ADDRESS_MATCH_FAIL:
+                $message = __(
+                    'A match of the Shipping Address City, State, and Postal Code failed.'
+                );
+                break;
             default:
-                $message = __($this->getMessage());
+                $message = __('We can\'t place the order.');
                 break;
         }
         return $message;
diff --git a/app/code/Magento/Paypal/Model/Express.php b/app/code/Magento/Paypal/Model/Express.php
index 2464ef48498ce967dc6b074e695f4b685bfc3bd0..a10a2654bf529b63a70c07247bba9b9c154368d0 100644
--- a/app/code/Magento/Paypal/Model/Express.php
+++ b/app/code/Magento/Paypal/Model/Express.php
@@ -266,6 +266,7 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
                 ApiProcessableException::API_COUNTRY_FILTER_DECLINE,
                 ApiProcessableException::API_MAXIMUM_AMOUNT_FILTER_DECLINE,
                 ApiProcessableException::API_OTHER_FILTER_DECLINE,
+                ApiProcessableException::API_ADDRESS_MATCH_FAIL,
             ]
         );
     }
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Api/ProcessableExceptionTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Api/ProcessableExceptionTest.php
index 63c6d364e82f43bddcc14fe7595560e494aef7fc..c90431dc4dc5979136d5f274517af4efe7c67c21 100644
--- a/app/code/Magento/Paypal/Test/Unit/Model/Api/ProcessableExceptionTest.php
+++ b/app/code/Magento/Paypal/Test/Unit/Model/Api/ProcessableExceptionTest.php
@@ -5,19 +5,16 @@
  */
 namespace Magento\Paypal\Test\Unit\Model\Api;
 
-use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\Paypal\Model\Api\ProcessableException;
 
 class ProcessableExceptionTest extends \PHPUnit_Framework_TestCase
 {
-    /**
-     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
-     */
-    protected $objectManager;
+    const UNKNOWN_CODE = 10411;
 
     /**
-     * @var \Magento\Paypal\Model\Api\ProcessableException
+     * @var ProcessableException
      */
-    protected $model;
+    private $model;
 
     /**
      * @param int $code
@@ -27,8 +24,7 @@ class ProcessableExceptionTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetUserMessage($code, $msg)
     {
-        $this->objectManager = new ObjectManager($this);
-        $this->model = new \Magento\Paypal\Model\Api\ProcessableException(__($msg), null, $code);
+        $this->model = new ProcessableException(__($msg), null, $code);
         $this->assertEquals($msg, $this->model->getUserMessage());
     }
 
@@ -39,28 +35,35 @@ class ProcessableExceptionTest extends \PHPUnit_Framework_TestCase
     {
         return [
             [
-                10001,
+                ProcessableException::API_INTERNAL_ERROR,
                 "I'm sorry - but we were not able to process your payment. "
                 . "Please try another payment method or contact us so we can assist you.",
             ],
             [
-                10417,
+                ProcessableException::API_UNABLE_PROCESS_PAYMENT_ERROR_CODE,
                 "I'm sorry - but we were not able to process your payment. "
                 . "Please try another payment method or contact us so we can assist you."
             ],
             [
-                10537,
+                ProcessableException::API_COUNTRY_FILTER_DECLINE,
                 "I'm sorry - but we are not able to complete your transaction. Please contact us so we can assist you."
             ],
             [
-                10538,
+                ProcessableException::API_MAXIMUM_AMOUNT_FILTER_DECLINE,
                 "I'm sorry - but we are not able to complete your transaction. Please contact us so we can assist you."
             ],
             [
-                10539,
+                ProcessableException::API_OTHER_FILTER_DECLINE,
                 "I'm sorry - but we are not able to complete your transaction. Please contact us so we can assist you."
             ],
-            [10411, "something went wrong"]
+            [
+                ProcessableException::API_ADDRESS_MATCH_FAIL,
+                'A match of the Shipping Address City, State, and Postal Code failed.'
+            ],
+            [
+                self::UNKNOWN_CODE,
+                "We can't place the order."
+            ]
         ];
     }
 }
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php b/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php
index 288b01bd05d399f3599158e686295044d250d767..75f4c14d8517e23b08dc59f46850ae63df5d4830 100644
--- a/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php
+++ b/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php
@@ -22,6 +22,7 @@ class ExpressTest extends \PHPUnit_Framework_TestCase
         ApiProcessableException::API_COUNTRY_FILTER_DECLINE,
         ApiProcessableException::API_MAXIMUM_AMOUNT_FILTER_DECLINE,
         ApiProcessableException::API_OTHER_FILTER_DECLINE,
+        ApiProcessableException::API_ADDRESS_MATCH_FAIL
     ];
 
     /**
diff --git a/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout.js b/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout.js
index e2f70141de02218a46bf0222af200e503ac35170..d70de53581276d34886263558deb455f03a55094 100644
--- a/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout.js
+++ b/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout.js
@@ -42,8 +42,8 @@ define(
                             }
                         ).done(
                             function (response) {
-                                if (response && response.token) {
-                                    paypalExpressCheckout.checkout.startFlow(response.token);
+                                if (response && response.url) {
+                                    paypalExpressCheckout.checkout.startFlow(response.url);
 
                                     return;
                                 }
diff --git a/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/iframe-methods.js b/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/iframe-methods.js
index 9d8ba97f26775ae95714cf8f15a2b892e6150fba..b95c0a7839a6dca8c21040c518192049e16611c5 100644
--- a/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/iframe-methods.js
+++ b/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/iframe-methods.js
@@ -50,6 +50,7 @@ define(
              */
             placePendingPaymentOrder: function () {
                 if (this.placeOrder()) {
+                    fullScreenLoader.startLoader();
                     this.isInAction(true);
                     // capture all click events
                     document.addEventListener('click', iframe.stopEventPropagation, true);
@@ -61,6 +62,7 @@ define(
                 return this._super()
                     .fail(
                         function () {
+                            fullScreenLoader.stopLoader();
                             self.isInAction(false);
                             document.removeEventListener('click', iframe.stopEventPropagation, true);
                         }
@@ -71,7 +73,15 @@ define(
              * After place order callback
              */
             afterPlaceOrder: function () {
+                if (this.iframeIsLoaded) {
+                    document.getElementById(this.getCode() + '-iframe')
+                        .contentWindow.location.reload();
+                }
+
                 this.paymentReady(true);
+                this.iframeIsLoaded = true;
+                this.isPlaceOrderActionAllowed(true);
+                fullScreenLoader.stopLoader();
             },
 
             /**
diff --git a/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/in-context/checkout-express.js b/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/in-context/checkout-express.js
index d93e0ea702fca98fcd447cc5786a830fa0f8df52..7538d3a02aa9b76a769845f5f32d471d110a7983 100644
--- a/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/in-context/checkout-express.js
+++ b/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/in-context/checkout-express.js
@@ -52,8 +52,8 @@ define(
                                         }
                                     ).done(
                                         function (response) {
-                                            if (response && response.token) {
-                                                paypalExpressCheckout.checkout.startFlow(response.token);
+                                            if (response && response.url) {
+                                                paypalExpressCheckout.checkout.startFlow(response.url);
 
                                                 return;
                                             }
diff --git a/app/code/Magento/Quote/Model/Quote/Item/Compare.php b/app/code/Magento/Quote/Model/Quote/Item/Compare.php
index f61dc25660c9d1dd68b132aaceedc0fd7356315e..10bb712025462fc11f99c2f55206c6cf10f8b854 100644
--- a/app/code/Magento/Quote/Model/Quote/Item/Compare.php
+++ b/app/code/Magento/Quote/Model/Quote/Item/Compare.php
@@ -23,6 +23,9 @@ class Compare
         if (is_string($value) && is_array(@unserialize($value))) {
             $value = @unserialize($value);
             unset($value['qty'], $value['uenc']);
+            $value = array_filter($value, function ($optionValue) {
+                return !empty($optionValue);
+            });
         }
         return $value;
     }
diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php
index d8aedf4a8b986a45e237e460e127ba4d5060a8a0..f69e299b4542e7669d9bc23df733d9bd8b63b242 100644
--- a/app/code/Magento/Quote/Model/QuoteManagement.php
+++ b/app/code/Magento/Quote/Model/QuoteManagement.php
@@ -21,6 +21,8 @@ use Magento\Sales\Api\Data\OrderInterfaceFactory as OrderFactory;
 use Magento\Sales\Api\OrderManagementInterface as OrderManagement;
 use Magento\Store\Model\StoreManagerInterface;
 use Magento\Quote\Model\Quote\Address;
+use Magento\Framework\App\ObjectManager;
+use Magento\Quote\Model\QuoteIdMaskFactory;
 
 /**
  * Class QuoteManagement
@@ -130,6 +132,11 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface
      */
     protected $quoteFactory;
 
+    /**
+     * @var QuoteIdMaskFactory
+     */
+    private $quoteIdMaskFactory;
+
     /**
      * @param EventManager $eventManager
      * @param QuoteValidator $quoteValidator
@@ -262,6 +269,12 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface
 
         $quote->setCustomer($customer);
         $quote->setCustomerIsGuest(0);
+        $quoteIdMaskFactory = $this->getQuoteIdMaskFactory();
+        /** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */
+        $quoteIdMask = $quoteIdMaskFactory->create()->load($cartId, 'quote_id');
+        if ($quoteIdMask->getId()) {
+            $quoteIdMask->delete();
+        }
         $this->quoteRepository->save($quote);
         return true;
 
@@ -547,4 +560,16 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface
             $shipping->setIsDefaultBilling(true);
         }
     }
+
+    /**
+     * @return QuoteIdMaskFactory
+     * @deprecated
+     */
+    private function getQuoteIdMaskFactory()
+    {
+        if (!$this->quoteIdMaskFactory) {
+            $this->quoteIdMaskFactory = ObjectManager::getInstance()->get(QuoteIdMaskFactory::class);
+        }
+        return $this->quoteIdMaskFactory;
+    }
 }
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/CompareTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/CompareTest.php
index a22d10aee9318aed5d07fa70768e8ecfa90ca940..07f9987a902522b5701c6fdab888274f664d2073 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/CompareTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/CompareTest.php
@@ -187,4 +187,31 @@ class CompareTest extends \PHPUnit_Framework_TestCase
             ->will($this->returnValue([]));
         $this->assertFalse($this->helper->compare($this->itemMock, $this->comparedMock));
     }
+
+    /**
+     * Verify that compare ignores empty options.
+     */
+    public function testCompareWithEmptyValues()
+    {
+        $this->itemMock->expects($this->any())
+            ->method('getProductId')
+            ->will($this->returnValue(1));
+        $this->comparedMock->expects($this->any())
+            ->method('getProductId')
+            ->will($this->returnValue(1));
+
+        $this->itemMock->expects($this->once())->method('getOptions')->willReturn([
+            $this->getOptionMock('option-1', serialize([
+                'non-empty-option' => 'test',
+                'empty_option' => ''
+            ]))
+        ]);
+        $this->comparedMock->expects($this->once())->method('getOptions')->willReturn([
+            $this->getOptionMock('option-1', serialize([
+                'non-empty-option' => 'test'
+            ]))
+        ]);
+        
+        $this->assertTrue($this->helper->compare($this->itemMock, $this->comparedMock));
+    }
 }
diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php
index cd2a56b3b9d7b414b24530e17dbf409dfcf2fe14..2664e7ef21ad76da3bfd6b844caf42d8bbdb8900 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php
@@ -124,7 +124,7 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
-    protected $quoteFactoryMock;
+    private $quoteIdMock;
 
     /**
      * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
@@ -238,7 +238,6 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
         );
 
         $this->quoteFactoryMock = $this->getMock('\Magento\Quote\Model\QuoteFactory', ['create'], [], '', false);
-
         $this->model = $objectManager->getObject(
             '\Magento\Quote\Model\QuoteManagement',
             [
@@ -264,6 +263,12 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
                 'quoteFactory' => $this->quoteFactoryMock
             ]
         );
+
+        // Set the new dependency
+        $this->quoteIdMock = $this->getMock('Magento\Quote\Model\QuoteIdMask', [], [], '', false);
+        $quoteIdFactoryMock = $this->getMock(\Magento\Quote\Model\QuoteIdMaskFactory::class, ['create'], [], '', false);
+        $this->setPropertyValue($this->model, 'quoteIdMaskFactory', $quoteIdFactoryMock);
+
     }
 
     public function testCreateEmptyCartAnonymous()
@@ -508,6 +513,13 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
         $customerId = 455;
         $storeId = 5;
 
+        $this->getPropertyValue($this->model, 'quoteIdMaskFactory')
+            ->expects($this->once())
+            ->method('create')
+            ->willReturn($this->quoteIdMock);
+        $this->quoteIdMock->expects($this->once())->method('load')->with($cartId, 'quote_id')->willReturnSelf();
+        $this->quoteIdMock->expects($this->once())->method('getId')->willReturn(10);
+        $this->quoteIdMock->expects($this->once())->method('delete');
         $quoteMock = $this->getMock(
             '\Magento\Quote\Model\Quote',
             ['getCustomerId', 'setCustomer', 'setCustomerIsGuest'],
@@ -739,7 +751,7 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
         $this->checkoutSessionMock->expects($this->once())->method('setLastOrderId')->with($orderId);
         $this->checkoutSessionMock->expects($this->once())->method('setLastRealOrderId')->with($orderIncrementId);
         $this->checkoutSessionMock->expects($this->once())->method('setLastOrderStatus')->with($orderStatus);
- 
+
         $this->assertEquals($orderId, $service->placeOrder($cartId));
     }
 
@@ -935,7 +947,7 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
         $order = $this->getMock(
             'Magento\Sales\Model\Order',
             ['setShippingAddress', 'getAddressesCollection', 'getAddresses', 'getBillingAddress', 'addAddresses',
-            'setBillingAddress', 'setAddresses', 'setPayment', 'setItems', 'setQuoteId'],
+                'setBillingAddress', 'setAddresses', 'setPayment', 'setItems', 'setQuoteId'],
             [],
             '',
             false
@@ -979,4 +991,37 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
             ->willReturn($cartMock);
         $this->assertEquals($cartMock, $this->model->getCartForCustomer($customerId));
     }
+
+    /**
+     * Get any object property value.
+     *
+     * @param $object
+     * @param $property
+     * @return mixed
+     */
+    protected function getPropertyValue($object, $property)
+    {
+        $reflection = new \ReflectionClass(get_class($object));
+        $reflectionProperty = $reflection->getProperty($property);
+        $reflectionProperty->setAccessible(true);
+
+        return $reflectionProperty->getValue($object);
+    }
+
+    /**
+     * Set object property value.
+     *
+     * @param $object
+     * @param $property
+     * @param $value
+     */
+    protected function setPropertyValue(&$object, $property, $value)
+    {
+        $reflection = new \ReflectionClass(get_class($object));
+        $reflectionProperty = $reflection->getProperty($property);
+        $reflectionProperty->setAccessible(true);
+        $reflectionProperty->setValue($object, $value);
+
+        return $object;
+    }
 }
diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js
index b636a613d622ffe50570117408c6be86b414df0a..606fe4013ea762c5460c49202907463d7c7952f2 100644
--- a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js
+++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js
@@ -13,26 +13,24 @@ define(
         'jquery',
         'Magento_Checkout/js/model/quote',
         'Magento_Checkout/js/model/resource-url-manager',
-        'Magento_Checkout/js/model/payment-service',
         'Magento_Checkout/js/model/error-processor',
         'Magento_SalesRule/js/model/payment/discount-messages',
         'mage/storage',
-        'Magento_Checkout/js/action/get-totals',
         'mage/translate',
-        'Magento_Checkout/js/model/payment/method-list'
+        'Magento_Checkout/js/action/get-payment-information',
+        'Magento_Checkout/js/model/totals'
     ],
     function (
         ko,
         $,
         quote,
         urlManager,
-        paymentService,
         errorProcessor,
         messageContainer,
         storage,
-        getTotalsAction,
         $t,
-        paymentMethodList
+        getPaymentInformationAction,
+        totals
     ) {
         'use strict';
         return function (couponCode, isApplied, isLoading) {
@@ -49,11 +47,10 @@ define(
                         var deferred = $.Deferred();
                         isLoading(false);
                         isApplied(true);
-                        getTotalsAction([], deferred);
-                        $.when(deferred).done(function() {
-                            paymentService.setPaymentMethods(
-                                paymentMethodList()
-                            );
+                        totals.isLoading(true);
+                        getPaymentInformationAction(deferred);
+                        $.when(deferred).done(function () {
+                            totals.isLoading(false);
                         });
                         messageContainer.addSuccessMessage({'message': message});
                     }
@@ -61,6 +58,7 @@ define(
             ).fail(
                 function (response) {
                     isLoading(false);
+                    totals.isLoading(false);
                     errorProcessor.process(response, messageContainer);
                 }
             );
diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartManagementTest.php
index c67470fd69ae592503f7b18dba7eee920ba133a1..a201724eaaa6824e9c0500b2108699be44e33285 100644
--- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartManagementTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartManagementTest.php
@@ -70,9 +70,9 @@ class GuestCartManagementTest extends WebapiAbstract
         $quote = $this->objectManager->create('Magento\Quote\Model\Quote')->load('test01', 'reserved_order_id');
         $cartId = $quote->getId();
         /** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */
-        $quoteIdMask = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
-            ->create('Magento\Quote\Model\QuoteIdMaskFactory')
-            ->create();
+        $quoteIdMaskFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+            ->create('Magento\Quote\Model\QuoteIdMaskFactory');
+        $quoteIdMask = $quoteIdMaskFactory->create();
         $quoteIdMask->load($cartId, 'quote_id');
         //Use masked cart Id
         $cartId = $quoteIdMask->getMaskedId();
@@ -110,6 +110,7 @@ class GuestCartManagementTest extends WebapiAbstract
         $this->assertEquals($customer->getId(), $quote->getCustomerId());
         $this->assertEquals($customer->getFirstname(), $quote->getCustomerFirstname());
         $this->assertEquals($customer->getLastname(), $quote->getCustomerLastname());
+        $this->assertNull($quoteIdMaskFactory->create()->load($cartId, 'masked_id')->getId());
     }
 
     /**