@fat-zebra/sdk 2.0.1-beta.0 → 2.0.1-beta.2

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.js CHANGED
@@ -10,9 +10,11 @@ import { emit, off, on } from '../shared/event-manager';
10
10
  import { PostMessageClient } from '../shared/post-message-client';
11
11
  import { BridgeEvent, PublicEvent, } from '../shared/types';
12
12
  import * as util from '../shared/util';
13
- import { logMethod } from "../logging/logMethod";
14
13
  import { setTransactionReference } from "../logging/logger-context";
14
+ import { logMethod } from "../logging/logMethod";
15
15
  import ThreeDSecure from "../three_d_secure";
16
+ import env from "../shared/env";
17
+ import { configureLogger } from "../logging/instrument";
16
18
  const HPP_DEFAULT_OPTIONS = {
17
19
  enableSca: false,
18
20
  hideButton: false,
@@ -34,6 +36,9 @@ class Hpp {
34
36
  channel: 'sca',
35
37
  target: this.iframe
36
38
  });
39
+ configureLogger({
40
+ baseUrl: env[process.env.API_ENV].payNowUrl
41
+ });
37
42
  }
38
43
  setListenersAndEmitReady() {
39
44
  const message = {
@@ -147,8 +152,7 @@ class Hpp {
147
152
  merchantUsername: this.username,
148
153
  cardToken: this.cardToken,
149
154
  test: this.test,
150
- challengeWindowSize: this.challengeWindowSize,
151
- tokenizeOnly: false
155
+ challengeWindowSize: this.challengeWindowSize
152
156
  });
153
157
  return; // do not continue execution to old 3DS
154
158
  }
