@fat-zebra/sdk 1.4.15 → 1.5.1
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/.jest/setup-env-vars.js +1 -0
- package/README.dev.md +1 -14
- package/build-styles.js +12 -0
- package/dist/click_to_pay/index.d.ts +5 -2
- package/dist/click_to_pay/index.js +57 -12
- package/dist/hpp/hpp.js +2 -0
- package/dist/local/fatzebra.css +91 -0
- package/dist/local/fatzebra.js.map +1 -1
- package/dist/main.d.ts +4 -2
- package/dist/main.js +24 -20
- package/dist/react/VerifyCard.d.ts +2 -2
- package/dist/react/VerifyCard.js +4 -4
- package/dist/react/VerifyExistingCard.d.ts +10 -0
- package/dist/react/VerifyExistingCard.js +12 -0
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +2 -1
- package/dist/react/paymentUrl.d.ts +12 -0
- package/dist/react/paymentUrl.js +33 -0
- package/dist/react/useFatZebra.d.ts +4 -2
- package/dist/react/useFatZebra.js +7 -5
- package/dist/react/verifyUrl.d.ts +8 -0
- package/dist/react/verifyUrl.js +22 -0
- package/dist/sca/cardinal.d.ts +11 -10
- package/dist/sca/cardinal.js +31 -9
- package/dist/sca/index.d.ts +3 -0
- package/dist/sca/index.js +52 -46
- package/dist/shared/api-gateway-client.d.ts +0 -7
- package/dist/shared/api-gateway-client.js +1 -35
- package/dist/shared/event-manager.d.ts +3 -1
- package/dist/shared/event-manager.js +7 -1
- package/dist/shared/types.d.ts +7 -12
- package/dist/shared/types.js +3 -6
- package/dist/validation/index.d.ts +1 -0
- package/dist/validation/index.js +1 -0
- package/dist/validation/schemas/click-to-pay/payment-intent.json +1 -1
- package/package.json +6 -7
package/.jest/setup-env-vars.js
CHANGED
package/README.dev.md
CHANGED
|
@@ -109,19 +109,6 @@ Visit https://fzapplepay.ngrok.io in Safari. That's all!
|
|
|
109
109
|
|
|
110
110
|
Webpack-dev-server supports hot reloading, meaning that code changes are reflected on the web page without restarting the server.
|
|
111
111
|
|
|
112
|
-
## PayPal
|
|
113
|
-
|
|
114
|
-
You can build & run for PayPal integration using:
|
|
115
|
-
```bash
|
|
116
|
-
npm run start:dev:paypal
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
You can also change the order request in:
|
|
120
|
-
```bash
|
|
121
|
-
# Change the `data` argument in the `paymentMethod` field
|
|
122
|
-
examples/paypal/merchant.ejs
|
|
123
|
-
```
|
|
124
|
-
|
|
125
112
|
## Build Javascript
|
|
126
113
|
|
|
127
114
|
There are two npm build scripts in `package.json` for building javascript files.
|
|
@@ -159,4 +146,4 @@ The release of the sdk follows a weekly schedule. In the beginning of a new rele
|
|
|
159
146
|
10. Prepare a new git tag for the new release version `git tag -a vX.X.X`.
|
|
160
147
|
11. Push git tag. `git push origin vX.X.X`.
|
|
161
148
|
|
|
162
|
-
Upon successful CI , a new entry with title 'Merged in release/vX.X,X' will be visible in the master branch page. This provides us with a clear view of what gets released in the past. Moreoever, we can quickly find out the list of features/bug fixes in a release by referring to the PR of the release candidate.
|
|
149
|
+
Upon successful CI , a new entry with title 'Merged in release/vX.X,X' will be visible in the master branch page. This provides us with a clear view of what gets released in the past. Moreoever, we can quickly find out the list of features/bug fixes in a release by referring to the PR of the release candidate.
|
package/build-styles.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
// Define the source file and the destination folder
|
|
5
|
+
const sourceFile = path.join(__dirname, './src/styles.css');
|
|
6
|
+
const destinationFolder = path.join(__dirname, 'dist/' + process.env.ENVIRONMENT);
|
|
7
|
+
const destinationFile = path.join(destinationFolder, 'fatzebra.css');
|
|
8
|
+
|
|
9
|
+
// Copy the file
|
|
10
|
+
fs.copyFileSync(sourceFile, destinationFile);
|
|
11
|
+
|
|
12
|
+
console.log('File copied successfully!');
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { PaymentIntent } from "../shared/types";
|
|
2
2
|
import { ClickToPayOptions } from "./types";
|
|
3
|
+
export declare const CLICK_TO_PAY_DEFAULT_OPTIONS: {
|
|
4
|
+
[key: string]: boolean | string;
|
|
5
|
+
};
|
|
3
6
|
interface ClickToPayModuleConfig {
|
|
4
7
|
paymentIntent: PaymentIntent;
|
|
5
8
|
username: string;
|
|
@@ -14,15 +17,15 @@ declare class ClickToPay {
|
|
|
14
17
|
private iframe;
|
|
15
18
|
private paymentIntent;
|
|
16
19
|
private username;
|
|
17
|
-
private cardToken;
|
|
18
20
|
private postMessageClient;
|
|
19
21
|
private test;
|
|
20
22
|
private options;
|
|
21
23
|
constructor(config: ClickToPayModuleConfig);
|
|
22
24
|
load(config: ClickToPayLoadParams): void;
|
|
23
25
|
getPayNowUrl(options?: {
|
|
24
|
-
[key: string]:
|
|
26
|
+
[key: string]: any;
|
|
25
27
|
}): string;
|
|
28
|
+
setCrossFramesEventListeners(): void;
|
|
26
29
|
purchase(): void;
|
|
27
30
|
}
|
|
28
31
|
export default ClickToPay;
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PostMessageClient } from "../shared/post-message-client";
|
|
2
|
+
import { BridgeEvent, PublicEvent } from "../shared/types";
|
|
2
3
|
import * as util from '../shared/util';
|
|
3
|
-
|
|
4
|
+
import { emit } from "../shared/event-manager";
|
|
5
|
+
export const CLICK_TO_PAY_DEFAULT_OPTIONS = {
|
|
4
6
|
iframe: true,
|
|
7
|
+
postmessage: true,
|
|
5
8
|
};
|
|
6
9
|
class ClickToPay {
|
|
7
10
|
constructor(config) {
|
|
8
11
|
this.paymentIntent = config.paymentIntent;
|
|
9
12
|
this.username = config.username;
|
|
10
13
|
this.test = config.test;
|
|
14
|
+
this.postMessageClient = new PostMessageClient({
|
|
15
|
+
channel: 'click_to_pay',
|
|
16
|
+
target: this.iframe
|
|
17
|
+
});
|
|
11
18
|
}
|
|
12
19
|
load(config) {
|
|
13
20
|
this.options = config.options;
|
|
@@ -15,6 +22,9 @@ class ClickToPay {
|
|
|
15
22
|
document.getElementById(config.containerId).appendChild(this.iframe);
|
|
16
23
|
const payNowUrl = this.getPayNowUrl(config.options);
|
|
17
24
|
this.iframe.setAttribute("src", payNowUrl);
|
|
25
|
+
this.iframe.onload = () => {
|
|
26
|
+
this.setCrossFramesEventListeners();
|
|
27
|
+
};
|
|
18
28
|
}
|
|
19
29
|
getPayNowUrl(options) {
|
|
20
30
|
const { payment } = this.paymentIntent;
|
|
@@ -25,18 +35,53 @@ class ClickToPay {
|
|
|
25
35
|
this.username,
|
|
26
36
|
payment.reference,
|
|
27
37
|
payment.currency,
|
|
28
|
-
|
|
38
|
+
// If amount is left as 0 (type: Number), it will be filtered out later
|
|
39
|
+
// So we convert to string as "0" will be allowed through the filter
|
|
40
|
+
// Yes, we do want $0 purchases (especially for tokenizeOnly / auth flows)
|
|
41
|
+
payment.amount.toString(),
|
|
29
42
|
this.paymentIntent.verification
|
|
30
43
|
].filter(part => part).join('/');
|
|
31
|
-
let
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
let searchParams = new URLSearchParams();
|
|
45
|
+
const combinedOptions = Object.assign(Object.assign({}, CLICK_TO_PAY_DEFAULT_OPTIONS), options);
|
|
46
|
+
Object.keys(combinedOptions).map(key => {
|
|
47
|
+
if (combinedOptions[key] !== null && combinedOptions[key] !== undefined) {
|
|
48
|
+
searchParams.append(util.toSnakeCase(key), combinedOptions[key]);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return searchParams.toString().length > 0 ? `${base}?${searchParams.toString()}` : `${base}`;
|
|
52
|
+
}
|
|
53
|
+
setCrossFramesEventListeners() {
|
|
54
|
+
const handlers = {};
|
|
55
|
+
handlers[BridgeEvent.TOKENIZE_CARD_RESPONSE] = (data) => {
|
|
56
|
+
if (data.errors) {
|
|
57
|
+
emit(PublicEvent.TOKENIZATION_ERROR, {
|
|
58
|
+
message: 'Card tokenization failed.',
|
|
59
|
+
errors: data.errors,
|
|
60
|
+
data: null,
|
|
61
|
+
});
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
emit(PublicEvent.TOKENIZATION_SUCCESS, {
|
|
66
|
+
message: 'Card tokenization success.',
|
|
67
|
+
data
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
handlers[PublicEvent.CLICK_TO_PAY_TOKENIZATION_ERROR] = (data) => {
|
|
72
|
+
emit(PublicEvent.CLICK_TO_PAY_TOKENIZATION_ERROR, {
|
|
73
|
+
message: 'Card tokenization failed.',
|
|
74
|
+
errors: data.errors,
|
|
75
|
+
data: null,
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
handlers[PublicEvent.CLICK_TO_PAY_TOKENIZATION_SUCCESS] = (data) => {
|
|
79
|
+
emit(PublicEvent.CLICK_TO_PAY_TOKENIZATION_SUCCESS, {
|
|
80
|
+
message: 'Card tokenization success.',
|
|
81
|
+
data
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
this.postMessageClient.setEventListeners(handlers);
|
|
40
85
|
}
|
|
41
86
|
purchase() {
|
|
42
87
|
const message = {
|
package/dist/hpp/hpp.js
CHANGED
|
@@ -154,6 +154,8 @@ class Hpp {
|
|
|
154
154
|
}
|
|
155
155
|
setPublicEventListeners() {
|
|
156
156
|
const handler = (event) => {
|
|
157
|
+
if (this.hppOptions.tokenizeOnly)
|
|
158
|
+
return;
|
|
157
159
|
const threedsData = event.detail.data;
|
|
158
160
|
const extra = util.toObjectWithSnakeCaseKeys(threedsData);
|
|
159
161
|
this.createPurchase(extra);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
.checkout-button-wrapper {
|
|
2
|
+
display: flex;
|
|
3
|
+
justify-content: center;
|
|
4
|
+
align-items: center;
|
|
5
|
+
height: 200px;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.iframe-checkout {
|
|
9
|
+
flex: 1;
|
|
10
|
+
border: none;
|
|
11
|
+
width: 100%;
|
|
12
|
+
height: 100%;
|
|
13
|
+
min-height: 0;
|
|
14
|
+
overflow: auto;
|
|
15
|
+
-webkit-overflow-scrolling: touch;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.iframe-foreground,
|
|
19
|
+
.iframe-background {
|
|
20
|
+
top: 0;
|
|
21
|
+
left: 0;
|
|
22
|
+
right: 0;
|
|
23
|
+
bottom: 0;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.iframe-foreground,
|
|
28
|
+
.iframe-background {
|
|
29
|
+
position: fixed;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.iframe-foreground {
|
|
33
|
+
z-index: -1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.iframe-background {
|
|
37
|
+
background: rgba(0, 0, 0, 0.5);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.iframe-foreground {
|
|
41
|
+
flex-grow: 1;
|
|
42
|
+
top: auto;
|
|
43
|
+
width: 100%;
|
|
44
|
+
max-width: 480px;
|
|
45
|
+
height: 80vh;
|
|
46
|
+
background-color: #ffffff;
|
|
47
|
+
border-radius: 25px 25px 0 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.slide-in .iframe-foreground {
|
|
51
|
+
transform: translateY(100vh);
|
|
52
|
+
transition: transform 0.4s ease, z-index 0.3s ease 0.4s;
|
|
53
|
+
z-index: -1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.slide-in .iframe-background {
|
|
57
|
+
opacity: 0;
|
|
58
|
+
z-index: -1;
|
|
59
|
+
transition: opacity 0.3s ease, z-index 0.3s ease 0.3s;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.slide-in.show .iframe-foreground {
|
|
63
|
+
transform: none;
|
|
64
|
+
transition: transform 0.4s ease;
|
|
65
|
+
z-index: 100;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.slide-in.show .iframe-background {
|
|
69
|
+
opacity: 1;
|
|
70
|
+
z-index: 0;
|
|
71
|
+
transition: opacity 0.3s ease;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@media only screen and (min-width: 480px) {
|
|
75
|
+
.iframe-foreground {
|
|
76
|
+
margin: 0 auto;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@media only screen and (min-width: 768px) {
|
|
81
|
+
.iframe-foreground {
|
|
82
|
+
margin: 0;
|
|
83
|
+
width: 400px;
|
|
84
|
+
height: 100vh;
|
|
85
|
+
left: 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.slide-in .iframe-foreground {
|
|
89
|
+
transform: translateX(-400px);
|
|
90
|
+
}
|
|
91
|
+
}
|