@miden-npm/angular 2.1.1 → 2.1.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.
@@ -9,7 +9,10 @@ import { FormsModule, NG_VALUE_ACCESSOR, FormGroup, FormControl, Validators, Rea
9
9
  import * as i2 from 'angular-imask';
10
10
  import { IMaskModule } from 'angular-imask';
11
11
  import { tap, finalize } from 'rxjs';
12
+ import { Notyf } from 'notyf';
13
+ import 'notyf/notyf.min.css';
12
14
  import * as CryptoJS from 'crypto-js';
15
+ import * as i4 from '@angular/platform-browser';
13
16
 
14
17
  class MidenPGAngular {
15
18
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MidenPGAngular, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -504,7 +507,18 @@ const getBaseUrl = (mode, caller) => {
504
507
  else if (mode === 'prod') {
505
508
  return caller === 'buzapay'
506
509
  ? 'https://api.buzapay.com/payment-gateway-api'
507
- : 'https://sandbox-api.midencards.io/miden-web';
510
+ : 'https://api.midencards.io/miden-web';
511
+ }
512
+ return '';
513
+ };
514
+ const getBaseAppUrl = (mode, caller) => {
515
+ if (mode === 'sandbox') {
516
+ return caller === 'buzapay'
517
+ ? 'https://sandbox-merchant.buzapay.com'
518
+ : 'https://sandbox.midencards.io';
519
+ }
520
+ else if (mode === 'prod') {
521
+ return caller === 'buzapay' ? 'https://merchant.buzapay.com' : 'https://midencards.io';
508
522
  }
509
523
  return '';
510
524
  };
@@ -1886,6 +1900,18 @@ class CheckoutService {
1886
1900
  headers,
1887
1901
  });
1888
1902
  }
1903
+ midenConfirmPayment(environment, reference, merchantId, caller) {
1904
+ const baseUrl = getBaseUrl(environment, caller);
1905
+ const headers = new HttpHeaders({
1906
+ uniqueKey: merchantId,
1907
+ });
1908
+ const apiKey = {
1909
+ miden: `api/v1/accrual/checkout/confirm-payment/${reference}`,
1910
+ };
1911
+ return this.http.get(`${baseUrl}/${apiKey[caller]}`, {
1912
+ headers,
1913
+ });
1914
+ }
1889
1915
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CheckoutService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
1890
1916
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CheckoutService, providedIn: 'root' });
1891
1917
  }
@@ -1948,11 +1974,13 @@ class PayByCardComponent {
1948
1974
  cdr;
1949
1975
  checkout;
1950
1976
  encryptService;
1951
- constructor(resources, cdr, checkout, encryptService) {
1977
+ sanitizer;
1978
+ constructor(resources, cdr, checkout, encryptService, sanitizer) {
1952
1979
  this.resources = resources;
1953
1980
  this.cdr = cdr;
1954
1981
  this.checkout = checkout;
1955
1982
  this.encryptService = encryptService;
1983
+ this.sanitizer = sanitizer;
1956
1984
  }
1957
1985
  secretKey = '';
1958
1986
  environment = 'sandbox';
@@ -1980,6 +2008,8 @@ class PayByCardComponent {
1980
2008
  countryStates = [];
1981
2009
  phoneCodeOptions = [];
1982
2010
  defaultCountryCode = '';
2011
+ notyf = null;
2012
+ baseAppUrl = '';
1983
2013
  formIndex = 0;
1984
2014
  setFormIndex(index) {
1985
2015
  this.formIndex = index;
@@ -2098,6 +2128,130 @@ class PayByCardComponent {
2098
2128
  }))
2099
2129
  .subscribe();
2100
2130
  }
2131
+ // --- 3DS state ---
2132
+ threeDSOpen = false;
2133
+ threeDSIframeSrc = null;
2134
+ // Listener reference (like useRef)
2135
+ messageListener;
2136
+ // --- Start 3DS Challenge ---
2137
+ midenThreeDSChallenge(url, value) {
2138
+ if (!url || !value) {
2139
+ this.message = '3DS challenge could not be started (missing stepUpUrl/JWT).';
2140
+ return;
2141
+ }
2142
+ // Build auto-submit HTML form
2143
+ const html = `<!doctype html>
2144
+ <html>
2145
+ <head><meta charset="utf-8" /></head>
2146
+ <body onload="document.forms[0].submit()">
2147
+ <form method="POST" action="${url}">
2148
+ <input type="hidden" name="JWT" value="${value}" />
2149
+ </form>
2150
+ </body>
2151
+ </html>`;
2152
+ // Convert to data URL
2153
+ const dataUrl = `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;
2154
+ // Angular requires sanitizing iframe URLs
2155
+ this.threeDSIframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(dataUrl);
2156
+ // Open modal/iframe
2157
+ this.threeDSOpen = true;
2158
+ this.cdr.markForCheck();
2159
+ // --- Listener for postMessage ---
2160
+ const listener = (event) => {
2161
+ // Success case
2162
+ if (event?.data === 'challenge_success' || event?.data?.status === 'success') {
2163
+ this.threeDSOpen = false;
2164
+ this.threeDSIframeSrc = null;
2165
+ this.cdr.detectChanges();
2166
+ this.handleMidenProceed();
2167
+ }
2168
+ // Failure case
2169
+ if (event?.data === 'challenge_failed' || event?.data?.status === 'failed') {
2170
+ this.threeDSOpen = false;
2171
+ this.threeDSIframeSrc = null;
2172
+ this.cdr.detectChanges();
2173
+ this.message = '3D Secure verification failed.';
2174
+ this.isMakingPayment = false;
2175
+ }
2176
+ };
2177
+ // Remove old listener if exists
2178
+ if (this.messageListener) {
2179
+ window.removeEventListener('message', this.messageListener);
2180
+ }
2181
+ // Save + attach listener
2182
+ this.messageListener = listener;
2183
+ window.addEventListener('message', listener);
2184
+ }
2185
+ // --- Cleanup (call this when leaving page) ---
2186
+ cleanupThreeDSListener() {
2187
+ if (this.messageListener) {
2188
+ window.removeEventListener('message', this.messageListener);
2189
+ this.messageListener = undefined;
2190
+ }
2191
+ }
2192
+ // --- Confirm Payment After 3DS ---
2193
+ async handleMidenProceed() {
2194
+ this.isMakingPayment = true;
2195
+ this.checkout
2196
+ .midenConfirmPayment(this.environment, this.transactionReference, this.secretKey, 'miden')
2197
+ .subscribe({
2198
+ next: async (response) => {
2199
+ if (response?.isSuccessful) {
2200
+ this.message = 'Payment authorization successful.';
2201
+ this.notyf.success({
2202
+ message: 'Payment authorization successful.',
2203
+ ...toastConfig,
2204
+ });
2205
+ this.isMakingPayment = false;
2206
+ // Emit success callback
2207
+ this.paymentAuthorized.emit({
2208
+ paymentId: this.transactionReference,
2209
+ paymentDate: new Date().toISOString(),
2210
+ paymentStatus: 'authorized',
2211
+ message: 'Payment authorization successful.',
2212
+ });
2213
+ }
2214
+ else {
2215
+ this.notyf.success({
2216
+ message: 'Payment authorization successful.',
2217
+ ...toastConfig,
2218
+ });
2219
+ this.isMakingPayment = false;
2220
+ }
2221
+ },
2222
+ error: (err) => {
2223
+ const status = err?.status ?? err?.response?.status;
2224
+ if ([500, 501, 502, 503].includes(status)) {
2225
+ this.isMakingPayment = false;
2226
+ this.message = 'Temporary server error. Please try again.';
2227
+ return;
2228
+ }
2229
+ const responseMessage = err?.error?.responseMessage ||
2230
+ err?.responseMessage ||
2231
+ err?.message ||
2232
+ 'Payment confirmation failed.';
2233
+ this.isMakingPayment = false;
2234
+ this.message = responseMessage;
2235
+ this.notyf.error({
2236
+ message: responseMessage,
2237
+ ...toastConfig,
2238
+ });
2239
+ this.onError.emit({ errorMessage: responseMessage });
2240
+ },
2241
+ });
2242
+ }
2243
+ // --- Handle Card Authorization Response ---
2244
+ handleMidenCard(data) {
2245
+ const threeDsRequired = data?.threeDsInteractionRequired;
2246
+ if (threeDsRequired) {
2247
+ const url = data?.threeDsHtml?.stepUpUrl;
2248
+ const cred = data?.threeDsHtml?.accessToken;
2249
+ this.midenThreeDSChallenge(url, cred);
2250
+ }
2251
+ else {
2252
+ this.handleMidenProceed();
2253
+ }
2254
+ }
2101
2255
  async proceedHandler() {
2102
2256
  if (this.formIndex === 0) {
2103
2257
  if (this.billingForm && this.billingForm.valid) {
@@ -2151,8 +2305,7 @@ class PayByCardComponent {
2151
2305
  narration: this.paymentObject?.narration || 'Test transaction',
2152
2306
  encryptedCardDetails: encryptedCardDetails.requestParam, // Use the encrypted card details
2153
2307
  billingDetails: billingDetails,
2154
- redirectUrl: this.paymentObject?.redirectUrl ||
2155
- 'https://sandbox-merchant.buzapay.com/account/three-ds-status',
2308
+ redirectUrl: this.paymentObject?.redirectUrl || `${this.baseAppUrl}/account/three-ds-status`,
2156
2309
  paymentReference: this.transactionReference,
2157
2310
  isCheckout: true,
2158
2311
  };
@@ -2166,7 +2319,7 @@ class PayByCardComponent {
2166
2319
  narration: this.paymentObject?.narration || 'Test transaction',
2167
2320
  encryptedCardDetails: encryptedCardDetails.requestParam, // Use the encrypted card details
2168
2321
  billingDetails: billingDetails,
2169
- redirectUrl: this.paymentObject?.redirectUrl || '',
2322
+ redirectUrl: this.paymentObject?.redirectUrl || `${this.baseAppUrl}/pay/verification`,
2170
2323
  paymentReference: this.transactionReference,
2171
2324
  isCheckout: true,
2172
2325
  postBackUrl: '',
@@ -2193,6 +2346,11 @@ class PayByCardComponent {
2193
2346
  processedResponse = this.encryptService.decryptPayload(this.environment, response.responseParam);
2194
2347
  }
2195
2348
  if (processedResponse?.isSuccessful) {
2349
+ // Miden flow
2350
+ if (this.caller === 'miden') {
2351
+ this.handleMidenCard(processedResponse);
2352
+ return;
2353
+ }
2196
2354
  // Check for 3DS authentication requirement
2197
2355
  if (processedResponse.threeDsInteractionRequired === true) {
2198
2356
  // Store 3DS data for the authentication page
@@ -2211,7 +2369,7 @@ class PayByCardComponent {
2211
2369
  // Encrypt 3DS data to pass as url param
2212
2370
  const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
2213
2371
  // Open 3DS authentication page in a new tab
2214
- const threeDsUrl = `https://sandbox-merchant.buzapay.com/account/three-ds-confirm?threeDsData=${encodeURIComponent(stringifiedThreeDsData)}&paymentReference=${processedResponse.transactionReference}`;
2372
+ const threeDsUrl = `${this.baseAppUrl}/account/three-ds-confirm?threeDsData=${encodeURIComponent(stringifiedThreeDsData)}&paymentReference=${processedResponse.transactionReference}`;
2215
2373
  window.open(threeDsUrl, '_self', 'noopener,noreferrer');
2216
2374
  this.message =
2217
2375
  '3D Secure authentication opened in new tab. Please complete the verification';
@@ -2237,7 +2395,7 @@ class PayByCardComponent {
2237
2395
  // Encrypt 3DS data to pass as url param
2238
2396
  const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
2239
2397
  // Open 3DS authentication page in a new tab
2240
- const threeDsUrl = `https://sandbox-merchant.buzapay.com/account/three-ds-confirm?threeDsData=${encodeURIComponent(stringifiedThreeDsData)}&paymentReference=${processedResponse.transactionReference}`;
2398
+ const threeDsUrl = `${this.baseAppUrl}/account/three-ds-confirm?threeDsData=${encodeURIComponent(stringifiedThreeDsData)}&paymentReference=${processedResponse.transactionReference}`;
2241
2399
  window.open(threeDsUrl, '_self', 'noopener,noreferrer');
2242
2400
  this.message =
2243
2401
  '3D Secure authentication opened in new tab. Please complete the verification';
@@ -2289,6 +2447,8 @@ class PayByCardComponent {
2289
2447
  }
2290
2448
  }
2291
2449
  async ngOnInit() {
2450
+ this.notyf = new Notyf();
2451
+ this.baseAppUrl = getBaseAppUrl(this.environment, this.caller);
2292
2452
  await this.generatePaymentLinkHandler();
2293
2453
  await this.getAllCountries();
2294
2454
  this.phoneCodeOptions = COUNTRIES.map((country) => {
@@ -2301,8 +2461,8 @@ class PayByCardComponent {
2301
2461
  };
2302
2462
  }).sort((a, b) => a.label.localeCompare(b.label));
2303
2463
  }
2304
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PayByCardComponent, deps: [{ token: ResourceService }, { token: i0.ChangeDetectorRef }, { token: CheckoutService }, { token: EncryptService }], target: i0.ɵɵFactoryTarget.Component });
2305
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: PayByCardComponent, isStandalone: true, selector: "pay-by-card", inputs: { secretKey: "secretKey", environment: "environment", caller: "caller", paymentObject: "paymentObject" }, outputs: { paymentAuthorized: "paymentAuthorized", onError: "onError" }, ngImport: i0, template: "<div class=\"flex flex-col gap-6\">\n <!-- Billing Details -->\n @if (formIndex === 0) {\n <form [formGroup]=\"billingForm\">\n <div class=\"grid grid-cols-2 gap-6 overflow-y-auto\">\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"address1\"\n label=\"Address Line 1\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'address1', 'Address Line 1') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2\">\n <base-input formControlName=\"address2\" label=\"Address Line 2\"></base-input>\n </div>\n <base-select\n formControlName=\"country\"\n label=\"Select Country\"\n [required]=\"true\"\n [options]=\"countries\"\n [loading]=\"loadingCountries\"\n [validationError]=\"getError('billing', 'country', 'Country') || ''\"\n (onSelectChange)=\"getCountryStates($event)\"\n ></base-select>\n <base-select\n formControlName=\"state\"\n label=\"Select State\"\n [required]=\"true\"\n [options]=\"countryStates\"\n [loading]=\"loadingStates\"\n [validationError]=\"getError('billing', 'state', 'State') || ''\"\n ></base-select>\n <base-input\n formControlName=\"city\"\n label=\"City\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'city', 'City') || ''\"\n ></base-input>\n <base-input\n formControlName=\"postalCode\"\n label=\"Postal Code\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'postalCode', 'Postal Code') || ''\"\n ></base-input>\n\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"emailAddress\"\n label=\"Email\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'emailAddress', 'Email Address') || ''\"\n ></base-input>\n </div>\n\n <div class=\"col-span-2\">\n <base-phone-number-input\n [phoneCodeOptions]=\"phoneCodeOptions\"\n [defaultCountryCode]=\"defaultCountryCode\"\n label=\"Phone number\"\n [preventPaste]=\"true\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'phoneNumber', 'Phone Number') || ''\"\n (codeChange)=\"onCodeChange($event)\"\n (valueChange)=\"onPhoneChange($event)\"\n ></base-phone-number-input>\n </div>\n </div>\n </form>\n }\n\n <!-- Card Details -->\n @if (formIndex === 1) {\n <form [formGroup]=\"payForm\">\n <div class=\"grid grid-cols-2 gap-6 overflow-y-auto\" style=\"max-height: 320px\">\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"customerName\"\n label=\"Card Name\"\n [required]=\"true\"\n [validationError]=\"getError('pay', 'customerName', 'Customer Name') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"cardNo\"\n label=\"Card Number\"\n [required]=\"true\"\n mask=\"0000 0000 0000 0000\"\n placeholder=\"0000 0000 0000 0000\"\n [preventPaste]=\"false\"\n [validationError]=\"getError('pay', 'cardNo', 'Card Number') || ''\"\n (onInputChange)=\"cardNumberInputHandler($event)\"\n ></base-input>\n </div>\n <base-input\n formControlName=\"expireDate\"\n label=\"Expiry Date\"\n [required]=\"true\"\n mask=\"00/00\"\n placeholder=\"00/00\"\n [validationError]=\"getError('pay', 'expireDate', 'Expiry Date') || ''\"\n ></base-input>\n <base-input\n formControlName=\"cvv\"\n label=\"CVV\"\n [required]=\"true\"\n mask=\"000\"\n placeholder=\"000\"\n [validationError]=\"getError('pay', 'cvv', 'CVV') || ''\"\n ></base-input>\n\n @if (cardType === 'Verve') {\n <base-input\n formControlName=\"cardPin\"\n label=\"Card Pin\"\n type=\"password\"\n placeholder=\"0000\"\n mask=\"0000\"\n [required]=\"true\"\n [validationError]=\"getError('pay', 'cardPin', 'Card Pin') || ''\"\n ></base-input>\n <div class=\"text-sm text-blue-600 mb-4\">\n <i class=\"fas fa-info-circle mr-1\"></i>\n Pin is required for Verve cards\n </div>\n }\n </div>\n </form>\n }\n\n <div class=\"flex items-center justify-between gap-4 mt-6 w-full\">\n @if (formIndex > 0) {\n <div class=\"w-1/2\">\n <base-button\n label=\"Previous\"\n type=\"secondary\"\n [caller]=\"caller\"\n (onClick)=\"goBack()\"\n ></base-button>\n </div>\n }\n <div [class]=\"formIndex === 0 ? 'w-full' : 'w-1/2'\">\n <base-button\n [label]=\"formIndex === 0 ? 'Proceed' : 'Pay ' + formatAmountHandler\"\n type=\"primary\"\n [caller]=\"caller\"\n [loading]=\"isMakingPayment\"\n (onClick)=\"proceedHandler()\"\n ></base-button>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: ButtonComponent, selector: "base-button", inputs: ["label", "type", "caller", "size", "paddingClassX", "disabled", "loading", "customClass"], outputs: ["onClick"] }, { kind: "component", type: InputComponent, selector: "base-input", inputs: ["label", "type", "placeholder", "validationError", "hint", "mask", "rules", "isAmountInput", "required", "disabled", "loading", "showCopyIcon", "preventPaste", "showBottomText"], outputs: ["onInputChange", "onInputBlur"] }, { kind: "component", type: SelectComponent, selector: "base-select", inputs: ["options", "placeholder", "hasSearch", "disabled", "loading", "validationError", "label", "hint", "required", "itemImageType", "showBottomText"], outputs: ["onSelectChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: PhoneNumberInputComponent, selector: "base-phone-number-input", inputs: ["phoneCodeOptions", "value", "label", "required", "disabled", "loading", "validationError", "hint", "defaultCountryCode", "preventPaste", "showCopyIcon", "containerClassName", "inputClassName", "placeholder"], outputs: ["valueChange", "codeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2464
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PayByCardComponent, deps: [{ token: ResourceService }, { token: i0.ChangeDetectorRef }, { token: CheckoutService }, { token: EncryptService }, { token: i4.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
2465
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: PayByCardComponent, isStandalone: true, selector: "pay-by-card", inputs: { secretKey: "secretKey", environment: "environment", caller: "caller", paymentObject: "paymentObject" }, outputs: { paymentAuthorized: "paymentAuthorized", onError: "onError" }, ngImport: i0, template: "@if (threeDSOpen) {\n <div class=\"fixed inset-0 z-50 flex items-center justify-center bg-white p-4\">\n <iframe\n title=\"Miden 3DS\"\n [src]=\"threeDSIframeSrc\"\n class=\"w-full h-full\"\n sandbox=\"allow-forms allow-scripts allow-same-origin allow-top-navigation\"\n ></iframe>\n </div>\n} @else {\n <div class=\"flex flex-col gap-6\">\n <!-- Billing Details -->\n @if (formIndex === 0) {\n <form [formGroup]=\"billingForm\">\n <div class=\"grid grid-cols-2 gap-6 overflow-y-auto\">\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"address1\"\n label=\"Address Line 1\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'address1', 'Address Line 1') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2\">\n <base-input formControlName=\"address2\" label=\"Address Line 2\"></base-input>\n </div>\n <base-select\n formControlName=\"country\"\n label=\"Select Country\"\n [required]=\"true\"\n [options]=\"countries\"\n [loading]=\"loadingCountries\"\n [validationError]=\"getError('billing', 'country', 'Country') || ''\"\n (onSelectChange)=\"getCountryStates($event)\"\n ></base-select>\n <base-select\n formControlName=\"state\"\n label=\"Select State\"\n [required]=\"true\"\n [options]=\"countryStates\"\n [loading]=\"loadingStates\"\n [validationError]=\"getError('billing', 'state', 'State') || ''\"\n ></base-select>\n <base-input\n formControlName=\"city\"\n label=\"City\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'city', 'City') || ''\"\n ></base-input>\n <base-input\n formControlName=\"postalCode\"\n label=\"Postal Code\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'postalCode', 'Postal Code') || ''\"\n ></base-input>\n\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"emailAddress\"\n label=\"Email\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'emailAddress', 'Email Address') || ''\"\n ></base-input>\n </div>\n\n <div class=\"col-span-2\">\n <base-phone-number-input\n [phoneCodeOptions]=\"phoneCodeOptions\"\n [defaultCountryCode]=\"defaultCountryCode\"\n label=\"Phone number\"\n [preventPaste]=\"true\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'phoneNumber', 'Phone Number') || ''\"\n (codeChange)=\"onCodeChange($event)\"\n (valueChange)=\"onPhoneChange($event)\"\n ></base-phone-number-input>\n </div>\n </div>\n </form>\n }\n\n <!-- Card Details -->\n @if (formIndex === 1) {\n <form [formGroup]=\"payForm\">\n <div class=\"grid grid-cols-2 gap-6 overflow-y-auto\" style=\"max-height: 320px\">\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"customerName\"\n label=\"Card Name\"\n [required]=\"true\"\n [validationError]=\"getError('pay', 'customerName', 'Customer Name') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"cardNo\"\n label=\"Card Number\"\n [required]=\"true\"\n mask=\"0000 0000 0000 0000\"\n placeholder=\"0000 0000 0000 0000\"\n [preventPaste]=\"false\"\n [validationError]=\"getError('pay', 'cardNo', 'Card Number') || ''\"\n (onInputChange)=\"cardNumberInputHandler($event)\"\n ></base-input>\n </div>\n <base-input\n formControlName=\"expireDate\"\n label=\"Expiry Date\"\n [required]=\"true\"\n mask=\"00/00\"\n placeholder=\"00/00\"\n [validationError]=\"getError('pay', 'expireDate', 'Expiry Date') || ''\"\n ></base-input>\n <base-input\n formControlName=\"cvv\"\n label=\"CVV\"\n [required]=\"true\"\n mask=\"000\"\n placeholder=\"000\"\n [validationError]=\"getError('pay', 'cvv', 'CVV') || ''\"\n ></base-input>\n\n @if (cardType === 'Verve') {\n <base-input\n formControlName=\"cardPin\"\n label=\"Card Pin\"\n type=\"password\"\n placeholder=\"0000\"\n mask=\"0000\"\n [required]=\"true\"\n [validationError]=\"getError('pay', 'cardPin', 'Card Pin') || ''\"\n ></base-input>\n <div class=\"text-sm text-blue-600 mb-4\">\n <i class=\"fas fa-info-circle mr-1\"></i>\n Pin is required for Verve cards\n </div>\n }\n </div>\n </form>\n }\n\n <div class=\"flex items-center justify-between gap-4 mt-6 w-full\">\n @if (formIndex > 0) {\n <div class=\"w-1/2\">\n <base-button\n label=\"Previous\"\n type=\"secondary\"\n [caller]=\"caller\"\n (onClick)=\"goBack()\"\n ></base-button>\n </div>\n }\n <div [class]=\"formIndex === 0 ? 'w-full' : 'w-1/2'\">\n <base-button\n [label]=\"formIndex === 0 ? 'Proceed' : 'Pay ' + formatAmountHandler\"\n type=\"primary\"\n [caller]=\"caller\"\n [loading]=\"isMakingPayment\"\n (onClick)=\"proceedHandler()\"\n ></base-button>\n </div>\n </div>\n </div>\n}\n", dependencies: [{ kind: "component", type: ButtonComponent, selector: "base-button", inputs: ["label", "type", "caller", "size", "paddingClassX", "disabled", "loading", "customClass"], outputs: ["onClick"] }, { kind: "component", type: InputComponent, selector: "base-input", inputs: ["label", "type", "placeholder", "validationError", "hint", "mask", "rules", "isAmountInput", "required", "disabled", "loading", "showCopyIcon", "preventPaste", "showBottomText"], outputs: ["onInputChange", "onInputBlur"] }, { kind: "component", type: SelectComponent, selector: "base-select", inputs: ["options", "placeholder", "hasSearch", "disabled", "loading", "validationError", "label", "hint", "required", "itemImageType", "showBottomText"], outputs: ["onSelectChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: PhoneNumberInputComponent, selector: "base-phone-number-input", inputs: ["phoneCodeOptions", "value", "label", "required", "disabled", "loading", "validationError", "hint", "defaultCountryCode", "preventPaste", "showCopyIcon", "containerClassName", "inputClassName", "placeholder"], outputs: ["valueChange", "codeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2306
2466
  }
2307
2467
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PayByCardComponent, decorators: [{
2308
2468
  type: Component,
@@ -2312,8 +2472,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2312
2472
  SelectComponent,
2313
2473
  ReactiveFormsModule,
2314
2474
  PhoneNumberInputComponent,
2315
- ], template: "<div class=\"flex flex-col gap-6\">\n <!-- Billing Details -->\n @if (formIndex === 0) {\n <form [formGroup]=\"billingForm\">\n <div class=\"grid grid-cols-2 gap-6 overflow-y-auto\">\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"address1\"\n label=\"Address Line 1\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'address1', 'Address Line 1') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2\">\n <base-input formControlName=\"address2\" label=\"Address Line 2\"></base-input>\n </div>\n <base-select\n formControlName=\"country\"\n label=\"Select Country\"\n [required]=\"true\"\n [options]=\"countries\"\n [loading]=\"loadingCountries\"\n [validationError]=\"getError('billing', 'country', 'Country') || ''\"\n (onSelectChange)=\"getCountryStates($event)\"\n ></base-select>\n <base-select\n formControlName=\"state\"\n label=\"Select State\"\n [required]=\"true\"\n [options]=\"countryStates\"\n [loading]=\"loadingStates\"\n [validationError]=\"getError('billing', 'state', 'State') || ''\"\n ></base-select>\n <base-input\n formControlName=\"city\"\n label=\"City\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'city', 'City') || ''\"\n ></base-input>\n <base-input\n formControlName=\"postalCode\"\n label=\"Postal Code\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'postalCode', 'Postal Code') || ''\"\n ></base-input>\n\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"emailAddress\"\n label=\"Email\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'emailAddress', 'Email Address') || ''\"\n ></base-input>\n </div>\n\n <div class=\"col-span-2\">\n <base-phone-number-input\n [phoneCodeOptions]=\"phoneCodeOptions\"\n [defaultCountryCode]=\"defaultCountryCode\"\n label=\"Phone number\"\n [preventPaste]=\"true\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'phoneNumber', 'Phone Number') || ''\"\n (codeChange)=\"onCodeChange($event)\"\n (valueChange)=\"onPhoneChange($event)\"\n ></base-phone-number-input>\n </div>\n </div>\n </form>\n }\n\n <!-- Card Details -->\n @if (formIndex === 1) {\n <form [formGroup]=\"payForm\">\n <div class=\"grid grid-cols-2 gap-6 overflow-y-auto\" style=\"max-height: 320px\">\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"customerName\"\n label=\"Card Name\"\n [required]=\"true\"\n [validationError]=\"getError('pay', 'customerName', 'Customer Name') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"cardNo\"\n label=\"Card Number\"\n [required]=\"true\"\n mask=\"0000 0000 0000 0000\"\n placeholder=\"0000 0000 0000 0000\"\n [preventPaste]=\"false\"\n [validationError]=\"getError('pay', 'cardNo', 'Card Number') || ''\"\n (onInputChange)=\"cardNumberInputHandler($event)\"\n ></base-input>\n </div>\n <base-input\n formControlName=\"expireDate\"\n label=\"Expiry Date\"\n [required]=\"true\"\n mask=\"00/00\"\n placeholder=\"00/00\"\n [validationError]=\"getError('pay', 'expireDate', 'Expiry Date') || ''\"\n ></base-input>\n <base-input\n formControlName=\"cvv\"\n label=\"CVV\"\n [required]=\"true\"\n mask=\"000\"\n placeholder=\"000\"\n [validationError]=\"getError('pay', 'cvv', 'CVV') || ''\"\n ></base-input>\n\n @if (cardType === 'Verve') {\n <base-input\n formControlName=\"cardPin\"\n label=\"Card Pin\"\n type=\"password\"\n placeholder=\"0000\"\n mask=\"0000\"\n [required]=\"true\"\n [validationError]=\"getError('pay', 'cardPin', 'Card Pin') || ''\"\n ></base-input>\n <div class=\"text-sm text-blue-600 mb-4\">\n <i class=\"fas fa-info-circle mr-1\"></i>\n Pin is required for Verve cards\n </div>\n }\n </div>\n </form>\n }\n\n <div class=\"flex items-center justify-between gap-4 mt-6 w-full\">\n @if (formIndex > 0) {\n <div class=\"w-1/2\">\n <base-button\n label=\"Previous\"\n type=\"secondary\"\n [caller]=\"caller\"\n (onClick)=\"goBack()\"\n ></base-button>\n </div>\n }\n <div [class]=\"formIndex === 0 ? 'w-full' : 'w-1/2'\">\n <base-button\n [label]=\"formIndex === 0 ? 'Proceed' : 'Pay ' + formatAmountHandler\"\n type=\"primary\"\n [caller]=\"caller\"\n [loading]=\"isMakingPayment\"\n (onClick)=\"proceedHandler()\"\n ></base-button>\n </div>\n </div>\n</div>\n" }]
2316
- }], ctorParameters: () => [{ type: ResourceService }, { type: i0.ChangeDetectorRef }, { type: CheckoutService }, { type: EncryptService }], propDecorators: { secretKey: [{
2475
+ ], template: "@if (threeDSOpen) {\n <div class=\"fixed inset-0 z-50 flex items-center justify-center bg-white p-4\">\n <iframe\n title=\"Miden 3DS\"\n [src]=\"threeDSIframeSrc\"\n class=\"w-full h-full\"\n sandbox=\"allow-forms allow-scripts allow-same-origin allow-top-navigation\"\n ></iframe>\n </div>\n} @else {\n <div class=\"flex flex-col gap-6\">\n <!-- Billing Details -->\n @if (formIndex === 0) {\n <form [formGroup]=\"billingForm\">\n <div class=\"grid grid-cols-2 gap-6 overflow-y-auto\">\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"address1\"\n label=\"Address Line 1\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'address1', 'Address Line 1') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2\">\n <base-input formControlName=\"address2\" label=\"Address Line 2\"></base-input>\n </div>\n <base-select\n formControlName=\"country\"\n label=\"Select Country\"\n [required]=\"true\"\n [options]=\"countries\"\n [loading]=\"loadingCountries\"\n [validationError]=\"getError('billing', 'country', 'Country') || ''\"\n (onSelectChange)=\"getCountryStates($event)\"\n ></base-select>\n <base-select\n formControlName=\"state\"\n label=\"Select State\"\n [required]=\"true\"\n [options]=\"countryStates\"\n [loading]=\"loadingStates\"\n [validationError]=\"getError('billing', 'state', 'State') || ''\"\n ></base-select>\n <base-input\n formControlName=\"city\"\n label=\"City\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'city', 'City') || ''\"\n ></base-input>\n <base-input\n formControlName=\"postalCode\"\n label=\"Postal Code\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'postalCode', 'Postal Code') || ''\"\n ></base-input>\n\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"emailAddress\"\n label=\"Email\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'emailAddress', 'Email Address') || ''\"\n ></base-input>\n </div>\n\n <div class=\"col-span-2\">\n <base-phone-number-input\n [phoneCodeOptions]=\"phoneCodeOptions\"\n [defaultCountryCode]=\"defaultCountryCode\"\n label=\"Phone number\"\n [preventPaste]=\"true\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'phoneNumber', 'Phone Number') || ''\"\n (codeChange)=\"onCodeChange($event)\"\n (valueChange)=\"onPhoneChange($event)\"\n ></base-phone-number-input>\n </div>\n </div>\n </form>\n }\n\n <!-- Card Details -->\n @if (formIndex === 1) {\n <form [formGroup]=\"payForm\">\n <div class=\"grid grid-cols-2 gap-6 overflow-y-auto\" style=\"max-height: 320px\">\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"customerName\"\n label=\"Card Name\"\n [required]=\"true\"\n [validationError]=\"getError('pay', 'customerName', 'Customer Name') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2\">\n <base-input\n formControlName=\"cardNo\"\n label=\"Card Number\"\n [required]=\"true\"\n mask=\"0000 0000 0000 0000\"\n placeholder=\"0000 0000 0000 0000\"\n [preventPaste]=\"false\"\n [validationError]=\"getError('pay', 'cardNo', 'Card Number') || ''\"\n (onInputChange)=\"cardNumberInputHandler($event)\"\n ></base-input>\n </div>\n <base-input\n formControlName=\"expireDate\"\n label=\"Expiry Date\"\n [required]=\"true\"\n mask=\"00/00\"\n placeholder=\"00/00\"\n [validationError]=\"getError('pay', 'expireDate', 'Expiry Date') || ''\"\n ></base-input>\n <base-input\n formControlName=\"cvv\"\n label=\"CVV\"\n [required]=\"true\"\n mask=\"000\"\n placeholder=\"000\"\n [validationError]=\"getError('pay', 'cvv', 'CVV') || ''\"\n ></base-input>\n\n @if (cardType === 'Verve') {\n <base-input\n formControlName=\"cardPin\"\n label=\"Card Pin\"\n type=\"password\"\n placeholder=\"0000\"\n mask=\"0000\"\n [required]=\"true\"\n [validationError]=\"getError('pay', 'cardPin', 'Card Pin') || ''\"\n ></base-input>\n <div class=\"text-sm text-blue-600 mb-4\">\n <i class=\"fas fa-info-circle mr-1\"></i>\n Pin is required for Verve cards\n </div>\n }\n </div>\n </form>\n }\n\n <div class=\"flex items-center justify-between gap-4 mt-6 w-full\">\n @if (formIndex > 0) {\n <div class=\"w-1/2\">\n <base-button\n label=\"Previous\"\n type=\"secondary\"\n [caller]=\"caller\"\n (onClick)=\"goBack()\"\n ></base-button>\n </div>\n }\n <div [class]=\"formIndex === 0 ? 'w-full' : 'w-1/2'\">\n <base-button\n [label]=\"formIndex === 0 ? 'Proceed' : 'Pay ' + formatAmountHandler\"\n type=\"primary\"\n [caller]=\"caller\"\n [loading]=\"isMakingPayment\"\n (onClick)=\"proceedHandler()\"\n ></base-button>\n </div>\n </div>\n </div>\n}\n" }]
2476
+ }], ctorParameters: () => [{ type: ResourceService }, { type: i0.ChangeDetectorRef }, { type: CheckoutService }, { type: EncryptService }, { type: i4.DomSanitizer }], propDecorators: { secretKey: [{
2317
2477
  type: Input
2318
2478
  }], environment: [{
2319
2479
  type: Input
@@ -2815,5 +2975,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2815
2975
  * Generated bundle index. Do not edit.
2816
2976
  */
2817
2977
 
2818
- export { BZP_CONFIG, BZP_CORRELATION_ID, BackComponent, ButtonComponent, COUNTRIES, CardComponent, CardSchemes, CheckoutService, CircleCountdownComponent, CopyComponent, CurrencyAmountComponent, EncryptService, HintComponent, IconArrowSwapComponent, IconBuzapayIconComponent, IconCardsComponent, IconCheckCircleComponent, IconChevronDownComponent, IconChevronLeftComponent, IconChevronUpComponent, IconCloseComponent, IconCoinComponent, IconCopySuccessComponent, IconCourthouseComponent, IconLoaderComponent, IconLockComponent, IconMidenLogoComponent, IconQrCodeComponent, IconUsdcComponent, IconUsdtComponent, ImageComponent, InputComponent, InputErrorComponent, LabelInfoComponent, MidenPGAngular, PayByCardComponent, PayByStableCoinComponent, PayByTransferComponent, RadioGroupComponent, ResourceService, SelectComponent, SuccessComponent, apiBaseUrl, buildDeviceInformation, cardType, checkObjectTruthy, currencySign, detect, formatAmount, getBaseUrl, getQueryParams, getValidationErrorMessage, provideMidenPG, restrictToNumericKeys, toastConfig, truncateString, urlValidator };
2978
+ export { BZP_CONFIG, BZP_CORRELATION_ID, BackComponent, ButtonComponent, COUNTRIES, CardComponent, CardSchemes, CheckoutService, CircleCountdownComponent, CopyComponent, CurrencyAmountComponent, EncryptService, HintComponent, IconArrowSwapComponent, IconBuzapayIconComponent, IconCardsComponent, IconCheckCircleComponent, IconChevronDownComponent, IconChevronLeftComponent, IconChevronUpComponent, IconCloseComponent, IconCoinComponent, IconCopySuccessComponent, IconCourthouseComponent, IconLoaderComponent, IconLockComponent, IconMidenLogoComponent, IconQrCodeComponent, IconUsdcComponent, IconUsdtComponent, ImageComponent, InputComponent, InputErrorComponent, LabelInfoComponent, MidenPGAngular, PayByCardComponent, PayByStableCoinComponent, PayByTransferComponent, RadioGroupComponent, ResourceService, SelectComponent, SuccessComponent, apiBaseUrl, buildDeviceInformation, cardType, checkObjectTruthy, currencySign, detect, formatAmount, getBaseAppUrl, getBaseUrl, getQueryParams, getValidationErrorMessage, provideMidenPG, restrictToNumericKeys, toastConfig, truncateString, urlValidator };
2819
2979
  //# sourceMappingURL=miden-npm-angular.mjs.map