@@ -1,7 +1,11 @@
1
- type LogOptions = {
2
- endpoint?: string;
3
- mapArgs?: (args: unknown[]) => unknown;
1
+ export type LogOptions<A extends unknown[]> = {
2
+ endpoint?: string | ((...args: A) => string);
3
+ mapArgs?: (args: A) => unknown;
4
4
  enabled?: () => boolean;
5
5
  };
6
- export declare function instrumentFunction<A extends any[], R>(methodName: string, fn: (...args: A) => R, opts?: LogOptions): (...args: A) => R;
6
+ type LoggerConfig = {
7
+ baseUrl?: string;
8
+ };
9
+ export declare function configureLogger(config: LoggerConfig): void;
10
+ export declare function instrumentFunction<A extends unknown[], R>(methodName: string, fn: (...args: A) => R, opts?: LogOptions<A>): (...args: A) => R;
7
11
  export {};
@@ -1,7 +1,13 @@
1
1
  import axios from "axios";
2
2
  import { getLoggerUsername, getTransactionReference } from "./logger-context";
3
+ let loggerConfig = {};
4
+ export function configureLogger(config) {
5
+ loggerConfig = config;
6
+ }
3
7
  function defaultEndpoint() {
4
- return `${process.env.PAYNOW_BASE_URL}/log_sdk`;
8
+ return loggerConfig.baseUrl
9
+ ? `${loggerConfig.baseUrl}/log_sdk`
10
+ : `${process.env.PAYNOW_BASE_URL}/log_sdk`;
5
11
  }
6
12
  function sendLog(endpoint, payload) {
7
13
  try {
@@ -20,12 +26,15 @@ function sendLog(endpoint, payload) {
20
26
  }
21
27
  }
22
28
  export function instrumentFunction(methodName, fn, opts = {}) {
23
- var _a, _b, _c;
24
- const endpoint = (_a = opts.endpoint) !== null && _a !== void 0 ? _a : defaultEndpoint();
25
- const enabled = (_b = opts.enabled) !== null && _b !== void 0 ? _b : (() => true);
26
- const mapArgs = (_c = opts.mapArgs) !== null && _c !== void 0 ? _c : ((a) => a);
29
+ var _a, _b;
30
+ const enabled = (_a = opts.enabled) !== null && _a !== void 0 ? _a : (() => true);
31
+ const mapArgs = (_b = opts.mapArgs) !== null && _b !== void 0 ? _b : ((a) => a);
27
32
  return function instrumented(...args) {
33
+ var _a;
28
34
  if (enabled()) {
35
+ const endpoint = typeof opts.endpoint === "function"
36
+ ? opts.endpoint(...args)
37
+ : (_a = opts.endpoint) !== null && _a !== void 0 ? _a : defaultEndpoint();
29
38
  const payload = {
30
39
  username: getLoggerUsername(),
31
40
  reference: getTransactionReference(),
@@ -1,7 +1,7 @@
1
- type LogOptions = {
2
- endpoint?: string;
3
- mapArgs?: (args: unknown[]) => unknown;
1
+ type LogOptions<A extends unknown[]> = {
2
+ endpoint?: string | ((args: A) => string);
3
+ mapArgs?: (args: A) => unknown;
4
4
  enabled?: () => boolean;
5
5
  };
6
- export declare function logMethod(opts?: LogOptions): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
6
+ export declare function logMethod(opts?: LogOptions<unknown[]>): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
7
7
  export {};
@@ -35,6 +35,7 @@ export function logMethod(opts = {}) {
35
35
  const original = descriptor.value;
36
36
  if (typeof original !== "function") {
37
37
  console.error(`@logMethod can only decorate methods (${propertyKey})`);
38
+ return descriptor;
38
39
  }
39
40
  descriptor.value = instrumentFunction(propertyKey, original, Object.assign(Object.assign({}, opts), { mapArgs: (_a = opts.mapArgs) !== null && _a !== void 0 ? _a : ((args) => args.map((a) => {
40
41
  if (!a || typeof a !== "object")
package/dist/main.d.ts CHANGED
@@ -27,10 +27,9 @@ export default class FatZebra {
27
27
  private sca;
28
28
  private fzConfig;
29
29
  private gatewayClient;
30
- private headless;
31
30
  constructor(config: FZConfig);
32
- tokenizeCard(card: Card): void;
33
- cardDidTokenize(callback: (data: any) => void): void;
31
+ tokenizeCard(card: Card, headless: HTMLIFrameElement): void;
32
+ cardDidTokenize(headless: HTMLIFrameElement, callback: (data: any) => void): void;
34
33
  verifyCard(params: VerifyCardParams): Promise<void>;
35
34
  renderPaymentsPage(params: HppLoadParams): void;
36
35
  renderApplePayButton(params: ApplePayParams): void;
package/dist/main.js CHANGED
@@ -27,7 +27,6 @@ import { validateApplePayLoadParams } from "./validation/validators/apple-pay-lo
27
27
  import { ApplePay } from "./applepay";
28
28
  import { setLoggerUsername } from "./logging/logger-context";
29
29
  import { logMethod } from "./logging/logMethod";
30
- import ThreeDSecure from "./three_d_secure";
31
30
  export default class FatZebra {
32
31
  constructor(config) {
33
32
  setLoggerUsername(config.username);
@@ -41,28 +40,29 @@ export default class FatZebra {
41
40
  gatewayClient: this.gatewayClient,
42
41
  });
43
42
  this.sca.loadScript();
44
- this.headless = bridge.load(process.env.PAYNOW_BRIDGE_URL);
45
43
  }
46
- tokenizeCard(card) {
44
+ tokenizeCard(card, headless) {
47
45
  const channel = 'sca';
48
- const message = {
49
- channel,
50
- subject: BridgeEvent.TOKENIZE_CARD_REQUEST,
51
- data: {
52
- access_token: window.localStorage.getItem(LocalStorageAccessTokenKey),
53
- card_holder: card.holder,
54
- card_number: card.number,
55
- card_expiry: `${card.expiryMonth}/${card.expiryYear}`,
56
- cvv: card.cvv,
57
- }
46
+ headless.onload = () => {
47
+ const message = {
48
+ channel,
49
+ subject: BridgeEvent.TOKENIZE_CARD_REQUEST,
50
+ data: {
51
+ access_token: window.localStorage.getItem(LocalStorageAccessTokenKey),
52
+ card_holder: card.holder,
53
+ card_number: card.number,
54
+ card_expiry: `${card.expiryMonth}/${card.expiryYear}`,
55
+ cvv: card.cvv,
56
+ }
57
+ };
58
+ headless.contentWindow.postMessage(message, '*');
58
59
  };
59
- this.headless.contentWindow.postMessage(message, '*');
60
60
  }
61
- cardDidTokenize(callback) {
61
+ cardDidTokenize(headless, callback) {
62
62
  const channel = 'sca';
63
63
  const postMessageClient = new PostMessageClient({
64
64
  channel,
65
- target: this.headless
65
+ target: headless
66
66
  });
67
67
  const handlers = {};
68
68
  handlers[BridgeEvent.TOKENIZE_CARD_RESPONSE] = (data) => {
@@ -81,44 +81,35 @@ export default class FatZebra {
81
81
  });
82
82
  return;
83
83
  }
84
- const threeDSecure = new ThreeDSecure({
85
- bridge: this.headless,
86
- environment: process.env.API_ENV
87
- });
88
84
  switch (params.paymentMethod.type) {
89
85
  case PaymentMethodType.CARD:
86
+ const headless = bridge.load(process.env.PAYNOW_BRIDGE_URL);
90
87
  const card = params.paymentMethod.data;
91
- this.cardDidTokenize((data) => __awaiter(this, void 0, void 0, function* () {
88
+ this.cardDidTokenize(headless, (data) => __awaiter(this, void 0, void 0, function* () {
92
89
  var _a;
93
- threeDSecure.run({
94
- paymentIntent: params.paymentIntent,
90
+ const bin = card.number.substr(0, 6);
91
+ this.sca.run({
95
92
  cardToken: data.token,
96
- merchantUsername: this.fzConfig.username,
93
+ customer: params.customer,
94
+ paymentIntent: params.paymentIntent,
95
+ bin,
97
96
  challengeWindowSize: (_a = params.options) === null || _a === void 0 ? void 0 : _a.challengeWindowSize,
98
- test: this.fzConfig.test,
99
- tokenizeOnly: true
100
97
  });
101
98
  }));
102
- this.tokenizeCard(card);
99
+ this.tokenizeCard(card, headless);
103
100
  break;
104
101
  case PaymentMethodType.CARD_ON_FILE:
105
102
  const cardToken = params.paymentMethod.data.token;
106
- threeDSecure.run({
103
+ const bin = (yield this.gatewayClient.getCard({ card_token: cardToken })).data.bin;
104
+ this.sca.run({
105
+ cardToken,
106
+ customer: params.customer,
107
107
  paymentIntent: params.paymentIntent,
108
- cardToken: cardToken,
109
- merchantUsername: this.fzConfig.username,
108
+ bin,
110
109
  challengeWindowSize: (_a = params.options) === null || _a === void 0 ? void 0 : _a.challengeWindowSize,
111
- test: this.fzConfig.test,
112
- tokenizeOnly: true
113
110
  });
114
111
  break;
115
112
  }
116
- const channel = 'sca';
117
- const postMessageClient = new PostMessageClient({
118
- channel,
119
- target: this.headless
120
- });
121
- postMessageClient.setEventListeners(threeDSecure.messageHandlers());
122
113
  });
123
114
  }
124
115
  renderPaymentsPage(params) {
@@ -5,8 +5,12 @@ import Sca from "../sca";
5
5
  import GatewayClient from "../shared/api-gateway-client";
6
6
  import { generateVerifyURL } from "./verifyUrl";
7
7
  import useMessage from "./useMessage";
8
- import { instrumentFunction } from "../logging/instrument";
9
- const logUseFatZebra = instrumentFunction("useFatZebra", (meta) => meta, { mapArgs: ([meta]) => [meta] });
8
+ import { configureLogger, instrumentFunction } from "../logging/instrument";
9
+ import env from "../shared/env";
10
+ const logUseFatZebra = instrumentFunction("useFatZebra", (meta) => meta, {
11
+ mapArgs: ([meta]) => meta,
12
+ endpoint: (meta) => `${env[meta.environment].payNowUrl}/log_sdk`,
13
+ });
10
14
  const useFatZebra = ({ config, handlers, cardToken }) => {
11
15
  const { options, accessToken, paymentIntent, username } = config;
12
16
  const sca = useMemo(() => {
@@ -25,6 +29,9 @@ const useFatZebra = ({ config, handlers, cardToken }) => {
25
29
  config
26
30
  });
27
31
  useEffect(() => {
32
+ configureLogger({
33
+ baseUrl: env[config.environment].payNowUrl
34
+ });
28
35
  logUseFatZebra({
29
36
  environment: config.environment,
30
37
  reference: config.paymentIntent.payment.reference,
@@ -44,8 +44,7 @@ const useMessage = ({ paymentIntent, options, handlers, sca, config }) => {
44
44
  paymentIntent,
45
45
  cardToken: data.token,
46
46
  merchantUsername: config.username,
47
- test: config.environment !== Environment.production,
48
- tokenizeOnly: config.options.tokenize_only
47
+ test: config.environment !== Environment.production
49
48
  });
50
49
  return;
51
50
  }
@@ -20,16 +20,14 @@ declare class ThreeDSecure {
20
20
  private challengeWindowSize;
21
21
  private successCallback;
22
22
  private failureCallback;
23
- private tokenizeOnly;
24
23
  private iframe?;
25
24
  constructor({ successCallback, failureCallback, environment, bridge, iframe }: ThreeDSecureConfig);
26
- run({ paymentIntent, cardToken, merchantUsername, challengeWindowSize, test, tokenizeOnly }: {
25
+ run({ paymentIntent, cardToken, merchantUsername, challengeWindowSize, test }: {
27
26
  paymentIntent: PaymentIntent;
28
27
  cardToken: string;
29
28
  merchantUsername: string;
30
29
  challengeWindowSize?: ChallengeWindowSize;
31
30
  test: boolean;
32
- tokenizeOnly?: boolean;
33
31
  }): void;
34
32
  setupResponse(data: DeviceDataCollectionMessage): void;
35
33
  messageHandlers(): {
@@ -19,7 +19,6 @@ import { ChallengeWindowSize } from "../sca/types";
19
19
  import * as util from "../shared/util";
20
20
  class ThreeDSecure {
21
21
  constructor({ successCallback, failureCallback, environment, bridge, iframe }) {
22
- this.tokenizeOnly = false;
23
22
  this.headlessBridge = bridge;
24
23
  this.environment = environment;
25
24
  this.successCallback = successCallback;
@@ -27,8 +26,7 @@ class ThreeDSecure {
27
26
  this.iframe = iframe;
28
27
  DeviceDataCollection.listenDataCollectionResponse(environment);
29
28
  }
30
- run({ paymentIntent, cardToken, merchantUsername, challengeWindowSize, test, tokenizeOnly }) {
31
- this.tokenizeOnly = tokenizeOnly;
29
+ run({ paymentIntent, cardToken, merchantUsername, challengeWindowSize, test }) {
32
30
  this.setLoading();
33
31
  this.paymentIntent = paymentIntent;
34
32
  this.test = test;
@@ -126,8 +124,6 @@ class ThreeDSecure {
126
124
  if (scenario.outcome.success) {
127
125
  this.reportSuccess(`FatZebra.3DS: 3DS success - ${scenario.description}.`, threeDSecureData);
128
126
  const extra = util.toObjectWithSnakeCaseKeys(threeDSecureData);
129
- if (this.tokenizeOnly)
130
- return; // DO NO process purchase if tokenizing only.
131
127
  this.createPurchase(extra);
132
128
  return;
133
129
  }
@@ -153,8 +149,6 @@ class ThreeDSecure {
153
149
  const extra = util.toObjectWithSnakeCaseKeys(threeDSecureData);
154
150
  if (scenario.outcome.success) {
155
151
  this.reportSuccess(`FatZebra.3DS: 3DS success - ${scenario.description}.`, threeDSecureData);
156
- if (this.tokenizeOnly)
157
- return; // DO NO process purchase if tokenizing only.
158
152
  this.createPurchase(extra);
159
153
  }
160
154
  else {
@@ -14,6 +14,7 @@ export default class DeviceDataCollection {
14
14
  static listenDataCollectionResponse(environment: Environment): void;
15
15
  private static hasEmittedProfileReady;
16
16
  private static handleDataCollectionResponse;
17
+ private static handleCollectionResponse;
17
18
  static collectDeviceData(): DeviceDataType;
18
19
  static setIframeUrl(url: string, jwt: string): void;
19
20
  static getForm(): HTMLFormElement | null;
@@ -1,6 +1,13 @@
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
+ };
1
7
  import { PublicEvent } from "../../shared/types";
2
8
  import { emit } from "../../shared/event-manager";
3
9
  import env from "../../shared/env";
10
+ import { logMethod } from "../../logging/logMethod";
4
11
  class DeviceDataCollection {
5
12
  // Create elements if they don't already exist
6
13
  createIframe() {
@@ -45,15 +52,19 @@ class DeviceDataCollection {
45
52
  return;
46
53
  if (this.hasEmittedProfileReady)
47
54
  return;
55
+ this.handleCollectionResponse(event);
56
+ }
57
+ static handleCollectionResponse(event) {
48
58
  const response = JSON.parse(event.data);
49
59
  if (response["MessageType"] == "profile.completed") {
60
+ this.hasEmittedProfileReady = true;
50
61
  emit(PublicEvent.DEVICE_PROFILE_READY_THREE_D_SECURE_EVENT, { message: null, data: null });
51
62
  }
52
- // Still proceed, even if status is false (as per recommendations from cybersource support team.
53
- if (response["Status"] === false) {
63
+ else if (response["Status"] == false) {
64
+ this.hasEmittedProfileReady = true;
65
+ // Still proceed, even if status is false (as per recommendations from cybersource support team.
54
66
  emit(PublicEvent.DEVICE_PROFILE_READY_THREE_D_SECURE_EVENT, { message: null, data: null });
55
67
  }
56
- this.hasEmittedProfileReady = true;
57
68
  }
58
69
  static collectDeviceData() {
59
70
  var _a, _b, _c, _d;
@@ -117,3 +128,11 @@ DeviceDataCollection.FORM_ID = "cardinal_collection_form";
117
128
  DeviceDataCollection.INPUT_ID = "cardinal_collection_form_input";
118
129
  DeviceDataCollection.hasEmittedProfileReady = false;
119
130
  export default DeviceDataCollection;
131
+ __decorate([
132
+ logMethod({
133
+ mapArgs: (args) => {
134
+ const params = args[0]; // grab the first argument.
135
+ return JSON.parse(params.data);
136
+ },
137
+ })
138
+ ], DeviceDataCollection, "handleCollectionResponse", null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fat-zebra/sdk",
3
- "version": "2.0.1-beta.0",
3
+ "version": "2.0.1-beta.2",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {