Skip to content

Commit e62dde1

Browse files
committed
wrap show around native promise to make await-able
1 parent ba7fd0d commit e62dde1

File tree

4 files changed

+88
-57
lines changed

4 files changed

+88
-57
lines changed

Diff for: __sdk__.js

+1
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,6 @@ module.exports = {
9595
},
9696
"three-domain-secure": {
9797
entry: "./src/three-domain-secure/interface",
98+
globals,
9899
},
99100
};

Diff for: src/three-domain-secure/component.jsx

+73-52
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import type {
1515
responseBody,
1616
MerchantPayloadData,
1717
SdkConfig,
18-
threeDSResponse,
18+
ThreeDSResponse,
19+
HeliosResponse,
1920
TDSProps,
2021
Update3DSTokenResponse,
2122
} from "./types";
@@ -63,7 +64,7 @@ const parseMerchantPayload = ({
6364

6465
export interface ThreeDomainSecureComponentInterface {
6566
isEligible(payload: MerchantPayloadData): Promise<boolean>;
66-
show(): Promise<threeDSResponse>;
67+
show(): Promise<ThreeDSResponse>;
6768
}
6869

6970
export class ThreeDomainSecureComponent {
@@ -131,63 +132,83 @@ export class ThreeDomainSecureComponent {
131132
}
132133
}
133134

134-
async show(): Promise<threeDSResponse> {
135+
async show(): Promise<ThreeDSResponse> {
135136
if (!this.threeDSIframe) {
136-
throw new ValidationError(`Ineligible for three domain secure`);
137+
return Promise.reject(
138+
new ValidationError(`Ineligible for three domain secure`)
139+
);
137140
}
138-
const promise = new ZalgoPromise();
139-
const cancelThreeDS = () => {
140-
return ZalgoPromise.try(() => {
141-
this.logger.warn("3DS Cancelled");
142-
}).then(() => {
143-
// eslint-disable-next-line no-use-before-define
141+
// eslint-disable-next-line compat/compat
142+
return new Promise((resolve, reject) => {
143+
let authenticationState,
144+
liabilityShift = "false";
145+
const cancelThreeDS = () => {
146+
return ZalgoPromise.try(() => {
147+
this.logger.warn("3DS Cancelled");
148+
}).then(() => {
149+
resolve({
150+
authenticationState: "cancelled",
151+
liabilityShift: "false",
152+
nonce: this.fastlaneNonce,
153+
});
154+
// eslint-disable-next-line no-use-before-define
155+
instance.close();
156+
});
157+
};
158+
159+
const instance = this.threeDSIframe({
160+
payerActionUrl: this.authenticationURL,
161+
onSuccess: async (res) => {
162+
const { reference_id, liability_shift, success } = res;
163+
let enrichedNonce;
164+
// Helios returns a boolen parameter: "success"
165+
// It will be true for all cases where liability is shifted to merchant
166+
// and false for downstream failures and errors
167+
authenticationState = success ? "success" : "errored";
168+
liabilityShift = liability_shift ? liability_shift : "false";
169+
170+
// call BT mutation to update fastlaneNonce with 3ds data
171+
// reference_id will be available for all usecases(success/failure)
172+
if (reference_id) {
173+
const gqlResponse = await this.updateNonceWith3dsData(reference_id);
174+
const { data, errors } = gqlResponse;
175+
if (data) {
176+
enrichedNonce =
177+
data.updateTokenizedCreditCardWithExternalThreeDSecure
178+
.paymentMethod.id;
179+
} else if (errors) {
180+
this.logger.warn("Errors returned when updating nonce", errors);
181+
}
182+
}
183+
184+
// Resolve the parent promise with enriched nonce if available
185+
// else, return the original nonce that the merchant sent
186+
resolve({
187+
authenticationState,
188+
liabilityShift,
189+
nonce: enrichedNonce || this.fastlaneNonce,
190+
});
191+
},
192+
onCancel: cancelThreeDS,
193+
onError: (err) => {
194+
instance.close();
195+
reject(
196+
new Error(
197+
`Error with obtaining 3DS auth response: ${JSON.stringify(err)}`
198+
)
199+
);
200+
},
201+
});
202+
203+
// Render the iframe
204+
instance.render("body").catch(() => {
144205
instance.close();
145206
});
146-
};
147-
// $FlowFixMe
148-
const instance = await this.threeDSIframe({
149-
payerActionUrl: this.authenticationURL,
150-
onSuccess: async (res) => {
151-
const { reference_id, authentication_status, liability_shift } = res;
152-
let enrichedNonce, response;
153-
154-
if (reference_id) {
155-
// $FlowFixMe ZalgoPromise not recognized
156-
response = await this.updateNonceWith3dsData(reference_id);
157-
}
158-
// $FlowIssue
159-
const { data, errors } = response;
160-
if (data) {
161-
enrichedNonce =
162-
data?.updateTokenizedCreditCardWithExternalThreeDSecure
163-
.paymentMethod.id;
164-
} else if (errors) {
165-
return promise.resolve({
166-
authenticationStatus: authentication_status,
167-
liabilityShift: liability_shift,
168-
nonce: enrichedNonce,
169-
});
170-
}
171-
},
172-
onCancel: cancelThreeDS,
173-
onError: (err) => {
174-
return ZalgoPromise.reject(
175-
new Error(
176-
`Error with obtaining 3DS auth response, ${JSON.stringify(err)}`
177-
)
178-
);
179-
},
180207
});
181-
182-
return instance
183-
.render("body")
184-
.then(() => promise)
185-
.finally(instance.close);
186208
}
187209

188-
updateNonceWith3dsData(
189-
threeDSRefID: string
190-
): ZalgoPromise<Update3DSTokenResponse> {
210+
updateNonceWith3dsData(threeDSRefID: string): Promise<any> {
211+
// $FlowFixMe Zalgopromise not recognized
191212
return this.graphQLClient.request({
192213
headers: {
193214
"Braintree-Version": "2023-09-28",

Diff for: src/three-domain-secure/types.js

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* @flow */
22
/* eslint-disable no-restricted-globals, promise/no-native */
3+
import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
34
import { type ZoidComponent } from "@krakenjs/zoid/src";
45

56
export type MerchantPayloadData = {|
@@ -70,27 +71,34 @@ export type SdkConfig = {|
7071
clientID: string,
7172
|};
7273

73-
export type threeDSResponse = {|
74+
export type ThreeDSResponse = {|
7475
liabilityShift: string,
75-
authenticationStatus: string,
76+
authenticationState: string,
7677
nonce?: string,
7778
|};
7879

80+
export type HeliosResponse = {|
81+
liability_shift?: string,
82+
reference_id?: string,
83+
success: boolean,
84+
|};
85+
7986
export type TDSResult = {||};
8087

8188
export type TDSProps = {|
8289
xcomponent?: string,
8390
payerActionUrl: string,
84-
onSuccess: (data: threeDSResponse) => void,
91+
onSuccess: (data: HeliosResponse) => Promise,
8592
onError: (mixed) => void,
93+
onCancel: (mixed) => ZalgoPromise,
8694
sdkMeta?: string,
8795
content?: void | {|
8896
windowMessage?: string,
8997
continueMessage?: string,
9098
cancelMessage?: string,
9199
interrogativeMessage?: string,
92100
|},
93-
nonce: string,
101+
nonce?: string,
94102
|};
95103

96104
export type UrlProps = {|

Diff for: src/three-domain-secure/utils.jsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ export function getFastlaneThreeDS(): TDSComponent {
4343
return (
4444
<Overlay
4545
context={context}
46-
close={close}
46+
// $FlowFixMe
47+
close={props.onCancel || close}
4748
focus={focus}
4849
event={event}
4950
frame={frame}

0 commit comments

Comments
 (0)