@fat-zebra/sdk 2.0.2-beta.1 → 2.0.2-beta.3

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/hpp/hpp.d.ts CHANGED
@@ -38,6 +38,7 @@ interface HppOptions {
38
38
  tokenizeOnly?: boolean;
39
39
  }
40
40
  declare class Hpp {
41
+ static readonly displayName = "Hpp";
41
42
  private iframe;
42
43
  private headless;
43
44
  private version;
@@ -50,16 +51,10 @@ declare class Hpp {
50
51
  private postMessageClient;
51
52
  private test;
52
53
  private hppOptions;
53
- private headlessLoaded;
54
- private headlessPreviouslyLoaded;
55
- private iframeLoaded;
56
54
  private isThreeDSecureEnabled;
57
55
  private challengeWindowSize;
58
56
  private scaHandler;
59
- private crossFrameListenersBound;
60
- private publicEventListenersBound;
61
57
  constructor(config: HppModuleConfig);
62
- setListenersAndEmitReady(): void;
63
58
  load(config: HppLoadParams): void;
64
59
  purchase(): void;
65
60
  getPayNowUrl(options?: {
@@ -71,6 +66,7 @@ declare class Hpp {
71
66
  createPurchase(extra?: {
72
67
  [key: string]: boolean | string;
73
68
  }): void;
74
- private reportHppStatus;
69
+ private reportIframeLoaded;
70
+ private reportTokenizeCardResponse;
75
71
  }
76
72
  export { Hpp, type HppLoadParams, HPP_DEFAULT_OPTIONS, };
package/dist/hpp/hpp.js CHANGED
@@ -40,66 +40,33 @@ class Hpp {
40
40
  this.sca = config.sca;
41
41
  this.test = config.test;
42
42
  this.version = config.version || 2;
43
- this.headlessLoaded = false;
44
- this.headlessPreviouslyLoaded = false;
45
- this.iframeLoaded = false;
46
43
  this.threeDSecure = config.threeDSecure;
47
- this.crossFrameListenersBound = false;
48
- this.publicEventListenersBound = false;
49
44
  this.isThreeDSecureEnabled = (_a = config.isThreeDSecureEnabled) !== null && _a !== void 0 ? _a : false;
50
45
  configureLogger({
51
46
  baseUrl: env[process.env.API_ENV].payNowUrl
52
47
  });
53
48
  }
54
- setListenersAndEmitReady() {
55
- this.reportHppStatus(this);
56
- if (!this.crossFrameListenersBound) {
57
- this.setCrossFramesEventListeners();
58
- this.crossFrameListenersBound = true;
59
- }
60
- if (this.headlessLoaded && this.iframeLoaded) {
61
- if (!this.publicEventListenersBound && !this.isThreeDSecureEnabled) {
62
- this.setPublicEventListeners();
63
- this.publicEventListenersBound = true;
64
- }
65
- emit(PublicEvent.HPP_READY);
66
- }
67
- else if (this.headlessPreviouslyLoaded && this.iframeLoaded) {
68
- // subsequent iframe loads after headless has been previously loaded
69
- // this caters for the SPA scenario
70
- if (!this.publicEventListenersBound && !this.isThreeDSecureEnabled) {
71
- this.setPublicEventListeners();
72
- this.publicEventListenersBound = true;
73
- }
74
- emit(PublicEvent.HPP_READY);
75
- }
76
- }
77
49
  load(config) {
78
50
  var _a;
79
51
  this.challengeWindowSize = (_a = config.options) === null || _a === void 0 ? void 0 : _a.challengeWindowSize;
80
52
  setTransactionReference(config.paymentIntent.payment.reference);
81
53
  this.hppOptions = config.options || {};
82
- const { el, isExisting } = bridge.load2(process.env.PAYNOW_BRIDGE_URL);
54
+ const { el } = bridge.load2(process.env.PAYNOW_BRIDGE_URL);
83
55
  this.headless = el;
84
- this.headlessPreviouslyLoaded = isExisting;
85
56
  this.iframe = document.createElement('iframe');
86
57
  document.getElementById(config.containerId).appendChild(this.iframe);
87
58
  this.postMessageClient = new PostMessageClient({
88
59
  channel: 'sca',
89
60
  target: this.iframe
90
61
  });
91
- this.headless.addEventListener('load', () => {
92
- this.headlessLoaded = true;
93
- this.setListenersAndEmitReady();
94
- });
62
+ this.setCrossFramesEventListeners();
95
63
  this.iframe.onload = () => {
96
- this.iframeLoaded = true;
97
- this.setListenersAndEmitReady();
64
+ this.reportIframeLoaded();
65
+ if (!this.isThreeDSecureEnabled) {
66
+ this.setPublicEventListeners();
67
+ }
68
+ emit(PublicEvent.HPP_READY);
98
69
  };
99
- if (this.headlessPreviouslyLoaded) {
100
- this.headlessLoaded = true;
101
- this.setListenersAndEmitReady();
102
- }
103
70
  const payNowUrl = this.getPayNowUrl(config.options);
104
71
  this.iframe.setAttribute("src", payNowUrl);
105
72
  this.iframe.setAttribute('allow', 'payment');
@@ -140,6 +107,7 @@ class Hpp {
140
107
  const handlers = {};
141
108
  handlers[BridgeEvent.TOKENIZE_CARD_RESPONSE] = (data) => {
142
109
  var _a;
110
+ this.reportTokenizeCardResponse(data);
143
111
  if (data.source === 'verifyCard')
144
112
  return;
145
113
  if (data.errors) {
@@ -250,14 +218,11 @@ class Hpp {
250
218
  on(PublicEvent.SCA_SUCCESS, this.scaHandler);
251
219
  }
252
220
  destroy() {
253
- if (this.publicEventListenersBound && this.scaHandler) {
221
+ var _a;
222
+ if (this.scaHandler) {
254
223
  off(PublicEvent.SCA_SUCCESS, this.scaHandler);
255
- this.publicEventListenersBound = false;
256
- }
257
- if (this.crossFrameListenersBound) {
258
- this.postMessageClient.removeEventListeners();
259
- this.crossFrameListenersBound = false;
260
224
  }
225
+ (_a = this.postMessageClient) === null || _a === void 0 ? void 0 : _a.removeEventListeners();
261
226
  }
262
227
  createPurchase(extra = null) {
263
228
  console.log('createPurchase');
@@ -280,9 +245,14 @@ class Hpp {
280
245
  }
281
246
  this.headless.contentWindow.postMessage(message, '*');
282
247
  }
283
- reportHppStatus(hpp) {
248
+ reportIframeLoaded() {
249
+ console.log('Iframe loaded');
250
+ }
251
+ reportTokenizeCardResponse(data) {
252
+ console.log('Tokenize card response received');
284
253
  }
285
254
  }
255
+ Hpp.displayName = "Hpp";
286
256
  __decorate([
287
257
  logMethod()
288
258
  ], Hpp.prototype, "setCrossFramesEventListeners", null);
@@ -293,20 +263,9 @@ __decorate([
293
263
  logMethod()
294
264
  ], Hpp.prototype, "createPurchase", null);
295
265
  __decorate([
296
- logMethod({
297
- mapArgs: (args) => {
298
- const hpp = args[0];
299
- return [
300
- {
301
- crossFrameListenersBound: hpp.crossFrameListenersBound,
302
- publicEventListenersBound: hpp.publicEventListenersBound,
303
- isThreeDSecureEnabled: hpp.isThreeDSecureEnabled,
304
- headlessLoaded: hpp.headlessLoaded,
305
- headlessPreviouslyLoaded: hpp.headlessPreviouslyLoaded,
306
- iframeLoaded: hpp.iframeLoaded,
307
- },
308
- ];
309
- },
310
- })
311
- ], Hpp.prototype, "reportHppStatus", null);
266
+ logMethod()
267
+ ], Hpp.prototype, "reportIframeLoaded", null);
268
+ __decorate([
269
+ logMethod()
270
+ ], Hpp.prototype, "reportTokenizeCardResponse", null);
312
271
  export { Hpp, HPP_DEFAULT_OPTIONS, };
@@ -34,12 +34,14 @@ export function instrumentFunction(methodName, fn, opts = {}) {
34
34
  const endpoint = typeof opts.endpoint === "function"
35
35
  ? opts.endpoint(...args)
36
36
  : (_a = opts.endpoint) !== null && _a !== void 0 ? _a : defaultEndpoint();
37
+ // evaluate mapArgs(args) before constructing payload so any side effects in mapArgs (like setTransactionReference) are propagated
38
+ const mappedArgs = mapArgs(args);
37
39
  const payload = {
38
40
  username: getLoggerUsername(),
39
41
  reference: getTransactionReference(),
40
42
  className: opts.className,
41
43
  method: methodName,
42
- arguments: mapArgs(args),
44
+ arguments: mappedArgs,
43
45
  timestamp: new Date().toISOString(),
44
46
  };
45
47
  sendLog(endpoint, payload);
@@ -31,16 +31,15 @@ import { instrumentFunction } from "./instrument";
31
31
  // Decorator factory
32
32
  export function logMethod(opts = {}) {
33
33
  return function (target, propertyKey, descriptor) {
34
- var _a, _b;
34
+ var _a;
35
35
  const original = descriptor.value;
36
36
  if (typeof original !== "function") {
37
37
  console.error(`@logMethod can only decorate methods (${propertyKey})`);
38
38
  return descriptor;
39
39
  }
40
- const className = typeof target === "function"
41
- ? target.name || "UnknownClass"
42
- : ((_a = target === null || target === void 0 ? void 0 : target.constructor) === null || _a === void 0 ? void 0 : _a.name) || "UnknownClass";
43
- descriptor.value = instrumentFunction(propertyKey, original, Object.assign(Object.assign({}, opts), { className, mapArgs: (_b = opts.mapArgs) !== null && _b !== void 0 ? _b : ((args) => args.map((a) => {
40
+ const ctor = typeof target === "function" ? target : target === null || target === void 0 ? void 0 : target.constructor;
41
+ const className = (ctor === null || ctor === void 0 ? void 0 : ctor.displayName) || (ctor === null || ctor === void 0 ? void 0 : ctor.name) || "UnknownClass";
42
+ descriptor.value = instrumentFunction(propertyKey, original, Object.assign(Object.assign({}, opts), { className, mapArgs: (_a = opts.mapArgs) !== null && _a !== void 0 ? _a : ((args) => args.map((a) => {
44
43
  if (!a || typeof a !== "object")
45
44
  return a;
46
45
  return Object.assign(Object.assign({}, a), { js_sdk: true });
package/dist/main.d.ts CHANGED
@@ -24,6 +24,7 @@ interface VerifyCardOptions {
24
24
  challengeWindowSize?: ChallengeWindowSize;
25
25
  }
26
26
  export default class FatZebra {
27
+ static readonly displayName = "FatZebra";
27
28
  private sca;
28
29
  private fzConfig;
29
30
  private gatewayClient;
@@ -45,6 +46,7 @@ export default class FatZebra {
45
46
  private setThreeDSecureListeners;
46
47
  private reportThreeDSecureFetched;
47
48
  private reportRequestThreedsEnabledTimeout;
49
+ private reportTokenizeCardResponse;
48
50
  checkout(): void;
49
51
  on(event: PublicEvent, callback: (e: any) => void): void;
50
52
  off(event: PublicEvent, callback: (e: any) => void): void;
package/dist/main.js CHANGED
@@ -28,7 +28,7 @@ import { ApplePay } from './applepay';
28
28
  import { setLoggerUsername, setTransactionReference } from './logging/logger-context';
29
29
  import { logMethod } from './logging/logMethod';
30
30
  import ThreeDSecure from './three_d_secure';
31
- export default class FatZebra {
31
+ class FatZebra {
32
32
  constructor(config) {
33
33
  var _a;
34
34
  this.threeDSecureListenersBound = false;
@@ -103,6 +103,7 @@ export default class FatZebra {
103
103
  });
104
104
  const handlers = {};
105
105
  handlers[BridgeEvent.TOKENIZE_CARD_RESPONSE] = (data) => {
106
+ this.reportTokenizeCardResponse(data);
106
107
  callback(data);
107
108
  };
108
109
  postMessageClient.setEventListeners(handlers, { once: true });
@@ -158,7 +159,6 @@ export default class FatZebra {
158
159
  });
159
160
  return;
160
161
  }
161
- setTransactionReference(params.paymentIntent.payment.reference);
162
162
  yield this.authReady;
163
163
  switch (params.paymentMethod.type) {
164
164
  case PaymentMethodType.CARD: {
@@ -307,6 +307,9 @@ export default class FatZebra {
307
307
  reportRequestThreedsEnabledTimeout(paymentIntent) {
308
308
  console.log('3DS enabled check timed out');
309
309
  }
310
+ reportTokenizeCardResponse(data) {
311
+ console.log('Tokenize card response received');
312
+ }
310
313
  checkout() {
311
314
  window.HPP.purchase();
312
315
  }
@@ -320,6 +323,8 @@ export default class FatZebra {
320
323
  onOnce(event, callback);
321
324
  }
322
325
  }
326
+ FatZebra.displayName = "FatZebra";
327
+ export default FatZebra;
323
328
  __decorate([
324
329
  logMethod({
325
330
  mapArgs: (args) => {
@@ -334,13 +339,14 @@ __decorate([
334
339
  __decorate([
335
340
  logMethod({
336
341
  mapArgs: (args) => {
337
- var _a;
342
+ var _a, _b, _c;
338
343
  const params = args[0];
344
+ setTransactionReference((_b = (_a = params.paymentIntent) === null || _a === void 0 ? void 0 : _a.payment) === null || _b === void 0 ? void 0 : _b.reference);
339
345
  return [
340
346
  {
341
347
  merchant_username: window.MerchantUsername,
342
348
  payment_intent: params === null || params === void 0 ? void 0 : params.paymentIntent,
343
- payment_method: (_a = params === null || params === void 0 ? void 0 : params.paymentMethod) === null || _a === void 0 ? void 0 : _a.type,
349
+ payment_method: (_c = params === null || params === void 0 ? void 0 : params.paymentMethod) === null || _c === void 0 ? void 0 : _c.type,
344
350
  options: params === null || params === void 0 ? void 0 : params.options,
345
351
  },
346
352
  ];
@@ -350,7 +356,9 @@ __decorate([
350
356
  __decorate([
351
357
  logMethod({
352
358
  mapArgs: (args) => {
359
+ var _a, _b;
353
360
  const params = args[0];
361
+ setTransactionReference((_b = (_a = params.paymentIntent) === null || _a === void 0 ? void 0 : _a.payment) === null || _b === void 0 ? void 0 : _b.reference);
354
362
  return [
355
363
  {
356
364
  payment_intent: params.paymentIntent,
@@ -387,6 +395,9 @@ __decorate([
387
395
  },
388
396
  })
389
397
  ], FatZebra.prototype, "reportRequestThreedsEnabledTimeout", null);
398
+ __decorate([
399
+ logMethod()
400
+ ], FatZebra.prototype, "reportTokenizeCardResponse", null);
390
401
  __decorate([
391
402
  logMethod()
392
403
  ], FatZebra.prototype, "checkout", null);
@@ -29,6 +29,7 @@ export interface ScaConfig {
29
29
  environment?: Environment;
30
30
  }
31
31
  declare class Sca {
32
+ static readonly displayName = "Sca";
32
33
  private _cardinal;
33
34
  private enrollmentResult;
34
35
  private paymentIntent;
package/dist/sca/index.js CHANGED
@@ -229,6 +229,7 @@ class Sca {
229
229
  }
230
230
  }
231
231
  }
232
+ Sca.displayName = "Sca";
232
233
  __decorate([
233
234
  logMethod({
234
235
  mapArgs: (args) => {
@@ -19,6 +19,7 @@ interface ThreeDSecureRunProps {
19
19
  test: boolean;
20
20
  }
21
21
  declare class ThreeDSecure {
22
+ static readonly displayName = "ThreeDSecure";
22
23
  private headlessBridge;
23
24
  private cybersourceReferenceId;
24
25
  private paymentIntent;
@@ -102,7 +102,7 @@ class ThreeDSecure {
102
102
  const message = {
103
103
  channel: 'sca',
104
104
  subject: BridgeEvent.ENROL_THREE_D_SECURE_REQUEST,
105
- data: Object.assign(Object.assign(Object.assign({ access_token: window.localStorage.getItem(LocalStorageAccessTokenKey), merchant_username: merchantUsername, card_token: cardToken }, paymentIntent.payment), { verification: paymentIntent.verification, reference_id: cybersourceReferenceId, return_url: env[this.environment].returnCybersourceUrl, acs_window_size: (_a = this.challengeWindowSize) !== null && _a !== void 0 ? _a : ChallengeWindowSize.SIZE_FULL_PAGE, device_channel: "BROWSER" }), snakeCaseKeys(DeviceDataCollection.collectDeviceData()))
105
+ data: Object.assign(Object.assign(Object.assign({ access_token: window.localStorage.getItem(LocalStorageAccessTokenKey), merchant_username: merchantUsername, card_token: cardToken }, paymentIntent.payment), { verification: paymentIntent.verification, reference_id: cybersourceReferenceId, return_url: env[this.environment].returnCybersourceUrl, acs_window_size: (_a = this.challengeWindowSize) !== null && _a !== void 0 ? _a : ChallengeWindowSize.SIZE_500X600, device_channel: "BROWSER" }), snakeCaseKeys(DeviceDataCollection.collectDeviceData()))
106
106
  };
107
107
  this.headlessBridge.contentWindow.postMessage(message, '*');
108
108
  }
@@ -115,7 +115,7 @@ class ThreeDSecure {
115
115
  stepUpUrl: data.step_up_url,
116
116
  cardToken: this.cardToken,
117
117
  accessToken: data.access_token,
118
- challengeWindowSize: (_a = this.challengeWindowSize) !== null && _a !== void 0 ? _a : ChallengeWindowSize.SIZE_FULL_PAGE,
118
+ challengeWindowSize: (_a = this.challengeWindowSize) !== null && _a !== void 0 ? _a : ChallengeWindowSize.SIZE_500X600,
119
119
  });
120
120
  return;
121
121
  }
@@ -197,6 +197,7 @@ class ThreeDSecure {
197
197
  }
198
198
  }
199
199
  }
200
+ ThreeDSecure.displayName = "ThreeDSecure";
200
201
  __decorate([
201
202
  logMethod({
202
203
  mapArgs: (args) => {
@@ -6,6 +6,7 @@ export interface DeviceDataCollectionMessage {
6
6
  reference_id: string;
7
7
  }
8
8
  export default class DeviceDataCollection {
9
+ static readonly displayName = "DeviceDataCollection";
9
10
  private static readonly IFRAME_ID;
10
11
  private static readonly IFRAME_NAME;
11
12
  private static readonly FORM_ID;
@@ -117,6 +117,7 @@ class DeviceDataCollection {
117
117
  }
118
118
  }
119
119
  }
120
+ DeviceDataCollection.displayName = "DeviceDataCollection";
120
121
  // Shared IDs so other classes can query the DOM directly too
121
122
  DeviceDataCollection.IFRAME_ID = "cardinal_collection_iframe";
122
123
  DeviceDataCollection.IFRAME_NAME = "collectionIframe";
@@ -1,5 +1,6 @@
1
1
  import { ChallengeWindowSize } from "../../sca/types";
2
2
  declare class ThreeDSecureChallengeWindow {
3
+ static readonly displayName = "ThreeDSecureChallengeWindow";
3
4
  private static OVERLAY_ID;
4
5
  private static CONTENT_ID;
5
6
  private static FRAME_WRAP_ID;
@@ -13,5 +14,6 @@ declare class ThreeDSecureChallengeWindow {
13
14
  cardToken: string;
14
15
  challengeWindowSize?: ChallengeWindowSize;
15
16
  }): void;
17
+ private static reportChallengeIframeError;
16
18
  }
17
19
  export default ThreeDSecureChallengeWindow;
@@ -1,3 +1,10 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { logMethod } from "../../logging/logMethod";
1
8
  import { ChallengeWindowSize } from "../../sca/types";
2
9
  class ThreeDSecureChallengeWindow {
3
10
  // Treat these as the *iframe viewport* sizes per 3DS spec.
@@ -134,7 +141,7 @@ class ThreeDSecureChallengeWindow {
134
141
  Object.assign(iframe.style, { border: "0", display: "block" });
135
142
  iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-top-navigation-by-user-activation");
136
143
  iframe.addEventListener("load", () => console.log("✅ step-up iframe loaded"));
137
- iframe.addEventListener("error", () => console.log("❌ step-up iframe error"));
144
+ iframe.addEventListener("error", ThreeDSecureChallengeWindow.reportChallengeIframeError);
138
145
  frameWrap.appendChild(iframe);
139
146
  // Hidden POST form -> targets the iframe
140
147
  let form = document.getElementById(ThreeDSecureChallengeWindow.CHALLENGE_FORM_ID);
@@ -162,9 +169,19 @@ class ThreeDSecureChallengeWindow {
162
169
  overlay.style.display = "flex";
163
170
  form.submit();
164
171
  }
172
+ static reportChallengeIframeError() {
173
+ console.log("❌ step-up iframe error");
174
+ }
165
175
  }
176
+ ThreeDSecureChallengeWindow.displayName = "ThreeDSecureChallengeWindow";
166
177
  ThreeDSecureChallengeWindow.OVERLAY_ID = "three_d_secure_challenge_overlay";
167
178
  ThreeDSecureChallengeWindow.CONTENT_ID = "three_d_secure_challenge_content";
168
179
  ThreeDSecureChallengeWindow.FRAME_WRAP_ID = "three_d_secure_challenge_frame_wrap";
169
180
  ThreeDSecureChallengeWindow.CHALLENGE_FORM_ID = "three_d_secure_challenge_form";
181
+ __decorate([
182
+ logMethod()
183
+ ], ThreeDSecureChallengeWindow, "showChallengeIframe", null);
184
+ __decorate([
185
+ logMethod()
186
+ ], ThreeDSecureChallengeWindow, "reportChallengeIframeError", null);
170
187
  export default ThreeDSecureChallengeWindow;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fat-zebra/sdk",
3
- "version": "2.0.2-beta.1",
3
+ "version": "2.0.2-beta.3",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {