-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(fraudnet): add fraudnet util for shared SDK components (#170)
* started test driving data collector util * add tests and todos, break fns down a bit * add fraudnet util * update correct fn url * cleanup * outline of fraudnet work * loadfraudnet exposed but not called * fix up error handling/swalloing * remove jest config and fraudnet from setup file * clean up fraudnet lints * fix loadfraudnet type * explicit response type * fix some flow typing of load fraudnet * fix flow type errors * fix some flow * type the fraudneturl const * fix duplicate param * use env ref in types * actual use constants type * 4.0.178 * update fraudnet urls --------- Co-authored-by: cdibble <[email protected]> Co-authored-by: cgdibble <[email protected]>
- Loading branch information
1 parent
83bd65c
commit 678c6d8
Showing
3 changed files
with
159 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/* eslint-disable promise/no-native, no-restricted-globals */ | ||
/* @flow */ | ||
|
||
import { ZalgoPromise } from "@krakenjs/zalgo-promise/src"; | ||
import { ENV } from "@paypal/sdk-constants/src"; | ||
import { memoize, type Memoized } from "@krakenjs/belter/src"; | ||
|
||
import { FRAUDNET_FNCLS, FRAUDNET_URL } from "./constants"; | ||
import { getLogger } from "./logger"; | ||
|
||
type FraudnetOptions = {| | ||
env: $Values<typeof ENV>, | ||
clientMetadataID: string, | ||
cspNonce: string, | ||
appName: string, | ||
queryStringParams?: { [string]: string | boolean }, | ||
|}; | ||
|
||
type FraudnetConfig = {| | ||
f: string, | ||
s: string, | ||
u?: string, | ||
cb1: string, | ||
sandbox?: boolean, | ||
io: boolean, | ||
|}; | ||
|
||
type CreateConfigOptions = {| | ||
env: $Values<typeof ENV>, | ||
cspNonce: string, | ||
clientMetadataID: string, | ||
appName: string, | ||
|}; | ||
|
||
type CreateFraudnetOptions = {| | ||
cspNonce: string, | ||
env: $Values<typeof ENV>, | ||
queryStringParams?: { [string]: string | boolean }, | ||
|}; | ||
|
||
export const createConfigScript = ({ | ||
env, | ||
cspNonce = "", | ||
clientMetadataID, | ||
appName, | ||
}: CreateConfigOptions): ZalgoPromise<void> => { | ||
return new ZalgoPromise((resolve) => { | ||
if (__TEST__) { | ||
return resolve(); | ||
} | ||
|
||
const config: FraudnetConfig = { | ||
f: clientMetadataID, | ||
s: appName, | ||
io: true, | ||
cb1: "fnCallback", | ||
}; | ||
|
||
if (env === ENV.SANDBOX) { | ||
config.sandbox = true; | ||
} | ||
|
||
const configScript = document.createElement("script"); | ||
|
||
configScript.setAttribute("nonce", cspNonce); | ||
configScript.setAttribute("type", "application/json"); | ||
configScript.setAttribute("id", "fconfig"); | ||
configScript.setAttribute("fncls", FRAUDNET_FNCLS); | ||
configScript.text = JSON.stringify(config); | ||
// eslint-disable-next-line compat/compat | ||
document.body?.appendChild(configScript); | ||
}); | ||
}; | ||
|
||
export const createFraudnetScript = ({ | ||
cspNonce, | ||
env, | ||
queryStringParams = {}, | ||
}: CreateFraudnetOptions): ZalgoPromise<void> => { | ||
return new ZalgoPromise((resolve, reject) => { | ||
const fraudnetScript = document.createElement("script"); | ||
const queryString = Object.keys(queryStringParams) | ||
.map( | ||
(key) => `${key}=${encodeURIComponent(String(queryStringParams[key]))}` | ||
) | ||
.join("&"); | ||
|
||
const fraudnetUrl = queryString.length | ||
? `${FRAUDNET_URL[env]}?${queryString}` | ||
: FRAUDNET_URL[env]; | ||
|
||
fraudnetScript.setAttribute("nonce", cspNonce || ""); | ||
fraudnetScript.setAttribute("src", fraudnetUrl); | ||
fraudnetScript.addEventListener("error", () => resolve()); | ||
|
||
window.fnCallback = resolve; | ||
// eslint-disable-next-line compat/compat | ||
document.body?.appendChild(fraudnetScript); | ||
|
||
fraudnetScript.addEventListener("load", () => { | ||
resolve(); | ||
}); | ||
fraudnetScript.addEventListener("error", () => { | ||
reject(new Error(`Fraudnet failed to load.`)); | ||
}); | ||
fraudnetScript.addEventListener("abort", () => { | ||
reject(new Error(`Fraudnet load was aborted.`)); | ||
}); | ||
}); | ||
}; | ||
|
||
type LoadFraudnetResponse = {| | ||
collect: () => Promise<*> | void, | ||
|}; | ||
type LoadFraudnet = (opts: FraudnetOptions) => LoadFraudnetResponse; | ||
|
||
export const loadFraudnet: Memoized<LoadFraudnet> = memoize( | ||
({ env, clientMetadataID, cspNonce, appName, queryStringParams = {} }) => { | ||
createConfigScript({ env, cspNonce, clientMetadataID, appName }); | ||
|
||
const fraudnetPromise = createFraudnetScript({ | ||
cspNonce, | ||
env, | ||
queryStringParams, | ||
}).catch(() => { | ||
getLogger().warn("ppcp_axo_init_fraudnet_failed"); | ||
}); | ||
|
||
return { | ||
collect: async () => { | ||
try { | ||
await fraudnetPromise; | ||
await window.PAYPAL.asyncData.collect(); | ||
} catch (err) { | ||
getLogger().warn("ppcp_axo_collect_fraudnet_failed"); | ||
} | ||
}, | ||
}; | ||
} | ||
); | ||
/* eslint-enable promise/no-native, no-restricted-globals */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters