@flittpayments/js-sdk 2.0.0

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.
@@ -0,0 +1,2574 @@
1
+ /**
2
+ * Modules registry
3
+ * @type {Object<string,any>}
4
+ */
5
+ const modules = {};
6
+ /**
7
+ * @type {Object<string,any>}
8
+ */
9
+ const instance = {};
10
+ /**
11
+ * @param {string} name
12
+ * @param {Object} [params]
13
+ * @returns {{}}
14
+ */
15
+ const newModule = function (name, params) {
16
+ if (!modules[name]) {
17
+ throw Error(['module is undefined', name].join(' '))
18
+ }
19
+ return new modules[name](params || {})
20
+ };
21
+
22
+ const addModule = function (name, module) {
23
+ if (modules[name]) {
24
+ throw Error(['module already added', name].join(' '))
25
+ }
26
+ modules[name] = module;
27
+ };
28
+
29
+ function Component(name, params) {
30
+ if (instance[name]) return instance[name]
31
+ return (instance[name] = newModule(name, params))
32
+ }
33
+
34
+ Component.get = function (name, params) {
35
+ return newModule(name, params)
36
+ };
37
+
38
+ Component.add = function (name, module) {
39
+ addModule(name, module);
40
+ return this
41
+ };
42
+
43
+ const digitTest = /^\d+$/;
44
+ const keyBreaker = /([^\[\]]+)|(\[\])/g;
45
+ const paramTest = /([^?#]*)(#.*)?$/;
46
+ const r20 = /%20/g;
47
+ const rbracket = /\[\]$/;
48
+ const matchSymbol = /\s([a-zA-Z]+)/;
49
+
50
+ const prep = (str) => {
51
+ return decodeURIComponent(str.replace(/\+/g, ' '))
52
+ };
53
+ const flatten = (array) => {
54
+ let result = [];
55
+ forEach(array, (item) => {
56
+ result = result.concat(isArray(item) ? flatten(item) : item);
57
+ });
58
+ return result
59
+ };
60
+
61
+ const recursiveParams = (prefix, obj, next) => {
62
+ if (isArray(obj)) {
63
+ forEach(obj, (item, prop) => {
64
+ if (rbracket.test(prefix)) {
65
+ next(prefix, item);
66
+ } else {
67
+ recursiveParams(prefix + '[' + (isPlainObject(obj) ? prop : '') + ']', item, next);
68
+ }
69
+ });
70
+ } else if (isPlainObject(obj)) {
71
+ forEach(obj, (item, prop) => {
72
+ recursiveParams(prefix + '[' + prop + ']', item, next);
73
+ });
74
+ } else {
75
+ next(prefix, obj);
76
+ }
77
+ };
78
+
79
+ const getType = (o) => {
80
+ return {}.toString.call(o).match(matchSymbol)[1].toLowerCase()
81
+ };
82
+ const isPlainObject = (o) => {
83
+ return !!o && typeof o === 'object' && o.constructor === Object
84
+ };
85
+
86
+ const isFunction = (o) => {
87
+ return getType(o) === 'function'
88
+ };
89
+
90
+ const isArray = (o) => {
91
+ return getType(o) === 'array'
92
+ };
93
+
94
+ const isElement = (o) => {
95
+ return o && o.nodeType === 1
96
+ };
97
+
98
+ const toArray = (o) => {
99
+ return [].slice.call(o)
100
+ };
101
+
102
+ const hasProp = (o, v) => {
103
+ return o && o.hasOwnProperty(v)
104
+ };
105
+
106
+ const forEach = (ob, cb, cx) => {
107
+ for (let p in ob) if (hasProp(ob, p)) cb.call(cx || null, ob[p], p);
108
+ };
109
+
110
+ const cleanObject = (ob) => {
111
+ for (let p in ob) {
112
+ if (hasProp(ob, p)) {
113
+ if (ob[p].length === 0) {
114
+ if (isArray(ob)) ob.splice(p, 1);
115
+ if (isPlainObject(ob)) delete ob[p];
116
+ } else if (isPlainObject(ob[p])) {
117
+ cleanObject(ob[p]);
118
+ }
119
+ }
120
+ }
121
+ return ob
122
+ };
123
+
124
+ const extend = (obj, ...args) => {
125
+ forEach(args, function (o) {
126
+ if (o !== null) {
127
+ forEach(o, function (value, key) {
128
+ if (isPlainObject(value)) {
129
+ obj[key] = extend(obj[key] || {}, value);
130
+ } else {
131
+ obj[key] = value;
132
+ }
133
+ });
134
+ }
135
+ });
136
+ return obj
137
+ };
138
+
139
+ const uuid = () => {
140
+ let a = 0,
141
+ b = '';
142
+ while (a++ < 36) {
143
+ if ((a * 51) & 52) {
144
+ b += (a ^ 15 ? 8 ^ (Math.random() * (a ^ 20 ? 16 : 4)) : 4).toString(16);
145
+ } else {
146
+ b += '-';
147
+ }
148
+ }
149
+ return b
150
+ };
151
+
152
+ const isObject = (o) => {
153
+ return getType(o) === 'object'
154
+ };
155
+
156
+ const isRegexp = (o) => {
157
+ return getType(o) === 'regexp'
158
+ };
159
+
160
+ const isArguments = (o) => {
161
+ return getType(o) === 'arguments'
162
+ };
163
+
164
+ const isError = (o) => {
165
+ return getType(o) === 'error'
166
+ };
167
+
168
+ const isDate = (o) => {
169
+ return getType(o) === 'date'
170
+ };
171
+
172
+ const isString = (o) => {
173
+ return getType(o) === 'string'
174
+ };
175
+
176
+ const isNumber = (o) => {
177
+ return getType(o) === 'number'
178
+ };
179
+
180
+ const map = (ob, cb, cx) => {
181
+ let p,
182
+ t,
183
+ r = [];
184
+ for (p in ob) if (hasProp(ob, p)) if ((t = cb.call(cx || null, ob[p], p)) !== undefined) r[p] = t;
185
+ return r
186
+ };
187
+
188
+ const querySelectorAll = (o, p) => {
189
+ return toArray((p || document).querySelectorAll(o))
190
+ };
191
+
192
+ const querySelector = (o, p) => {
193
+ return (p || document).querySelector(o)
194
+ };
195
+
196
+ const deparam = (params) => {
197
+ const data = {};
198
+ if (params.charAt(0) === '?') params = params.slice(1);
199
+ if (params && paramTest.test(params)) {
200
+ forEach(params.split('&'), (pair) => {
201
+ let parts = pair.split('='),
202
+ key = prep(parts.shift()),
203
+ value = prep(parts.join('=')),
204
+ current = data;
205
+ if (key) {
206
+ parts = key.match(keyBreaker);
207
+ for (let j = 0, l = parts.length - 1; j < l; j++) {
208
+ if (!current[parts[j]]) {
209
+ current[parts[j]] = digitTest.test(parts[j + 1]) || parts[j + 1] === '[]' ? [] : {};
210
+ }
211
+ current = current[parts[j]];
212
+ }
213
+ const lastPart = parts.pop();
214
+ if (lastPart === '[]') {
215
+ current.push(value);
216
+ } else {
217
+ current[lastPart] = value;
218
+ }
219
+ }
220
+ });
221
+ }
222
+ return data
223
+ };
224
+
225
+ const param = (obj) => {
226
+ const result = [];
227
+ forEach(obj, (item, prop) => {
228
+ recursiveParams(prop, item, (key, value) => {
229
+ value = value == null ? '' : value;
230
+ result.push([encodeURIComponent(key), encodeURIComponent(value)].join('='));
231
+ });
232
+ });
233
+ return result.join('&').replace(r20, '+')
234
+ };
235
+
236
+ const removeElement = (el) => {
237
+ el.parentNode.removeChild(el);
238
+ };
239
+
240
+ const createElement = (tag) => {
241
+ return document.createElement(tag)
242
+ };
243
+
244
+ const addClass = (...args) => {
245
+ const el = args.shift();
246
+ if (isElement(el) === false) return
247
+ const classList = el.className.trim().split(/\s+/);
248
+ const tokens = flatten(args.map((item) => item.trim().split(/\s+/)));
249
+ tokens.forEach((token) => {
250
+ if (token && !~classList.indexOf(token)) {
251
+ classList.push(token);
252
+ }
253
+ });
254
+ el.className = classList.join(' ').trim();
255
+ };
256
+
257
+ const removeClass = (...args) => {
258
+ const el = args.shift();
259
+ if (isElement(el) === false) return
260
+ const classList = el.className.trim().split(/\s+/);
261
+ const tokens = flatten(args.map((item) => item.trim().split(/\s+/)));
262
+ tokens.forEach((token) => {
263
+ if (token) {
264
+ const index = classList.indexOf(token);
265
+ if (!!~index) {
266
+ classList.splice(index, 1);
267
+ }
268
+ }
269
+ });
270
+ el.className = classList.join(' ').trim();
271
+ };
272
+
273
+ const removeAttr = (el, attrs) => {
274
+ if (isElement(el) === false) return false
275
+ if (isPlainObject(attrs)) {
276
+ forEach(attrs, (value) => {
277
+ el.removeAttribute(value);
278
+ });
279
+ }
280
+ };
281
+
282
+ const addAttr = (el, attrs) => {
283
+ if (isElement(el) === false) return false
284
+ if (isPlainObject(attrs)) {
285
+ forEach(attrs, (value, name) => {
286
+ el.setAttribute(name, value);
287
+ });
288
+ }
289
+ };
290
+
291
+ const getStyle = (el, prop, getComputedStyle) => {
292
+ getComputedStyle = window.getComputedStyle;
293
+ return (getComputedStyle ? getComputedStyle(el) : el['currentStyle'])[
294
+ prop.replace(/-(\w)/gi, function (word, letter) {
295
+ return letter.toUpperCase()
296
+ })
297
+ ]
298
+ };
299
+
300
+ const getPath = (path) => {
301
+ const props = path.split('.');
302
+ const first = props.shift();
303
+ let value = null;
304
+ if (hasProp(window, first)) {
305
+ value = window[first];
306
+ forEach(props, (name) => {
307
+ value = hasProp(value, name) ? value[name] : null;
308
+ });
309
+ }
310
+ return value
311
+ };
312
+
313
+ const stringFormat = (format, params, expr) => {
314
+ return (format || '').replace(expr || /{(.+?)}/g, (match, prop) => {
315
+ return params[prop] || match
316
+ })
317
+ };
318
+
319
+ const cssUnit = (value, unit) => {
320
+ return String(value || 0)
321
+ .concat(unit || '')
322
+ .concat(' !important')
323
+ };
324
+ /**
325
+ * @function
326
+ * @type {function(*, *, *)}
327
+ */
328
+ const getPaymentRequest = ((cx) => {
329
+ let NativePaymentRequest;
330
+ if (hasProp(cx, 'PaymentRequest') && isFunction(cx.PaymentRequest)) {
331
+ NativePaymentRequest = cx.PaymentRequest;
332
+ }
333
+ return (methods, details, options) => {
334
+ let request = null;
335
+ details = details || {};
336
+ details.id = uuid();
337
+ options = options || {};
338
+ if (NativePaymentRequest) {
339
+ try {
340
+ request = new NativePaymentRequest(methods, details, options);
341
+ } catch (e) {
342
+ request = null;
343
+ }
344
+ }
345
+ return request
346
+ }
347
+ })(window);
348
+
349
+ const jsonParse = (value, defaults) => {
350
+ try {
351
+ return JSON.parse(value)
352
+ } catch (e) {
353
+ return defaults
354
+ }
355
+ };
356
+
357
+ var Utils = /*#__PURE__*/Object.freeze({
358
+ __proto__: null,
359
+ addAttr: addAttr,
360
+ addClass: addClass,
361
+ cleanObject: cleanObject,
362
+ createElement: createElement,
363
+ cssUnit: cssUnit,
364
+ deparam: deparam,
365
+ extend: extend,
366
+ forEach: forEach,
367
+ getPath: getPath,
368
+ getPaymentRequest: getPaymentRequest,
369
+ getStyle: getStyle,
370
+ getType: getType,
371
+ hasProp: hasProp,
372
+ isArguments: isArguments,
373
+ isArray: isArray,
374
+ isDate: isDate,
375
+ isElement: isElement,
376
+ isError: isError,
377
+ isFunction: isFunction,
378
+ isNumber: isNumber,
379
+ isObject: isObject,
380
+ isPlainObject: isPlainObject,
381
+ isRegexp: isRegexp,
382
+ isString: isString,
383
+ jsonParse: jsonParse,
384
+ map: map,
385
+ param: param,
386
+ querySelector: querySelector,
387
+ querySelectorAll: querySelectorAll,
388
+ removeAttr: removeAttr,
389
+ removeClass: removeClass,
390
+ removeElement: removeElement,
391
+ stringFormat: stringFormat,
392
+ toArray: toArray,
393
+ uuid: uuid
394
+ });
395
+
396
+ const ApiOrigin = 'https://pay.flitt.com';
397
+
398
+ const ApiEndpoint = {
399
+ gateway: '/latest/checkout-v2/index.html',
400
+ element: '/latest/checkout-v2/button/element.html',
401
+ };
402
+
403
+ const ProxyUrl = 'http://secure-redirect.cloudipsp.com/submit/';
404
+
405
+ const GooglePayApi = 'https://pay.google.com/gp/p/js/pay.js';
406
+
407
+ const GoogleBaseRequest = {
408
+ apiVersion: 2,
409
+ apiVersionMinor: 0,
410
+ allowedPaymentMethods: [
411
+ {
412
+ type: 'CARD',
413
+ parameters: {
414
+ allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
415
+ allowedCardNetworks: ['AMEX', 'DISCOVER', 'INTERAC', 'JCB', 'MASTERCARD', 'VISA'],
416
+ },
417
+ },
418
+ ],
419
+ };
420
+
421
+ const GooglePayLanguages = [
422
+ 'ar',
423
+ 'bg',
424
+ 'ca',
425
+ 'zh',
426
+ 'hr',
427
+ 'cs',
428
+ 'da',
429
+ 'nl',
430
+ 'en',
431
+ 'et',
432
+ 'fi',
433
+ 'fr',
434
+ 'de',
435
+ 'el',
436
+ 'id',
437
+ 'it',
438
+ 'ja',
439
+ 'ko',
440
+ 'ms',
441
+ 'no',
442
+ 'pl',
443
+ 'pt',
444
+ 'ru',
445
+ 'sr',
446
+ 'sk',
447
+ 'sl',
448
+ 'es',
449
+ 'sv',
450
+ 'th',
451
+ 'tr',
452
+ 'uk',
453
+ ];
454
+
455
+ const PaymentRequestDetails = {
456
+ total: {
457
+ label: 'Total',
458
+ amount: {
459
+ currency: 'USD',
460
+ value: '0.00',
461
+ },
462
+ },
463
+ };
464
+
465
+ const ApiFrameCss = {
466
+ width: '1px !important',
467
+ height: '1px !important',
468
+ left: '1px !important',
469
+ bottom: '1px !important',
470
+ position: 'fixed !important',
471
+ border: '0px !important',
472
+ };
473
+
474
+ const ButtonFrameCss = {
475
+ border: 'none !important',
476
+ margin: '0 !important',
477
+ padding: '0 !important',
478
+ display: 'block !important',
479
+ width: '1px !important',
480
+ 'min-width': '100% !important',
481
+ background: 'transparent !important',
482
+ position: 'relative !important',
483
+ opacity: '0 !important',
484
+ overflow: 'hidden !important',
485
+ height: '100% !important',
486
+ outline: 'none !important',
487
+ 'z-index': '1 !important',
488
+ };
489
+
490
+ const ButtonFrameAttrs = {
491
+ tabindex: '-1',
492
+ scrolling: 'no',
493
+ frameborder: 0,
494
+ allowtransparency: true,
495
+ allowpaymentrequest: true,
496
+ };
497
+
498
+ const ButtonCoverCss = {
499
+ 'z-index': '2 !important',
500
+ position: 'absolute !important',
501
+ border: 'none !important',
502
+ background: 'transparent !important',
503
+ left: '0 !important',
504
+ top: '0 !important',
505
+ cursor: 'pointer !important',
506
+ outline: 'none !important',
507
+ width: '100% !important',
508
+ height: '100% !important',
509
+ };
510
+
511
+ const ButtonCoverAttrs = {
512
+ role: 'button',
513
+ 'aria-pressed': 'false',
514
+ };
515
+
516
+ const ButtonContainerCss = {
517
+ border: '0 !important',
518
+ margin: '0 !important',
519
+ padding: '0 !important',
520
+ display: 'block !important',
521
+ background: 'transparent !important',
522
+ 'user-select': 'none !important',
523
+ overflow: 'hidden !important',
524
+ position: 'relative !important',
525
+ opacity: '1 !important',
526
+ height: '0 !important',
527
+ width: '100% !important',
528
+ outline: 'none !important',
529
+ };
530
+
531
+ const ButtonDefaultColor = 'dark';
532
+
533
+ const ButtonColorMap = {
534
+ dark: 'dark',
535
+ light: 'light',
536
+ black: 'dark',
537
+ white: 'light',
538
+ };
539
+
540
+ const ButtonLabelMap = {
541
+ ar: '',
542
+ bg: '',
543
+ ca: '',
544
+ zh: '',
545
+ hr: '',
546
+ cs: '',
547
+ da: '',
548
+ nl: '',
549
+ en: 'Pay with',
550
+ et: '',
551
+ es: 'Comprar con',
552
+ el: '',
553
+ fi: '',
554
+ fr: 'Acheter avec',
555
+ de: 'Zahlen über',
556
+ id: '',
557
+ it: 'Acquista con',
558
+ ja: '',
559
+ ko: '',
560
+ ms: '',
561
+ no: '',
562
+ pl: 'Zapłać przez',
563
+ pt: '',
564
+ ru: 'Оплатить через',
565
+ sr: '',
566
+ sk: 'Zaplatiť cez',
567
+ sl: '',
568
+ sv: '',
569
+ th: '',
570
+ tr: '',
571
+ uk: 'Оплатити через',
572
+ };
573
+
574
+ var Config = /*#__PURE__*/Object.freeze({
575
+ __proto__: null,
576
+ ApiEndpoint: ApiEndpoint,
577
+ ApiFrameCss: ApiFrameCss,
578
+ ApiOrigin: ApiOrigin,
579
+ ButtonColorMap: ButtonColorMap,
580
+ ButtonContainerCss: ButtonContainerCss,
581
+ ButtonCoverAttrs: ButtonCoverAttrs,
582
+ ButtonCoverCss: ButtonCoverCss,
583
+ ButtonDefaultColor: ButtonDefaultColor,
584
+ ButtonFrameAttrs: ButtonFrameAttrs,
585
+ ButtonFrameCss: ButtonFrameCss,
586
+ ButtonLabelMap: ButtonLabelMap,
587
+ GoogleBaseRequest: GoogleBaseRequest,
588
+ GooglePayApi: GooglePayApi,
589
+ GooglePayLanguages: GooglePayLanguages,
590
+ PaymentRequestDetails: PaymentRequestDetails,
591
+ ProxyUrl: ProxyUrl
592
+ });
593
+
594
+ const PENDING = 0;
595
+ const RESOLVED = 1;
596
+ const REJECTED = 2;
597
+ const PROGRESS = 3;
598
+
599
+ function Deferred() {
600
+ const resolveCallbacks = [];
601
+ const rejectCallbacks = [];
602
+ const notifyCallbacks = [];
603
+ let status = PENDING;
604
+ let resultContext = undefined;
605
+ let resultArgs = null;
606
+ let chainArgs = null;
607
+ const executeCallback = (context, args, callbacks) => {
608
+ const list = [].concat(callbacks);
609
+ const save = (chainArgs, isArgs) => {
610
+ if (isArgs) {
611
+ resultArgs = Array.from(chainArgs);
612
+ } else {
613
+ resultArgs = [chainArgs];
614
+ }
615
+ };
616
+ const execute = () => {
617
+ const item = list.shift();
618
+ if (item) {
619
+ chainArgs = item.apply(resultContext, resultArgs);
620
+ if (chainArgs !== undefined) {
621
+ if (chainArgs && chainArgs.then) {
622
+ chainArgs.then((...chainArgs) => {
623
+ save(chainArgs, true);
624
+ execute();
625
+ });
626
+ } else {
627
+ save(chainArgs);
628
+ execute();
629
+ }
630
+ } else {
631
+ execute();
632
+ }
633
+ }
634
+ };
635
+ resultContext = context;
636
+ resultArgs = args;
637
+ execute();
638
+ };
639
+ /**
640
+ * @lends Deferred.prototype
641
+ */
642
+ const promise = {
643
+ done(callback) {
644
+ if (isFunction(callback)) {
645
+ if (status === REJECTED) {
646
+ callback.apply(resultContext, resultArgs);
647
+ }
648
+ resolveCallbacks.push(callback);
649
+ }
650
+ return this
651
+ },
652
+ fail(callback) {
653
+ if (isFunction(callback)) {
654
+ if (status === REJECTED) {
655
+ callback.apply(resultContext, resultArgs);
656
+ }
657
+ rejectCallbacks.push(callback);
658
+ }
659
+ return this
660
+ },
661
+ progress(callback) {
662
+ if (isFunction(callback)) {
663
+ if (status === PROGRESS) {
664
+ callback.apply(resultContext, resultArgs);
665
+ }
666
+ notifyCallbacks.push(callback);
667
+ }
668
+ return this
669
+ },
670
+ always(callback) {
671
+ return this.done(callback).fail(callback)
672
+ },
673
+ then(resolve, reject, progress) {
674
+ if (isFunction(resolve)) {
675
+ this.done(resolve);
676
+ }
677
+ if (isFunction(reject)) {
678
+ this.fail(reject);
679
+ }
680
+ if (isFunction(progress)) {
681
+ this.progress(reject);
682
+ }
683
+ return this
684
+ },
685
+ promise(object) {
686
+ if (object === null) {
687
+ return promise
688
+ }
689
+ forEach(promise, (item, prop) => {
690
+ object[prop] = item;
691
+ });
692
+ return object
693
+ },
694
+ state: function () {
695
+ return status
696
+ },
697
+ isPending() {
698
+ return status === PENDING
699
+ },
700
+ isRejected() {
701
+ return status === REJECTED
702
+ },
703
+ isResolved() {
704
+ return status === RESOLVED
705
+ },
706
+ resetState() {
707
+ status = PENDING;
708
+ return this
709
+ },
710
+ resolveWith(context, args) {
711
+ if (status === PENDING) {
712
+ status = RESOLVED;
713
+ executeCallback(context, args, resolveCallbacks);
714
+ }
715
+ return this
716
+ },
717
+ rejectWith(context, args) {
718
+ if (status === PENDING) {
719
+ status = REJECTED;
720
+ executeCallback(context, args, rejectCallbacks);
721
+ }
722
+ return this
723
+ },
724
+ notifyWith(context, args) {
725
+ if (status === PENDING) {
726
+ status = PROGRESS;
727
+ executeCallback(context, args, notifyCallbacks);
728
+ status = PENDING;
729
+ }
730
+ return this
731
+ },
732
+
733
+ resolve() {
734
+ return this.resolveWith(this, Array.from(arguments))
735
+ },
736
+ reject() {
737
+ return this.rejectWith(this, Array.from(arguments))
738
+ },
739
+ notify() {
740
+ return this.notifyWith(this, Array.from(arguments))
741
+ },
742
+ };
743
+ return promise
744
+ }
745
+
746
+ let init = false;
747
+ const fnTest = /xyz/.test(
748
+ function () {
749
+ return 'xyz'
750
+ }.toString()
751
+ )
752
+ ? /\b_super\b/
753
+ : /.*/;
754
+
755
+ function ClassObject() {}
756
+
757
+ ClassObject.prototype._super = function () {};
758
+
759
+ ClassObject.prototype.instance = function (params) {
760
+ return new this.constructor(params)
761
+ };
762
+
763
+ ClassObject.prototype.proxy = function (fn) {
764
+ fn = typeof fn == 'string' ? this[fn] : fn;
765
+ return (function (cx, cb) {
766
+ return function () {
767
+ return cb.apply(cx, [this].concat(Array.prototype.slice.call(arguments)))
768
+ }
769
+ })(this, fn)
770
+ };
771
+
772
+ function superMethod(parent, name, method) {
773
+ return function () {
774
+ let temp = this._super,
775
+ result;
776
+ this._super = parent[name];
777
+ result = method.apply(this, arguments);
778
+ this._super = temp;
779
+ return result
780
+ }
781
+ }
782
+
783
+ function assign(target, instance) {
784
+ let prop,
785
+ proto,
786
+ parent = target.prototype;
787
+ init = true;
788
+ proto = new target();
789
+ init = false;
790
+ for (prop in instance) {
791
+ if (instance.hasOwnProperty(prop)) {
792
+ if (
793
+ typeof parent[prop] == 'function' &&
794
+ typeof instance[prop] == 'function' &&
795
+ fnTest.test(instance[prop])
796
+ ) {
797
+ proto[prop] = superMethod(parent, prop, instance[prop]);
798
+ } else {
799
+ proto[prop] = instance[prop];
800
+ }
801
+ }
802
+ }
803
+ return proto
804
+ }
805
+
806
+ ClassObject.extend = function extend(instance) {
807
+ function Class() {
808
+ if (!init && this) this['init'].apply(this, arguments);
809
+ }
810
+ Class.prototype = assign(this, instance);
811
+ Class.prototype.constructor = Class;
812
+ Class.extend = extend;
813
+ return Class
814
+ };
815
+
816
+ const Event = ClassObject.extend({
817
+ init() {
818
+ this.events = {};
819
+ this.empty = [];
820
+ },
821
+ on(type, callback) {
822
+ (this.events[type] = this.events[type] || []).push(callback);
823
+ return this
824
+ },
825
+ off(type, callback) {
826
+ type || (this.events = {});
827
+ let list = this.events[type] || this.empty,
828
+ i = (list.length = callback ? list.length : 0);
829
+ while (i--) callback === list[i] && list.splice(i, 1);
830
+ return this
831
+ },
832
+ trigger(type) {
833
+ let e = this.events[type] || this.empty,
834
+ list = e.length > 0 ? e.slice(0, e.length) : e,
835
+ i = 0,
836
+ j;
837
+ while ((j = list[i++])) j.apply(j, this.empty.slice.call(arguments, 1));
838
+ return this
839
+ },
840
+ });
841
+
842
+ const Module = ClassObject.extend({
843
+ utils: Utils,
844
+ getListener() {
845
+ if (!this._listener_) this._listener_ = new Event();
846
+ return this._listener_
847
+ },
848
+ destroy() {
849
+ this.off();
850
+ },
851
+ on(type, callback) {
852
+ this.getListener().on(type, callback);
853
+ return this
854
+ },
855
+ off(type, callback) {
856
+ this.getListener().off(type, callback);
857
+ return this
858
+ },
859
+ proxy(fn) {
860
+ if (!this._proxy_cache_) this._proxy_cache_ = {};
861
+ if (this.utils.isString(fn)) {
862
+ if (!this._proxy_cache_[fn]) {
863
+ this._proxy_cache_[fn] = this._super(fn);
864
+ }
865
+ return this._proxy_cache_[fn]
866
+ }
867
+ return this._super(fn)
868
+ },
869
+ trigger() {
870
+ this.getListener().trigger.apply(this.getListener(), arguments);
871
+ return this
872
+ },
873
+ each(ob, cb) {
874
+ this.utils.forEach(ob, this.proxy(cb));
875
+ },
876
+ addAttr(el, ob) {
877
+ if (!this.utils.isElement(el)) return false
878
+ this.utils.forEach(ob, function (v, k) {
879
+ el.setAttribute(k, v);
880
+ });
881
+ },
882
+ addCss(el, ob) {
883
+ if (!this.utils.isElement(el)) return false
884
+ this.utils.forEach(
885
+ ob,
886
+ function (v, k) {
887
+ this.addCssProperty(el, k, v);
888
+ },
889
+ this
890
+ );
891
+ },
892
+ addCssProperty(el, style, value) {
893
+ let result = el.style.cssText.match(
894
+ new RegExp('(?:[;\\s]|^)(' + style.replace('-', '\\-') + '\\s*:(.*?)(;|$))')
895
+ ),
896
+ idx;
897
+ if (result) {
898
+ idx = result.index + result[0].indexOf(result[1]);
899
+ el.style.cssText =
900
+ el.style.cssText.substring(0, idx) +
901
+ style +
902
+ ': ' +
903
+ value +
904
+ ';' +
905
+ el.style.cssText.substring(idx + result[1].length);
906
+ } else {
907
+ el.style.cssText += ' ' + style + ': ' + value + ';';
908
+ }
909
+ },
910
+ addEvent(el, ev, cb) {
911
+ if (!el || !ev || !cb) return false
912
+ cb = this.proxy(cb);
913
+ if (el.addEventListener) el.addEventListener(ev, cb);
914
+ else if (el['attachEvent']) el['attachEvent']('on' + ev, cb);
915
+ },
916
+ removeEvent(el, ev, cb) {
917
+ if (!el || !ev || !cb) return false
918
+ cb = this.proxy(cb);
919
+ if (el.removeEventListener) el.removeEventListener(ev, cb, false);
920
+ else if (el['detachEvent']) el['detachEvent']('on' + ev, cb);
921
+ },
922
+ prepareForm(url, data, target, method) {
923
+ const form = this.utils.createElement('form');
924
+ this.addAttr(form, {
925
+ action: url,
926
+ target: target || '_self',
927
+ method: method || 'POST',
928
+ });
929
+ this.addCss(form, {
930
+ display: 'none',
931
+ });
932
+ this.utils.forEach(
933
+ data,
934
+ function (v, k, el) {
935
+ el = this.utils.createElement('input');
936
+ el.type = 'hidden';
937
+ el.name = k;
938
+ el.value = v;
939
+ form.appendChild(el);
940
+ },
941
+ this
942
+ );
943
+ return form
944
+ },
945
+ });
946
+
947
+ const Connector = Module.extend({
948
+ ns: 'crossDomain',
949
+ origin: '*',
950
+ uniqueId: 1,
951
+ signature: null,
952
+ init(params) {
953
+ this.setTarget(params.target);
954
+ this.setOrigin(params.origin);
955
+ this.create();
956
+ },
957
+ create() {
958
+ this.addEvent(window, 'message', 'router');
959
+ },
960
+ setOrigin(origin) {
961
+ this.origin = origin || '*';
962
+ },
963
+ setTarget(target) {
964
+ this.target = target;
965
+ return this
966
+ },
967
+ getUID() {
968
+ return ++this.uniqueId
969
+ },
970
+ destroy() {
971
+ this.removeEvent(window, 'message', 'router');
972
+ this._super();
973
+ },
974
+ router(window, ev, response) {
975
+ if (this.target !== ev.source) return false
976
+ try {
977
+ response = JSON.parse(ev.data);
978
+ } catch (e) {}
979
+ if (response && response.action && response.data) {
980
+ this.trigger(response.action, response.data);
981
+ }
982
+ },
983
+ send(action, data, request, options) {
984
+ if (!this.target) {
985
+ return
986
+ }
987
+ request = JSON.stringify({
988
+ action: action,
989
+ data: data,
990
+ });
991
+ options = {
992
+ targetOrigin: this.origin,
993
+ delegate: 'payment',
994
+ };
995
+ try {
996
+ this.target.postMessage(request, options);
997
+ } catch (e) {
998
+ this.target.postMessage(request, this.origin, []);
999
+ }
1000
+ },
1001
+ });
1002
+
1003
+ var styles = (data) => `
1004
+ <style>
1005
+ .flitt-modal {
1006
+ box-sizing: border-box;
1007
+ margin: 100px auto;
1008
+ max-width: 680px;
1009
+ background-color: #fff;
1010
+ border-radius: 5px;
1011
+ box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
1012
+ overflow: hidden;
1013
+ }
1014
+
1015
+ @media (max-width: 850px) {
1016
+ .flitt-modal {
1017
+ margin: 50px auto;
1018
+ }
1019
+ }
1020
+
1021
+ @media (max-width: 695px) {
1022
+ .flitt-modal {
1023
+ max-width: 100%;
1024
+ margin: 5px;
1025
+ }
1026
+ }
1027
+
1028
+ .flitt-modal-wrapper {
1029
+ box-sizing: border-box;
1030
+ overflow: auto;
1031
+ position: fixed;
1032
+ z-index: 99999;
1033
+ left: 0;
1034
+ bottom: 0;
1035
+ top: 0;
1036
+ right: 0;
1037
+ background-color: rgba(0, 0, 0, 0.2);
1038
+ }
1039
+
1040
+ .flitt-modal-header {
1041
+ box-sizing: border-box;
1042
+ background-color: #fafafa;
1043
+ height: 50px;
1044
+ box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
1045
+ border-top-left-radius: 5px;
1046
+ border-top-right-radius: 5px;
1047
+ }
1048
+
1049
+ .flitt-modal-close {
1050
+ box-sizing: border-box;
1051
+ float: right;
1052
+ overflow: hidden;
1053
+ height: 50px;
1054
+ text-decoration: none;
1055
+ border-top-right-radius: 5px;
1056
+ color: #949494;
1057
+ }
1058
+
1059
+ .flitt-modal-close:hover, .flitt-modal-close:focus, .flitt-modal-close:active {
1060
+ text-decoration: none;
1061
+ color: #646464;
1062
+ }
1063
+
1064
+ .flitt-modal-close:before {
1065
+ content: "×";
1066
+ font-size: 50px;
1067
+ line-height: 50px;
1068
+ padding: 0 10px;
1069
+ }
1070
+
1071
+ .flitt-modal-title {
1072
+ box-sizing: border-box;
1073
+ border-top-left-radius: 5px;
1074
+ line-height: 20px;
1075
+ height: 50px;
1076
+ padding: 5px 15px;
1077
+ font-size: 12px;
1078
+ display: table-cell;
1079
+ vertical-align: middle;
1080
+ }
1081
+ .flitt-modal-content {
1082
+ box-sizing: border-box;
1083
+ border-bottom-left-radius: 5px;
1084
+ min-height: 650px;
1085
+ }
1086
+ .flitt-modal-iframe {
1087
+ overflow-x: hidden;
1088
+ border: 0;
1089
+ display: block;
1090
+ width: 100%;
1091
+ height: 750px;
1092
+ }
1093
+ </style>
1094
+ `;
1095
+
1096
+ var acs = (data) => `
1097
+ ${styles()}
1098
+ <div class="flitt-modal-wrapper">
1099
+ <div class="flitt-modal">
1100
+ <div class="flitt-modal-header">
1101
+ <a href="javascript:void(0)" class="flitt-modal-close"></a>
1102
+ <div class="flitt-modal-title">
1103
+ ${data.messages.modalHeader}
1104
+ <a href='javascript:void(0)'>${data.messages.modalLinkLabel}</a>
1105
+ </div>
1106
+ </div>
1107
+ <div class="flitt-modal-content">
1108
+ <iframe src="about:blank" class="flitt-modal-iframe" frameborder="0" allowtransparency="true"></iframe>
1109
+ </div>
1110
+ </div>
1111
+ </div>
1112
+ `;
1113
+
1114
+ var Views = /*#__PURE__*/Object.freeze({
1115
+ __proto__: null,
1116
+ acs: acs
1117
+ });
1118
+
1119
+ function empty(name) {
1120
+ return function (data) {
1121
+ return ['template', name, 'not found'].join(' ')
1122
+ }
1123
+ }
1124
+
1125
+ const Template = ClassObject.extend({
1126
+ init(name) {
1127
+ this.view = Views[name] || empty(name);
1128
+ },
1129
+ render(data) {
1130
+ return this.view(data)
1131
+ },
1132
+ });
1133
+
1134
+ const Modal = Module.extend({
1135
+ init(data) {
1136
+ this.checkout = data.checkout;
1137
+ this.model = data.model || {};
1138
+ this.messages = data.checkout.params.messages || {};
1139
+ this.template = new Template('acs');
1140
+ this.body = this.utils.querySelector('body');
1141
+ this.initModal();
1142
+ this.initConnector();
1143
+ },
1144
+ initModal() {
1145
+ this.name = ['modal-iframe', this.getRandomNumber()].join('-');
1146
+ this.modal = this.utils.createElement('div');
1147
+ this.modal.innerHTML = this.template.render({
1148
+ model: this.model,
1149
+ messages: this.messages,
1150
+ });
1151
+ this.iframe = this.find('.flitt-modal-iframe');
1152
+ this.addAttr(this.iframe, { name: this.name, id: this.name });
1153
+ if (this.model['send_data']) {
1154
+ this.form = this.prepareForm(this.model['url'], this.model['send_data'], this.name);
1155
+ this.modal.appendChild(this.form);
1156
+ } else {
1157
+ this.iframe.src = this.model['url'];
1158
+ }
1159
+ this.addEvent(this.find('.flitt-modal-close'), 'click', 'closeModal');
1160
+ this.addEvent(this.find('.flitt-modal-title a'), 'click', 'submitForm');
1161
+ this.initScrollbar();
1162
+ this.body.appendChild(this.modal);
1163
+ if (this.form) {
1164
+ this.form.submit();
1165
+ }
1166
+ },
1167
+ measureScrollbar() {
1168
+ const scrollDiv = document.createElement('div');
1169
+ scrollDiv.className = 'modal-scrollbar-measure';
1170
+ this.body.appendChild(scrollDiv);
1171
+ this.utils.removeElement(scrollDiv);
1172
+ return scrollDiv.offsetWidth - scrollDiv.clientWidth
1173
+ },
1174
+ checkScrollbar() {
1175
+ let documentElementRect;
1176
+ let fullWindowWidth = window.innerWidth;
1177
+ if (!fullWindowWidth) {
1178
+ documentElementRect = document.documentElement.getBoundingClientRect();
1179
+ fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
1180
+ }
1181
+ this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
1182
+ this.scrollbarWidth = this.measureScrollbar();
1183
+ },
1184
+ initScrollbar() {
1185
+ this.checkScrollbar();
1186
+ this.bodyPad = parseInt(this.utils.getStyle(this.body, 'padding-right') || 0, 10);
1187
+ this.originalBodyPad = document.body.style.paddingRight || '';
1188
+ this.originalOverflow = document.body.style.overflow || '';
1189
+ if (this.bodyIsOverflowing) {
1190
+ this.addCss(this.body, {
1191
+ paddingRight: [this.bodyPad + this.scrollbarWidth, 'px'].join(''),
1192
+ overflow: 'hidden',
1193
+ });
1194
+ }
1195
+ },
1196
+ resetScrollbar() {
1197
+ this.addCss(this.body, {
1198
+ paddingRight: this.originalBodyPad ? [this.originalBodyPad, 'px'].join('') : '',
1199
+ overflow: this.originalOverflow,
1200
+ });
1201
+ },
1202
+ getRandomNumber() {
1203
+ return Math.round(Math.random() * 1000000000)
1204
+ },
1205
+ find(selector) {
1206
+ return this.utils.querySelector(selector, this.modal)
1207
+ },
1208
+ closeModal(el, ev) {
1209
+ ev.preventDefault();
1210
+ this.trigger('close', this.data);
1211
+ this.removeModal();
1212
+ },
1213
+ submitForm(el, ev) {
1214
+ ev.preventDefault();
1215
+ this.trigger('submit', this.data);
1216
+ this.addAttr(this.form, {
1217
+ target: '_blank',
1218
+ });
1219
+ this.form.submit();
1220
+ },
1221
+ removeModal() {
1222
+ this.destroy();
1223
+ },
1224
+ destroy() {
1225
+ this.utils.removeElement(this.modal);
1226
+ this.resetScrollbar();
1227
+ this.connector.destroy();
1228
+ this._super();
1229
+ },
1230
+ initConnector() {
1231
+ this.connector = new Connector({ target: this.iframe.contentWindow });
1232
+ this.connector.on('response', this.proxy('onResponse'));
1233
+ },
1234
+ onResponse(ev, data) {
1235
+ this.sendResponse(data);
1236
+ this.removeModal();
1237
+ },
1238
+ sendResponse(data) {
1239
+ this.checkout.connector.send('request', {
1240
+ uid: data.uid,
1241
+ action: 'api.checkout.proxy',
1242
+ method: 'send',
1243
+ params: data,
1244
+ });
1245
+ },
1246
+ });
1247
+
1248
+ const Model = Module.extend({
1249
+ init(data) {
1250
+ this.data = data || {};
1251
+ this.create();
1252
+ },
1253
+ create() {},
1254
+ eachProps(args) {
1255
+ const name = args[1] ? args[0] : null;
1256
+ const callback = args[1] ? args[1] : args[0];
1257
+ const list = name ? this.alt(name, []) : this.data;
1258
+ return {
1259
+ list: list,
1260
+ callback: callback,
1261
+ }
1262
+ },
1263
+ each() {
1264
+ const props = this.eachProps(arguments);
1265
+ for (let prop in props.list) {
1266
+ if (props.list.hasOwnProperty(prop)) {
1267
+ props.callback(this.instance(props.list[prop]), props.list[prop], prop);
1268
+ }
1269
+ }
1270
+ },
1271
+ filter() {
1272
+ const props = this.eachProps(arguments);
1273
+ for (let prop in props.list) {
1274
+ if (props.list.hasOwnProperty(prop)) {
1275
+ const item = this.instance(props.list[prop]);
1276
+ if (props.callback(item, props.list[prop], prop)) {
1277
+ return props.list[prop]
1278
+ }
1279
+ }
1280
+ }
1281
+ },
1282
+ find() {
1283
+ const props = this.eachProps(arguments);
1284
+ for (let prop in props.list) {
1285
+ if (props.list.hasOwnProperty(prop)) {
1286
+ const item = this.instance(props.list[prop]);
1287
+ if (props.callback(item, props.list[prop], prop)) {
1288
+ return item
1289
+ }
1290
+ }
1291
+ }
1292
+ return false
1293
+ },
1294
+ alt(prop, defaults) {
1295
+ prop = this.attr(prop);
1296
+ return typeof prop === 'undefined' ? defaults : prop
1297
+ },
1298
+ attr(key, value) {
1299
+ let i = 0,
1300
+ data = this.data,
1301
+ name = (key || '').split('.'),
1302
+ prop = name.pop(),
1303
+ len = arguments.length;
1304
+ for (; i < name.length; i++) {
1305
+ if (data && data.hasOwnProperty(name[i])) {
1306
+ data = data[name[i]];
1307
+ } else {
1308
+ if (len === 2) {
1309
+ data = data[name[i]] = {};
1310
+ } else {
1311
+ break
1312
+ }
1313
+ }
1314
+ }
1315
+ if (len === 1) {
1316
+ return data ? data[prop] : undefined
1317
+ }
1318
+ if (len === 2) {
1319
+ data[prop] = value;
1320
+ }
1321
+ return this
1322
+ },
1323
+ stringify() {
1324
+ return JSON.stringify(this.serialize())
1325
+ },
1326
+ serialize() {
1327
+ return this.data
1328
+ },
1329
+ });
1330
+
1331
+ const Response = Model.extend({
1332
+ stringFormat(string) {
1333
+ const that = this;
1334
+ return (string || '').replace(/{(.+?)}/g, function (match, prop) {
1335
+ return that.attr(['order.order_data', prop].join('.')) || match
1336
+ })
1337
+ },
1338
+ setConnector(connector) {
1339
+ this.connector = connector;
1340
+ return this
1341
+ },
1342
+ setUID(uid) {
1343
+ this.uid = uid;
1344
+ return this
1345
+ },
1346
+ getUID() {
1347
+ return this.uid
1348
+ },
1349
+ formDataProxy(url, data, target, method) {
1350
+ location.assign(
1351
+ [
1352
+ ProxyUrl,
1353
+ JSON.stringify({
1354
+ url: url,
1355
+ params: data,
1356
+ target: target,
1357
+ method: method,
1358
+ }),
1359
+ ].join('#')
1360
+ );
1361
+ },
1362
+ formDataSubmit(url, data, target, method) {
1363
+ if (url.match(/^http:/)) {
1364
+ return this.formDataProxy(url, data, target, method)
1365
+ }
1366
+ const action = this.stringFormat(url);
1367
+ const form = this.prepareForm(action, data, target, method);
1368
+ const body = this.utils.querySelector('body');
1369
+ body.appendChild(form);
1370
+ form.submit();
1371
+ form.parentNode.removeChild(form);
1372
+ },
1373
+ inProgress() {
1374
+ return this.attr('order.in_progress')
1375
+ },
1376
+ readyToSubmit() {
1377
+ return this.attr('order.ready_to_submit')
1378
+ },
1379
+ waitForResponse() {
1380
+ return this.attr('order.pending')
1381
+ },
1382
+ needVerifyCode() {
1383
+ return this.attr('order.need_verify_code')
1384
+ },
1385
+ redirectUrl() {
1386
+ if (this.attr('url')) {
1387
+ this.redirectToUrl(this.attr('url'));
1388
+ return true
1389
+ }
1390
+ return false
1391
+ },
1392
+ redirectToUrl(url) {
1393
+ location.assign(url);
1394
+ },
1395
+ submitToMerchant() {
1396
+ const ready = this.attr('order.ready_to_submit');
1397
+ const url = this.attr('model.url') || this.attr('order.response_url');
1398
+ const method = this.attr('order.method');
1399
+ const action = this.attr('order.action');
1400
+ const data = this.attr('model.send_data') || this.attr('order.order_data');
1401
+ if (ready && url && data) {
1402
+ if (action === 'redirect' || data['get_without_parameters'] === true) {
1403
+ this.redirectToUrl(url);
1404
+ } else {
1405
+ this.formDataSubmit(url, data, '_self', method);
1406
+ }
1407
+ return true
1408
+ }
1409
+ },
1410
+ submitForm() {
1411
+ const method = this.attr('method');
1412
+ const url = this.attr('url');
1413
+ const data = this.attr('send_data');
1414
+ if (url && data) {
1415
+ this.formDataSubmit(url, data, '_self', method);
1416
+ return true
1417
+ }
1418
+ return false
1419
+ },
1420
+ sendResponse() {
1421
+ const action = this.attr('action');
1422
+ if (action === 'submit') return this.submitForm()
1423
+ if (action === 'redirect') return this.redirectUrl()
1424
+ return false
1425
+ },
1426
+ prepare3dsData() {
1427
+ const params = {};
1428
+ const data = this.attr('submit3ds');
1429
+ if (data['3ds']) {
1430
+ params.token = this.attr('token');
1431
+ params.uid = this.getUID();
1432
+ params.frame = true;
1433
+ if (data['send_data'].TermUrl) {
1434
+ data['send_data'].TermUrl = [data['send_data'].TermUrl, this.utils.param(params)].join(
1435
+ '#!!'
1436
+ );
1437
+ }
1438
+ }
1439
+ return data
1440
+ },
1441
+ waitOn3dsDecline() {
1442
+ const data = this.alt('submit3ds.checkout_data', {
1443
+ js_wait_on_3ds_decline: false,
1444
+ js_wait_on_3ds_decline_duration: 0,
1445
+ });
1446
+ return data.js_wait_on_3ds_decline ? data.js_wait_on_3ds_decline_duration : 0
1447
+ },
1448
+ submit3dsForm() {
1449
+ if (this.attr('submit3ds.checkout_data')) {
1450
+ this.connector.trigger('modal', this.prepare3dsData());
1451
+ }
1452
+ },
1453
+ supportedMethod(method) {
1454
+ const item = this.find('methods', function (item) {
1455
+ return item.alt('supportedMethods', '').match(method)
1456
+ });
1457
+ if (item) {
1458
+ this.attr('methods', [item.serialize()]);
1459
+ } else {
1460
+ this.attr('methods', []);
1461
+ }
1462
+ },
1463
+ });
1464
+
1465
+ const Api = Module.extend({
1466
+ defaults: {
1467
+ origin: ApiOrigin,
1468
+ endpoint: ApiEndpoint,
1469
+ messages: {
1470
+ modalHeader:
1471
+ 'Now you will be redirected to your bank 3DSecure. If you are not redirected please refer',
1472
+ modalLinkLabel: 'link',
1473
+ },
1474
+ },
1475
+ init(params) {
1476
+ this.initParams(params);
1477
+ },
1478
+ url(type, url) {
1479
+ return [this.params.origin, this.params.endpoint[type] || '/', url || ''].join('')
1480
+ },
1481
+ extendParams(params) {
1482
+ this.utils.extend(this.params, params);
1483
+ return this
1484
+ },
1485
+ initParams(params) {
1486
+ this.params = this.utils.extend({}, this.defaults);
1487
+ this.extendParams(params);
1488
+ this.setOrigin(this.params.origin);
1489
+ this.loaded = false;
1490
+ this.created = false;
1491
+ },
1492
+ setOrigin(origin) {
1493
+ if (this.utils.isString(origin)) {
1494
+ this.params.origin = origin;
1495
+ }
1496
+ return this
1497
+ },
1498
+ scope(callback) {
1499
+ callback = this.proxy(callback);
1500
+ if (this.createFrame().loaded === true) {
1501
+ callback();
1502
+ } else {
1503
+ this.on('checkout.api', callback);
1504
+ }
1505
+ },
1506
+ request(model, method, params) {
1507
+ const defer = Deferred();
1508
+ const data = {
1509
+ uid: this.connector.getUID(),
1510
+ action: model,
1511
+ method: method,
1512
+ params: params || {},
1513
+ };
1514
+ this.connector.send('request', data);
1515
+ this.connector.on(
1516
+ data.uid,
1517
+ this.proxy(function (ev, response, model, action) {
1518
+ const responseModel = new Response(response);
1519
+ responseModel.setUID(data.uid);
1520
+ responseModel.setConnector(this.connector);
1521
+ action = 'resolveWith';
1522
+ if (responseModel.attr('submit3ds')) {
1523
+ action = 'notifyWith';
1524
+ }
1525
+ if (responseModel.attr('error')) {
1526
+ action = 'rejectWith';
1527
+ }
1528
+ defer[action](this, [responseModel]);
1529
+ })
1530
+ );
1531
+ return defer
1532
+ },
1533
+ loadFrame(url) {
1534
+ this.iframe = this.utils.createElement('iframe');
1535
+ this.addAttr(this.iframe, {
1536
+ allowtransparency: true,
1537
+ frameborder: 0,
1538
+ scrolling: 'no',
1539
+ });
1540
+ this.addAttr(this.iframe, { src: url });
1541
+ this.addCss(this.iframe, ApiFrameCss);
1542
+ this.body = this.utils.querySelector('body');
1543
+ if (this.body.firstChild) {
1544
+ this.body.insertBefore(this.iframe, this.body.firstChild);
1545
+ } else {
1546
+ this.body.appendChild(this.iframe);
1547
+ }
1548
+ return this.iframe
1549
+ },
1550
+ createFrame() {
1551
+ if (this.created === false) {
1552
+ this.created = true;
1553
+ this.iframe = this.loadFrame(this.url('gateway'));
1554
+ this.connector = new Connector({
1555
+ target: this.iframe.contentWindow,
1556
+ origin: this.params.origin,
1557
+ });
1558
+ this.connector.on('load', this.proxy('onLoadConnector'));
1559
+ this.connector.on('modal', this.proxy('onOpenModal'));
1560
+ }
1561
+ return this
1562
+ },
1563
+ onOpenModal(xhr, model) {
1564
+ this.modal = new Modal({
1565
+ checkout: this,
1566
+ model: model,
1567
+ });
1568
+ this.modal.on('close', this.proxy('_onCloseModal'));
1569
+ },
1570
+ onCloseModal(modal, data) {
1571
+ this.trigger('modal.close', modal, data);
1572
+ },
1573
+ onLoadConnector() {
1574
+ this.loaded = true;
1575
+ this.connector.off('load');
1576
+ this.trigger('checkout.api');
1577
+ this.off('checkout.api');
1578
+ },
1579
+ });
1580
+
1581
+ const GooglePayClient = Module.extend({
1582
+ id: 'google-payments-api',
1583
+ init() {
1584
+ this.client = null;
1585
+ this.wrapper = this.utils.querySelector('head');
1586
+ this.defer = Deferred();
1587
+ },
1588
+ load() {
1589
+ if (this.utils.getPath('google.payments.api.PaymentsClient')) {
1590
+ return this.defer.resolveWith(this)
1591
+ }
1592
+ if (this.utils.querySelector('#'.concat(this.id))) {
1593
+ return this.defer
1594
+ }
1595
+ this.script = this.utils.createElement('script');
1596
+ this.addAttr(this.script, {
1597
+ id: this.id,
1598
+ async: true,
1599
+ src: GooglePayApi,
1600
+ });
1601
+ this.utils.isElement(this.wrapper) && this.wrapper.appendChild(this.script);
1602
+ this.addEvent(this.script, 'load', 'onLoadSuccess');
1603
+ this.addEvent(this.script, 'error', 'onLoadError');
1604
+ return this.defer
1605
+ },
1606
+ show(methods) {
1607
+ const method = methods.find(function (item) {
1608
+ return item.supportedMethods === 'https://google.com/pay'
1609
+ });
1610
+ const client = this.getClient({ environment: method.data.environment });
1611
+ return client.loadPaymentData(method.data)
1612
+ },
1613
+ readyToPay(cx, response) {
1614
+ if (response.result) {
1615
+ this.defer.resolveWith(this);
1616
+ }
1617
+ },
1618
+ onError(cx, error) {
1619
+ this.defer.rejectWith(this, error);
1620
+ },
1621
+ onLoadSuccess() {
1622
+ const client = this.getClient();
1623
+ if (client)
1624
+ client
1625
+ .isReadyToPay(GoogleBaseRequest)
1626
+ .then(this.proxy('readyToPay'))
1627
+ .catch(this.proxy('onError'));
1628
+ },
1629
+ onLoadError() {
1630
+ this.defer.rejectWith(this);
1631
+ },
1632
+ getClient(options) {
1633
+ if (options || this.client === null) {
1634
+ const PaymentClient = this.utils.getPath('google.payments.api.PaymentsClient');
1635
+ if (PaymentClient) {
1636
+ this.client = new PaymentClient(options);
1637
+ } else {
1638
+ this.onError(null, new Error('Google Client Error'));
1639
+ }
1640
+ }
1641
+ return this.client
1642
+ },
1643
+ });
1644
+
1645
+ const GooglePay = new GooglePayClient();
1646
+
1647
+ const getPaymentMethods = () => {
1648
+ return [
1649
+ [
1650
+ 'google',
1651
+ {
1652
+ supportedMethods: 'https://google.com/pay',
1653
+ data: GoogleBaseRequest,
1654
+ },
1655
+ ],
1656
+ [
1657
+ 'apple',
1658
+ {
1659
+ supportedMethods: 'https://apple.com/apple-pay',
1660
+ },
1661
+ () => hasProp(window, 'ApplePaySession'),
1662
+ ],
1663
+ ]
1664
+ };
1665
+
1666
+ let requestDeferred = null;
1667
+
1668
+ let requestSupported = {
1669
+ fallback: false,
1670
+ provider: [],
1671
+ };
1672
+
1673
+ const getSupportedMethods = () => {
1674
+ if (requestDeferred) return requestDeferred
1675
+ requestDeferred = Deferred();
1676
+ const methods = getPaymentMethods();
1677
+ const details = PaymentRequestDetails
1678
+ ;(function check() {
1679
+ const item = methods.shift();
1680
+ if (item === undefined) {
1681
+ if (requestSupported.provider.indexOf('google') === -1) {
1682
+ requestSupported.fallback = true;
1683
+ requestSupported.provider.push('google');
1684
+ }
1685
+ return requestDeferred.resolve(requestSupported)
1686
+ }
1687
+ const method = item.shift();
1688
+ const config = item.shift();
1689
+ const callback = item.shift();
1690
+ if (isFunction(callback) && callback() === false) {
1691
+ setTimeout(check, 25);
1692
+ return false
1693
+ }
1694
+ const request = getPaymentRequest([config], details, {});
1695
+ if (request) {
1696
+ request
1697
+ .canMakePayment()
1698
+ .then(function (status) {
1699
+ if (status === true) requestSupported.provider.push(method);
1700
+ setTimeout(check, 25);
1701
+ })
1702
+ .catch(function () {
1703
+ setTimeout(check, 25);
1704
+ });
1705
+ } else {
1706
+ setTimeout(check, 25);
1707
+ }
1708
+ })();
1709
+ return requestDeferred
1710
+ };
1711
+
1712
+ const PaymentRequestInterface = Module.extend({
1713
+ config: {
1714
+ payment_system: '',
1715
+ fallback: false,
1716
+ methods: [],
1717
+ details: {},
1718
+ options: {},
1719
+ },
1720
+ supported: {
1721
+ fallback: false,
1722
+ provider: [],
1723
+ },
1724
+ payload: {
1725
+ payment_system: null,
1726
+ provider: [],
1727
+ },
1728
+ params: {},
1729
+ getSupportedMethods() {
1730
+ return getSupportedMethods().then((supported) => {
1731
+ this.setSupported(supported);
1732
+ return supported
1733
+ })
1734
+ },
1735
+ init(params) {
1736
+ this.params = params || {};
1737
+ },
1738
+ setSupported(supported) {
1739
+ this.supported = supported;
1740
+ this.trigger('supported', supported);
1741
+ return this
1742
+ },
1743
+ setPayload(payload) {
1744
+ this.payload = payload;
1745
+ this.trigger('payload', payload);
1746
+ return this
1747
+ },
1748
+ setMerchant(merchant) {
1749
+ this.merchant = merchant;
1750
+ },
1751
+ setApi(api) {
1752
+ if (api instanceof Api) this.api = api;
1753
+ return this
1754
+ },
1755
+ getProviderPayload(method) {
1756
+ return this.payload.provider[method] || {}
1757
+ },
1758
+ isMethodSupported(method) {
1759
+ return this.supported.provider.indexOf(method) !== -1
1760
+ },
1761
+ isFallbackMethod(method) {
1762
+ return method === 'google' && this.supported.fallback
1763
+ },
1764
+ });
1765
+
1766
+ const PaymentRequestApi = PaymentRequestInterface.extend({
1767
+ request(method, params, success, failure) {
1768
+ if (this.api) {
1769
+ this.api.scope(
1770
+ this.proxy(function () {
1771
+ this.api
1772
+ .request('api.checkout.pay', method, params)
1773
+ .done(this.proxy(success))
1774
+ .fail(this.proxy(failure));
1775
+ })
1776
+ );
1777
+ }
1778
+ },
1779
+ update(data) {
1780
+ const defer = Deferred();
1781
+ this.request(
1782
+ 'methods',
1783
+ data,
1784
+ function (cx, model) {
1785
+ this.onUpdate(cx, model);
1786
+ defer.resolveWith(this, [model]);
1787
+ },
1788
+ function (cx, model) {
1789
+ this.onError(cx, model);
1790
+ defer.rejectWith(this, [model]);
1791
+ }
1792
+ );
1793
+ return defer
1794
+ },
1795
+ onUpdate(cx, model) {
1796
+ this.setPayload(model.serialize());
1797
+ },
1798
+ onError(cx, model) {
1799
+ this.trigger('error', model);
1800
+ },
1801
+ isPending() {
1802
+ return this.pendingState === true
1803
+ },
1804
+ setPending(state) {
1805
+ this.pendingState = state;
1806
+ setTimeout(() => {
1807
+ this.trigger('pending', state);
1808
+ }, 100);
1809
+ },
1810
+ beforeCallback(defer) {
1811
+ defer.resolve();
1812
+ },
1813
+ setBeforeCallback(callback) {
1814
+ if (isFunction(callback)) {
1815
+ this.beforeCallback = callback;
1816
+ }
1817
+ return this
1818
+ },
1819
+ before() {
1820
+ if (this.isPending()) return
1821
+ this.setPending(true);
1822
+ const defer = Deferred();
1823
+ defer.always(
1824
+ this.proxy(function () {
1825
+ this.setPending(false);
1826
+ })
1827
+ );
1828
+ this.beforeCallback(defer);
1829
+ return defer
1830
+ },
1831
+ pay(method) {
1832
+ if (this.isPending()) return
1833
+ this.setPending(true);
1834
+ const payload = this.getProviderPayload(method);
1835
+ const response = Deferred();
1836
+ response.always(function () {
1837
+ this.setPending(false);
1838
+ });
1839
+ if (this.isMethodSupported(method) === false) {
1840
+ return response.rejectWith(this, [{ test: true }])
1841
+ }
1842
+ if (this.isFallbackMethod(method)) {
1843
+ this.makePaymentFallback(response, payload.methods);
1844
+ } else {
1845
+ this.makeNativePayment(response, payload);
1846
+ }
1847
+ return response
1848
+ .done(function (details) {
1849
+ this.trigger('details', {
1850
+ payment_system: this.payload.payment_system,
1851
+ data: details,
1852
+ });
1853
+ })
1854
+ .fail(function (error) {
1855
+ this.trigger('error', error);
1856
+ if (this.params.embedded === true) {
1857
+ location.reload();
1858
+ this.trigger('reload', this.params);
1859
+ }
1860
+ })
1861
+ },
1862
+ makeNativePayment(defer, payload) {
1863
+ const self = this;
1864
+ const request = getPaymentRequest(payload.methods, payload.details, payload.options);
1865
+ this.addEvent(request, 'merchantvalidation', 'merchantValidation');
1866
+ request
1867
+ .canMakePayment()
1868
+ .then(function () {
1869
+ request
1870
+ .show()
1871
+ .then(function (response) {
1872
+ response.complete('success').then(function () {
1873
+ defer.resolveWith(self, [response.details]);
1874
+ });
1875
+ })
1876
+ .catch(function (e) {
1877
+ defer.rejectWith(self, [{ code: e.code, message: e.message }]);
1878
+ });
1879
+ })
1880
+ .catch(function (e) {
1881
+ defer.rejectWith(self, [{ code: e.code, message: e.message }]);
1882
+ });
1883
+ },
1884
+ makePaymentFallback(defer, methods) {
1885
+ const self = this;
1886
+ GooglePay.load().then(() => {
1887
+ GooglePay.show(methods)
1888
+ .then((details) => {
1889
+ defer.resolveWith(self, [details]);
1890
+ })
1891
+ .catch((e) => {
1892
+ defer.rejectWith(self, [{ code: e.code, message: e.message }]);
1893
+ });
1894
+ });
1895
+ },
1896
+ appleSession(params) {
1897
+ const defer = Deferred();
1898
+ this.request(
1899
+ 'session',
1900
+ params,
1901
+ function (c, model) {
1902
+ defer.resolveWith(this, [model.serialize()]);
1903
+ },
1904
+ function (c, model) {
1905
+ defer.rejectWith(this, [model]);
1906
+ }
1907
+ );
1908
+ return defer
1909
+ },
1910
+ merchantValidation(cx, event) {
1911
+ const { validationURL } = event;
1912
+ const { host } = location;
1913
+ this.appleSession({
1914
+ url: validationURL,
1915
+ domain: host,
1916
+ merchant_id: this.merchant,
1917
+ })
1918
+ .done(function (session) {
1919
+ try {
1920
+ event.complete(session.data);
1921
+ } catch (error) {
1922
+ this.trigger('error', error);
1923
+ }
1924
+ })
1925
+ .fail(function (error) {
1926
+ this.trigger('error', error);
1927
+ });
1928
+ },
1929
+ });
1930
+
1931
+ const PaymentElement = Module.extend({
1932
+ defaults: {
1933
+ method: null,
1934
+ appendTo: null,
1935
+ className: 'payment-element',
1936
+ origin: ApiOrigin,
1937
+ endpoint: ApiEndpoint.element,
1938
+ mode: 'plain',
1939
+ color: 'black',
1940
+ lang: 'en',
1941
+ height: 38,
1942
+ },
1943
+ init(params) {
1944
+ this.params = {};
1945
+ this.utils.extend(this.params, this.defaults);
1946
+ this.utils.extend(this.params, params);
1947
+ this.initElement();
1948
+ },
1949
+ getElementUrl() {
1950
+ return [this.params.origin, this.params.endpoint].join('')
1951
+ },
1952
+ getElementOptions() {
1953
+ return this.utils.param({
1954
+ method: this.params.method,
1955
+ mode: this.params.mode,
1956
+ style: this.params.style,
1957
+ color: this.params.color,
1958
+ lang: this.params.lang,
1959
+ })
1960
+ },
1961
+ initElement() {
1962
+ this.element = this.utils.createElement('div');
1963
+ this.iframe = this.utils.createElement('iframe');
1964
+ this.button = this.utils.createElement('a');
1965
+ this.addCss(this.element, ButtonContainerCss);
1966
+ this.addCss(this.button, ButtonCoverCss);
1967
+ this.addAttr(this.button, ButtonCoverAttrs);
1968
+ this.addCss(this.iframe, ButtonFrameCss);
1969
+ this.addAttr(this.iframe, ButtonFrameAttrs);
1970
+ this.addAttr(this.iframe, {
1971
+ src: [this.getElementUrl(), this.getElementOptions()].join('?'),
1972
+ });
1973
+ this.addEvent(this.iframe, 'load', 'onloadConnector');
1974
+ this.addEvent(this.iframe, 'error', 'errorConnector');
1975
+ this.addAttr(this.element, {
1976
+ class: this.params.className,
1977
+ });
1978
+ this.element.appendChild(this.iframe);
1979
+ this.element.appendChild(this.button);
1980
+ },
1981
+ errorConnector() {
1982
+ log('frame load error');
1983
+ },
1984
+ onloadConnector() {
1985
+ this.connector = new Connector({
1986
+ target: this.iframe.contentWindow,
1987
+ origin: this.params.origin,
1988
+ });
1989
+ },
1990
+ send(action, data) {
1991
+ if (this.connector) {
1992
+ this.connector.send(action, data);
1993
+ }
1994
+ },
1995
+ onEvent(cx, ev) {
1996
+ ev.preventDefault();
1997
+ if (this.pending) return false
1998
+ this.send('event', { type: ev.type });
1999
+ },
2000
+ onClick() {
2001
+ if (this.pending) return false
2002
+ this.request.before().done(this.proxy('onClickDone')).fail(this.proxy('onClickFail'));
2003
+ },
2004
+ onClickDone() {
2005
+ this.request.pay(this.params.method);
2006
+ },
2007
+ onClickFail() {},
2008
+ onSupported(cx, supported) {
2009
+ if (supported.provider.includes(this.params.method)) {
2010
+ this.mount();
2011
+ }
2012
+ },
2013
+ onPayload(cx, payload) {
2014
+ if (payload.allowed.includes(this.params.method)) {
2015
+ this.show();
2016
+ }
2017
+ },
2018
+ onPending(cx, state) {
2019
+ this.pending = state;
2020
+ this.send('pending', { state: state });
2021
+ },
2022
+ initEvents() {
2023
+ this.addEvent(this.button, 'mouseenter', 'onEvent');
2024
+ this.addEvent(this.button, 'mouseleave', 'onEvent');
2025
+ this.addEvent(this.button, 'blur', 'onEvent');
2026
+ this.addEvent(this.button, 'focus', 'onEvent');
2027
+ this.addEvent(this.button, 'click', 'onClick');
2028
+ },
2029
+ setPaymentRequest(request) {
2030
+ if (!(request instanceof PaymentRequestApi))
2031
+ throw Error('request is not instance of PaymentRequestApi')
2032
+ this.request = request;
2033
+ const onSupported = this.proxy('onSupported');
2034
+ const onPayload = this.proxy('onPayload');
2035
+ const onPending = this.proxy('onPending');
2036
+ this.request.off('supported', onSupported).on('supported', onSupported);
2037
+ this.request.off('payload', onPayload).on('payload', onPayload);
2038
+ this.request.off('pending', onPending).on('pending', onPending);
2039
+ return this
2040
+ },
2041
+ appendTo(appendTo) {
2042
+ const container = this.utils.querySelector(appendTo);
2043
+ if (container) container.appendChild(this.element);
2044
+ this.initEvents();
2045
+ return this
2046
+ },
2047
+ mount() {
2048
+ this.appendTo(this.params.appendTo);
2049
+ },
2050
+ isMounted() {
2051
+ return document.body.contains(this.element)
2052
+ },
2053
+ show() {
2054
+ if (this.isMounted() === false) return this
2055
+ this.addCss(this.iframe, {
2056
+ transition: 'opacity 0.6s 0.4s ease-out',
2057
+ opacity: this.utils.cssUnit(1),
2058
+ });
2059
+ this.addCss(this.element, {
2060
+ transition: 'height 0.2s ease-out',
2061
+ height: this.utils.cssUnit(this.params.height, 'px'),
2062
+ });
2063
+ this.trigger('show', {});
2064
+ return this
2065
+ },
2066
+ hide() {
2067
+ if (this.isMounted() === false) return this
2068
+ this.addCss(this.iframe, {
2069
+ transition: 'opacity 0.4s ease-out',
2070
+ opacity: this.utils.cssUnit(0),
2071
+ });
2072
+ this.addCss(this.element, {
2073
+ transition: 'height 0.2s 0.4s ease-out',
2074
+ height: this.utils.cssUnit(0, 'px'),
2075
+ });
2076
+ this.trigger('hide', {});
2077
+ return this
2078
+ },
2079
+ });
2080
+
2081
+ const PaymentButton = Module.extend({
2082
+ defaults: {
2083
+ origin: ApiOrigin,
2084
+ endpoint: ApiEndpoint,
2085
+ methods: ['apple', 'google'],
2086
+ element: null,
2087
+ style: {
2088
+ height: 38,
2089
+ mode: 'default',
2090
+ type: 'long',
2091
+ color: 'black',
2092
+ },
2093
+ data: {
2094
+ lang: 'en',
2095
+ },
2096
+ before(defer) {
2097
+ defer.resolve();
2098
+ },
2099
+ },
2100
+ init(params) {
2101
+ this.elements = {};
2102
+ this.supported = false;
2103
+ this.params = {
2104
+ element: params.element,
2105
+ methods: params.methods || this.defaults.methods,
2106
+ origin: params.origin || this.defaults.origin,
2107
+ endpoint: this.utils.extend({}, this.defaults.endpoint, params.endpoint),
2108
+ style: this.utils.extend({}, this.defaults.style, params.style),
2109
+ before: params.before || this.defaults.before,
2110
+ data: this.utils.extend({}, this.defaults.data, params.data),
2111
+ };
2112
+ this.initApi(params.api);
2113
+ this.initPaymentRequestApi();
2114
+ this.initElements();
2115
+ this.update();
2116
+ },
2117
+ initApi(api) {
2118
+ if (api instanceof Api) {
2119
+ this.api = api;
2120
+ } else {
2121
+ this.api = new Api({
2122
+ origin: this.params.origin,
2123
+ endpoint: this.params.endpoint,
2124
+ });
2125
+ }
2126
+ },
2127
+ initPaymentRequestApi() {
2128
+ this.request = new PaymentRequestApi();
2129
+ this.request.setApi(this.api);
2130
+ this.request.setMerchant(this.params.data.merchant_id);
2131
+ this.request.setBeforeCallback(this.params.before);
2132
+ this.request.on('details', this.proxy('onDetails'));
2133
+ this.request.on('error', this.proxy('onError'));
2134
+ },
2135
+ initElements() {
2136
+ const style = this.params.style;
2137
+ const data = this.params.data;
2138
+ const origin = this.params.origin;
2139
+ const appendTo = this.params.element;
2140
+ const endpoint = this.params.endpoint.element;
2141
+ const request = this.request;
2142
+ this.container = this.utils.querySelector(this.params.element);
2143
+ this.addCss(this.container, {
2144
+ display: 'flex',
2145
+ gap: '1rem',
2146
+ 'flex-direction': 'column',
2147
+ });
2148
+ forEach(this.params.methods, function (method) {
2149
+ const element = new PaymentElement({
2150
+ origin: origin,
2151
+ endpoint: endpoint,
2152
+ method: method,
2153
+ appendTo: appendTo,
2154
+ color: style.color,
2155
+ mode: style.mode,
2156
+ lang: data.lang,
2157
+ height: style.height,
2158
+ });
2159
+ element.setPaymentRequest(request);
2160
+ });
2161
+ request.getSupportedMethods();
2162
+ },
2163
+ update(data) {
2164
+ return this.request.update(this.utils.extend(this.params.data, data || {}))
2165
+ },
2166
+ onDetails(cx, data) {
2167
+ this.api.scope(() => {
2168
+ this.api
2169
+ .request('api.checkout.form', 'request', this.utils.extend({}, this.params.data, data))
2170
+ .done(this.proxy('onSuccess'))
2171
+ .fail(this.proxy('onError'));
2172
+ });
2173
+ },
2174
+ onSuccess(cx, data) {
2175
+ this.trigger('success', data);
2176
+ },
2177
+ onError(cx, data) {
2178
+ this.trigger('error', data);
2179
+ },
2180
+ });
2181
+
2182
+ const parseConfig = (config) => {
2183
+ const data = {
2184
+ payment_system: config.payment_system,
2185
+ provider: {},
2186
+ };
2187
+ const methods = config.methods || [];
2188
+ const details = config.details || {};
2189
+ const options = config.options || {};
2190
+ const regex = new RegExp('//([a-z]+)\\.com/');
2191
+ methods.forEach(function (item) {
2192
+ const match = regex.exec(item.supportedMethods);
2193
+ if (match === null) return
2194
+ data.provider[match[1]] = {
2195
+ methods: [item],
2196
+ details: details,
2197
+ options: options,
2198
+ };
2199
+ });
2200
+ return data
2201
+ };
2202
+
2203
+ const PaymentContainer = Module.extend({
2204
+ defaults: {
2205
+ element: null,
2206
+ method: 'card',
2207
+ data: {
2208
+ lang: 'en',
2209
+ },
2210
+ style: {},
2211
+ },
2212
+ init(params) {
2213
+ this.initParams(params);
2214
+ this.initEvents();
2215
+ },
2216
+ initParams(params) {
2217
+ this.params = this.utils.extend({}, this.defaults, params);
2218
+ this.element = this.utils.querySelector(this.params.element);
2219
+ this.connector = new Connector({
2220
+ target: window.parent,
2221
+ });
2222
+ this.payment = new PaymentRequestApi({
2223
+ embedded: true,
2224
+ });
2225
+ },
2226
+ extendParams(params) {
2227
+ this.utils.extend(this.params, {
2228
+ method: params.method,
2229
+ style: params.style,
2230
+ data: params.data,
2231
+ css: params.css,
2232
+ });
2233
+ },
2234
+ getGoogleLangSupport(lang, defaults) {
2235
+ return GooglePayLanguages.indexOf(lang) !== -1 ? lang : defaults
2236
+ },
2237
+ getButtonColor(color) {
2238
+ return ButtonColorMap[color] || ButtonDefaultColor
2239
+ },
2240
+ getGoogleSvg(color, lang, mode) {
2241
+ const params = {
2242
+ endpoint: 'https://www.gstatic.com/instantbuy/svg',
2243
+ color: this.getButtonColor(color),
2244
+ mode: mode || 'plain',
2245
+ lang: lang || 'en',
2246
+ };
2247
+ let format = 'url("{endpoint}/{color}/{mode}/{lang}.svg")';
2248
+ if (mode === 'plain') {
2249
+ format = 'url("{endpoint}/{color}_gpay.svg")';
2250
+ }
2251
+ if (mode === 'buy') {
2252
+ format = 'url("{endpoint}/{color}/{lang}.svg")';
2253
+ }
2254
+ return this.utils.stringFormat(format, params)
2255
+ },
2256
+ getAppleSvg(color) {
2257
+ const format = 'url("svg/apple-pay-{color}.svg")';
2258
+ const params = {
2259
+ color: this.getButtonColor(color),
2260
+ };
2261
+ return this.utils.stringFormat(format, params)
2262
+ },
2263
+ getAppleLabel(lang) {
2264
+ return ButtonLabelMap[lang || 'en']
2265
+ },
2266
+ addFrameImage() {
2267
+ const frame =
2268
+ this.utils.querySelector('iframe', this.element) || this.utils.createElement('iframe');
2269
+ const url = 'https://pay.google.com/gp/p/generate_gpay_btn_img';
2270
+ const style = this.params.style || {};
2271
+ const lang = this.getGoogleLangSupport(this.params.data.lang, 'en');
2272
+ const query = {
2273
+ buttonColor: style.color || 'black',
2274
+ browserLocale: lang,
2275
+ buttonSizeMode: 'fill',
2276
+ };
2277
+ const src = [url, this.utils.param(query)].join('?');
2278
+ this.addAttr(frame, {
2279
+ scrolling: 'no',
2280
+ frameborder: 0,
2281
+ src: src,
2282
+ });
2283
+ this.element.appendChild(frame);
2284
+ this.element.classList.remove('short', 'long');
2285
+ },
2286
+ styleButton() {
2287
+ let element = this.element;
2288
+ let params = this.params;
2289
+ let method = params.method;
2290
+ let style = params.style || {};
2291
+ let lang = params.data.lang || 'en';
2292
+ let css = params.css || {};
2293
+ element.setAttribute('class', '');
2294
+ element.classList.add('button', 'pending');
2295
+ if (method === 'card') method = 'google';
2296
+ if (method) {
2297
+ element.classList.add(method);
2298
+ }
2299
+ {
2300
+ element.classList.add(lang);
2301
+ }
2302
+ if (style.type) {
2303
+ element.classList.add(style.type);
2304
+ }
2305
+ if (style.mode) {
2306
+ element.classList.add(style.mode);
2307
+ }
2308
+ if (style.color) {
2309
+ element.classList.add(style.color);
2310
+ }
2311
+ if (method === 'google') {
2312
+ if (style.type === 'short') {
2313
+ style.mode = 'plain';
2314
+ }
2315
+ if (style.mode === 'default') {
2316
+ this.addFrameImage();
2317
+ } else {
2318
+ css.image = this.getGoogleSvg(style.color, lang, style.mode);
2319
+ }
2320
+ }
2321
+ if (method === 'apple') {
2322
+ css.image = this.getAppleSvg(style.color);
2323
+ css.label = this.getAppleLabel(lang, style.mode);
2324
+ }
2325
+ {
2326
+ this.utils.forEach(css, function (value, name) {
2327
+ element.style.setProperty(['--', name].join(''), value);
2328
+ });
2329
+ }
2330
+ },
2331
+ initEvents() {
2332
+ this.payment.on(
2333
+ 'details',
2334
+ this.proxy(function (cx, data) {
2335
+ this.connector.send('details', data);
2336
+ this.connector.send('complete', data);
2337
+ })
2338
+ );
2339
+ this.payment.on(
2340
+ 'reload',
2341
+ this.proxy(function (cx, data) {
2342
+ this.connector.send('reload', data);
2343
+ })
2344
+ );
2345
+ this.payment.on(
2346
+ 'error',
2347
+ this.proxy(function (cx, data) {
2348
+ this.connector.send('error', data);
2349
+ })
2350
+ );
2351
+ this.connector.on(
2352
+ 'options',
2353
+ this.proxy(function (cx, data) {
2354
+ this.extendParams(data);
2355
+ this.styleButton();
2356
+ })
2357
+ );
2358
+ this.connector.on(
2359
+ 'pay',
2360
+ this.proxy(function () {
2361
+ if (!this.element.classList.contains('pending')) {
2362
+ if (this.params.method === 'apple') {
2363
+ const payload = this.payment.payload || {};
2364
+ const apple = payload.provider['apple'] || {};
2365
+ this.connector.send('pay', {
2366
+ payment_system: payload.payment_system,
2367
+ methods: apple.methods,
2368
+ details: apple.details,
2369
+ options: apple.options,
2370
+ });
2371
+ } else {
2372
+ this.payment
2373
+ .setSupported({
2374
+ fallback: false,
2375
+ provider: ['google'],
2376
+ })
2377
+ .pay('google');
2378
+ }
2379
+ }
2380
+ })
2381
+ );
2382
+ this.connector.on(
2383
+ 'config',
2384
+ this.proxy(function (cx, data) {
2385
+ this.payment.setPayload((data = parseConfig(data)));
2386
+ if (data.payment_system && Object.keys(data.provider).length > 0) {
2387
+ this.element.classList.remove('pending');
2388
+ this.element.classList.add('ready');
2389
+ this.connector.send('show', {});
2390
+ } else {
2391
+ this.connector.send('hide', {});
2392
+ }
2393
+ })
2394
+ );
2395
+ this.connector.on(
2396
+ 'event',
2397
+ this.proxy(function (cx, data) {
2398
+ if (data.type === 'mouseenter') {
2399
+ this.element.classList.add('hover');
2400
+ }
2401
+ if (data.type === 'mouseleave') {
2402
+ this.element.classList.remove('hover');
2403
+ }
2404
+ if (data.type === 'focusin') {
2405
+ this.element.classList.add('active');
2406
+ }
2407
+ if (data.type === 'focusout') {
2408
+ this.element.classList.remove('active');
2409
+ }
2410
+ })
2411
+ );
2412
+ },
2413
+ });
2414
+
2415
+ const Widget = Api.extend({
2416
+ init(params) {
2417
+ this.initParams(params);
2418
+ this.initWidget();
2419
+ },
2420
+ initWidget() {
2421
+ this.initOptions(this.params.options);
2422
+ if (this.utils.isString(this.params.element)) {
2423
+ this.initElement(this.params.element);
2424
+ }
2425
+ },
2426
+ initOptions() {
2427
+ if (this.utils.isPlainObject(this.params.options)) {
2428
+ this.params.options = this.params.options || {};
2429
+ }
2430
+ },
2431
+ initElement(el) {},
2432
+ addSelectorEvent(el, ev, cb) {
2433
+ this.each(this.utils.querySelectorAll(el), function (cx, element) {
2434
+ this.addEvent(element, ev, cb);
2435
+ });
2436
+ return this
2437
+ },
2438
+ getRequestParams() {
2439
+ return {}
2440
+ },
2441
+ sendRequest(el, ev) {
2442
+ if (ev.defaultPrevented) return
2443
+ ev.preventDefault();
2444
+ this.trigger('request', this.getRequestParams(el));
2445
+ this.scope(function () {
2446
+ this.request('api.checkout.form', 'request', this.getRequestParams(el))
2447
+ .done(this.proxy('onSuccess'))
2448
+ .fail(this.proxy('onError'))
2449
+ .progress(this.proxy('onProgress'));
2450
+ });
2451
+ },
2452
+ onProgress(cx, model) {
2453
+ this.trigger('progress', model);
2454
+ },
2455
+ onSuccess(cx, model) {
2456
+ model.sendResponse();
2457
+ model.submitToMerchant();
2458
+ this.trigger('success', model);
2459
+ },
2460
+ onError(cx, model) {
2461
+ this.trigger('error', model);
2462
+ },
2463
+ });
2464
+
2465
+ const FormData = Module.extend({
2466
+ init(form) {
2467
+ this.setFormElement(form);
2468
+ },
2469
+ setFormElement(form) {
2470
+ if (this.utils.isElement(form)) {
2471
+ this.form = form;
2472
+ }
2473
+ },
2474
+ getData(filter) {
2475
+ const params = this.deparam(this.serializeArray());
2476
+ return filter === true ? this.utils.cleanObject(params) : params
2477
+ },
2478
+ serializeArray() {
2479
+ const list = this.utils.toArray(this.form.elements);
2480
+ return this.utils.map(list, function (field) {
2481
+ if (field.disabled || field.name === '') return
2482
+ if (field.type.match('checkbox|radio') && !field.checked) return
2483
+ return {
2484
+ name: field.name,
2485
+ value: field.value,
2486
+ }
2487
+ })
2488
+ },
2489
+ serializeAndEncode() {
2490
+ return this.utils
2491
+ .map(this.serializeArray(), function (field) {
2492
+ return [field.name, encodeURIComponent(field.value)].join('=')
2493
+ })
2494
+ .join('&')
2495
+ },
2496
+ deparam(obj) {
2497
+ let prop,
2498
+ result = {};
2499
+ const breaker = /[^\[\]]+|\[\]$/g;
2500
+ const attr = function (name, value) {
2501
+ let i,
2502
+ data = result,
2503
+ last = name.pop(),
2504
+ len = name.length;
2505
+ for (i = 0; i < len; i++) {
2506
+ if (!data[name[i]]) data[name[i]] = len === i + 1 && last === '[]' ? [] : {};
2507
+ data = data[name[i]];
2508
+ }
2509
+ if (last === '[]') {
2510
+ data.push(value);
2511
+ } else {
2512
+ data[last] = value;
2513
+ }
2514
+ };
2515
+ for (prop in obj) {
2516
+ if (obj.hasOwnProperty(prop)) {
2517
+ attr(obj[prop].name.match(breaker), obj[prop].value);
2518
+ }
2519
+ }
2520
+ return result
2521
+ },
2522
+ });
2523
+
2524
+ const WidgetForm = Widget.extend({
2525
+ initElement(el) {
2526
+ this.addSelectorEvent(el, 'submit', 'sendRequest');
2527
+ },
2528
+ getRequestParams(el) {
2529
+ return this.utils.extend({}, this.params.options, new FormData(el).getData())
2530
+ },
2531
+ });
2532
+
2533
+ const WidgetButton = Widget.extend({
2534
+ attributes: {},
2535
+ initElement(el) {
2536
+ if (this.utils.isPlainObject(this.params.attributes)) {
2537
+ this.utils.extend(this.attributes, this.params.attributes);
2538
+ }
2539
+ this.addSelectorEvent(el, 'click', 'sendRequest');
2540
+ },
2541
+ getRequestParams(el) {
2542
+ return this.utils.extend({}, this.params.options, this.getElementData(el))
2543
+ },
2544
+ getElementData(el) {
2545
+ const result = {};
2546
+ this.utils.forEach(this.attributes, function (value, key) {
2547
+ if (el.hasAttribute(key)) {
2548
+ result[value] = el.getAttribute(key);
2549
+ }
2550
+ });
2551
+ return result
2552
+ },
2553
+ });
2554
+
2555
+ Component.add('Api', Api);
2556
+ Component.add('Connector', Connector);
2557
+ Component.add('PaymentButton', PaymentButton);
2558
+ Component.add('PaymentRequestApi', PaymentRequestApi);
2559
+ Component.add('PaymentElement', PaymentElement);
2560
+ Component.add('FormWidget', WidgetForm);
2561
+ Component.add('ButtonWidget', WidgetButton);
2562
+
2563
+ Component.Utils = Utils;
2564
+ Component.Config = Config;
2565
+ Component.Api = Api;
2566
+ Component.Module = Module;
2567
+ Component.Connector = Connector;
2568
+ Component.Response = Response;
2569
+ Component.PaymentRequestApi = PaymentRequestApi;
2570
+ Component.PaymentContainer = PaymentContainer;
2571
+ Component.PaymentElement = PaymentElement;
2572
+ Component.PaymentButton = PaymentButton;
2573
+
2574
+ export { Api, Config, Connector, Module, PaymentButton, PaymentContainer, PaymentElement, PaymentRequestApi, Response, Utils, Component as default };