Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Implement Stripe CC and Stripe ApplePay payment methods #1983

Merged
merged 23 commits into from
Mar 30, 2020
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
55eadeb
Server side changes for payment method integrations
nerrad Mar 26, 2020
bdade01
update needed npm packages (and add some types)
nerrad Mar 26, 2020
42f1f8a
updates to contexts
nerrad Mar 26, 2020
bb67ffe
remove stepContent from payment config for payment methods
nerrad Mar 26, 2020
070023a
update payment method interface and typedefs
nerrad Mar 26, 2020
c96a16b
add apple pay and stripe cc integration and remove paypal
nerrad Mar 26, 2020
e7f3939
remove save payment checkbox from checkout block
nerrad Mar 26, 2020
28268ae
Include an id prop for tabs
nerrad Mar 26, 2020
ae5ed30
fix activePaymentMethod pass through on rendered payment method element
nerrad Mar 26, 2020
d18776b
add styles for payment method fields
nerrad Mar 26, 2020
fefa852
fix rebase conflict
nerrad Mar 26, 2020
4166ee8
do a test payment request for applePay to determine if the current br…
nerrad Mar 26, 2020
6cff2f3
don’t console.error for stripe loading.
nerrad Mar 26, 2020
a2e855e
Fix placeholder errors in the editor
nerrad Mar 26, 2020
1eaa888
improve styling and add missing validation for inline card element
nerrad Mar 28, 2020
a17f3b9
update pacakge-lock
nerrad Mar 28, 2020
a89e811
rename payment-methods-demo folder to payment-methods-extension
nerrad Mar 30, 2020
39378f9
expose checkbox control on payment method interface
nerrad Mar 30, 2020
3082d4c
export payment-methods-extension to it’s own asset build
nerrad Mar 30, 2020
e8d94fc
don’t enqueue a style that doesn’t exist
nerrad Mar 30, 2020
b461b87
add full stop to comments and remove obsolete comment blcok
nerrad Mar 30, 2020
b43e759
fix spacing
nerrad Mar 30, 2020
17ec991
switch `activeContent` to `content` for payment method registration c…
nerrad Mar 30, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions assets/css/abstracts/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ $block-container-side-padding: $block-side-ui-width + $block-padding + 2 * $bloc

// Cart block
$cart-image-width: 5rem;

// Card element widths
$card-element-small-width: 5rem;
$card-element-width: 7rem;
3 changes: 2 additions & 1 deletion assets/js/base/components/payment-methods/payment-methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const PaymentMethods = () => {
);
return paymentMethod
? cloneElement( paymentMethod, {
activePaymentMethod: paymentMethod.id,
activePaymentMethod,
...currentPaymentMethodInterface.current,
} )
: null;
Expand Down Expand Up @@ -110,6 +110,7 @@ const PaymentMethods = () => {
'Payment Methods',
'woo-gutenberg-products-block'
) }
id="wc-block-payment-methods"
>
{ getRenderedTab() }
</Tabs>
Expand Down
105 changes: 105 additions & 0 deletions assets/js/base/components/payment-methods/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
width: 50%;
> img {
width: 100%;
height: 48px;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be max-height? Are we setting an expected/standard dimensions for gateways to use?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to ensure that there's some consistency in styling here. Otherwise multiple express payment methods could risk being varying heights?

}
}
> li:nth-child(even) {
Expand All @@ -46,3 +47,107 @@
}
}
}

.wc-block-card-elements {
display: flex;
width: 100%;
}

.wc-block-gateway-container {
position: relative;
margin-bottom: $gap-large;
white-space: nowrap;

&.wc-card-number-element {
flex: auto;
}

&.wc-card-expiry-element,
&.wc-card-cvc-element {
width: $card-element-width;
margin-left: $gap-small;
}

.wc-block-gateway-input {
background-color: #fff;
padding: $gap-small $gap;
border-radius: 4px;
border: 1px solid $input-border-gray;
width: 100%;
font-size: 16px;
line-height: 22px;
font-family: inherit;
margin: 0;
box-sizing: border-box;
height: 48px;
color: $input-text-active;

&:focus {
background-color: #fff;
}
}

&:focus {
background-color: #fff;
}

label {
position: absolute;
transform: translateY(#{$gap-small});
left: 0;
top: 0;
transform-origin: top left;
font-size: 16px;
line-height: 22px;
color: $gray-50;
transition: transform 200ms ease;
margin: 0 $gap;
overflow: hidden;
text-overflow: ellipsis;
max-width: calc(100% - #{ 2 * $gap });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a double space before the 2, I think starting/ending spacing in curly braces should be removed?

Suggested change
max-width: calc(100% - #{ 2 * $gap });
max-width: calc(100% - #{2 * $gap});

I don't know why stylelint didn't catch those.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why stylelint didn't catch those.

Yup no idea.


@media screen and (prefers-reduced-motion: reduce) {
transition: none;
}
}

&.wc-inline-card-element {
label {
margin-left: $gap-largest;
}
.wc-block-gateway-input.focused.empty,
.wc-block-gateway-input:not(.empty) {
& + label {
margin-left: $gap;
transform: translateY(#{$gap-smallest}) scale(0.75);
}
}
& + .wc-block-form-input-validation-error {
position: static;
margin-top: -$gap-large;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this working? I've had issues with this before (values became positive) and found a SO thread saying interpolation should be used. -#{$gap-large} I didn't test, just stood out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working for me, maybe the webpack plugin handles it better than it used to?

}
}

.wc-block-gateway-input.focused.empty,
.wc-block-gateway-input:not(.empty) {
padding: $gap-large $gap $gap-smallest;
& + label {
transform: translateY(#{$gap-smallest}) scale(0.75);
}
}

.wc-block-gateway-input.has-error {
border-color: $error-red;
&:focus {
outline-color: $error-red;
}
}

.wc-block-gateway-input.has-error + label {
color: $error-red;
}
}

.wc-blocks-credit-card-images {
padding-top: $gap-small;
}
6 changes: 5 additions & 1 deletion assets/js/base/components/tabs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const Tabs = ( {
instanceId,
ariaLabel = __( 'Tabbed Content', 'woo-gutenberg-products-block' ),
children,
id,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we generate a default fallback for ID like on selectedId.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly just an optional id for the entire tabs container. There's an issue (#1474) for reviewing/improving/replacing this tabs component I added, when we get to that at some point, we can use the opportunity to review whether this id is even needed (or improve).

} ) => {
const [ selected, setSelected ] = useState(
initialTabName || ( tabs.length > 0 ? tabs[ 0 ].name : '' )
Expand All @@ -38,7 +39,10 @@ const Tabs = ( {
}
const selectedId = `${ instanceId }-${ selectedTab.name }`;
return (
<div className={ classnames( 'wc-block-components-tabs', className ) }>
<div
className={ classnames( 'wc-block-components-tabs', className ) }
id={ id }
>
<div
role="tablist"
aria-label={ ariaLabel }
Expand Down
18 changes: 12 additions & 6 deletions assets/js/base/context/cart-checkout/checkout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,18 @@ export const CheckoutProvider = ( {
useEffect( () => {
currentObservers.current = observers;
}, [ observers ] );
const onCheckoutCompleteSuccess = emitterSubscribers( subscriber )
.onCheckoutCompleteSuccess;
const onCheckoutCompleteError = emitterSubscribers( subscriber )
.onCheckoutCompleteError;
const onCheckoutProcessing = emitterSubscribers( subscriber )
.onCheckoutProcessing;
const onCheckoutCompleteSuccess = useMemo(
() => emitterSubscribers( subscriber ).onCheckoutCompleteSuccess,
[]
);
const onCheckoutCompleteError = useMemo(
() => emitterSubscribers( subscriber ).onCheckoutCompleteError,
[]
);
const onCheckoutProcessing = useMemo(
() => emitterSubscribers( subscriber ).onCheckoutProcessing,
[]
);

/**
* @type {CheckoutDispatchActions}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export const PaymentMethodDataProvider = ( {
hasFailed: paymentStatus === FAILED,
isSuccessful: paymentStatus === SUCCESS,
};

/**
* @type {PaymentMethodDataContext}
*/
Expand Down
2 changes: 1 addition & 1 deletion assets/js/base/context/cart-checkout/validation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const ValidationContext = createContext( {
setValidationErrors: ( errors ) => void errors,
clearValidationError: ( property ) => void property,
clearAllValidationErrors: () => void null,
getValidationErrorId: ( inputId ) => void inputId,
getValidationErrorId: ( inputId ) => inputId,
} );

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { __ } from '@wordpress/i18n';
import { getCurrencyFromPriceResponse } from '@woocommerce/base-utils';
import { useEffect, useRef } from '@wordpress/element';
import { DISPLAY_CART_PRICES_INCLUDING_TAX } from '@woocommerce/block-settings';
import { ValidationInputError } from '@woocommerce/base-components/validation';
import CheckboxControl from '@woocommerce/base-components/checkbox-control';

/**
* Internal dependencies
Expand Down Expand Up @@ -178,6 +180,10 @@ export const usePaymentMethodInterface = () => {
onShippingRateSelectSuccess,
onShippingRateSelectFail,
},
components: {
ValidationInputError,
CheckboxControl,
},
onSubmit,
activePaymentMethod,
setActivePaymentMethod,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export default class PaymentMethodConfig {
assertConfigHasProperties( config, [
'id',
'label',
'stepContent',
'ariaLabel',
'activeContent',
'edit',
Expand All @@ -29,7 +28,6 @@ export default class PaymentMethodConfig {
throw new Error( 'The id for the payment method must be a string' );
}
assertValidElement( config.label, 'label' );
assertValidElement( config.stepContent, 'stepContent' );
assertValidElement( config.activeContent, 'activeContent' );
assertValidElement( config.edit, 'edit' );
if ( typeof config.ariaLabel !== 'string' ) {
Expand Down
14 changes: 0 additions & 14 deletions assets/js/blocks/cart-checkout/checkout/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import withScrollToTop from '@woocommerce/base-hocs/with-scroll-to-top';
*/
import CheckoutSidebar from './sidebar/index.js';
import './style.scss';
import '../../../payment-methods-demo';

const Block = ( { isEditor = false, ...props } ) => (
<CheckoutProvider isEditor={ isEditor }>
Expand Down Expand Up @@ -75,7 +74,6 @@ const Checkout = ( {
} = useValidationContext();

const [ contactFields, setContactFields ] = useState( {} );
const [ shouldSavePayment, setShouldSavePayment ] = useState( true );
const [ shippingAsBilling, setShippingAsBilling ] = useState( true );

const validateSubmit = () => {
Expand Down Expand Up @@ -335,18 +333,6 @@ const Checkout = ( {
) }
>
<PaymentMethods />
{ /*@todo this should be something the payment method controls*/ }
<CheckboxControl
className="wc-block-checkout__save-card-info"
label={ __(
'Save payment information to my account for future purchases.',
'woo-gutenberg-products-block'
) }
checked={ shouldSavePayment }
onChange={ () =>
setShouldSavePayment( ! shouldSavePayment )
}
/>
</FormStep>
<div className="wc-block-checkout__actions">
{ attributes.showReturnToCart && (
Expand Down
Loading