Skip to content

Commit 6a03fcd

Browse files
feat: added ACH Bank Transfer
1 parent 7c1c2f8 commit 6a03fcd

21 files changed

+536
-28
lines changed

hyperswitch-sdk-ios

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit e7ade8ff1660f1729d47271870ee421118c329fd

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"prepare": "husky"
3838
},
3939
"dependencies": {
40+
"@react-native-clipboard/clipboard": "^1.16.1",
4041
"@sentry/react-native": "^5.9.1",
4142
"pako": "^2.1.0",
4243
"react-native-code-push": "^8.3.1",

src/components/elements/ModalHeader.res

+8-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ let make = (~onModalClose) => {
2929
| PaymentScreenContext.PAYMENTSHEET => nativeProp.configuration.paymentSheetHeaderText
3030
| PaymentScreenContext.SAVEDCARDSCREEN =>
3131
nativeProp.configuration.savedPaymentScreenHeaderText
32+
| BANK_TRANSFER(_) => None
3233
} {
3334
| Some(var) =>
3435
<View style={viewStyle(~maxWidth=60.->pct, ())}>
@@ -64,9 +65,13 @@ let make = (~onModalClose) => {
6465
overrideStyle=Some(textStyle(~color="black", ()))
6566
/>
6667
</View>}
67-
<CustomTouchableOpacity onPress={_ => onModalClose()}>
68-
<Icon name="close" width=16. height=16. fill=iconColor />
69-
</CustomTouchableOpacity>
68+
{switch paymentScreenType {
69+
| BANK_TRANSFER(_) => React.null
70+
| _ =>
71+
<CustomTouchableOpacity onPress={_ => onModalClose()}>
72+
<Icon name="close" width=16. height=16. fill=iconColor />
73+
</CustomTouchableOpacity>
74+
}}
7075
</>}
7176
</View>
7277
</View>

src/contexts/LoadingContext.res

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ type sdkPaymentState =
44
| ProcessingPayments(option<processingPayments>)
55
| PaymentSuccess
66
| PaymentCancelled
7+
| BankTransfer
78
let defaultSetter = (_: sdkPaymentState) => ()
89
let loadingContext = React.createContext((FillingDetails, defaultSetter))
910

src/contexts/PaymentScreenContext.res

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
type paymentScreenType = PAYMENTSHEET | SAVEDCARDSCREEN
1+
type paymentScreenType =
2+
PAYMENTSHEET | SAVEDCARDSCREEN | BANK_TRANSFER(option<PaymentConfirmTypes.ach_credit_transfer>)
23
let dafaultVal = SAVEDCARDSCREEN
34

45
let paymentScreenTypeContext = React.createContext((dafaultVal, (_: paymentScreenType) => ()))

src/hooks/AllPaymentHooks.res

+17
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ let useBrowserHook = () => {
367367
let useRedirectHook = () => {
368368
let (nativeProp, _) = React.useContext(NativePropContext.nativePropContext)
369369
let (allApiData, setAllApiData) = React.useContext(AllApiDataContext.allApiDataContext)
370+
let (_, setPaymentScreenType) = React.useContext(PaymentScreenContext.paymentScreenTypeContext)
371+
let (_, setLoading) = React.useContext(LoadingContext.loadingContext)
370372
let redirectioBrowserHook = useBrowserHook()
371373
let retrievePayment = useRetrieveHook()
372374
let apiLogWrapper = LoggerHook.useApiLogWrapper()
@@ -428,6 +430,21 @@ let useRedirectHook = () => {
428430
| None => ()
429431
}
430432
}
433+
| "display_bank_transfer_information" => {
434+
switch nextAction {
435+
| None => ()
436+
| Some(data) =>
437+
setLoading(BankTransfer)
438+
setPaymentScreenType(
439+
BANK_TRANSFER(
440+
Some(
441+
data.bank_transfer_steps_and_charges_detail->getACH_bank_transfer->getACH_details,
442+
),
443+
),
444+
)
445+
}
446+
()
447+
}
431448
| _ =>
432449
switch status {
433450
| "succeeded" =>

src/hooks/PMListModifier.res

+20
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,26 @@ let useListModifier = () => {
268268
setConfirmButtonDataRef
269269
/>,
270270
})
271+
| BANK_TRANSFER(bankTransferVal) =>
272+
let fields =
273+
redirectionList
274+
->Array.find(l => {
275+
l.name === bankTransferVal.payment_method_type ++ "_bank_transfer"
276+
})
277+
->Option.getOr(Types.defaultRedirectType)
278+
279+
Some({
280+
name: fields.text,
281+
componentHoc: (~isScreenFocus, ~setConfirmButtonDataRef) =>
282+
<Redirect
283+
isScreenFocus
284+
isDynamicFields={true}
285+
dynamicFields={bankTransferVal.required_field}
286+
redirectProp=BANK_TRANSFER(bankTransferVal)
287+
fields
288+
setConfirmButtonDataRef
289+
/>,
290+
})
271291
} {
272292
| Some(tab) =>
273293
let isInvalidScreen =

src/hooks/S3ApiHook.res

+25
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,31 @@ let getLocaleStrings: Js.Json.t => localeStrings = data => {
243243
defaultLocale.enterValidDigitsText,
244244
),
245245
digitsText: Utils.getString(res, "digitsText", defaultLocale.digitsText),
246+
disclaimerTextAchTransfer: Utils.getString(
247+
res,
248+
"disclaimerTextAchTransfer",
249+
defaultLocale.disclaimerTextAchTransfer,
250+
),
251+
instructionalTextOfAchTransfer: Utils.getString(
252+
res,
253+
"instructionalTextOfAchTransfer",
254+
defaultLocale.instructionalTextOfAchTransfer,
255+
),
256+
accountDetailsText: Utils.getString(
257+
res,
258+
"accountDetailsText",
259+
defaultLocale.accountDetailsText,
260+
),
261+
achBankTransferText: Utils.getString(
262+
res,
263+
"achBankTransferText",
264+
defaultLocale.achBankTransferText,
265+
),
266+
bankName: Utils.getString(res, "bankName", defaultLocale.bankName),
267+
routingNumber: Utils.getString(res, "routingNumber", defaultLocale.routingNumber),
268+
swiftCode: Utils.getString(res, "swiftCode", defaultLocale.swiftCode),
269+
doneText: Utils.getString(res, "doneText", defaultLocale.doneText),
270+
copyToClipboard: Utils.getString(res, "copyToClipboard", defaultLocale.copyToClipboard),
246271
}
247272
| None => defaultLocale
248273
}

src/hooks/ThemebasedStyle.res

+42
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,13 @@ type themeBasedStyleObj = {
173173
shadowColor: string,
174174
shadowIntensity: float,
175175
primaryButtonHeight: float,
176+
disclaimerBackgroundColor: string,
177+
disclaimerTextColor: string,
178+
instructionalTextColor: string,
179+
poweredByTextColor: string,
180+
detailsViewTextKeyColor: string,
181+
detailsViewTextValueColor: string,
182+
silverBorderColor:string,
176183
}
177184

178185
let darkRecord = {
@@ -251,6 +258,13 @@ let darkRecord = {
251258
normalTextInputBoderColor: "rgba(204, 210, 226, 0.75)",
252259
shadowColor: "black",
253260
shadowIntensity: 2.,
261+
disclaimerBackgroundColor: "#FDF3E0",
262+
disclaimerTextColor: "#D57F0C",
263+
instructionalTextColor: "#999999",
264+
poweredByTextColor: "#111111",
265+
detailsViewTextKeyColor: "#999999",
266+
detailsViewTextValueColor: "#333333",
267+
silverBorderColor:"#CCCCCC",
254268
}
255269
let lightRecord = {
256270
primaryButtonHeight: 45.,
@@ -328,6 +342,13 @@ let lightRecord = {
328342
normalTextInputBoderColor: "rgba(204, 210, 226, 0.75)",
329343
shadowColor: "black",
330344
shadowIntensity: 2.,
345+
disclaimerBackgroundColor: "#FDF3E0",
346+
disclaimerTextColor: "#D57F0C",
347+
instructionalTextColor: "#999999",
348+
poweredByTextColor: "#111111",
349+
detailsViewTextKeyColor: "#999999",
350+
detailsViewTextValueColor: "#333333",
351+
silverBorderColor:"#CCCCCC",
331352
}
332353

333354
let minimal = {
@@ -406,6 +427,13 @@ let minimal = {
406427
normalTextInputBoderColor: "rgba(204, 210, 226, 0.75)",
407428
shadowColor: "black",
408429
shadowIntensity: 3.,
430+
disclaimerBackgroundColor: "#FDF3E0",
431+
disclaimerTextColor: "#D57F0C",
432+
instructionalTextColor: "#999999",
433+
poweredByTextColor: "#111111",
434+
detailsViewTextKeyColor: "#999999",
435+
detailsViewTextValueColor: "#333333",
436+
silverBorderColor:"#CCCCCC",
409437
}
410438

411439
let flatMinimal = {
@@ -484,6 +512,13 @@ let flatMinimal = {
484512
normalTextInputBoderColor: "rgba(204, 210, 226, 0.75)",
485513
shadowColor: "black",
486514
shadowIntensity: 3.,
515+
disclaimerBackgroundColor: "#FDF3E0",
516+
disclaimerTextColor: "#D57F0C",
517+
instructionalTextColor: "#999999",
518+
poweredByTextColor: "#111111",
519+
detailsViewTextKeyColor: "#999999",
520+
detailsViewTextValueColor: "#333333",
521+
silverBorderColor:"#CCCCCC",
487522
}
488523

489524
let some = (~override, ~fn, ~default) => {
@@ -870,6 +905,13 @@ let itemToObj = (
870905
~defaultProp=themeObj.shadowIntensity,
871906
),
872907
paymentSheetOverlay: themeObj.paymentSheetOverlay,
908+
disclaimerBackgroundColor: themeObj.disclaimerBackgroundColor,
909+
disclaimerTextColor: themeObj.disclaimerTextColor,
910+
instructionalTextColor: themeObj.instructionalTextColor,
911+
poweredByTextColor: themeObj.poweredByTextColor,
912+
detailsViewTextKeyColor: themeObj.detailsViewTextKeyColor,
913+
detailsViewTextValueColor: themeObj.detailsViewTextValueColor,
914+
silverBorderColor:themeObj.silverBorderColor,
873915
}
874916
}
875917

src/icons/Icon.res

+6
Large diffs are not rendered by default.

src/pages/payment/ACHBankDetails.res

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
open ReactNative
2+
open Style
3+
open ThemebasedStyle
4+
5+
module DetailsView = {
6+
@react.component
7+
let make = (~title, ~value) => {
8+
<View style={viewStyle(~flexDirection=#row, ~gap=5., ~alignItems=#center, ())}>
9+
<Text style={textStyle(~fontSize=10., ~fontWeight=#400, ~color=useThemeBasedStyle().detailsViewTextKeyColor, ())}>
10+
{React.string(title ++ ":")}
11+
</Text>
12+
<Text style={textStyle(~fontSize=12., ~fontWeight=#400, ~color=useThemeBasedStyle().detailsViewTextValueColor, ())}>
13+
{React.string(value)}
14+
</Text>
15+
</View>
16+
}
17+
}
18+
19+
@react.component
20+
let make = (~data: PaymentConfirmTypes.ach_credit_transfer) => {
21+
let (clicked, setClicked) = React.useState(_ => false)
22+
let handleSuccessFailure = AllPaymentHooks.useHandleSuccessFailure()
23+
let localeObject = GetLocale.useGetLocalObj()
24+
<View>
25+
<View style={array([viewStyle(~flexDirection=#row, ~gap=8., ~alignItems=#center, ())])}>
26+
<Icon name={"ach bank transfer"} height=20. width=20. />
27+
<TextWrapper
28+
textType={HeadingBold}
29+
text=localeObject.achBankTransferText
30+
overrideStyle=Some(Style.textStyle(~fontSize=16.0, ~fontWeight=#600, ()))
31+
/>
32+
</View>
33+
<Space height=20.0 />
34+
<View style={array([viewStyle(~flexDirection=#row, ~gap=4., ~alignItems=#center, ())])}>
35+
<Icon name={"bank"} height=20. width=20. />
36+
<TextWrapper
37+
textType={HeadingBold}
38+
text=localeObject.accountDetailsText
39+
overrideStyle=Some(Style.textStyle(~fontSize=14.0, ~fontWeight=#600, ()))
40+
/>
41+
</View>
42+
<Space height=6.0 />
43+
<TextWrapper
44+
textType={CardText}
45+
text=localeObject.instructionalTextOfAchTransfer
46+
overrideStyle=Some(Style.textStyle(~fontSize=12.0, ~fontWeight=#400, ~color=useThemeBasedStyle().instructionalTextColor, ()))
47+
/>
48+
<Space height=12.0 />
49+
<View
50+
style={viewStyle(
51+
~paddingVertical=16.->dp,
52+
~paddingHorizontal=14.->dp,
53+
~borderRadius=8.,
54+
~borderWidth=0.5,
55+
~borderColor=useThemeBasedStyle().silverBorderColor,
56+
~gap=12.,
57+
(),
58+
)}>
59+
<DetailsView title=localeObject.accountNumberText value={data.account_number} />
60+
<DetailsView title=localeObject.bankName value={data.bank_name} />
61+
<DetailsView title=localeObject.routingNumber value={data.routing_number} />
62+
<DetailsView title=localeObject.swiftCode value={data.swift_code} />
63+
</View>
64+
<Space height=18.0 />
65+
<View
66+
style={viewStyle(
67+
~flexDirection=#row,
68+
~gap=4.,
69+
~paddingVertical=10.->dp,
70+
~paddingHorizontal=12.->dp,
71+
~borderRadius=8.,
72+
~backgroundColor=useThemeBasedStyle().disclaimerBackgroundColor,
73+
(),
74+
)}>
75+
<Icon name={"disclaimer"} height=20. width=20. />
76+
<Text
77+
style={textStyle(~fontSize=12., ~fontWeight=#400, ~lineHeight=18., ~color=useThemeBasedStyle().disclaimerTextColor, ())}>
78+
{React.string(localeObject.disclaimerTextAchTransfer)}
79+
</Text>
80+
</View>
81+
<Space height=28.0 />
82+
<CustomButton
83+
text={clicked ? localeObject.doneText : localeObject.copyToClipboard}
84+
borderRadius=4.
85+
onPress={_ => {
86+
if clicked {
87+
handleSuccessFailure(
88+
~apiResStatus=PaymentConfirmTypes.defaultSuccess,
89+
~closeSDK=true,
90+
~reset=false,
91+
(),
92+
)
93+
} else {
94+
setClicked(_ => true)
95+
let textToCopy =
96+
localeObject.accountNumberText ++
97+
" : " ++
98+
data.account_number ++
99+
"\n" ++
100+
localeObject.bankName ++
101+
" : " ++
102+
data.bank_name ++
103+
"\n" ++
104+
localeObject.bankName ++
105+
" : " ++
106+
data.routing_number ++
107+
"\n" ++
108+
localeObject.swiftCode ++
109+
" : " ++
110+
data.swift_code
111+
// let copyToClipboard = () => {
112+
// Clipboard.setString(textToCopy)
113+
RNClipboard.setString(textToCopy)
114+
// }
115+
}
116+
}}
117+
/>
118+
<Space height=14.0 />
119+
<View
120+
style={viewStyle(
121+
~flexDirection=#row,
122+
~alignItems=#center,
123+
~justifyContent=#center,
124+
~gap=4.,
125+
(),
126+
)}>
127+
<TextWrapper
128+
textType={Heading}
129+
overrideStyle={Some(
130+
textStyle(~fontSize=10., ~fontWeight=#400, ~lineHeight=12., ~color=useThemeBasedStyle().poweredByTextColor, ()),
131+
)}>
132+
// {"powered by"->React.string}
133+
{localeObject.poweredBy->React.string}
134+
</TextWrapper>
135+
// <TextWrapper
136+
// textType={Heading}
137+
// overrideStyle={Some(textStyle(~fontSize=12., ~fontWeight=#600, ~lineHeight=12., ()))}>
138+
// {"hyperswitch"->React.string}
139+
// </TextWrapper>
140+
</View>
141+
<CustomTouchableOpacity onPress={_ => ()} />
142+
<Space height=8.0 />
143+
</View>
144+
}

src/pages/payment/ClickableTextElement.res

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ let make = (
2626
let newSheetType = switch isSavedCardScreen {
2727
| PAYMENTSHEET => PaymentScreenContext.SAVEDCARDSCREEN
2828
| SAVEDCARDSCREEN => PaymentScreenContext.PAYMENTSHEET
29+
| _ => PaymentScreenContext.PAYMENTSHEET
2930
}
3031
setSaveCardScreen(newSheetType)
3132
}

0 commit comments

Comments
 (0)