mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
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:
parent
6811b9085a
commit
f6ddb95ae5
4 changed files with 65 additions and 9 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue