Feature: Add UI for SCA error banner and re-authentication flow#46319
Feature: Add UI for SCA error banner and re-authentication flow#46319blimpich merged 13 commits intoExpensify:mainfrom
Conversation
|
Looked at this locally. I think we should apply these changes so that (A) the authenticate button only shows if the error banner also shows, and (B) so that the error banner will show even if the user is on a free trial and even if there is no amount owed. Lemme know what you think. diff --git a/src/libs/SubscriptionUtils.ts b/src/libs/SubscriptionUtils.ts
index 0cc4e05f7b..8516d8e082 100644
--- a/src/libs/SubscriptionUtils.ts
+++ b/src/libs/SubscriptionUtils.ts
@@ -175,7 +175,7 @@ function hasAmountOwed(): boolean {
* @returns Whether there is a card authentication error.
*/
function hasCardAuthenticatedError() {
- return stripeCustomerId?.status === 'authentication_required' && amountOwed === 0;
+ return stripeCustomerId?.status === 'authentication_required' && getAmountOwed() === 0;
}
/**
@@ -460,5 +460,6 @@ export {
getCardForSubscriptionBilling,
hasSubscriptionGreenDotInfo,
hasRetryBillingError,
+ hasCardAuthenticatedError,
PAYMENT_STATUS,
};
diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx
index df3c6809e1..a501c61a8b 100644
--- a/src/pages/settings/Subscription/CardSection/CardSection.tsx
+++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx
@@ -32,6 +32,7 @@ import CardSectionDataEmpty from './CardSectionDataEmpty';
import RequestEarlyCancellationMenuItem from './RequestEarlyCancellationMenuItem';
import type {BillingStatusResult} from './utils';
import CardSectionUtils from './utils';
+import { hasCardAuthenticatedError } from '@libs/SubscriptionUtils';
function CardSection() {
const [isRequestRefundModalVisible, setIsRequestRefundModalVisible] = useState(false);
@@ -85,7 +86,9 @@ function CardSection() {
BillingBanner = <TrialStartedBillingBanner />;
} else if (SubscriptionUtils.hasUserFreeTrialEnded()) {
BillingBanner = <TrialEndedBillingBanner />;
- } else if (billingStatus) {
+ }
+
+ if (billingStatus) {
BillingBanner = (
<SubscriptionBillingBanner
title={billingStatus.title}
@@ -144,7 +147,7 @@ function CardSection() {
large
/>
)}
- {billingStatus?.isAuthenticationRequired !== undefined && (
+ {hasCardAuthenticatedError() && (
<Button
text={translate('subscription.cardSection.authenticatePayment')}
isDisabled={isOffline || !billingStatus?.isAuthenticationRequired} |
|
@blimpich Looks a bit weird this part: "getAmountOwed() === 0", do we need to check for owed amount for authentication error? Shouldn't it be only like this return stripeCustomerId?.status === 'authentication_required' ? |
This confuses me too, and to be completely honest I don't understand why that is the logic, but that is the logic that we have in the Old Dot version of the application too, so we should try to mimic it. I looked into why that code was written that way in the old version of the app, but there wasn't really an explanation in the PR that added it, so 🤷. Lets keep it with the owed amount conditional. My guess is that if there is an owed amount we have prioritized showing a different error banner instead of the authentication error banner. |
|
@blimpich Can you please verify it works or not |
|
@waterim I will try to get to it today. I was on vacation yesterday so couldn't get to it. |
|
Error banner looks good but when I click "Authenticate" it just opens up a empty billing card form. It looks like the problem is that we clear the authenticationLink onyx key here, which means we aren't able to reuse it when we try to reauthenticate. The clearing of the authentication link also seems to be how we decide to close the the iframe modal in the first place. That's an issue. We need the modal to close without clearing the authentication link from our onyx data. @waterim can you figure out a way to do that? Screen.Recording.2024-07-31.at.1.39.46.PM.mov |
|
I will try it tomorrow without clearing the link |
|
If we can clear it on success and keep it on failure then that should be good but I also don't see a problem with keeping it. There's nothing in that link that I'm worried about being exposed on the frontend. |
|
Hmmm, so the iframe opens but then closes before rendering. Not sure why that is. Screen.Recording.2024-08-01.at.2.15.35.PM.mov |
|
I can make the modal not auto-close by removing this line but I still just get a blank page instead of the stripe verification screen. Probably something backend I need to adjust here. Looking into it. |
|
Ah, I think I've figured it out. Comes down to onyx updates. The old way we did this was we would call Lets do this:
The changes I'm going to make also mean that we shouldn't need to use makeRequestWithSideEffect here. The backend will update the onyx key and push it to the frontend. Does that sound good @waterim? |
|
Sounds great and makes a lot of sense for me know. thank you! |
|
@mananjadhav Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
I'll start with the review of this code, but I don't see any screenshots/videos for the testing. @waterim Can you please add them? |
|
@mananjadhav Its not possible to test it without a local backend and dev env stripe Also I will be able to upload a video with steps only when @blimpich ngrok is online (in 3-4 hours from now) If its okay for you you are able to go through code for now and when @blimpich will be online we can proceed with testing this flow manually |
|
@mananjadhav added video with the flow Firstly you will need to fail the 3ds secure and after this PRs flow starts from "Authenticate payment" |
| BillingBanner = <TrialEndedBillingBanner />; | ||
| } else if (billingStatus) { | ||
| } | ||
| if (billingStatus) { |
There was a problem hiding this comment.
Is this else if --> if intentional?
Are we saying along with Trial/Trial ended banner we would show the authenticate payment button?
There was a problem hiding this comment.
I think I got the change now.
Reviewer Checklist
Screenshots/VideosAndroid: mWeb Chromemweb-chrome-sca-error.moviOS: NativeiOS: mWeb Safarimweb-safari-sca-error.movMacOS: Chrome / Safariweb-sca-error.movMacOS: Desktopdesktop-sca-error.mov |
|
@blimpich There is no popup shown on payment currency change right. Steps:
|
Correct. That is a known issue, choosing not to prioritize right now. |
mananjadhav
left a comment
There was a problem hiding this comment.
The code changes look good and also works well.
My iOS build is failing but this feature is anyway not available for native app.
Another follow up thing unrelated to the current PR could be, when clicking on Submit instead of Fail, Authenticate payment modal doesn't have a good visible loader. This is I think loaded from iframe. The rest it looks good.
blimpich
left a comment
There was a problem hiding this comment.
Looks good and tests well but can we follow up on this comment I made awhile back?
The changes I'm going to make also mean that we shouldn't need to use makeRequestWithSideEffect here. The backend will update the onyx key and push it to the frontend.
It would be good to get rid of the side effect usage where we can, and I think we can here.
|
@waterim can you also update this branch with |
|
@blimpich Sure! |
|
@blimpich updated, can you test please? |
|
Ugh, I was wrong, I misunderstood one of the backend api endpoints and how it worked. @waterim can you please revert the changes related to getting rid of |
|
Sure! Will revert it tomorrow morning :) |
blimpich
left a comment
There was a problem hiding this comment.
Tested it again, works great! Lets merge this!!!
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/blimpich in version: 9.0.23-0 🚀
|
|
@mvtglobally yes staging points to prod stripe, sorry I should have written something here before you QA'ed. Please skip QA for this. |
|
🚀 Deployed to production by https://github.com/chiragsalian in version: 9.0.23-0 🚀
|



Details
Add UI for SCA error banner and re-authentication flow
Fixed Issues
$ #46064
PROPOSAL: N/A
Tests
NOTE: You need to connect to someone local backend to test live mode of the stripe
/settings/subscription/add-payment-cardOffline tests
Same as tests
QA Steps
None
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)myBool && <MyComponent />.src/languages/*files and using the translation methodWaiting for Copylabel for a copy review on the original GH to get the correct copy.STYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG))Avataris modified, I verified thatAvataris working as expected in all cases)ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Web
Screen.Recording.2024-08-12.at.23.39.49.mov