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

Conversation

nerrad
Copy link
Contributor

@nerrad nerrad commented Mar 17, 2020

Fixes: #1471

This pull implements the Stripe ApplePay and Stripe CC payment methods in the Checkout block and gets us one step closer to having the blocks fully functional. There are still some todos after merging this pull but I'm submitting it for review now because:

  • The payment methods have their logic pretty much wired up.
  • UI/UX behaviour is functionally complete.
  • Existing behaviour for the checkout block is not compromised, so we can merge and still test while developing.
  • The work is at a point where others can jump in to fine tune and polish as we complete remaining tasks for the checkout block. Delaying merge until that's all complete makes it more difficult to accomplish those remaining tasks.
  • This pull is already large. I'm wary of doing all the work needed in this pull making it that much harder to review (it's already larger than I'd like).

Incomplete tasks:

This pull has some todos that are not complete. Once this pull is merged, I will go through this list (and inline todos) and determine what needs documented as issues.

Complete tasks

  • UI/UX for payment methods are complete and functional (up to the point of actual processing).
  • stripe.js is wired up and hooked in to the current event emitters.
  • Payment method api and interface has been fine-tuned to expose needed elements to the payment methods.
  • When express payment methods are initialized, if there are no payment methods reporting that they can be used for payment on the frontend, don't show the express payments section.
  • Express payment methods will show previews in the editor for the buttons.
  • The payment method api now receives an edit node so payment methods can indicate what gets shown when in the editor view.
  • Numerous type-defs have been created for Stripe (but there may need to be some fixes in followups).
  • removed demo paypal logic.
  • Add actions server side to blocks that payment methods can hook into.
  • Add a Stripe php class server side that is used for the Stripe payment method integration server side.

Screenshots

Here's some screenshots/gifs to give an overview of completed things (and to verify I tested what I could 😄 )

When there are no express payment methods that can pay (in this case Apple Pay is configured but I'm viewing checkout in the frontend in Chrome)

Image 2020-03-26 at 4 07 17 PM

Field behaviour for Stripe Credit Card
Screen Recording 2020-03-26 at 04 07 PM

Example of inline validation errors

Image 2020-03-26 at 4 08 13 PM

Apple Pay in Safari on desktop

Image 2020-03-26 at 4 31 39 PM

Apple Pay, Safari desktop, browser payment interface opened.

Image 2020-03-26 at 5 05 02 PM

Apple Pay, Safari - iPhone X
Image 2020-03-26 at 4 35 20 PM

ApplePay, Safari - iPhone X - browser payment interface opened.

Image 2020-03-26 at 5 05 57 PM

Testing

The following are the important things you are testing:

  • When viewing checkout block in the editor or the frontend, and when interacting with existing ui, there are no console errors, and the block itself is functional.
  • When payment methods are configured, they show up in the block as expected in the frontend and editor (please do ask if behaviour is expected or not if unsure).
  • ApplePay button should show up when the payment method is configured and you are testing on a publicly accessible website with ssl setup. Clicking the button should open the browser payment request interface for ApplePay and have the correct totals. Behaviour after completing payment is not wired up or supported yet, so we're not testing that.
  • Stripe CC can be tested in local dev environment. Inputs should respond and update as expected for values entered. Submitting the checkout after entering values in the payment method inputs are not expected to work yet as that has not been wired up to the server.

To setup for testing

  • you will need Stripe Payment extension installed. You can find setup information etc in the fieldguide article: PCYsg-85x-p2 - In this article you are only concerned about Stripe CC and ApplePay instructions.
  • For Apple Pay, you must test on a publicly accessible site that has an SSL cert (I used Atomic Ephemeral sites). Remember, Apple Pay only works in Safari and on supported devices (you wouldn't believe how many times I forgot this)!
  • For easier installation, I used the package-plugin npm script included in our build tools.

@nerrad nerrad self-assigned this Mar 17, 2020
@nerrad nerrad added focus: components Work that introduces new or updates existing components. category: extensibility Work involving adding or updating extensibility. Useful to combine with other scopes impacted. labels Mar 17, 2020
@nerrad nerrad added this to the Future Release milestone Mar 17, 2020
@nerrad nerrad force-pushed the add/implement-stripe-apple-pay branch from d26889c to 728cdf3 Compare March 18, 2020 14:17
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch from 9e90ae5 to bd800ce Compare March 18, 2020 14:32
@nerrad nerrad force-pushed the add/implement-stripe-apple-pay branch from 728cdf3 to a27467a Compare March 19, 2020 08:56
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch from bd800ce to e0ca954 Compare March 20, 2020 10:23
@nerrad nerrad force-pushed the add/implement-stripe-apple-pay branch from a27467a to a44f244 Compare March 20, 2020 14:03
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch from e0ca954 to 4eeea99 Compare March 20, 2020 14:06
@nerrad nerrad force-pushed the add/implement-stripe-apple-pay branch from a44f244 to 5a43c8f Compare March 20, 2020 16:50
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch from 4eeea99 to b37a7a9 Compare March 20, 2020 16:52
@nerrad nerrad force-pushed the add/implement-stripe-apple-pay branch from 5a43c8f to ffcabaf Compare March 21, 2020 16:11
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch from 9a055a5 to 61cc733 Compare March 21, 2020 16:12
@github-actions
Copy link
Contributor

github-actions bot commented Mar 21, 2020

Size Change: -105 kB (4%)

Total Size: 2.15 MB

Filename Size Change
build/active-filters.js 8.29 kB -3 B (0%)
build/all-products.js 66.2 kB +3 B (0%)
build/all-reviews.js 11 kB +3 B (0%)
build/attribute-filter-frontend.js 17 kB -4 B (0%)
build/cart-frontend.js 158 kB +1 B
build/cart.js 75 kB +1 B
build/checkout-frontend.js 163 kB -107 kB (65%) 🏆
build/checkout.js 76.5 kB -107 kB (140%) 🏆
build/featured-category.js 146 kB -1 B
build/featured-product.js 59.4 kB +1 B
build/price-filter-frontend.js 14.1 kB +4 B (0%)
build/price-filter.js 10.4 kB +2 B (0%)
build/product-best-sellers.js 7.62 kB -2 B (0%)
build/product-category.js 8.53 kB -2 B (0%)
build/product-new.js 7.78 kB -1 B
build/product-on-sale.js 8.18 kB -2 B (0%)
build/product-tag.js 6.68 kB -1 B
build/product-top-rated.js 7.75 kB -3 B (0%)
build/reviews-by-category.js 13 kB +2 B (0%)
build/reviews-by-product.js 14.5 kB +3 B (0%)
build/reviews-frontend.js 9.09 kB -1 B
build/style-rtl.css 14.3 kB +266 B (1%)
build/style.css 14.3 kB +265 B (1%)
build/vendors.js 367 kB +7 B (0%)
build/wc-blocks-registry.js 1.51 kB -17 B (1%)
build/wc-payment-method-extensions.js 109 kB +109 kB (100%) 🆘
ℹ️ View Unchanged
Filename Size Change
build/active-filters-frontend.js 7.53 kB 0 B
build/all-products-frontend.js 17.3 kB 0 B
build/all-reviews-legacy.js 10.8 kB 0 B
build/attribute-filter.js 11.8 kB 0 B
build/block-error-boundary-legacy.js 774 B 0 B
build/block-error-boundary.js 774 B 0 B
build/blocks-legacy.js 2.92 kB 0 B
build/blocks.js 2.92 kB 0 B
build/checkbox-control-style-legacy.js 779 B 0 B
build/checkbox-control-style.js 781 B 0 B
build/custom-select-control-style-legacy.js 782 B 0 B
build/custom-select-control-style.js 783 B 0 B
build/editor-legacy-rtl.css 12.6 kB 0 B
build/editor-legacy.css 12.6 kB 0 B
build/editor-rtl.css 13.5 kB 0 B
build/editor.css 13.5 kB 0 B
build/featured-category-legacy.js 146 kB 0 B
build/featured-product-legacy.js 59.5 kB 0 B
build/handpicked-products-legacy.js 7.31 kB 0 B
build/handpicked-products.js 7.51 kB 0 B
build/panel-style-legacy.js 773 B 0 B
build/panel-style.js 773 B 0 B
build/product-best-sellers-legacy.js 7.41 kB 0 B
build/product-categories-legacy.js 3.2 kB 0 B
build/product-categories.js 3.19 kB 0 B
build/product-category-legacy.js 8.32 kB 0 B
build/product-new-legacy.js 7.58 kB 0 B
build/product-on-sale-legacy.js 7.92 kB 0 B
build/product-search-legacy.js 3.64 kB 0 B
build/product-search.js 3.86 kB 0 B
build/product-tag-legacy.js 6.48 kB 0 B
build/product-top-rated-legacy.js 7.55 kB 0 B
build/products-by-attribute-legacy.js 8.47 kB 0 B
build/products-by-attribute.js 8.68 kB 0 B
build/reviews-by-category-legacy.js 12.7 kB 0 B
build/reviews-by-product-legacy.js 14.2 kB 0 B
build/reviews-frontend-legacy.js 8.4 kB 0 B
build/snackbar-notice-style-legacy.js 778 B 0 B
build/snackbar-notice-style.js 778 B 0 B
build/spinner-style-legacy.js 772 B 0 B
build/spinner-style.js 772 B 0 B
build/style-legacy-rtl.css 3.68 kB 0 B
build/style-legacy.css 3.68 kB 0 B
build/vendors-legacy.js 280 kB 0 B
build/vendors-style-legacy-rtl.css 1.97 kB 0 B
build/vendors-style-legacy.css 1.97 kB 0 B
build/vendors-style-legacy.js 108 B 0 B
build/vendors-style-rtl.css 1.97 kB 0 B
build/vendors-style.css 1.97 kB 0 B
build/vendors-style.js 109 B 0 B
build/wc-blocks-data.js 6.64 kB 0 B
build/wc-settings.js 2.14 kB 0 B

compressed-size-action

@nerrad nerrad force-pushed the add/implement-stripe-apple-pay branch from ffcabaf to a1ca8b3 Compare March 23, 2020 09:50
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch from 61cc733 to 5fbb2b2 Compare March 23, 2020 09:51
@nerrad nerrad force-pushed the add/implement-stripe-apple-pay branch from a1ca8b3 to 5206f57 Compare March 23, 2020 13:36
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch from 5fbb2b2 to bc2fb74 Compare March 23, 2020 13:50
@nerrad nerrad force-pushed the add/implement-stripe-apple-pay branch from 5206f57 to 3abbda1 Compare March 23, 2020 18:39
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch 2 times, most recently from 278d58d to 5cc5b43 Compare March 23, 2020 21:10
nerrad added 5 commits March 27, 2020 17:00
If payment methods use these classes for their fields then the styles will get applied. It _could_ allow for consistent styling, we may have to provide design documentation for this?

These are styles in cases where payment methods have to use elements provided by the gateway (eg. Stripe elements). In future iterations we could look at providing components to payment methods to use (if they aren’t restricted by the gateway).
@nerrad nerrad force-pushed the add/stripe-cc-payment-method branch from 44ca2fe to a2e855e Compare March 27, 2020 21:01
@nerrad
Copy link
Contributor Author

nerrad commented Mar 28, 2020

@haszari The issues you were experiencing were due to the production build being broken (I'm assuming that's what you were testing with). The reason why I didn't see those issues is because I build my plugin zip based on the dev build (so I could see error stacks). It turns out that production was broken in master (not introduced by this branch) and thanks to help from @senadir , fixed in #2042. After #2042 was merged into master, I rebased this branch on top of it, so this should be good to go for testing again.

@nerrad
Copy link
Contributor Author

nerrad commented Mar 28, 2020

@senadir regarding your testing (thanks for the notes!). I'm noting what I experienced when trying to reproduce. I'm thinking these can be handled in followups (those more skilled with css can tackle them?)

tabbing between inputs doesn’t focus them, so I can’t write until I click on the the input to write

It wasn't clear what browser this was happening for you, so I tested Chrome, Safari and Firefox. The only browser I could reproduce this in was Safari. Not sure yet how we'll fix this for Safari.

after writing and deleting, we end up with double placeholder + label, seems to only happen for the first two inputs.

The only browser I could reproduce this in was Firefox and even then, I can't reproduce reliably, sometimes it happens, other times it doesn't (no matter how I try to select and delete).

I'm not sure if it also covers what happen when you click "Place order" it’s not working for me well
TypeError: undefined is not an object (evaluating 'stripe.createSource')

Logic handling when the button clicked is not expected to be functional in this pull, I'd planned on doing that as a followup.

@haszari
Copy link
Member

haszari commented Mar 29, 2020

@haszari The issues you were experiencing were due to the production build being broken (I'm assuming that's what you were testing with).

@nerrad I was testing with a debug build this time. I think all the issues I noted were minor style fixes for Twenty Twenty - we can follow up separately.

@@ -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?

}
& + .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?

@@ -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).

} from '../../stripe-utils';

/**
* External dependencies
Copy link
Member

Choose a reason for hiding this comment

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

I've noticed in recent files you've worked on you've started defining internal before external - is there a reason for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ha! I always get mixed up and go with whatever I remember doing last. It didn't even occur to me I was doing it wrong. If the convention is external first (which makes sense) I should definitely be consistent with that. I created an issue (#2052)

/**
* @type {[ StripePaymentRequest|null, function( StripePaymentRequest ):StripePaymentRequest|null]}
*/
// @ts-ignore
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 temporary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. I have a personal todo (not an issue) to review all @ts-ignore usages and see about fixing. I just don't want to waste time on fixing things that is because I can't figure out how to properly document a particular type.

{ __( 'Credit/Debit Card', 'woo-gutenberg-products-block' ) }
</strong>
),
activeContent: <StripeCreditCard />,
Copy link
Member

Choose a reason for hiding this comment

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

I think content would be fine for naming - I think you used active because it's a tab, but I don't think thats important when it comes to naming things in the common API.

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 didn't just use activeContent because it's in a tab. I used it because it's the component to render when the payment method is selected (and thus made active). However, I do realize that we could probably just get away with content here since there is no other "content" type (other than label which is already distinctive). I'll change.

),
activeContent: <StripeCreditCard />,
edit: <EditPlaceHolder />,
canMakePayment: stripePromise,
Copy link
Member

Choose a reason for hiding this comment

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

The naming of this one is slightly odd. I assume this is basically whether or not the method will be enabled or visible? Remember some gateways (offline, invoice etc) don't technically take payment.

Copy link
Contributor Author

@nerrad nerrad Mar 30, 2020

Choose a reason for hiding this comment

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

It's for a consistent api, because some payment methods can only make a payment given certain conditions on the environment (browser in use, configured properly, third party library loaded etc). This allows for a consistent way for gateways to indicate they can make payment. For offline, or invoice payment methods they could just do Promise.resolve( true ) as the value for this property.

try {
stripe = loadStripe( getApiKey() );
} catch ( error ) {
// eslint-disable-next-line no-console
Copy link
Member

Choose a reason for hiding this comment

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

Will be be a customer facing error or a silent one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If stripe fails to load here, then the payment method itself will not load or display anything. The reason why I commented this out is because it does a console error in the admin.... I need to revisit though, I'm going to add a @todo for a followup.

*
* @return {StripeServerData}
*/
const getStripeServerData = () => {
Copy link
Member

Choose a reason for hiding this comment

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

So if I understand correctly, gateways might need to pass data to themselves via settings, but we need to ensure block checkout is loaded first?

How about a common API on the PHP side for gateways to insert variables, and then have either the checkout or payment provider load them in somehow and pass through to payment method on initialisation.

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 like that idea. Adding as a follow-up.

@@ -212,17 +213,17 @@
* @property {string} redirectUrl This is the url that
* checkout will redirect
* to when it's ready.
* @property {function()} onCheckoutCompleteSuccess Used to register a
* @property {function(function())} onCheckoutCompleteSuccess Used to register a
Copy link
Member

Choose a reason for hiding this comment

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

What does this mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It means that the "type" for this value is a function that receives a function as it's argument.

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
category: extensibility Work involving adding or updating extensibility. Useful to combine with other scopes impacted. focus: components Work that introduces new or updates existing components.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create Payment Methods for Stripe
6 participants