@paypal/checkout-components 5.0.347 → 5.0.348
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/button.js +1 -1
- package/dist/test/button.js +1 -1
- package/package.json +8 -4
- package/src/funding/venmo/config.jsx +10 -8
- package/src/funding/venmo/config.test.js +3 -2
- package/src/lib/appSwitchResume.js +35 -33
- package/src/lib/appSwithResume.test.js +6 -14
- package/src/three-domain-secure/api.js +3 -28
- package/src/three-domain-secure/component.jsx +5 -34
- package/src/three-domain-secure/component.test.js +1 -2
- package/src/three-domain-secure/interface.js +3 -5
- package/src/three-domain-secure/interface.test.js +2 -2
- package/src/three-domain-secure/utils.jsx +2 -2
- package/src/three-domain-secure/utils.test.js +3 -3
- package/src/types.js +1 -0
- package/src/zoid/buttons/component.jsx +15 -5
- package/src/zoid/card-fields/component.jsx +12 -0
- package/src/zoid/venmo/component.jsx +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paypal/checkout-components",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.348",
|
|
4
4
|
"description": "PayPal Checkout components, for integrating checkout products.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"debug": "cross-env NODE_ENV=debug",
|
|
13
13
|
"delete-size": "rm dist/size.* dist/report.html",
|
|
14
14
|
"demo": "serve ./demo -l 1337",
|
|
15
|
-
"dev": "npm run check-node-version && babel-node
|
|
15
|
+
"dev": "npm run check-node-version && babel-node ./node_modules/.bin/webpack-dev-server -- --config webpack.config.dev.js --port 9001 --host localhost.paypal.com --open /index.htm --https --hot=false --static './demo/dev'",
|
|
16
16
|
"eslint-find-rules": "eslint-find-rules --current .eslintrc.js --unused --plugin",
|
|
17
17
|
"flow": "flow",
|
|
18
18
|
"flow-typed": "rm -rf flow-typed && flow-typed install && rm flow-typed/npm/puppeteer_*",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"jest-e2e": "rm -f ./test/e2e/screenshots/*.png && jest test/e2e",
|
|
22
22
|
"jest-screenshot": "jest test/screenshot --env=node --no-cache",
|
|
23
23
|
"jest-ssr": "jest test/ssr --env=node --no-cache --collectCoverage --collectCoverageFrom='src/' --coverageDirectory='coverage/jest'",
|
|
24
|
-
"karma": "cross-env NODE_ENV=test babel-node
|
|
24
|
+
"karma": "cross-env NODE_ENV=test babel-node ./node_modules/.bin/karma start",
|
|
25
25
|
"lint": "eslint --ext .js --ext .jsx src/ test/ *.js",
|
|
26
26
|
"postversion": "./scripts/postversion.sh",
|
|
27
27
|
"preversion": "./scripts/preversion.sh",
|
|
@@ -34,11 +34,15 @@
|
|
|
34
34
|
"typecheck": "npm run flow",
|
|
35
35
|
"version": "./scripts/version.sh",
|
|
36
36
|
"vitest": "vitest",
|
|
37
|
-
"webpack": "babel-node
|
|
37
|
+
"webpack": "babel-node ./node_modules/.bin/webpack --",
|
|
38
38
|
"webpack-size": "npm run webpack -- --config webpack.config.size",
|
|
39
39
|
"prepare": "husky install",
|
|
40
40
|
"screenshot-server": "babel-node ./test/percy/server/index.js"
|
|
41
41
|
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": "^18",
|
|
44
|
+
"npm": "8"
|
|
45
|
+
},
|
|
42
46
|
"files": [
|
|
43
47
|
"src/",
|
|
44
48
|
"dist/",
|
|
@@ -23,19 +23,20 @@ export function getVenmoConfig(): FundingSourceConfig {
|
|
|
23
23
|
|
|
24
24
|
eligible: ({ experiment, shippingChange, displayOnly, flow }) => {
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* enableVenmo checks native browser compatibility and ramp
|
|
27
|
+
* ignore above compatibility if forcing to web
|
|
28
28
|
*/
|
|
29
|
-
if (
|
|
29
|
+
if (
|
|
30
|
+
experiment &&
|
|
31
|
+
experiment.enableVenmo === false &&
|
|
32
|
+
experiment.venmoWebEnabled !== true &&
|
|
33
|
+
experiment.venmoEnableWebOnNonNativeBrowser !== true
|
|
34
|
+
) {
|
|
30
35
|
return false;
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
/**
|
|
34
39
|
* Shipping callbacks will not work with Venmo unless venmo web is enabled.
|
|
35
|
-
*
|
|
36
|
-
* Note that this could cause the Venmo button to not show up on first render
|
|
37
|
-
* if a merchant passes a shipping callback but does not have a client ID
|
|
38
|
-
* that has Venmo Web enabled.
|
|
39
40
|
*/
|
|
40
41
|
if (!experiment?.venmoWebEnabled && shippingChange) {
|
|
41
42
|
return false;
|
|
@@ -62,7 +63,8 @@ export function getVenmoConfig(): FundingSourceConfig {
|
|
|
62
63
|
if (
|
|
63
64
|
platform === PLATFORM.MOBILE &&
|
|
64
65
|
experiment &&
|
|
65
|
-
experiment.venmoWebEnabled
|
|
66
|
+
experiment.venmoWebEnabled !== true &&
|
|
67
|
+
experiment.venmoEnableWebOnNonNativeBrowser !== true
|
|
66
68
|
) {
|
|
67
69
|
return {
|
|
68
70
|
native: true,
|
|
@@ -13,6 +13,7 @@ describe("Venmo eligibility", () => {
|
|
|
13
13
|
fundingEligibility: {},
|
|
14
14
|
experiment: {
|
|
15
15
|
venmoWebEnabled: true,
|
|
16
|
+
venmoEnableWebOnNonNativeBrowser: true,
|
|
16
17
|
},
|
|
17
18
|
wallet: expect.any,
|
|
18
19
|
flow: BUTTON_FLOW.PURCHASE,
|
|
@@ -74,7 +75,7 @@ describe("Venmo eligibility", () => {
|
|
|
74
75
|
expect(isVenmoEligible).toEqual(true);
|
|
75
76
|
});
|
|
76
77
|
|
|
77
|
-
test("should not be eligible if a shipping callback is passed & experiment does not include venmoWebEnabled", () => {
|
|
78
|
+
test("should not be eligible if a shipping callback is passed & experiment does not include venmoWebEnabled or venmoEnableWebOnNonNativeBrowser", () => {
|
|
78
79
|
const isVenmoEligible = venmoConfig.eligible?.({
|
|
79
80
|
...baseEligibilityProps,
|
|
80
81
|
experiment: {},
|
|
@@ -84,7 +85,7 @@ describe("Venmo eligibility", () => {
|
|
|
84
85
|
expect(isVenmoEligible).toEqual(false);
|
|
85
86
|
});
|
|
86
87
|
|
|
87
|
-
test("should be eligible if shipping callback exists & experiment includes venmoWebEnabled", () => {
|
|
88
|
+
test("should be eligible if shipping callback exists & experiment includes venmoWebEnabled or venmoEnableWebOnNonNativeBrowser", () => {
|
|
88
89
|
const isVenmoEligible = venmoConfig.eligible?.({
|
|
89
90
|
...baseEligibilityProps,
|
|
90
91
|
shippingChange: true,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* @flow */
|
|
2
2
|
import { FUNDING } from "@paypal/sdk-constants/src";
|
|
3
|
+
import { parseQuery } from "@krakenjs/belter/src";
|
|
3
4
|
|
|
4
5
|
import { APP_SWITCH_RETURN_HASH } from "../constants";
|
|
5
6
|
|
|
@@ -16,46 +17,47 @@ export type AppSwitchResumeParams = {|
|
|
|
16
17
|
|};
|
|
17
18
|
|
|
18
19
|
export function getAppSwitchResumeParams(): AppSwitchResumeParams | null {
|
|
19
|
-
const
|
|
20
|
+
const hashString = window.location.hash && window.location.hash.slice(1);
|
|
21
|
+
const [hash, queryString] = hashString.split("?");
|
|
22
|
+
|
|
20
23
|
const isPostApprovalAction = [
|
|
21
24
|
APP_SWITCH_RETURN_HASH.ONAPPROVE,
|
|
22
25
|
APP_SWITCH_RETURN_HASH.ONCANCEL,
|
|
23
26
|
APP_SWITCH_RETURN_HASH.ONERROR,
|
|
24
|
-
].includes(
|
|
27
|
+
].includes(hash);
|
|
25
28
|
if (!isPostApprovalAction) {
|
|
26
29
|
return null;
|
|
27
30
|
}
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return null;
|
|
31
|
+
|
|
32
|
+
const {
|
|
33
|
+
token,
|
|
34
|
+
PayerID,
|
|
35
|
+
buttonSessionID,
|
|
36
|
+
billingToken,
|
|
37
|
+
paymentID,
|
|
38
|
+
subscriptionID,
|
|
39
|
+
vaultSetupToken,
|
|
40
|
+
fundingSource,
|
|
41
|
+
} = parseQuery(queryString);
|
|
42
|
+
|
|
43
|
+
const params: AppSwitchResumeParams = {
|
|
44
|
+
orderID: token,
|
|
45
|
+
buttonSessionID,
|
|
46
|
+
payerID: PayerID,
|
|
47
|
+
billingToken,
|
|
48
|
+
paymentID,
|
|
49
|
+
subscriptionID,
|
|
50
|
+
// URLSearchParams get returns as string,
|
|
51
|
+
// but below code excepts a value from list of string.
|
|
52
|
+
// $FlowIgnore[incompatible-type]
|
|
53
|
+
fundingSource,
|
|
54
|
+
vaultSetupToken,
|
|
55
|
+
// the isPostApprovalAction already ensures
|
|
56
|
+
// that the function will exit if url hash is not one of supported values.
|
|
57
|
+
// $FlowIgnore[incompatible-type]
|
|
58
|
+
checkoutState: hash,
|
|
59
|
+
};
|
|
60
|
+
return params;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
export function isAppSwitchResumeFlow(): boolean {
|
|
@@ -26,23 +26,17 @@ describe("app switch resume flow", () => {
|
|
|
26
26
|
|
|
27
27
|
test("should test fetching resume params when parameters are correctly passed", () => {
|
|
28
28
|
vi.spyOn(window, "location", "get").mockReturnValue({
|
|
29
|
-
hash:
|
|
30
|
-
search: `buttonSessionID=${buttonSessionID}&orderID=${orderID}&fundingSource=${fundingSource}`,
|
|
29
|
+
hash: `#onApprove?buttonSessionID=${buttonSessionID}&token=${orderID}&fundingSource=${fundingSource}`,
|
|
31
30
|
});
|
|
32
31
|
|
|
33
32
|
const params = getAppSwitchResumeParams();
|
|
34
33
|
|
|
35
34
|
expect.assertions(2);
|
|
36
35
|
expect(params).toEqual({
|
|
37
|
-
billingToken: null,
|
|
38
36
|
buttonSessionID,
|
|
39
37
|
checkoutState: "onApprove",
|
|
40
38
|
fundingSource,
|
|
41
39
|
orderID,
|
|
42
|
-
payerID: null,
|
|
43
|
-
paymentID: null,
|
|
44
|
-
subscriptionID: null,
|
|
45
|
-
vaultSetupToken: null,
|
|
46
40
|
});
|
|
47
41
|
expect(isAppSwitchResumeFlow()).toEqual(true);
|
|
48
42
|
});
|
|
@@ -50,7 +44,7 @@ describe("app switch resume flow", () => {
|
|
|
50
44
|
test("should test fetching resume params with invalid callback passed", () => {
|
|
51
45
|
vi.spyOn(window, "location", "get").mockReturnValue({
|
|
52
46
|
hash: "#Unknown",
|
|
53
|
-
search: `buttonSessionID=${buttonSessionID}&
|
|
47
|
+
search: `buttonSessionID=${buttonSessionID}&token=${orderID}&fundingSource=${fundingSource}`,
|
|
54
48
|
});
|
|
55
49
|
|
|
56
50
|
const params = getAppSwitchResumeParams();
|
|
@@ -62,8 +56,7 @@ describe("app switch resume flow", () => {
|
|
|
62
56
|
|
|
63
57
|
test("should test null fetching resume params with invalid callback passed", () => {
|
|
64
58
|
vi.spyOn(window, "location", "get").mockReturnValue({
|
|
65
|
-
hash:
|
|
66
|
-
search: `buttonSessionID=${buttonSessionID}&orderID=${orderID}&fundingSource=${fundingSource}`,
|
|
59
|
+
hash: `#Unknown?buttonSessionID=${buttonSessionID}&token=${orderID}&fundingSource=${fundingSource}`,
|
|
67
60
|
});
|
|
68
61
|
|
|
69
62
|
const params = getAppSwitchResumeParams();
|
|
@@ -73,10 +66,9 @@ describe("app switch resume flow", () => {
|
|
|
73
66
|
expect(isAppSwitchResumeFlow()).toEqual(false);
|
|
74
67
|
});
|
|
75
68
|
|
|
76
|
-
test("should test fetching resume params when parameters are correctly passed", () => {
|
|
69
|
+
test("should test fetching multiple resume params when parameters are correctly passed", () => {
|
|
77
70
|
vi.spyOn(window, "location", "get").mockReturnValue({
|
|
78
|
-
hash:
|
|
79
|
-
search: `buttonSessionID=${buttonSessionID}&orderID=${orderID}&fundingSource=${fundingSource}&billingToken=BA-124&payerID=PP-122&paymentID=PAY-123&subscriptionID=I-1234&vaultSetupToken=VA-3`,
|
|
71
|
+
hash: `#onApprove?buttonSessionID=${buttonSessionID}&token=${orderID}&fundingSource=${fundingSource}&billingToken=BA-124&PayerID=PP-payer-122&paymentID=PAY-123&subscriptionID=I-1234&vaultSetupToken=VA-3`,
|
|
80
72
|
});
|
|
81
73
|
|
|
82
74
|
const params = getAppSwitchResumeParams();
|
|
@@ -88,7 +80,7 @@ describe("app switch resume flow", () => {
|
|
|
88
80
|
checkoutState: "onApprove",
|
|
89
81
|
fundingSource,
|
|
90
82
|
orderID,
|
|
91
|
-
payerID: "PP-122",
|
|
83
|
+
payerID: "PP-payer-122",
|
|
92
84
|
paymentID: "PAY-123",
|
|
93
85
|
subscriptionID: "I-1234",
|
|
94
86
|
vaultSetupToken: "VA-3",
|
|
@@ -39,40 +39,15 @@ export class HTTPClient implements HTTPClientType {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export class RestClient extends HTTPClient {
|
|
42
|
-
request({
|
|
43
|
-
return callRestAPI({
|
|
44
|
-
url: baseURL ?? this.baseURL ?? "",
|
|
45
|
-
accessToken: this.accessToken,
|
|
46
|
-
...rest,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
authRequest({
|
|
42
|
+
request({
|
|
50
43
|
baseURL,
|
|
51
44
|
accessToken,
|
|
52
45
|
...rest
|
|
53
46
|
}: HTTPRequestOptions): ZalgoPromise<{ ... }> {
|
|
54
|
-
return
|
|
55
|
-
method: "post",
|
|
47
|
+
return callRestAPI({
|
|
56
48
|
url: baseURL ?? this.baseURL ?? "",
|
|
57
|
-
|
|
58
|
-
// $FlowIssue
|
|
59
|
-
Authorization: `Basic ${accessToken}`,
|
|
60
|
-
},
|
|
49
|
+
accessToken: accessToken ?? this.accessToken,
|
|
61
50
|
...rest,
|
|
62
|
-
}).then(({ body }) => {
|
|
63
|
-
if (body && body.error === "invalid_client") {
|
|
64
|
-
throw new Error(
|
|
65
|
-
`Auth Api invalid client id: \n\n${JSON.stringify(body, null, 4)}`
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (!body || !body.access_token) {
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Auth Api response error:\n\n${JSON.stringify(body, null, 4)}`
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return body.access_token;
|
|
76
51
|
});
|
|
77
52
|
}
|
|
78
53
|
}
|
|
@@ -3,24 +3,21 @@
|
|
|
3
3
|
/* eslint-disable no-restricted-globals, promise/no-native */
|
|
4
4
|
import { type LoggerType } from "@krakenjs/beaver-logger/src";
|
|
5
5
|
import { type ZoidComponent } from "@krakenjs/zoid/src";
|
|
6
|
-
import { base64encode } from "@krakenjs/belter/src";
|
|
7
6
|
import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
|
|
8
7
|
import { FPTI_KEY, CURRENCY } from "@paypal/sdk-constants/src";
|
|
9
8
|
|
|
10
|
-
import { PAYMENT_3DS_VERIFICATION
|
|
9
|
+
import { PAYMENT_3DS_VERIFICATION } from "../constants/api";
|
|
11
10
|
import { ValidationError } from "../lib";
|
|
12
11
|
|
|
13
12
|
import type {
|
|
14
13
|
requestData,
|
|
15
|
-
responseBody,
|
|
16
14
|
GqlResponse,
|
|
17
15
|
MerchantPayloadData,
|
|
18
16
|
SdkConfig,
|
|
19
17
|
ThreeDSResponse,
|
|
20
18
|
TDSProps,
|
|
21
|
-
Request,
|
|
22
19
|
} from "./types";
|
|
23
|
-
import {
|
|
20
|
+
import { getThreeDS } from "./utils";
|
|
24
21
|
import type { GraphQLClient, RestClient } from "./api";
|
|
25
22
|
|
|
26
23
|
const parseSdkConfig = ({ sdkConfig, logger }): SdkConfig => {
|
|
@@ -99,35 +96,9 @@ export class ThreeDomainSecureComponent {
|
|
|
99
96
|
const data = parseMerchantPayload({ merchantPayload });
|
|
100
97
|
this.fastlaneNonce = merchantPayload.nonce;
|
|
101
98
|
|
|
102
|
-
try {
|
|
103
|
-
const basicAuth = base64encode(`${this.sdkConfig.clientID}:`);
|
|
104
|
-
const authData = {
|
|
105
|
-
grant_type: `client_credentials`,
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
if (this.sdkConfig.merchantID?.length) {
|
|
109
|
-
// $FlowFixMe invalid error on key assignment
|
|
110
|
-
authData.target_subject = this.sdkConfig.merchantID[0];
|
|
111
|
-
}
|
|
112
|
-
// $FlowFixMe
|
|
113
|
-
const accessToken = await this.restClient.authRequest<Request, string>({
|
|
114
|
-
baseURL: `${this.sdkConfig.paypalApiDomain}${AUTH}`,
|
|
115
|
-
accessToken: `${basicAuth}`,
|
|
116
|
-
data: authData,
|
|
117
|
-
});
|
|
118
|
-
// $FlowIssue confusing ZalgoPromise return type with resolved string value
|
|
119
|
-
this.restClient.setAccessToken(accessToken);
|
|
120
|
-
} catch (error) {
|
|
121
|
-
this.logger.warn(error);
|
|
122
|
-
throw error;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
99
|
try {
|
|
126
100
|
// $FlowFixMe
|
|
127
|
-
const { status, links } = await this.restClient.request
|
|
128
|
-
requestData,
|
|
129
|
-
responseBody
|
|
130
|
-
>({
|
|
101
|
+
const { status, links } = await this.restClient.request({
|
|
131
102
|
method: "POST",
|
|
132
103
|
baseURL: `${this.sdkConfig.paypalApiDomain}/${PAYMENT_3DS_VERIFICATION}`,
|
|
133
104
|
data,
|
|
@@ -139,7 +110,7 @@ export class ThreeDomainSecureComponent {
|
|
|
139
110
|
(link) => link.rel === "payer-action"
|
|
140
111
|
).href;
|
|
141
112
|
responseStatus = true;
|
|
142
|
-
this.threeDSIframe =
|
|
113
|
+
this.threeDSIframe = getThreeDS();
|
|
143
114
|
}
|
|
144
115
|
return responseStatus;
|
|
145
116
|
} catch (error) {
|
|
@@ -180,7 +151,7 @@ export class ThreeDomainSecureComponent {
|
|
|
180
151
|
// Helios returns a boolen parameter: "success"
|
|
181
152
|
// It will be true for all cases where liability is shifted to merchant
|
|
182
153
|
// and false for downstream failures and errors
|
|
183
|
-
authenticationState = success ? "
|
|
154
|
+
authenticationState = success ? "succeeded" : "errored";
|
|
184
155
|
liabilityShift = liability_shift ? liability_shift : "false";
|
|
185
156
|
|
|
186
157
|
// call BT mutation to update fastlaneNonce with 3ds data
|
|
@@ -12,7 +12,7 @@ const defaultSdkConfig = {
|
|
|
12
12
|
authenticationToken: "sdk-client-token",
|
|
13
13
|
};
|
|
14
14
|
vi.mock("./utils", () => ({
|
|
15
|
-
|
|
15
|
+
getThreeDS: vi.fn(() => {
|
|
16
16
|
return vi.fn(() => ({
|
|
17
17
|
render: vi.fn().mockResolvedValue({}),
|
|
18
18
|
close: vi.fn(),
|
|
@@ -45,7 +45,6 @@ const mockRestClient = {
|
|
|
45
45
|
},
|
|
46
46
|
],
|
|
47
47
|
}),
|
|
48
|
-
authRequest: vi.fn(),
|
|
49
48
|
};
|
|
50
49
|
|
|
51
50
|
const mockEligibilityRequest = (body = defaultEligibilityResponse) => {
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
getPayPalAPIDomain,
|
|
6
6
|
getSDKToken,
|
|
7
7
|
getClientID,
|
|
8
|
-
getMerchantID,
|
|
9
8
|
} from "@paypal/sdk-client/src";
|
|
10
9
|
import { destroy as zoidDestroy } from "@krakenjs/zoid/src";
|
|
11
10
|
|
|
@@ -17,13 +16,13 @@ import {
|
|
|
17
16
|
type ThreeDomainSecureComponentInterface,
|
|
18
17
|
} from "./component";
|
|
19
18
|
import { GraphQLClient, RestClient } from "./api";
|
|
20
|
-
import {
|
|
19
|
+
import { getThreeDS } from "./utils";
|
|
21
20
|
|
|
22
21
|
const BRAINTREE_PROD = "https://payments.braintree-api.com";
|
|
23
22
|
const BRAINTREE_SANDBOX = "https://payments.sandbox.braintree-api.com";
|
|
24
23
|
|
|
25
24
|
export function setup() {
|
|
26
|
-
|
|
25
|
+
getThreeDS();
|
|
27
26
|
}
|
|
28
27
|
export function destroy(err?: mixed) {
|
|
29
28
|
zoidDestroy(err);
|
|
@@ -34,7 +33,7 @@ export const ThreeDomainSecureClient: LazyExport<ThreeDomainSecureComponentInter
|
|
|
34
33
|
__get__: () => {
|
|
35
34
|
const threeDomainSecureInstance = new ThreeDomainSecureComponent({
|
|
36
35
|
logger: getLogger(),
|
|
37
|
-
restClient: new RestClient(),
|
|
36
|
+
restClient: new RestClient({ accessToken: getSDKToken() }),
|
|
38
37
|
graphQLClient: new GraphQLClient({
|
|
39
38
|
baseURL:
|
|
40
39
|
getEnv() === "production" ? BRAINTREE_PROD : BRAINTREE_SANDBOX,
|
|
@@ -45,7 +44,6 @@ export const ThreeDomainSecureClient: LazyExport<ThreeDomainSecureComponentInter
|
|
|
45
44
|
authenticationToken: getSDKToken(),
|
|
46
45
|
paypalApiDomain: getPayPalAPIDomain(),
|
|
47
46
|
clientID: getClientID(),
|
|
48
|
-
merchantID: getMerchantID(),
|
|
49
47
|
},
|
|
50
48
|
});
|
|
51
49
|
return devEnvOnlyExport({
|
|
@@ -11,7 +11,7 @@ import { destroy as zoidDestroy } from "@krakenjs/zoid/src";
|
|
|
11
11
|
|
|
12
12
|
import { ThreeDomainSecureComponent } from "./component";
|
|
13
13
|
import { GraphQLClient, RestClient } from "./api";
|
|
14
|
-
import {
|
|
14
|
+
import { getThreeDS } from "./utils";
|
|
15
15
|
import { setup, destroy, ThreeDomainSecureClient } from "./interface";
|
|
16
16
|
|
|
17
17
|
vi.mock("@paypal/sdk-client/src");
|
|
@@ -23,7 +23,7 @@ vi.mock("./utils");
|
|
|
23
23
|
describe("ThreeDomainSecure interface", () => {
|
|
24
24
|
it("should setup and destroy", () => {
|
|
25
25
|
setup();
|
|
26
|
-
expect(
|
|
26
|
+
expect(getThreeDS).toHaveBeenCalledTimes(1);
|
|
27
27
|
|
|
28
28
|
const err = new Error("test error");
|
|
29
29
|
destroy(err);
|
|
@@ -18,8 +18,8 @@ import type { TDSProps } from "./types";
|
|
|
18
18
|
|
|
19
19
|
export type TDSComponent = ZoidComponent<TDSProps>;
|
|
20
20
|
|
|
21
|
-
export function
|
|
22
|
-
return inlineMemoize(
|
|
21
|
+
export function getThreeDS(): TDSComponent {
|
|
22
|
+
return inlineMemoize(getThreeDS, () => {
|
|
23
23
|
const component = create({
|
|
24
24
|
tag: "fastlane-threeds",
|
|
25
25
|
url: ({ props }) => props.payerActionUrl,
|
|
@@ -6,7 +6,7 @@ import { noop } from "@krakenjs/belter/src";
|
|
|
6
6
|
import { describe, expect, vi } from "vitest";
|
|
7
7
|
import { getEnv } from "@paypal/sdk-client/src";
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { getThreeDS } from "./utils";
|
|
10
10
|
|
|
11
11
|
vi.mock("@paypal/sdk-client/src");
|
|
12
12
|
|
|
@@ -27,7 +27,7 @@ describe("Three Domain Secure Utils", () => {
|
|
|
27
27
|
type: "zoidComponent",
|
|
28
28
|
}));
|
|
29
29
|
|
|
30
|
-
const fastlaneComponent =
|
|
30
|
+
const fastlaneComponent = getThreeDS();
|
|
31
31
|
expect(fastlaneComponent).toBeDefined();
|
|
32
32
|
// expect(createMock).toHaveBeenCalledTimes(1);
|
|
33
33
|
});
|
|
@@ -43,7 +43,7 @@ describe("Three Domain Secure Utils", () => {
|
|
|
43
43
|
type: "zoidComponent",
|
|
44
44
|
}));
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
getThreeDS();
|
|
47
47
|
|
|
48
48
|
expect(window.xchild).toBeDefined();
|
|
49
49
|
expect(window.xchild).toEqual({
|
package/src/types.js
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
getSDKAttribute,
|
|
43
43
|
getJsSdkLibrary,
|
|
44
44
|
wasShopperInsightsUsed,
|
|
45
|
+
isPayPalTrustedUrl,
|
|
45
46
|
} from "@paypal/sdk-client/src";
|
|
46
47
|
import {
|
|
47
48
|
rememberFunding,
|
|
@@ -292,15 +293,24 @@ export const getButtonsComponent: () => ButtonsComponent = memoize(() => {
|
|
|
292
293
|
},
|
|
293
294
|
|
|
294
295
|
props: {
|
|
295
|
-
// App Switch Properties
|
|
296
296
|
appSwitchWhenAvailable: {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
// change this to a boolean - Shane 11 Dec 2024
|
|
300
|
-
type: "string",
|
|
297
|
+
type: "boolean",
|
|
298
|
+
queryParam: true,
|
|
301
299
|
required: false,
|
|
302
300
|
},
|
|
303
301
|
|
|
302
|
+
redirect: {
|
|
303
|
+
type: "function",
|
|
304
|
+
sendToChild: true,
|
|
305
|
+
value: () => (url) => {
|
|
306
|
+
if (isPayPalTrustedUrl(url)) {
|
|
307
|
+
location.href = url;
|
|
308
|
+
} else {
|
|
309
|
+
throw new Error(`Unable to redirect to provided url ${url}`);
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
|
|
304
314
|
hashChangeHandler: {
|
|
305
315
|
type: "function",
|
|
306
316
|
sendToChild: false,
|
|
@@ -77,6 +77,7 @@ type CardFieldsProps = {|
|
|
|
77
77
|
fundingEligibility: FundingEligibilityType,
|
|
78
78
|
disableCard?: $ReadOnlyArray<$Values<typeof CARD>>,
|
|
79
79
|
currency: $Values<typeof CURRENCY>,
|
|
80
|
+
amount: string,
|
|
80
81
|
intent: $Values<typeof INTENT>,
|
|
81
82
|
commit: boolean,
|
|
82
83
|
vault: boolean,
|
|
@@ -297,6 +298,12 @@ export const getCardFieldsComponent: () => CardFieldsComponent = memoize(
|
|
|
297
298
|
value: ({ props }) => props.parent.props.locale,
|
|
298
299
|
},
|
|
299
300
|
|
|
301
|
+
amount: {
|
|
302
|
+
type: "object",
|
|
303
|
+
value: ({ props }) => props.parent.props.amount,
|
|
304
|
+
required: false,
|
|
305
|
+
},
|
|
306
|
+
|
|
300
307
|
onApprove: {
|
|
301
308
|
type: "function",
|
|
302
309
|
required: false,
|
|
@@ -639,6 +646,11 @@ export const getCardFieldsComponent: () => CardFieldsComponent = memoize(
|
|
|
639
646
|
value: getLocale,
|
|
640
647
|
},
|
|
641
648
|
|
|
649
|
+
amount: {
|
|
650
|
+
type: "object",
|
|
651
|
+
required: false,
|
|
652
|
+
},
|
|
653
|
+
|
|
642
654
|
onApprove: {
|
|
643
655
|
type: "function",
|
|
644
656
|
required: false,
|
|
@@ -296,6 +296,12 @@ export function getVenmoCheckoutComponent(): VenmoCheckoutComponent {
|
|
|
296
296
|
required: false,
|
|
297
297
|
},
|
|
298
298
|
|
|
299
|
+
venmoEnableWebOnNonNativeBrowser: {
|
|
300
|
+
type: "boolean",
|
|
301
|
+
queryParam: true,
|
|
302
|
+
required: false,
|
|
303
|
+
},
|
|
304
|
+
|
|
299
305
|
venmoVaultEnabled: {
|
|
300
306
|
type: "boolean",
|
|
301
307
|
queryParam: true,
|