@fat-zebra/sdk 2.0.1-beta.12 → 2.0.1-beta.14

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
@@ -59,7 +59,7 @@ declare class Hpp {
59
59
  private crossFrameListenersBound;
60
60
  private publicEventListenersBound;
61
61
  constructor(config: HppModuleConfig);
62
- setListenersAndEmitReady(): Promise<void>;
62
+ setListenersAndEmitReady(): void;
63
63
  load(config: HppLoadParams): void;
64
64
  purchase(): void;
65
65
  getPayNowUrl(options?: {
@@ -71,5 +71,6 @@ declare class Hpp {
71
71
  createPurchase(extra?: {
72
72
  [key: string]: boolean | string;
73
73
  }): void;
74
+ private reportHppStatus;
74
75
  }
75
76
  export { Hpp, type HppLoadParams, HPP_DEFAULT_OPTIONS, };
package/dist/hpp/hpp.js CHANGED
@@ -4,14 +4,16 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
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
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
8
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
9
- return new (P || (P = Promise))(function (resolve, reject) {
10
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
11
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
12
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
13
- step((generator = generator.apply(thisArg, _arguments || [])).next());
14
- });
7
+ var __rest = (this && this.__rest) || function (s, e) {
8
+ var t = {};
9
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
10
+ t[p] = s[p];
11
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
12
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
13
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
14
+ t[p[i]] = s[p[i]];
15
+ }
16
+ return t;
15
17
  };
16
18
  import * as bridge from '../shared/bridge-client';
17
19
  import { LocalStorageAccessTokenKey } from '../shared/constants';
@@ -50,28 +52,27 @@ class Hpp {
50
52
  });
51
53
  }
52
54
  setListenersAndEmitReady() {
53
- return __awaiter(this, void 0, void 0, function* () {
54
- if (!this.crossFrameListenersBound) {
55
- this.setCrossFramesEventListeners();
56
- this.crossFrameListenersBound = true;
57
- }
58
- if (this.headlessLoaded && this.iframeLoaded) {
59
- if (!this.publicEventListenersBound && !this.isThreeDSecureEnabled) {
60
- this.setPublicEventListeners();
61
- this.publicEventListenersBound = true;
62
- }
63
- emit(PublicEvent.HPP_READY);
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
64
  }
65
- else if (this.headlessPreviouslyLoaded && this.iframeLoaded) {
66
- // subsequent iframe loads after headless has been previously loaded
67
- // this caters for the SPA scenario
68
- if (!this.publicEventListenersBound && !this.isThreeDSecureEnabled) {
69
- this.setPublicEventListeners();
70
- this.publicEventListenersBound = true;
71
- }
72
- emit(PublicEvent.HPP_READY);
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
73
  }
74
- });
74
+ emit(PublicEvent.HPP_READY);
75
+ }
75
76
  }
