New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(payment): BOLT-19 added BoltCheckout implementation for customer… #1163
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nicely done! I like this idea more than than the first revision #1158, we re-use the existing strategy without creating additional one that behaves pretty much in the same way
@davidchin @icatalina can you take a look at these two possible options and let us know your thoughts. The possible way that we will choose more likely correspond to the philosophy of the existing customer strategy, hence your input will be invaluable
e390ee6
to
1dd651f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! There is only one minor concern
@davidchin can take a look?
} | ||
} catch (error) { | ||
resolve(); | ||
throw error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
per our discussion, it worth to just log an error in order to not interrupt the default flow (will check if throw
fully interrupts the default flow). continueWith strategy is not as vital for checkout as a strategy of a payment provider. we can remain the default flow if we have any issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked it and it is working as expected. If we somehow get an error, we will continue with default flow without any problem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the intention is good. But I think what we should do, from SDK library's perspective, is to return an error and let the client to catch and decide what to do next as a recovery. The client may choose to silently ignore the error and log it behind the scene. Or it may choose to display a message informing that the shopper that something went wrong but they can still progress.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, except some tests names. I've sent my propositions to @Sireks in slack message.
isContinuingAsGuest: false, | ||
}); | ||
|
||
expect(customerStrategyReducer(initialState, action).statuses).toEqual({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is that expect useful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is.
Already fixed all those propositions that you sent me in slack.
1dd651f
to
a243be0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @Sireks. It's looking good no major issue with the code itself. However, as I mentioned in your other PR, I'm blocking this for now until we get some clarification from product.
const { methodId } = options; | ||
|
||
if (!methodId) { | ||
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InvalidArgument
is a better error to throw (i.e.: the required argument is not passed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
const { developerConfig, publishableKey } = paymentMethod.initializationData; | ||
|
||
return this._boltScriptLoader.load(publishableKey, paymentMethod.config.testMode, developerConfig) | ||
.then(boltCheckout => this._boltClient = boltCheckout) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer async/await
for any new files that we create.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
.then(() => this._store.getState()); | ||
} | ||
|
||
private openCustomBoltCheckoutWidget(email: string, methodId: string): Promise<InternalCheckoutSelectors> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a convention of prefixing private members, including methods, with an underscore. This is because when TS is compiled to JS, people know that they shouldn't be accessing those members.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed!
}; | ||
|
||
this._boltClient.openCheckout(email, callbacks) | ||
.then(result => !result && resolve()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can openCheckout
return an error / rejected promise. If so, we need to handle it accordingly,.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is already wrapped in try...catch
.
I will remove that then
chaining, because it is unnecessary anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The try/catch
block has no effect because you're using the then
syntax. It only works if you use the async/await
syntax.
} | ||
|
||
private openCustomBoltCheckoutWidget(email: string, methodId: string): Promise<InternalCheckoutSelectors> { | ||
return new Promise(resolve => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need to manually construct a Promise
as openCheckout
already returns one. So you can just chain to it and return a Promise that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will check this one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will change the method to make it more readable, but I need to keep new Promise(resolve => ...)
to make all the code that left run only if the modal was closed.
If Bolt Checkout modal was closed, it's ok, we will run default customer flow. But if shopper will continue with Bolt Checkout Modal, he/she will be redirected to Success page in the end of the flow.
} | ||
} catch (error) { | ||
resolve(); | ||
throw error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the intention is good. But I think what we should do, from SDK library's perspective, is to return an error and let the client to catch and decide what to do next as a recovery. The client may choose to silently ignore the error and log it behind the scene. Or it may choose to display a message informing that the shopper that something went wrong but they can still progress.
throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod); | ||
} | ||
|
||
return this._store.dispatch(this._customerActionCreator.signInCustomer(credentials, options)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this mean that if a shopper chooses to sign into their BC account, and then refresh the page before they get a chance to complete whatever that's needed in the Bolt widget, they won't be prompted to complete the Bolt widget again (because the shopper is already signed in so they will be prompted to complete the next/shipping step instead)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am working on the implementation right now. We need to check if there any customContinueFlowEnabled in Checkout component and then handle to open customer step to open the BoltCheckout modal again.
May be you can give me some advice how to do it right
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logged in shopper will have Bolt checkout modal open each time when open Checkout page and if the shopper has Bolt Account
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have to be careful on this because you're assuming that the shopper wants to use Bolt. It might be that they intentionally close the Bolt modal. But they are prompted again everytime they reopen checkout or go back to the customer step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But we don't know why the user closed Bolt Checkout modal, maybe shopper want to get more stuff to make the order or so. We will open the modal only for those customer that has their own Bolt Account. Otherwise the modal will not be showed.
We discussed this case a couple times... And we made the decision to make it like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand your team has made a decision. And I'm sorry if you feel like we're revisiting that decision. But considering that decision was made without consulting with our team, I think it's reasonable for us to question it and perhaps make adjustments to it if we both agree they are appropriate.
Anyway the reason why I brought this up is because you're making an assumption that shoppers with an existing Bolt account really want to use Bolt. Having a Bolt account does not mean the shopper wants to use it. It just means they have an account which they may choose to use it. Anyway, I guess you can say the shopper can just close it again if they really don't want use Bolt. That's fair enough. But what if the store has PayPal enabled and the shopper (with an existing Bolt account) clicks on the PayPal button on the cart page, authorises the payment on PayPal side and then get redirected to checkout, would they see the Bolt modal open automatically? If that's the case, I think we have a problem. At least, we have to make sure that if there's a payment in progress, don't try to encourage the shopper to abandon it and switch to use Bolt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @davidchin!
It's ok. We will discuss the issue and I or someone from my team will tell you about what we will doing next.
But it's a question for another task and the case has not to be a blocker for current task.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand your team has made a decision. And I'm sorry if you feel like we're revisiting that decision. But considering that decision was made without consulting with our team, I think it's reasonable for us to question it and perhaps make adjustments to it if we both agree they are appropriate.
@davidchin this is what these 2 PRs about, as long as the flow is a bit tricky, we made some decisions and started conversation with these 2 POCs
I think we have to be careful on this because you're assuming that the shopper wants to use Bolt. It might be that they intentionally close the Bolt modal. But they are prompted again everytime they reopen checkout or go back to the customer step.
To my knowdledge, we have decided to introduce some flag in checkout session (the research on this feature is in the progress), that will be set whenever a buyer mananges popup, so in the scope of single quote they will not be bombarded with the popup over and overagain
tslint.json
Outdated
@@ -4,6 +4,7 @@ | |||
"max-line-length": false, | |||
"no-empty": false, | |||
"no-shadowed-variable": false, | |||
"object-literal-sort-keys": false | |||
"object-literal-sort-keys": false, | |||
"cyclomatic-complexity": false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should try to resolve the cyclomatic complexity by refactoring the code rather than disabling the rule. If the refactoring takes too much effort and you'd rather tackle it separately, then you can disable the rule locally for the file only rather than disabling it globally for all files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed!
0ffb8f5
to
60ca262
Compare
…s with bolt account
60ca262
to
ea1248f
Compare
@davidchin |
…s with bolt account
What?
Added BoltCheckout implementation for customers with bolt account.
Why?
We need to add custom flow for continue as guest, sign in and sign up events, to show BoltCheckout modal if the customer has BoltAccount
Task: https://jira.bigcommerce.com/browse/BOLT-19
Sibling pull-request
checkout-js: bigcommerce/checkout-js#619
Testing / Proof
Some gifs to figure out how it looks like:
There how it will looks like if the user have default flow or customer hasn't bolt account:
@bigcommerce/checkout @bigcommerce/payments