Skip to content

Commit

Permalink
feat(fraudnet): add fraudnet util for shared SDK components (#170)
Browse files Browse the repository at this point in the history
* 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
3 people authored Dec 15, 2023
1 parent 83bd65c commit 678c6d8
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* @flow */
import { ENV } from "@paypal/sdk-constants/src";

export const FPTI_CONTEXT_TYPE = {
ORDER_ID: ("EC-Token": "EC-Token"),
Expand All @@ -13,3 +14,19 @@ export const FPTI_TRANSITION = {
export const FPTI_STATE = {
PXP: ("PXP_CHECK": "PXP_CHECK"),
};

type FraudnetUrl = {|
[$Values<typeof ENV>]: string,
|};

export const FRAUDNET_URL: FraudnetUrl = {
[ENV.LOCAL]:
"https://cdn-latest.static.engineering.dev.paypalinc.com/qaRdaAssets/fraudnet/async/fb-raw.js",
[ENV.STAGE]:
"https://cdn-latest.static.engineering.dev.paypalinc.com/qaRdaAssets/fraudnet/async/fb-raw.js",
[ENV.SANDBOX]: "https://c.paypal.com/da/r/fb.js",
[ENV.PRODUCTION]: "https://c.paypal.com/da/r/fb.js",
[ENV.TEST]: "https://c.paypal.com/da/r/fb.js",
};

export const FRAUDNET_FNCLS = "fnparams-dede7cc5-15fd-4c75-a9f4-36c430ee3a99";
141 changes: 141 additions & 0 deletions src/fraudnet.js
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 */
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from "./logger";
export * from "./types";
export * from "./global";
export * from "./script";
export * from "./fraudnet";
export * from "./meta";
export * from "./api";
export * from "./experiment";
Expand Down

0 comments on commit 678c6d8

Please sign in to comment.