76
77
  load(config) {
77
78
  var _a;
@@ -139,6 +140,8 @@ class Hpp {
139
140
  const handlers = {};
140
141
  handlers[BridgeEvent.TOKENIZE_CARD_RESPONSE] = (data) => {
141
142
  var _a;
143
+ if (data.source === 'verifyCard')
144
+ return;
142
145
  if (data.errors) {
143
146
  emit(PublicEvent.TOKENIZATION_ERROR, {
144
147
  message: 'Card tokenization failed.',
@@ -172,6 +175,7 @@ class Hpp {
172
175
  return; // do not continue execution to old 3DS
173
176
  }
174
177
  this.sca.run({
178
+ source: 'hpp',
175
179
  cardToken: data.token,
176
180
  customer: this.customer,
177
181
  paymentIntent: this.paymentIntent,
@@ -235,10 +239,12 @@ class Hpp {
235
239
  setPublicEventListeners() {
236
240
  console.log('setPublicEventListeners');
237
241
  this.scaHandler = (event) => {
242
+ if (event.detail.data.source === 'verifyCard')
243
+ return;
238
244
  if (this.hppOptions.tokenizeOnly)
239
245
  return;
240
246
  const threedsData = event.detail.data;
241
- const extra = util.toObjectWithSnakeCaseKeys(threedsData);
247
+ const _a = util.toObjectWithSnakeCaseKeys(threedsData), { source } = _a, extra = __rest(_a, ["source"]);
242
248
  this.createPurchase(extra);
243
249
  };
244
250
  on(PublicEvent.SCA_SUCCESS, this.scaHandler);
@@ -248,6 +254,10 @@ class Hpp {
248
254
  off(PublicEvent.SCA_SUCCESS, this.scaHandler);
249
255
  this.publicEventListenersBound = false;
250
256
  }
257
+ if (this.crossFrameListenersBound) {
258
+ this.postMessageClient.removeEventListeners();
259
+ this.crossFrameListenersBound = false;
260
+ }
251
261
  }
252
262
  createPurchase(extra = null) {
253
263
  console.log('createPurchase');
@@ -270,8 +280,33 @@ class Hpp {
270
280
  }
271
281
  this.headless.contentWindow.postMessage(message, '*');
272
282
  }
283
+ reportHppStatus(hpp) {
284
+ }
273
285
  }
286
+ __decorate([
287
+ logMethod()
288
+ ], Hpp.prototype, "setCrossFramesEventListeners", null);
289
+ __decorate([
290
+ logMethod()
291
+ ], Hpp.prototype, "setPublicEventListeners", null);
274
292
  __decorate([
275
293
  logMethod()
276
294
  ], Hpp.prototype, "createPurchase", null);
295
+ __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);
277
312
  export { Hpp, HPP_DEFAULT_OPTIONS, };
package/dist/main.js CHANGED
@@ -25,7 +25,7 @@ import { Hpp } from './hpp';
25
25
  import ClickToPay from './click_to_pay';
26
26
  import { validateApplePayLoadParams } from './validation/validators/apple-pay-load-params-button-validator';
27
27
  import { ApplePay } from './applepay';
28
- import { setLoggerUsername } from './logging/logger-context';
28
+ import { setLoggerUsername, setTransactionReference } from './logging/logger-context';
29
29
  import { logMethod } from './logging/logMethod';
30
30
  import ThreeDSecure from './three_d_secure';
31
31
  export default class FatZebra {
@@ -85,6 +85,7 @@ export default class FatZebra {
85
85
  channel,
86
86
  subject: BridgeEvent.TOKENIZE_CARD_REQUEST,
87
87
  data: {
88
+ source: 'verifyCard',
88
89
  access_token: window.localStorage.getItem(LocalStorageAccessTokenKey),
89
90
  card_holder: card.holder,
90
91
  card_number: card.number,
@@ -104,7 +105,7 @@ export default class FatZebra {
104
105
  handlers[BridgeEvent.TOKENIZE_CARD_RESPONSE] = (data) => {
105
106
  callback(data);
106
107
  };
107
- postMessageClient.setEventListeners(handlers);
108
+ postMessageClient.setEventListeners(handlers, { once: true });
108
109
  }
109
110
  requestThreeDSecureEnabled(timeout, paymentIntent) {
110
111
  return __awaiter(this, void 0, void 0, function* () {
@@ -125,7 +126,7 @@ export default class FatZebra {
125
126
  resolve(enabled);
126
127
  }
127
128
  },
128
- });
129
+ }, { once: true });
129
130
  const message = {
130
131
  channel,
131
132
  subject: 'fzi.is-enabled-three-d-secure-req',
@@ -157,6 +158,7 @@ export default class FatZebra {
157
158
  });
158
159
  return;
159
160
  }
161
+ setTransactionReference(params.paymentIntent.payment.reference);
160
162
  yield this.authReady;
161
163
  switch (params.paymentMethod.type) {
162
164
  case PaymentMethodType.CARD: {
@@ -177,6 +179,7 @@ export default class FatZebra {
177
179
  else {
178
180
  const bin = card.number.substr(0, 6);
179
181
  this.sca.run({
182
+ source: 'verifyCard',
180
183
  cardToken: data.token,
181
184
  customer: params.customer,
182
185
  paymentIntent: params.paymentIntent,
@@ -206,6 +209,7 @@ export default class FatZebra {
206
209
  card_token: cardToken,
207
210
  })).data.bin;
208
211
  this.sca.run({
212
+ source: 'verifyCard',
209
213
  cardToken,
210
214
  customer: params.customer,
211
215
  paymentIntent: params.paymentIntent,
@@ -3,7 +3,9 @@ import { EventCallback, Customer, PaymentIntent } from '../shared/types';
3
3
  import { CardinalManager } from './cardinal';
4
4
  import GatewayClient from '../shared/api-gateway-client';
5
5
  import { Environment } from "../shared/env";
6
+ type ScaSource = 'verifyCard' | 'hpp';
6
7
  export interface ScaRunProps {
8
+ source?: ScaSource;
7
9
  cardToken: string;
8
10
  customer?: Customer;
9
11
  paymentIntent: PaymentIntent;
@@ -39,6 +41,7 @@ declare class Sca {
39
41
  private successCallback;
40
42
  private failureCallback;
41
43
  private environmentConfig;
44
+ private source;
42
45
  constructor({ gatewayClient, successCallback, failureCallback }: ScaConfig);
43
46
  loadScript(): void;
44
47
  get cardinal(): CardinalManager;
package/dist/sca/index.js CHANGED
@@ -45,27 +45,28 @@ class Sca {
45
45
  }
46
46
  reportFailure(message, data) {
47
47
  if (this.failureCallback) {
48
- const event = new CustomEvent(PublicEvent.SCA_ERROR, { detail: { errors: [message], data: data } });
48
+ const event = new CustomEvent(PublicEvent.SCA_ERROR, { detail: { errors: [message], data: Object.assign(Object.assign({}, data), { source: this.source }) } });
49
49
  this.failureCallback(event);
50
50
  }
51
51
  else {
52
- emit(PublicEvent.SCA_ERROR, { errors: [message], data: data });
52
+ emit(PublicEvent.SCA_ERROR, { errors: [message], data: Object.assign(Object.assign({}, data), { source: this.source }) });
53
53
  }
54
54
  console.log(message);
55
55
  }
56
56
  reportSuccess(message, data) {
57
57
  if (this.successCallback) {
58
- const event = new CustomEvent(PublicEvent.SCA_SUCCESS, { detail: data });
58
+ const event = new CustomEvent(PublicEvent.SCA_SUCCESS, { detail: { data: Object.assign(Object.assign({}, data), { source: this.source }) } });
59
59
  this.successCallback(event);
60
60
  }
61
61
  else {
62
- emit(PublicEvent.SCA_SUCCESS, { message, data });
62
+ emit(PublicEvent.SCA_SUCCESS, { message, data: Object.assign(Object.assign({}, data), { source: this.source }) });
63
63
  }
64
64
  console.log(message);
65
65
  }
66
66
  run(config) {
67
67
  return __awaiter(this, void 0, void 0, function* () {
68
68
  console.log('Running 3DS (SCA)');
69
+ this.source = config.source;
69
70
  try {
70
71
  if (!this._cardinal) {
71
72
  this._cardinal = new CardinalManager();
@@ -260,6 +261,7 @@ __decorate([
260
261
  const params = args[0];
261
262
  return [
262
263
  {
264
+ source: params.source,
263
265
  payment_intent: params.paymentIntent
264
266
  },
265
267
  ];
@@ -42,9 +42,13 @@ declare class PostMessageClient {
42
42
  private fzEnv;
43
43
  private target;
44
44
  private domain;
45
+ private messageListener;
45
46
  constructor(config: PostMessageClientConfig);
46
- setEventListeners(handlers: EventHandlers): void;
47
+ setEventListeners(handlers: EventHandlers, options?: {
48
+ once?: boolean;
49
+ }): void;
47
50
  setEventListenersLegacy(handlers: EventHandlers): void;
51
+ removeEventListeners(): void;
48
52
  send(message: PostMessage | PostMessageLegacy): void;
49
53
  }
50
54
  export { PostMessageClient, };
@@ -10,14 +10,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import env, { Environment } from "./env";
11
11
  class PostMessageClient {
12
12
  constructor(config) {
13
+ this.messageListener = null;
13
14
  this.channel = config.channel;
14
15
  this.fzEnv = config.environment || process.env.API_ENV;
15
16
  this.domain = env[this.fzEnv].payNowUrl;
16
17
  this.target = config.target;
17
18
  }
18
19
  // Handle event messages that conform to PostMessage format.
19
- setEventListeners(handlers) {
20
- window.addEventListener("message", (event) => __awaiter(this, void 0, void 0, function* () {
20
+ setEventListeners(handlers, options = {}) {
21
+ this.messageListener = (event) => __awaiter(this, void 0, void 0, function* () {
21
22
  const validationEnabled = ![Environment.test, Environment.local, Environment.development].includes(this.fzEnv);
22
23
  const isChannelValid = event.data.channel === this.channel;
23
24
  const isOriginValid = event.origin === this.domain;
@@ -29,6 +30,14 @@ class PostMessageClient {
29
30
  const subject = message.subject;
30
31
  const handler = handlers[subject];
31
32
  if (handler) {
33
+ // Intentionally not using addEventListener's built-in { once } option.
34
+ // That would remove the listener on the first message event of any kind,
35
+ // so an unrelated message arriving before the expected subject would silently consume the listener
36
+ // and cause a timeout. Instead, we remove only after a matching subject is found.
37
+ if (options.once && this.messageListener) {
38
+ console.log(subject, 'Removing message listener after first use');
39
+ window.removeEventListener('message', this.messageListener);
40
+ }
32
41
  handler(message.data);
33
42
  }
34
43
  else {
@@ -36,7 +45,8 @@ class PostMessageClient {
36
45
  // not to handle certain messages posted from child frame.
37
46
  console.log(`[WARNING] No handler registered for subject ${subject}, message ${JSON.stringify(message)}`);
38
47
  }
39
- }));
48
+ });
49
+ window.addEventListener("message", this.messageListener);
40
50
  }
41
51
  // Handle event messages that do not conform to PostMessage format.
42
52
  setEventListenersLegacy(handlers) {
@@ -59,6 +69,12 @@ class PostMessageClient {
59
69
  }
60
70
  });
61
71
  }
72
+ removeEventListeners() {
73
+ if (this.messageListener) {
74
+ window.removeEventListener("message", this.messageListener);
75
+ this.messageListener = null;
76
+ }
77
+ }
62
78
  send(message) {
63
79
  this.target.contentWindow.postMessage(message, this.domain);
64
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fat-zebra/sdk",
3
- "version": "2.0.1-beta.12",
3
+ "version": "2.0.1-beta.14",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {