From c2b30ab3a9159914d427491eed3e2f3b69545724 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 11 Apr 2017 14:28:49 +0300 Subject: [PATCH 01/22] Check if apple pay is available --- demo/peacock/src/modules/checkout.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demo/peacock/src/modules/checkout.js b/demo/peacock/src/modules/checkout.js index 97044e89c5..1c75e961c8 100644 --- a/demo/peacock/src/modules/checkout.js +++ b/demo/peacock/src/modules/checkout.js @@ -32,6 +32,8 @@ export type CheckoutState = { billingAddress: ShippingAddress, }; +export const checkApplePay = () => foxApi.applePay.available(); + export const selectCreditCard = createAction('CHECKOUT_SET_CREDIT_CARD'); export const setEditStage = createAction('CHECKOUT_SET_EDIT_STAGE'); export const setBillingData = createAction('CHECKOUT_SET_BILLING_DATA', (key, value) => [key, value]); From 980ebb32cb29e60060b3ab30c152ef8deec67711 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 11 Apr 2017 14:29:17 +0300 Subject: [PATCH 02/22] Add the apple pay button --- demo/peacock/src/pages/checkout/checkout.css | 19 ++++++++++++++++++- demo/peacock/src/pages/checkout/checkout.jsx | 14 +++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/demo/peacock/src/pages/checkout/checkout.css b/demo/peacock/src/pages/checkout/checkout.css index 9cc23a91a5..bd90176463 100644 --- a/demo/peacock/src/pages/checkout/checkout.css +++ b/demo/peacock/src/pages/checkout/checkout.css @@ -13,6 +13,19 @@ } } +.apple-pay { + background-color: black; + background-image: -webkit-named-image(apple-pay-logo-white); + background-size: cover; + background-origin: content-box; + background-repeat: no-repeat; + width: 100%; + height: 44px; + border-radius: 0; + margin-top: 20px; + padding: 10px 0; +} + .wrapper { display: flex; height: 100vh; @@ -143,7 +156,6 @@ .place-order-block { margin: 20px 0; - height: 58px; } .place-order-button { @@ -151,6 +163,11 @@ height: 58px; } + .apple-pay { + border-radius: 4px; + height: 58px; + } + .order-summary { margin-top: 40px; } diff --git a/demo/peacock/src/pages/checkout/checkout.jsx b/demo/peacock/src/pages/checkout/checkout.jsx index 5a65be6d4c..9cbcb73a2a 100644 --- a/demo/peacock/src/pages/checkout/checkout.jsx +++ b/demo/peacock/src/pages/checkout/checkout.jsx @@ -31,7 +31,8 @@ import type { CheckoutActions } from './types'; import type { AsyncStatus } from 'types/async-actions'; // actions -import * as actions from 'modules/checkout'; +import * as actions from 'modules/checkout'; +import { checkApplePay } from 'modules/checkout'; import { EditStages } from 'modules/checkout'; import { fetch as fetchCart, hideCart } from 'modules/cart'; import { fetchUser } from 'modules/auth'; @@ -181,6 +182,16 @@ class Checkout extends Component { return emailIsSet(user); } + get applePayButton() { + if (!checkApplePay()) return null; + + return ( + + {this.applePayButton} ); From 95308249d56c955e3788a019c25cabd19873df73 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 12 Apr 2017 17:43:16 +0300 Subject: [PATCH 03/22] Add the ability to start the payment process + refactor --- demo/peacock/src/modules/checkout.js | 40 +++++++++++++++++++- demo/peacock/src/pages/checkout/checkout.jsx | 24 +++++++++++- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/demo/peacock/src/modules/checkout.js b/demo/peacock/src/modules/checkout.js index 1c75e961c8..b6c8595ac1 100644 --- a/demo/peacock/src/modules/checkout.js +++ b/demo/peacock/src/modules/checkout.js @@ -32,8 +32,6 @@ export type CheckoutState = { billingAddress: ShippingAddress, }; -export const checkApplePay = () => foxApi.applePay.available(); - export const selectCreditCard = createAction('CHECKOUT_SET_CREDIT_CARD'); export const setEditStage = createAction('CHECKOUT_SET_EDIT_STAGE'); export const setBillingData = createAction('CHECKOUT_SET_BILLING_DATA', (key, value) => [key, value]); @@ -43,6 +41,7 @@ export const setBillingAddress = createAction('CHECKOUT_SET_BILLING_ADDRESS'); export const toggleShippingModal = createAction('TOGGLE_SHIPPING_MODAL'); export const toggleDeliveryModal = createAction('TOGGLE_DELIVERY_MODAL'); export const togglePaymentModal = createAction('TOGGLE_PAYMENT_MODAL'); +const applePayAvailable = createAction('APPLE_PAY_AVAILABLE'); const markAddressAsDeleted = createAction('CHECKOUT_MARK_ADDRESS_AS_DELETED'); const markAddressAsRestored = createAction( 'CHECKOUT_MARK_ADDRESS_AS_RESTORED', @@ -107,6 +106,36 @@ function addressToPayload(address) { return payload; } +const _checkApplePay = createAsyncActions( + 'checkApplePay', + function() { + const { dispatch } = this; + + return foxApi.applePay.available() + .then((resp) => { + dispatch(applePayAvailable(resp)); + }); + } +); + +export const checkApplePay = _checkApplePay.perform; + +const _beginApplePay = createAsyncActions( + 'beginApplePay', + function(payment) { + return foxApi.applePay.beginApplePay(payment) + .then(() => { + console.log('payment is successfull, from checkout.js'); + }) + .catch((err) => { + console.log('error occurred in checkout.js, _beginApplePay'); + throw new Error(err); + }); + } +); + +export const beginApplePay = _beginApplePay.perform; + const _removeShippingMethod = createAsyncActions( 'removeShippingMethod', function() { @@ -465,6 +494,7 @@ const initialState: CheckoutState = { shippingModalVisible: false, deliveryModalVisible: false, paymentModalVisible: false, + applePayAvailable: false, }; function sortAddresses(addresses: Array
): Array
{ @@ -505,6 +535,12 @@ const reducer = createReducer({ billingData, }; }, + [applePayAvailable]: (state, available) => { + return { + ...state, + applePayAvailable: available, + }; + }, [shippingMethodsActions.succeeded]: (state, list) => { return { ...state, diff --git a/demo/peacock/src/pages/checkout/checkout.jsx b/demo/peacock/src/pages/checkout/checkout.jsx index 9cbcb73a2a..8a8fe9679a 100644 --- a/demo/peacock/src/pages/checkout/checkout.jsx +++ b/demo/peacock/src/pages/checkout/checkout.jsx @@ -32,7 +32,6 @@ import type { AsyncStatus } from 'types/async-actions'; // actions import * as actions from 'modules/checkout'; -import { checkApplePay } from 'modules/checkout'; import { EditStages } from 'modules/checkout'; import { fetch as fetchCart, hideCart } from 'modules/cart'; import { fetchUser } from 'modules/auth'; @@ -74,6 +73,8 @@ class Checkout extends Component { tracking.checkoutStart(cart.lineItems); }); + this.props.checkApplePay(); + if (!this.isEmailSetForCheckout()) { this.props.fetchUser(); } @@ -182,12 +183,31 @@ class Checkout extends Component { return emailIsSet(user); } + @autobind beginApplePay() { + console.log('starting the apple pay inside the checkout.jsx'); + const total = this.props.cart.totals.total; + console.log('the total from the cart -> ', total); + const amount = (parseFloat(total)/100).toFixed(2); + console.log('amount -> ', amount); + const paymentRequest = { + countryCode: 'US', + currencyCode: 'USD', + total: { + label: 'Stripe.com', + amount: amount.toString(), + }, + }; + console.log('payment request obj -> ', paymentRequest); + this.props.beginApplePay(paymentRequest); + } + get applePayButton() { - if (!checkApplePay()) return null; + if (!this.props.applePayAvailable) return null; return ( + {this.applePayButton} @@ -189,8 +242,16 @@ class Cart extends Component { } } -const mapStateToProps = state => ({ ...state.cart, ...state.auth }); +const mapStateToProps = (state) => { + return { + ...state.cart, + ...state.auth, + applePayAvailable: _.get(state.checkout, 'applePayAvailable', false), + }; +}; export default connect(mapStateToProps, { ...actions, + checkApplePay, + beginApplePay, })(localized(Cart)); diff --git a/demo/peacock/src/pages/checkout/checkout.css b/demo/peacock/src/pages/checkout/checkout.css index bd90176463..b29116ee26 100644 --- a/demo/peacock/src/pages/checkout/checkout.css +++ b/demo/peacock/src/pages/checkout/checkout.css @@ -13,19 +13,6 @@ } } -.apple-pay { - background-color: black; - background-image: -webkit-named-image(apple-pay-logo-white); - background-size: cover; - background-origin: content-box; - background-repeat: no-repeat; - width: 100%; - height: 44px; - border-radius: 0; - margin-top: 20px; - padding: 10px 0; -} - .wrapper { display: flex; height: 100vh; diff --git a/demo/peacock/src/pages/checkout/checkout.jsx b/demo/peacock/src/pages/checkout/checkout.jsx index 8a8fe9679a..3f80d68c82 100644 --- a/demo/peacock/src/pages/checkout/checkout.jsx +++ b/demo/peacock/src/pages/checkout/checkout.jsx @@ -73,8 +73,6 @@ class Checkout extends Component { tracking.checkoutStart(cart.lineItems); }); - this.props.checkApplePay(); - if (!this.isEmailSetForCheckout()) { this.props.fetchUser(); } @@ -172,7 +170,6 @@ class Checkout extends Component { checkout() { return this.props.checkout() .then(() => { - this.props.setEditStage(EditStages.FINISHED); browserHistory.push('/checkout/done'); }); } @@ -183,35 +180,6 @@ class Checkout extends Component { return emailIsSet(user); } - @autobind beginApplePay() { - console.log('starting the apple pay inside the checkout.jsx'); - const total = this.props.cart.totals.total; - console.log('the total from the cart -> ', total); - const amount = (parseFloat(total)/100).toFixed(2); - console.log('amount -> ', amount); - const paymentRequest = { - countryCode: 'US', - currencyCode: 'USD', - total: { - label: 'Stripe.com', - amount: amount.toString(), - }, - }; - console.log('payment request obj -> ', paymentRequest); - this.props.beginApplePay(paymentRequest); - } - - get applePayButton() { - if (!this.props.applePayAvailable) return null; - - return ( - - {this.applePayButton} ); From 118fb77af749b26cc75e2666b48177d18d60f97d Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 18 May 2017 14:53:37 +0300 Subject: [PATCH 05/22] Clean up checkout --- demo/peacock/src/pages/checkout/checkout.css | 6 +----- demo/peacock/src/pages/checkout/checkout.jsx | 17 ++++++++--------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/demo/peacock/src/pages/checkout/checkout.css b/demo/peacock/src/pages/checkout/checkout.css index b29116ee26..9cc23a91a5 100644 --- a/demo/peacock/src/pages/checkout/checkout.css +++ b/demo/peacock/src/pages/checkout/checkout.css @@ -143,14 +143,10 @@ .place-order-block { margin: 20px 0; - } - - .place-order-button { - border-radius: 4px; height: 58px; } - .apple-pay { + .place-order-button { border-radius: 4px; height: 58px; } diff --git a/demo/peacock/src/pages/checkout/checkout.jsx b/demo/peacock/src/pages/checkout/checkout.jsx index 3f80d68c82..9a24fc6d1e 100644 --- a/demo/peacock/src/pages/checkout/checkout.jsx +++ b/demo/peacock/src/pages/checkout/checkout.jsx @@ -11,6 +11,12 @@ import * as tracking from 'lib/analytics'; import { emailIsSet, isGuest } from 'paragons/auth'; import classNames from 'classnames'; +// actions +import * as actions from 'modules/checkout'; +import { EditStages } from 'modules/checkout'; +import { fetch as fetchCart, hideCart } from 'modules/cart'; +import { fetchUser } from 'modules/auth'; + // components import Shipping from './shipping/shipping'; import Delivery from './delivery/delivery'; @@ -22,20 +28,13 @@ import Loader from 'ui/loader'; import OrderTotals from 'components/order-summary/totals'; import Button from 'ui/buttons'; -// styles -import styles from './checkout.css'; - // types import type { CheckoutState, EditStage } from 'modules/checkout'; import type { CheckoutActions } from './types'; import type { AsyncStatus } from 'types/async-actions'; -// actions -import * as actions from 'modules/checkout'; -import { EditStages } from 'modules/checkout'; -import { fetch as fetchCart, hideCart } from 'modules/cart'; -import { fetchUser } from 'modules/auth'; - +// styles +import styles from './checkout.css'; type Props = CheckoutState & CheckoutActions & { setEditStage: (stage: EditStage) => Object, From e9b1f10c93f6a897082dce5833f7b1349f1e6d08 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 18 May 2017 20:11:56 +0300 Subject: [PATCH 06/22] Fix the margins --- demo/peacock/src/components/cart/cart.css | 14 +++++++++++++- demo/peacock/src/components/cart/cart.jsx | 4 +++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/demo/peacock/src/components/cart/cart.css b/demo/peacock/src/components/cart/cart.css index 1d87db768e..d502d1cc59 100644 --- a/demo/peacock/src/components/cart/cart.css +++ b/demo/peacock/src/components/cart/cart.css @@ -137,14 +137,26 @@ } @media (--large) { + .cart-content { + height: calc(100% - 130px); + + &.with-apple-pay { + height: calc(100% - 206px); + } + } + .cart-footer { + height: 80px; width: 100%; position: absolute; bottom: 0; display: flex; align-items: center; - justify-content: flex-end; + justify-content: flex-start; flex-direction: column; + &.with-apple-pay { + height: 156px; + } } .checkout-button { diff --git a/demo/peacock/src/components/cart/cart.jsx b/demo/peacock/src/components/cart/cart.jsx index 05a56ef276..171cd9bc0d 100644 --- a/demo/peacock/src/components/cart/cart.jsx +++ b/demo/peacock/src/components/cart/cart.jsx @@ -144,7 +144,9 @@ class Cart extends Component { @autobind beginApplePay() { console.log('starting the apple pay inside the checkout.jsx'); - const total = this.props.cart.totals.total; + const total = this.props.totals.total; + console.log('total -> ', total); + console.log('subTotal -> ', this.props.totals.subTotal); console.log('the total from the cart -> ', total); const amount = (parseFloat(total)/100).toFixed(2); console.log('amount -> ', amount); From 1aa713bc5c238c57a43bfac72fddd4d4df20998a Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 25 May 2017 20:17:42 +0300 Subject: [PATCH 07/22] Add line items to apple pay request --- demo/peacock/src/components/cart/cart.jsx | 11 ++++++++--- demo/peacock/src/modules/checkout.js | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/demo/peacock/src/components/cart/cart.jsx b/demo/peacock/src/components/cart/cart.jsx index 171cd9bc0d..b09e97e49d 100644 --- a/demo/peacock/src/components/cart/cart.jsx +++ b/demo/peacock/src/components/cart/cart.jsx @@ -144,10 +144,9 @@ class Cart extends Component { @autobind beginApplePay() { console.log('starting the apple pay inside the checkout.jsx'); - const total = this.props.totals.total; + const { total, taxes, adjustments } = this.props.totals; console.log('total -> ', total); console.log('subTotal -> ', this.props.totals.subTotal); - console.log('the total from the cart -> ', total); const amount = (parseFloat(total)/100).toFixed(2); console.log('amount -> ', amount); const paymentRequest = { @@ -167,8 +166,14 @@ class Cart extends Component { 'name', ], }; + + const lineItems = { + taxes: taxes, + promotion: adjustments, + }; console.log('payment request obj -> ', paymentRequest); - this.props.beginApplePay(paymentRequest).then(() => { + console.log('lineItems -> ', lineItems); + this.props.beginApplePay(paymentRequest, lineItems).then(() => { console.log('redirecting to the order confirmation page...'); browserHistory.push('/checkout/done') }); diff --git a/demo/peacock/src/modules/checkout.js b/demo/peacock/src/modules/checkout.js index b6c8595ac1..8b1ad1ca23 100644 --- a/demo/peacock/src/modules/checkout.js +++ b/demo/peacock/src/modules/checkout.js @@ -122,8 +122,8 @@ export const checkApplePay = _checkApplePay.perform; const _beginApplePay = createAsyncActions( 'beginApplePay', - function(payment) { - return foxApi.applePay.beginApplePay(payment) + function(paymentRequest, lineItems) { + return foxApi.applePay.beginApplePay(paymentRequest, lineItems) .then(() => { console.log('payment is successfull, from checkout.js'); }) From c122de96d85b3581d70f4e01faf4572321bbdeed Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 26 May 2017 17:03:21 +0300 Subject: [PATCH 08/22] Make user log in or enter an email before using apple pay --- demo/peacock/src/components/cart/cart.jsx | 42 +++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/demo/peacock/src/components/cart/cart.jsx b/demo/peacock/src/components/cart/cart.jsx index b09e97e49d..5bd992bf3a 100644 --- a/demo/peacock/src/components/cart/cart.jsx +++ b/demo/peacock/src/components/cart/cart.jsx @@ -9,6 +9,7 @@ import { browserHistory } from 'lib/history'; import { autobind } from 'core-decorators'; import * as tracking from 'lib/analytics'; import localized from 'lib/i18n'; +import { emailIsSet } from 'paragons/auth'; // actions import * as actions from 'modules/cart'; @@ -23,6 +24,7 @@ import { skuIdentity } from '@foxcomm/wings/lib/paragons/sku'; import { parseError } from '@foxcomm/api-js'; import Overlay from 'ui/overlay/overlay'; import ActionLink from 'ui/action-link/action-link'; +import GuestAuth from 'pages/checkout/guest-auth/guest-auth'; // types import type { Totals } from 'modules/cart'; @@ -45,17 +47,19 @@ type Props = { t: any, applePayAvailable: boolean, checkApplePay: Function, // signature + location: Object, }; type State = { errors?: Array, + guestAuth: boolean, }; class Cart extends Component { props: Props; state: State = { - + guestAuth: false, }; componentDidMount() { @@ -92,6 +96,12 @@ class Cart extends Component { }); } + @autobind + isEmailSetForCheckout() { + const user = _.get(this.props, 'user', null); + return emailIsSet(user); + } + get lineItems() { if (_.isEmpty(this.props.skus)) { return ( @@ -179,17 +189,43 @@ class Cart extends Component { }); } + @autobind + checkAuth() { + const emailSet = this.isEmailSetForCheckout(); + + if (emailSet) { + this.setState({ guestAuth: false }); + this.beginApplePay(); + } else { + this.setState({ guestAuth: true }); + } + } + get applePayButton() { if (!this.props.applePayAvailable) return null; + const disabled = _.size(this.props.skus) < 1; return (