Merge pull request #11573 from overleaf/ii-payment-page-migration-three-d-secure

[web] Payment page migration 3DS

GitOrigin-RevId: b1049882c0f9fd17af2d2974e3f59b01af353c8f
This commit is contained in:
ilkin-overleaf 2023-02-08 11:47:13 +02:00 committed by Copybot
parent 6811b9085a
commit f6ddb95ae5
4 changed files with 65 additions and 9 deletions

View file

@ -36,5 +36,3 @@ block content
)
p !{translate("for_visa_mastercard_and_discover", {}, ['strong', 'strong', 'strong'])}
p !{translate("for_american_express", {}, ['strong', 'strong', 'strong'])}
+studentCheckModal

View file

@ -1,9 +1,9 @@
import { useState, useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { FormGroup, ControlLabel } from 'react-bootstrap'
import classnames from 'classnames'
import { CardElementChangeState } from '../../../../../../../types/recurly/elements'
import { ElementsInstance } from 'recurly__recurly-js'
import classnames from 'classnames'
type CardElementProps = {
className?: string

View file

@ -15,6 +15,7 @@ import CompanyDetails from './company-details'
import CouponCode from './coupon-code'
import TosAgreementNotice from './tos-agreement-notice'
import SubmitButton from './submit-button'
import ThreeDSecure from './three-d-secure'
import getMeta from '../../../../../utils/meta'
import { postJSON } from '../../../../../infrastructure/fetch-json'
import * as eventTracking from '../../../../../infrastructure/event-tracking'
@ -215,6 +216,22 @@ function CheckoutPanel() {
)
}
const handleThreeDToken = (token: TokenPayload) => {
// on SCA verification success: show payment UI in processing mode and
// resubmit the payment with the new token final success or error will be
// handled by `completeSubscription`
completeSubscription(null, undefined, token)
setGenericError('')
setThreeDSecureActionTokenId(undefined)
setIsProcessing(true)
}
const handleThreeDError = (error: RecurlyError) => {
// on SCA verification error: show payment UI with the error message
setGenericError(`Error: ${error.message}`)
setThreeDSecureActionTokenId(undefined)
}
const handlePaymentMethod = (e: React.ChangeEvent<HTMLInputElement>) => {
setPaymentMethod(e.target.value)
}
@ -265,6 +282,13 @@ function CheckoutPanel() {
return (
<>
{threeDSecureActionTokenId && (
<ThreeDSecure
actionTokenId={threeDSecureActionTokenId}
onToken={handleThreeDToken}
onError={handleThreeDError}
/>
)}
<div className={classnames({ hidden: threeDSecureActionTokenId })}>
<PriceSwitchHeader
planCode={plan.planCode}

View file

@ -1,18 +1,52 @@
import { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { Alert } from 'react-bootstrap'
import { RecurlyError, TokenPayload } from 'recurly__recurly-js'
function ThreeDSecure() {
type ThreeDSecureProps = {
actionTokenId: string
onToken: (token: TokenPayload) => void
onError: (error: RecurlyError) => void
}
function ThreeDSecure({ actionTokenId, onToken, onError }: ThreeDSecureProps) {
const { t } = useTranslation()
const container = useRef<HTMLDivElement>(null)
const recurlyContainer = useRef<HTMLDivElement>(null)
useEffect(() => {
// scroll the UI into view (timeout needed to make sure the element is
// visible)
const timeout = setTimeout(() => {
container.current?.scrollIntoView()
}, 0)
return () => {
clearTimeout(timeout)
}
}, [])
useEffect(() => {
if (!recurly || !recurlyContainer.current) return
// instanciate and configure Recurly 3DSecure flow
const risk = recurly.Risk()
const threeDSecure = risk.ThreeDSecure({ actionTokenId })
threeDSecure.on('token', onToken)
threeDSecure.on('error', onError)
threeDSecure.attach(recurlyContainer.current)
}, [actionTokenId, onToken, onError])
return (
<div className="three-d-secure-container--react">
<div className="three-d-secure-container--react" ref={container}>
<Alert bsStyle="info" className="small" aria-live="assertive">
<strong>{t('card_must_be_authenticated_by_3dsecure')}</strong>
</Alert>
<div className="three-d-secure-recurly-container">
{/* {threeDSecureFlowError && <>{threeDSecureFlowError.message}</>} */}
{/* <ThreeDSecureAction {...props} /> */}
</div>
<div
className="three-d-secure-recurly-container"
ref={recurlyContainer}
/>
</div>
)
}