@miden-npm/angular 2.1.4 → 2.1.6
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.
|
@@ -1662,6 +1662,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1662
1662
|
|
|
1663
1663
|
class PhoneNumberInputComponent {
|
|
1664
1664
|
phoneCodeOptions = [];
|
|
1665
|
+
/**
|
|
1666
|
+
* This is the phone number value from the parent.
|
|
1667
|
+
* We'll keep the internal input in sync with it.
|
|
1668
|
+
*/
|
|
1665
1669
|
value;
|
|
1666
1670
|
valueChange = new EventEmitter();
|
|
1667
1671
|
codeChange = new EventEmitter();
|
|
@@ -1684,6 +1688,8 @@ class PhoneNumberInputComponent {
|
|
|
1684
1688
|
selectedCode = '+1';
|
|
1685
1689
|
ngOnInit() {
|
|
1686
1690
|
this.initSelectedCode();
|
|
1691
|
+
// ✅ hydrate internal input from parent value on first mount
|
|
1692
|
+
this.syncPhoneNumberFromInput(this.value);
|
|
1687
1693
|
}
|
|
1688
1694
|
ngOnChanges(changes) {
|
|
1689
1695
|
if (changes['defaultCountryCode'] && !changes['defaultCountryCode'].firstChange) {
|
|
@@ -1692,6 +1698,11 @@ class PhoneNumberInputComponent {
|
|
|
1692
1698
|
if (changes['phoneCodeOptions'] && !changes['phoneCodeOptions'].firstChange) {
|
|
1693
1699
|
this.ensureValidSelection();
|
|
1694
1700
|
}
|
|
1701
|
+
// ✅ whenever parent value changes (or component remounts with an existing value),
|
|
1702
|
+
// update the internal form control so the UI shows it.
|
|
1703
|
+
if (changes['value']) {
|
|
1704
|
+
this.syncPhoneNumberFromInput(changes['value'].currentValue);
|
|
1705
|
+
}
|
|
1695
1706
|
}
|
|
1696
1707
|
get safeDefaultCode() {
|
|
1697
1708
|
return this.phoneCodeOptions?.[0]?.value ?? '+1';
|
|
@@ -1710,21 +1721,36 @@ class PhoneNumberInputComponent {
|
|
|
1710
1721
|
initSelectedCode() {
|
|
1711
1722
|
const nextValue = this.defaultCountryCode ?? this.safeDefaultCode;
|
|
1712
1723
|
this.selectedCode = nextValue;
|
|
1724
|
+
// keep form select in sync
|
|
1725
|
+
this.phoneNumberInputForm.patchValue({ phoneNumberExt: nextValue }, { emitEvent: false });
|
|
1726
|
+
// emit formatted code to parent
|
|
1713
1727
|
this.codeChange.emit(this.getFormattedCode(nextValue));
|
|
1714
|
-
this.phoneNumberInputForm.patchValue({ phoneNumberExt: nextValue });
|
|
1715
1728
|
}
|
|
1716
1729
|
ensureValidSelection() {
|
|
1717
1730
|
const exists = this.phoneCodeOptions.some((o) => o.value === this.selectedCode);
|
|
1718
1731
|
if (!exists) {
|
|
1719
1732
|
this.selectedCode = this.defaultCountryCode ?? this.safeDefaultCode;
|
|
1733
|
+
this.phoneNumberInputForm.patchValue({ phoneNumberExt: this.selectedCode }, { emitEvent: false });
|
|
1720
1734
|
this.codeChange.emit(this.getFormattedCode(this.selectedCode));
|
|
1721
1735
|
}
|
|
1722
1736
|
}
|
|
1737
|
+
syncPhoneNumberFromInput(val) {
|
|
1738
|
+
const current = this.phoneNumberInputForm.get('phoneNumber')?.value ?? '';
|
|
1739
|
+
const next = val ?? '';
|
|
1740
|
+
if (current !== next) {
|
|
1741
|
+
this.phoneNumberInputForm.patchValue({ phoneNumber: next }, { emitEvent: false });
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1723
1744
|
onCountryChange(e) {
|
|
1724
1745
|
this.selectedCode = e;
|
|
1725
|
-
|
|
1746
|
+
// keep internal form control in sync
|
|
1747
|
+
this.phoneNumberInputForm.patchValue({ phoneNumberExt: this.selectedCode }, { emitEvent: false });
|
|
1748
|
+
this.codeChange.emit(this.getFormattedCode(this.selectedCode));
|
|
1726
1749
|
}
|
|
1727
1750
|
onPhoneChange(e) {
|
|
1751
|
+
// keep internal form control in sync
|
|
1752
|
+
this.phoneNumberInputForm.patchValue({ phoneNumber: e }, { emitEvent: false });
|
|
1753
|
+
// emit to parent
|
|
1728
1754
|
this.valueChange.emit(e);
|
|
1729
1755
|
}
|
|
1730
1756
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PhoneNumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -1879,6 +1905,40 @@ class CheckoutService {
|
|
|
1879
1905
|
headers,
|
|
1880
1906
|
});
|
|
1881
1907
|
}
|
|
1908
|
+
validateCardPaymentOtp(environment, { merchantId, ...rest }, caller = 'buzapay') {
|
|
1909
|
+
const baseUrl = getBaseUrl(environment, caller);
|
|
1910
|
+
if (!merchantId || merchantId.trim() === '') {
|
|
1911
|
+
throw new Error('merchantId is required for authorizeCardPayment');
|
|
1912
|
+
}
|
|
1913
|
+
const headers = new HttpHeaders({
|
|
1914
|
+
merchantId: merchantId.trim(),
|
|
1915
|
+
uniqueKey: merchantId.trim(),
|
|
1916
|
+
});
|
|
1917
|
+
const apiKey = {
|
|
1918
|
+
buzapay: 'api/v1/checkout/card-payment/validate-otp',
|
|
1919
|
+
miden: '',
|
|
1920
|
+
};
|
|
1921
|
+
return this.http.post(`${baseUrl}/${apiKey[caller]}`, rest, {
|
|
1922
|
+
headers,
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
resendCardPaymentOtp(environment, { merchantId, ...rest }, caller = 'buzapay') {
|
|
1926
|
+
const baseUrl = getBaseUrl(environment, caller);
|
|
1927
|
+
if (!merchantId || merchantId.trim() === '') {
|
|
1928
|
+
throw new Error('merchantId is required for authorizeCardPayment');
|
|
1929
|
+
}
|
|
1930
|
+
const headers = new HttpHeaders({
|
|
1931
|
+
merchantId: merchantId.trim(),
|
|
1932
|
+
uniqueKey: merchantId.trim(),
|
|
1933
|
+
});
|
|
1934
|
+
const apiKey = {
|
|
1935
|
+
buzapay: 'api/v1/checkout/card-payment/resend-otp',
|
|
1936
|
+
miden: '',
|
|
1937
|
+
};
|
|
1938
|
+
return this.http.post(`${baseUrl}/${apiKey[caller]}`, rest, {
|
|
1939
|
+
headers,
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1882
1942
|
getPaymentReferenceDetails(environment, paymentReference, caller = 'buzapay') {
|
|
1883
1943
|
const baseUrl = getBaseUrl(environment, caller);
|
|
1884
1944
|
const apiKey = {
|
|
@@ -2001,6 +2061,8 @@ class PayByCardComponent {
|
|
|
2001
2061
|
loadingCountries = false;
|
|
2002
2062
|
loadingStates = false;
|
|
2003
2063
|
isMakingPayment = false;
|
|
2064
|
+
isValidatingOtp = false;
|
|
2065
|
+
isSendingOtp = false;
|
|
2004
2066
|
cardType = '';
|
|
2005
2067
|
message = '';
|
|
2006
2068
|
transactionReference = '';
|
|
@@ -2033,6 +2095,9 @@ class PayByCardComponent {
|
|
|
2033
2095
|
cvv: new FormControl('', [Validators.required]),
|
|
2034
2096
|
cardPin: new FormControl(''), // Only required for Verve cards
|
|
2035
2097
|
});
|
|
2098
|
+
otpForm = new FormGroup({
|
|
2099
|
+
otp: new FormControl('', [Validators.required]),
|
|
2100
|
+
});
|
|
2036
2101
|
onCodeChange(e) {
|
|
2037
2102
|
this.billingForm.patchValue({ phoneNumberExt: e });
|
|
2038
2103
|
}
|
|
@@ -2040,7 +2105,11 @@ class PayByCardComponent {
|
|
|
2040
2105
|
this.billingForm.patchValue({ phoneNumber: e });
|
|
2041
2106
|
}
|
|
2042
2107
|
getError(formKey, controlName, label) {
|
|
2043
|
-
const control = formKey === 'billing'
|
|
2108
|
+
const control = formKey === 'billing'
|
|
2109
|
+
? this.billingForm.get(controlName)
|
|
2110
|
+
: formKey === 'pay'
|
|
2111
|
+
? this.payForm.get(controlName)
|
|
2112
|
+
: this.otpForm.get(controlName);
|
|
2044
2113
|
return getValidationErrorMessage(control, label);
|
|
2045
2114
|
}
|
|
2046
2115
|
get formatAmountHandler() {
|
|
@@ -2263,189 +2332,250 @@ class PayByCardComponent {
|
|
|
2263
2332
|
this.billingForm.markAllAsTouched();
|
|
2264
2333
|
}
|
|
2265
2334
|
}
|
|
2266
|
-
else {
|
|
2335
|
+
else if (this.formIndex === 1) {
|
|
2267
2336
|
if (this.payForm && this.payForm.valid) {
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2337
|
+
this.isMakingPayment = true;
|
|
2338
|
+
// Create card details object for encryption
|
|
2339
|
+
const cardDetails = {
|
|
2340
|
+
pan: this.payForm.value.cardNo ? this.payForm.value.cardNo.replaceAll(' ', '') : '',
|
|
2341
|
+
expiryDate: this.payForm.value.expireDate ?? '',
|
|
2342
|
+
cvv: this.payForm.value.cvv ?? '',
|
|
2343
|
+
cardScheme: this.cardType,
|
|
2344
|
+
nameOnCard: this.payForm.value.customerName ?? '',
|
|
2345
|
+
...(this.cardType === 'Verve' && { pin: this.payForm.value.cardPin ?? '' }),
|
|
2346
|
+
};
|
|
2347
|
+
// Get billing details from the form control
|
|
2348
|
+
const billingDetails = {
|
|
2349
|
+
address2: this.billingForm.value.address2 ?? '',
|
|
2350
|
+
address1: this.billingForm.value.address1 ?? '',
|
|
2351
|
+
postalCode: this.billingForm.value.postalCode ?? '',
|
|
2352
|
+
state: this.billingForm.value.state ?? '',
|
|
2353
|
+
city: this.billingForm.value.city ?? '',
|
|
2354
|
+
country: this.billingForm.value.country ?? '',
|
|
2355
|
+
emailAddress: this.billingForm.value.emailAddress ?? '',
|
|
2356
|
+
phoneNumber: this.billingForm.value.phoneNumber
|
|
2357
|
+
? `${this.billingForm.value.phoneNumberExt}${this.billingForm.value.phoneNumber}`
|
|
2358
|
+
: '',
|
|
2359
|
+
};
|
|
2360
|
+
// Encrypt card details using payload encryption method
|
|
2361
|
+
const encryptedCardDetails = this.encryptService.encryptPayload(this.secretKey, cardDetails);
|
|
2362
|
+
// Test: Decrypt to verify encryption works
|
|
2363
|
+
// const decryptedTest = this.encryptService.decryptPayload(
|
|
2364
|
+
// this.environment,
|
|
2365
|
+
// encryptedCardDetails.requestParam,
|
|
2366
|
+
// );
|
|
2367
|
+
let payload = null;
|
|
2368
|
+
let payloadMiden = null;
|
|
2369
|
+
if (this.caller === 'buzapay') {
|
|
2370
|
+
payload = {
|
|
2371
|
+
customerId: this.paymentObject?.email || this.payForm.value.customerName || '',
|
|
2372
|
+
amount: this.paymentObject?.amount.toString(),
|
|
2373
|
+
currency: this.paymentObject?.currency || 'USD',
|
|
2374
|
+
narration: this.paymentObject?.narration || 'Test transaction',
|
|
2375
|
+
encryptedCardDetails: encryptedCardDetails.requestParam, // Use the encrypted card details
|
|
2376
|
+
billingDetails: billingDetails,
|
|
2377
|
+
redirectUrl: this.paymentObject?.redirectUrl || `${this.baseAppUrl}/account/three-ds-status`,
|
|
2378
|
+
paymentReference: this.transactionReference,
|
|
2379
|
+
isCheckout: true,
|
|
2278
2380
|
};
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2381
|
+
}
|
|
2382
|
+
else {
|
|
2383
|
+
const deviceInformation = buildDeviceInformation();
|
|
2384
|
+
payloadMiden = {
|
|
2385
|
+
customerId: this.paymentObject?.email || this.payForm.value.customerName || '',
|
|
2386
|
+
amount: this.paymentObject?.amount.toString(),
|
|
2387
|
+
currency: this.paymentObject?.currency || 'USD',
|
|
2388
|
+
narration: this.paymentObject?.narration || 'Test transaction',
|
|
2389
|
+
encryptedCardDetails: encryptedCardDetails.requestParam, // Use the encrypted card details
|
|
2390
|
+
billingDetails: billingDetails,
|
|
2391
|
+
redirectUrl: this.paymentObject?.redirectUrl || `${this.baseAppUrl}/pay/verification`,
|
|
2392
|
+
paymentReference: this.transactionReference,
|
|
2393
|
+
isCheckout: true,
|
|
2394
|
+
postBackUrl: '',
|
|
2395
|
+
saveCard: false,
|
|
2396
|
+
deviceInformation,
|
|
2291
2397
|
};
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
// );
|
|
2299
|
-
let payload = null;
|
|
2300
|
-
let payloadMiden = null;
|
|
2301
|
-
if (this.caller === 'buzapay') {
|
|
2302
|
-
payload = {
|
|
2303
|
-
customerId: this.paymentObject?.email || this.payForm.value.customerName || '',
|
|
2304
|
-
amount: this.paymentObject?.amount.toString(),
|
|
2305
|
-
currency: this.paymentObject?.currency || 'USD',
|
|
2306
|
-
narration: this.paymentObject?.narration || 'Test transaction',
|
|
2307
|
-
encryptedCardDetails: encryptedCardDetails.requestParam, // Use the encrypted card details
|
|
2308
|
-
billingDetails: billingDetails,
|
|
2309
|
-
redirectUrl: this.paymentObject?.redirectUrl || `${this.baseAppUrl}/account/three-ds-status`,
|
|
2310
|
-
paymentReference: this.transactionReference,
|
|
2311
|
-
isCheckout: true,
|
|
2312
|
-
};
|
|
2313
|
-
}
|
|
2314
|
-
else {
|
|
2315
|
-
const deviceInformation = buildDeviceInformation();
|
|
2316
|
-
payloadMiden = {
|
|
2317
|
-
customerId: this.paymentObject?.email || this.payForm.value.customerName || '',
|
|
2318
|
-
amount: this.paymentObject?.amount.toString(),
|
|
2319
|
-
currency: this.paymentObject?.currency || 'USD',
|
|
2320
|
-
narration: this.paymentObject?.narration || 'Test transaction',
|
|
2321
|
-
encryptedCardDetails: encryptedCardDetails.requestParam, // Use the encrypted card details
|
|
2322
|
-
billingDetails: billingDetails,
|
|
2323
|
-
redirectUrl: this.paymentObject?.redirectUrl || `${this.baseAppUrl}/pay/verification`,
|
|
2324
|
-
paymentReference: this.transactionReference,
|
|
2325
|
-
isCheckout: true,
|
|
2326
|
-
postBackUrl: '',
|
|
2327
|
-
saveCard: false,
|
|
2328
|
-
deviceInformation,
|
|
2329
|
-
};
|
|
2398
|
+
}
|
|
2399
|
+
this.checkout
|
|
2400
|
+
.authorizeCardPayment(this.environment, this.caller === 'buzapay'
|
|
2401
|
+
? {
|
|
2402
|
+
...payload,
|
|
2403
|
+
merchantId: this.secretKey,
|
|
2330
2404
|
}
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2405
|
+
: {
|
|
2406
|
+
...payloadMiden,
|
|
2407
|
+
merchantId: this.secretKey,
|
|
2408
|
+
}, this.caller)
|
|
2409
|
+
.subscribe({
|
|
2410
|
+
next: async (response) => {
|
|
2411
|
+
let processedResponse = response;
|
|
2412
|
+
// Check if response is encrypted (has responseParam)
|
|
2413
|
+
if (response?.responseParam) {
|
|
2414
|
+
// Decrypt the response
|
|
2415
|
+
processedResponse = this.encryptService.decryptPayload(this.environment, response.responseParam);
|
|
2336
2416
|
}
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
}, this.caller)
|
|
2341
|
-
.subscribe({
|
|
2342
|
-
next: async (response) => {
|
|
2343
|
-
let processedResponse = response;
|
|
2344
|
-
// Check if response is encrypted (has responseParam)
|
|
2345
|
-
if (response?.responseParam) {
|
|
2346
|
-
// Decrypt the response
|
|
2347
|
-
processedResponse = this.encryptService.decryptPayload(this.environment, response.responseParam);
|
|
2348
|
-
}
|
|
2349
|
-
if (processedResponse?.isSuccessful) {
|
|
2350
|
-
// Miden flow
|
|
2351
|
-
if (this.caller === 'miden') {
|
|
2352
|
-
this.handleMidenCard(processedResponse);
|
|
2353
|
-
return;
|
|
2354
|
-
}
|
|
2355
|
-
// Check for 3DS authentication requirement
|
|
2356
|
-
if (processedResponse.threeDsInteractionRequired === true) {
|
|
2357
|
-
// Store 3DS data for the authentication page
|
|
2358
|
-
const threeDsData = {
|
|
2359
|
-
transactionReference: processedResponse.transactionReference,
|
|
2360
|
-
threeDsHtml: processedResponse.threeDsHtml,
|
|
2361
|
-
amount: processedResponse.amount,
|
|
2362
|
-
responseMessage: processedResponse.responseMessage,
|
|
2363
|
-
// Pass all 3DS details
|
|
2364
|
-
paReq: processedResponse.threeDsHtml?.paReq,
|
|
2365
|
-
termUrl: processedResponse.threeDsHtml?.termUrl,
|
|
2366
|
-
action: processedResponse.threeDsHtml?.action,
|
|
2367
|
-
acsUrl: processedResponse.threeDsHtml?.acsUrl,
|
|
2368
|
-
md: processedResponse.threeDsHtml?.md,
|
|
2369
|
-
};
|
|
2370
|
-
// Encrypt 3DS data to pass as url param
|
|
2371
|
-
const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
|
|
2372
|
-
// Open 3DS authentication page in a new tab
|
|
2373
|
-
const threeDsUrl = `${this.baseAppUrl}/account/three-ds-confirm?threeDsData=${encodeURIComponent(stringifiedThreeDsData)}&paymentReference=${processedResponse.transactionReference}`;
|
|
2374
|
-
window.open(threeDsUrl, '_self', 'noopener,noreferrer');
|
|
2375
|
-
this.message =
|
|
2376
|
-
'3D Secure authentication opened in new tab. Please complete the verification';
|
|
2377
|
-
this.isMakingPayment = false;
|
|
2378
|
-
return;
|
|
2379
|
-
}
|
|
2380
|
-
// Fallback check: if response message indicates 3DS is required
|
|
2381
|
-
if (processedResponse.responseMessage === 'Payer Interaction Required' &&
|
|
2382
|
-
processedResponse.threeDsHtml) {
|
|
2383
|
-
// Store 3DS data for the authentication page
|
|
2384
|
-
const threeDsData = {
|
|
2385
|
-
transactionReference: processedResponse.transactionReference,
|
|
2386
|
-
threeDsHtml: processedResponse.threeDsHtml,
|
|
2387
|
-
amount: processedResponse.amount,
|
|
2388
|
-
responseMessage: processedResponse.responseMessage,
|
|
2389
|
-
// Pass all 3DS details
|
|
2390
|
-
paReq: processedResponse.threeDsHtml?.paReq,
|
|
2391
|
-
termUrl: processedResponse.threeDsHtml?.termUrl,
|
|
2392
|
-
action: processedResponse.threeDsHtml?.action,
|
|
2393
|
-
acsUrl: processedResponse.threeDsHtml?.acsUrl,
|
|
2394
|
-
md: processedResponse.threeDsHtml?.md,
|
|
2395
|
-
};
|
|
2396
|
-
// Encrypt 3DS data to pass as url param
|
|
2397
|
-
const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
|
|
2398
|
-
// Open 3DS authentication page in a new tab
|
|
2399
|
-
const threeDsUrl = `${this.baseAppUrl}/account/three-ds-confirm?threeDsData=${encodeURIComponent(stringifiedThreeDsData)}&paymentReference=${processedResponse.transactionReference}`;
|
|
2400
|
-
window.open(threeDsUrl, '_self', 'noopener,noreferrer');
|
|
2401
|
-
this.message =
|
|
2402
|
-
'3D Secure authentication opened in new tab. Please complete the verification';
|
|
2403
|
-
this.isMakingPayment = false;
|
|
2404
|
-
return;
|
|
2405
|
-
}
|
|
2406
|
-
// Emit the transaction reference to parent component
|
|
2407
|
-
if (processedResponse.transactionReference &&
|
|
2408
|
-
processedResponse.transactionReference.trim() !== '') {
|
|
2409
|
-
this.paymentAuthorized.emit({
|
|
2410
|
-
paymentId: processedResponse.transactionReference,
|
|
2411
|
-
paymentDate: response?.data?.updatedAt ?? new Date().toISOString(),
|
|
2412
|
-
paymentStatus: 'authorized',
|
|
2413
|
-
message: this.message,
|
|
2414
|
-
});
|
|
2415
|
-
}
|
|
2416
|
-
this.message = 'Card payment authorized successfully';
|
|
2417
|
+
if (processedResponse?.isSuccessful) {
|
|
2418
|
+
// Verve OTPValidationRequired flow
|
|
2419
|
+
if (processedResponse?.otpValidationRequired) {
|
|
2417
2420
|
this.isMakingPayment = false;
|
|
2421
|
+
this.setFormIndex(2);
|
|
2422
|
+
this.cdr.markForCheck();
|
|
2423
|
+
return;
|
|
2418
2424
|
}
|
|
2419
|
-
|
|
2425
|
+
// Miden flow
|
|
2426
|
+
if (this.caller === 'miden') {
|
|
2427
|
+
this.handleMidenCard(processedResponse);
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2430
|
+
// Check for 3DS authentication requirement
|
|
2431
|
+
if (processedResponse.threeDsInteractionRequired === true) {
|
|
2432
|
+
// Store 3DS data for the authentication page
|
|
2433
|
+
const threeDsData = {
|
|
2434
|
+
transactionReference: processedResponse.transactionReference,
|
|
2435
|
+
threeDsHtml: processedResponse.threeDsHtml,
|
|
2436
|
+
amount: processedResponse.amount,
|
|
2437
|
+
responseMessage: processedResponse.responseMessage,
|
|
2438
|
+
// Pass all 3DS details
|
|
2439
|
+
paReq: processedResponse.threeDsHtml?.paReq,
|
|
2440
|
+
termUrl: processedResponse.threeDsHtml?.termUrl,
|
|
2441
|
+
action: processedResponse.threeDsHtml?.action,
|
|
2442
|
+
acsUrl: processedResponse.threeDsHtml?.acsUrl,
|
|
2443
|
+
md: processedResponse.threeDsHtml?.md,
|
|
2444
|
+
};
|
|
2445
|
+
// Encrypt 3DS data to pass as url param
|
|
2446
|
+
const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
|
|
2447
|
+
// Open 3DS authentication page in a new tab
|
|
2448
|
+
const threeDsUrl = `${this.baseAppUrl}/account/three-ds-confirm?threeDsData=${encodeURIComponent(stringifiedThreeDsData)}&paymentReference=${processedResponse.transactionReference}`;
|
|
2449
|
+
window.open(threeDsUrl, '_self', 'noopener,noreferrer');
|
|
2450
|
+
this.message =
|
|
2451
|
+
'3D Secure authentication opened in new tab. Please complete the verification';
|
|
2420
2452
|
this.isMakingPayment = false;
|
|
2421
|
-
|
|
2422
|
-
this.onError.emit({ errorMessage: this.message });
|
|
2453
|
+
return;
|
|
2423
2454
|
}
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2455
|
+
// Fallback check: if response message indicates 3DS is required
|
|
2456
|
+
if (processedResponse.responseMessage === 'Payer Interaction Required' &&
|
|
2457
|
+
processedResponse.threeDsHtml) {
|
|
2458
|
+
// Store 3DS data for the authentication page
|
|
2459
|
+
const threeDsData = {
|
|
2460
|
+
transactionReference: processedResponse.transactionReference,
|
|
2461
|
+
threeDsHtml: processedResponse.threeDsHtml,
|
|
2462
|
+
amount: processedResponse.amount,
|
|
2463
|
+
responseMessage: processedResponse.responseMessage,
|
|
2464
|
+
// Pass all 3DS details
|
|
2465
|
+
paReq: processedResponse.threeDsHtml?.paReq,
|
|
2466
|
+
termUrl: processedResponse.threeDsHtml?.termUrl,
|
|
2467
|
+
action: processedResponse.threeDsHtml?.action,
|
|
2468
|
+
acsUrl: processedResponse.threeDsHtml?.acsUrl,
|
|
2469
|
+
md: processedResponse.threeDsHtml?.md,
|
|
2470
|
+
};
|
|
2471
|
+
// Encrypt 3DS data to pass as url param
|
|
2472
|
+
const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
|
|
2473
|
+
// Open 3DS authentication page in a new tab
|
|
2474
|
+
const threeDsUrl = `${this.baseAppUrl}/account/three-ds-confirm?threeDsData=${encodeURIComponent(stringifiedThreeDsData)}&paymentReference=${processedResponse.transactionReference}`;
|
|
2475
|
+
window.open(threeDsUrl, '_self', 'noopener,noreferrer');
|
|
2476
|
+
this.message =
|
|
2477
|
+
'3D Secure authentication opened in new tab. Please complete the verification';
|
|
2478
|
+
this.isMakingPayment = false;
|
|
2479
|
+
return;
|
|
2431
2480
|
}
|
|
2432
|
-
|
|
2433
|
-
|
|
2481
|
+
// Emit the transaction reference to parent component
|
|
2482
|
+
if (processedResponse.transactionReference &&
|
|
2483
|
+
processedResponse.transactionReference.trim() !== '') {
|
|
2484
|
+
this.paymentAuthorized.emit({
|
|
2485
|
+
paymentId: processedResponse.transactionReference,
|
|
2486
|
+
paymentDate: response?.data?.updatedAt ?? new Date().toISOString(),
|
|
2487
|
+
paymentStatus: 'authorized',
|
|
2488
|
+
message: this.message,
|
|
2489
|
+
});
|
|
2434
2490
|
}
|
|
2491
|
+
this.message = 'Card payment authorized successfully';
|
|
2492
|
+
this.isMakingPayment = false;
|
|
2493
|
+
}
|
|
2494
|
+
// Failure path for miden
|
|
2495
|
+
if (processedResponse && !processedResponse.isSuccessful && this.caller === 'miden') {
|
|
2496
|
+
this.message = processedResponse.responseMessage;
|
|
2435
2497
|
this.onError.emit({ errorMessage: this.message });
|
|
2436
|
-
}
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2498
|
+
}
|
|
2499
|
+
// Failure path for buzapay
|
|
2500
|
+
if (processedResponse && processedResponse.message && this.caller === 'buzapay') {
|
|
2501
|
+
this.message = response.message;
|
|
2502
|
+
this.onError.emit({ errorMessage: this.message });
|
|
2503
|
+
}
|
|
2504
|
+
this.isMakingPayment = false;
|
|
2505
|
+
},
|
|
2506
|
+
error: (err) => {
|
|
2507
|
+
this.isMakingPayment = false;
|
|
2508
|
+
if (err.error?.responseParam) {
|
|
2509
|
+
// Decrypt error response
|
|
2510
|
+
const decryptedErrorResponse = this.encryptService.decryptPayload(this.environment, err.error.responseParam);
|
|
2511
|
+
this.message = decryptedErrorResponse.responseMessage || 'Payment failed';
|
|
2512
|
+
}
|
|
2513
|
+
else {
|
|
2514
|
+
this.message = err.error.message || err.error.responseMessage || 'Payment failed';
|
|
2515
|
+
}
|
|
2516
|
+
this.onError.emit({ errorMessage: this.message });
|
|
2517
|
+
},
|
|
2518
|
+
});
|
|
2444
2519
|
}
|
|
2445
2520
|
else {
|
|
2446
2521
|
this.payForm.markAllAsTouched();
|
|
2447
2522
|
}
|
|
2448
2523
|
}
|
|
2524
|
+
else {
|
|
2525
|
+
if (this.otpForm && this.otpForm.valid) {
|
|
2526
|
+
this.isValidatingOtp = true;
|
|
2527
|
+
this.checkout
|
|
2528
|
+
.validateCardPaymentOtp(this.environment, {
|
|
2529
|
+
transactionReference: this.transactionReference,
|
|
2530
|
+
otp: this.otpForm.value.otp,
|
|
2531
|
+
merchantId: this.secretKey,
|
|
2532
|
+
}, this.caller)
|
|
2533
|
+
.subscribe({
|
|
2534
|
+
next: async (response) => {
|
|
2535
|
+
this.isValidatingOtp = false;
|
|
2536
|
+
this.paymentAuthorized.emit({
|
|
2537
|
+
paymentId: response.transactionReference,
|
|
2538
|
+
paymentDate: response?.data?.updatedAt ?? new Date().toISOString(),
|
|
2539
|
+
paymentStatus: 'authorized',
|
|
2540
|
+
message: response?.responseMessage,
|
|
2541
|
+
});
|
|
2542
|
+
},
|
|
2543
|
+
error: (err) => {
|
|
2544
|
+
this.isValidatingOtp = false;
|
|
2545
|
+
this.message =
|
|
2546
|
+
err.error.message || err.error.responseMessage || 'Validate OTP Failed';
|
|
2547
|
+
this.onError.emit({ errorMessage: this.message });
|
|
2548
|
+
},
|
|
2549
|
+
});
|
|
2550
|
+
}
|
|
2551
|
+
else {
|
|
2552
|
+
this.otpForm.markAllAsTouched();
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
async resendOtp() {
|
|
2557
|
+
this.isSendingOtp = true;
|
|
2558
|
+
this.checkout
|
|
2559
|
+
.resendCardPaymentOtp(this.environment, {
|
|
2560
|
+
transactionReference: this.transactionReference,
|
|
2561
|
+
merchantId: this.secretKey,
|
|
2562
|
+
}, this.caller)
|
|
2563
|
+
.subscribe({
|
|
2564
|
+
next: async (response) => {
|
|
2565
|
+
if (response?.isSuccessful) {
|
|
2566
|
+
this.isSendingOtp = false;
|
|
2567
|
+
this.notyf.success({
|
|
2568
|
+
message: 'OTP Sent Successfully.',
|
|
2569
|
+
...toastConfig,
|
|
2570
|
+
});
|
|
2571
|
+
}
|
|
2572
|
+
},
|
|
2573
|
+
error: (err) => {
|
|
2574
|
+
this.isSendingOtp = false;
|
|
2575
|
+
this.message = err.error.message || err.error.responseMessage || 'OTP Sending Failed';
|
|
2576
|
+
this.onError.emit({ errorMessage: this.message });
|
|
2577
|
+
},
|
|
2578
|
+
});
|
|
2449
2579
|
}
|
|
2450
2580
|
async ngOnInit() {
|
|
2451
2581
|
this.notyf = new Notyf();
|
|
@@ -2463,7 +2593,7 @@ class PayByCardComponent {
|
|
|
2463
2593
|
}).sort((a, b) => a.label.localeCompare(b.label));
|
|
2464
2594
|
}
|
|
2465
2595
|
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 });
|
|
2466
|
-
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 <div class=\"col-span-2 sm:col-span-1\">\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 </div>\n <div class=\"col-span-2 sm:col-span-1\">\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 </div>\n <div class=\"col-span-2 sm:col-span-1\">\n <base-input\n formControlName=\"city\"\n label=\"City\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'city', 'City') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2 sm:col-span-1\">\n <base-input\n formControlName=\"postalCode\"\n label=\"Postal Code\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'postalCode', 'Postal Code') || ''\"\n ></base-input>\n </div>\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 });
|
|
2596
|
+
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 <div class=\"col-span-2 sm:col-span-1\">\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 </div>\n <div class=\"col-span-2 sm:col-span-1\">\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 </div>\n <div class=\"col-span-2 sm:col-span-1\">\n <base-input\n formControlName=\"city\"\n label=\"City\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'city', 'City') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2 sm:col-span-1\">\n <base-input\n formControlName=\"postalCode\"\n label=\"Postal Code\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'postalCode', 'Postal Code') || ''\"\n ></base-input>\n </div>\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 [value]=\"billingForm.get('phoneNumber')?.value ?? ''\"\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 000\"\n placeholder=\"0000 0000 0000 0000\"\n [preventPaste]=\"true\"\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 <!-- Verve OTP Verification -->\n @if (formIndex === 2) {\n <form [formGroup]=\"otpForm\">\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=\"otp\"\n label=\"OTP\"\n [required]=\"true\"\n [validationError]=\"getError('otp', 'otp', 'OTP') || ''\"\n ></base-input>\n </div>\n </div>\n <p class=\"text-primary text-sm mt-2\">\n Didn't get OTP?\n <span\n [class]=\"isSendingOtp ? '' : 'underline cursor-pointer'\"\n (click)=\"isSendingOtp ? null : resendOtp()\"\n >{{ isSendingOtp ? 'Sending...' : 'Resend OTP' }}</span\n >\n </p>\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 @if (formIndex < 2) {\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 }\n @if (formIndex === 2) {\n <div class=\"w-1/2\">\n <base-button\n label=\"Validate OTP\"\n type=\"primary\"\n [caller]=\"caller\"\n [loading]=\"isValidatingOtp\"\n (onClick)=\"proceedHandler()\"\n ></base-button>\n </div>\n }\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 });
|
|
2467
2597
|
}
|
|
2468
2598
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PayByCardComponent, decorators: [{
|
|
2469
2599
|
type: Component,
|
|
@@ -2473,7 +2603,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2473
2603
|
SelectComponent,
|
|
2474
2604
|
ReactiveFormsModule,
|
|
2475
2605
|
PhoneNumberInputComponent,
|
|
2476
|
-
], 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 <div class=\"col-span-2 sm:col-span-1\">\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 </div>\n <div class=\"col-span-2 sm:col-span-1\">\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 </div>\n <div class=\"col-span-2 sm:col-span-1\">\n <base-input\n formControlName=\"city\"\n label=\"City\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'city', 'City') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2 sm:col-span-1\">\n <base-input\n formControlName=\"postalCode\"\n label=\"Postal Code\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'postalCode', 'Postal Code') || ''\"\n ></base-input>\n </div>\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]=\"
|
|
2606
|
+
], 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 <div class=\"col-span-2 sm:col-span-1\">\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 </div>\n <div class=\"col-span-2 sm:col-span-1\">\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 </div>\n <div class=\"col-span-2 sm:col-span-1\">\n <base-input\n formControlName=\"city\"\n label=\"City\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'city', 'City') || ''\"\n ></base-input>\n </div>\n <div class=\"col-span-2 sm:col-span-1\">\n <base-input\n formControlName=\"postalCode\"\n label=\"Postal Code\"\n [required]=\"true\"\n [validationError]=\"getError('billing', 'postalCode', 'Postal Code') || ''\"\n ></base-input>\n </div>\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 [value]=\"billingForm.get('phoneNumber')?.value ?? ''\"\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 000\"\n placeholder=\"0000 0000 0000 0000\"\n [preventPaste]=\"true\"\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 <!-- Verve OTP Verification -->\n @if (formIndex === 2) {\n <form [formGroup]=\"otpForm\">\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=\"otp\"\n label=\"OTP\"\n [required]=\"true\"\n [validationError]=\"getError('otp', 'otp', 'OTP') || ''\"\n ></base-input>\n </div>\n </div>\n <p class=\"text-primary text-sm mt-2\">\n Didn't get OTP?\n <span\n [class]=\"isSendingOtp ? '' : 'underline cursor-pointer'\"\n (click)=\"isSendingOtp ? null : resendOtp()\"\n >{{ isSendingOtp ? 'Sending...' : 'Resend OTP' }}</span\n >\n </p>\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 @if (formIndex < 2) {\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 }\n @if (formIndex === 2) {\n <div class=\"w-1/2\">\n <base-button\n label=\"Validate OTP\"\n type=\"primary\"\n [caller]=\"caller\"\n [loading]=\"isValidatingOtp\"\n (onClick)=\"proceedHandler()\"\n ></base-button>\n </div>\n }\n </div>\n </div>\n}\n" }]
|
|
2477
2607
|
}], ctorParameters: () => [{ type: ResourceService }, { type: i0.ChangeDetectorRef }, { type: CheckoutService }, { type: EncryptService }, { type: i4.DomSanitizer }], propDecorators: { secretKey: [{
|
|
2478
2608
|
type: Input
|
|
2479
2609
|
}], environment: [{
|
|
@@ -2776,6 +2906,10 @@ class PayByTransferComponent {
|
|
|
2776
2906
|
this.countDownTime = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
|
2777
2907
|
this.cdr.markForCheck(); // 👈 notify OnPush to re-render
|
|
2778
2908
|
}
|
|
2909
|
+
resetPaymentAccountDetails() {
|
|
2910
|
+
this.paymentAccountDetails = null;
|
|
2911
|
+
this.cdr.markForCheck();
|
|
2912
|
+
}
|
|
2779
2913
|
transferForm = new FormGroup({
|
|
2780
2914
|
customerName: new FormControl('', [Validators.required]),
|
|
2781
2915
|
});
|
|
@@ -2842,7 +2976,7 @@ class PayByTransferComponent {
|
|
|
2842
2976
|
await this.checkout.generatePaymentAccount(this.environment, payload, this.caller).subscribe({
|
|
2843
2977
|
next: async (response) => {
|
|
2844
2978
|
if (response?.isSuccessful) {
|
|
2845
|
-
this.paymentAccountDetails = response;
|
|
2979
|
+
this.paymentAccountDetails = this.caller === 'buzapay' ? response.data : response;
|
|
2846
2980
|
this.startTimer();
|
|
2847
2981
|
this.message = 'Virtual account generated successfully for payment.';
|
|
2848
2982
|
this.isMakingPayment = false;
|
|
@@ -2866,13 +3000,14 @@ class PayByTransferComponent {
|
|
|
2866
3000
|
.subscribe({
|
|
2867
3001
|
next: async (response) => {
|
|
2868
3002
|
if (response?.isSuccessful) {
|
|
2869
|
-
this.paymentReferenceDetails =
|
|
3003
|
+
this.paymentReferenceDetails =
|
|
3004
|
+
this.caller === 'buzapay' ? response.data : response;
|
|
2870
3005
|
// Check if payment has been made (paymentStatus is "Payment Received")
|
|
2871
|
-
if (
|
|
3006
|
+
if (this.paymentReferenceDetails?.paymentStatus === 'Payment Received') {
|
|
2872
3007
|
this.paymentMade = true;
|
|
2873
3008
|
}
|
|
2874
|
-
if (
|
|
2875
|
-
|
|
3009
|
+
if (this.paymentReferenceDetails?.finalTransactionStatus === null ||
|
|
3010
|
+
this.paymentReferenceDetails?.paymentStatus === null) {
|
|
2876
3011
|
if (this.isConfirmCall) {
|
|
2877
3012
|
this.message = 'Transaction not confirmed !!';
|
|
2878
3013
|
}
|
|
@@ -2881,7 +3016,7 @@ class PayByTransferComponent {
|
|
|
2881
3016
|
this.paymentReferenceStatus = 'pending';
|
|
2882
3017
|
this.paymentAuthorized.emit({
|
|
2883
3018
|
paymentId: this.transactionReference,
|
|
2884
|
-
paymentDate:
|
|
3019
|
+
paymentDate: this.paymentReferenceDetails?.updatedAt ?? new Date().toISOString(),
|
|
2885
3020
|
paymentStatus: this.paymentReferenceStatus,
|
|
2886
3021
|
message: this.message,
|
|
2887
3022
|
});
|
|
@@ -2890,18 +3025,18 @@ class PayByTransferComponent {
|
|
|
2890
3025
|
this.paymentReferenceStatus = 'confirmed';
|
|
2891
3026
|
this.paymentAuthorized.emit({
|
|
2892
3027
|
paymentId: this.transactionReference,
|
|
2893
|
-
paymentDate:
|
|
3028
|
+
paymentDate: this.paymentReferenceDetails?.updatedAt ?? new Date().toISOString(),
|
|
2894
3029
|
paymentStatus: this.paymentReferenceStatus,
|
|
2895
3030
|
message: this.message,
|
|
2896
3031
|
});
|
|
2897
3032
|
}
|
|
2898
3033
|
}
|
|
2899
|
-
else if (
|
|
2900
|
-
|
|
2901
|
-
|
|
3034
|
+
else if (this.paymentReferenceDetails?.finalTransactionStatus === 'Success' ||
|
|
3035
|
+
this.paymentReferenceDetails?.paymentStatus === 'Received' ||
|
|
3036
|
+
this.paymentReferenceDetails?.paymentStatus === 'Payment Received') {
|
|
2902
3037
|
this.paymentAuthorized.emit({
|
|
2903
3038
|
paymentId: this.transactionReference,
|
|
2904
|
-
paymentDate:
|
|
3039
|
+
paymentDate: this.paymentReferenceDetails?.updatedAt ?? new Date().toISOString(),
|
|
2905
3040
|
paymentStatus: this.paymentReferenceStatus,
|
|
2906
3041
|
message: this.message,
|
|
2907
3042
|
});
|
|
@@ -2915,7 +3050,7 @@ class PayByTransferComponent {
|
|
|
2915
3050
|
this.message = response.responseMessage;
|
|
2916
3051
|
this.paymentAuthorized.emit({
|
|
2917
3052
|
paymentId: this.transactionReference,
|
|
2918
|
-
paymentDate:
|
|
3053
|
+
paymentDate: new Date().toISOString(),
|
|
2919
3054
|
paymentStatus: this.paymentReferenceStatus,
|
|
2920
3055
|
message: this.message,
|
|
2921
3056
|
});
|
|
@@ -2941,7 +3076,7 @@ class PayByTransferComponent {
|
|
|
2941
3076
|
}
|
|
2942
3077
|
}
|
|
2943
3078
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PayByTransferComponent, deps: [{ token: CheckoutService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
2944
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: PayByTransferComponent, isStandalone: true, selector: "pay-by-transfer", inputs: { secretKey: "secretKey", environment: "environment", caller: "caller", paymentObject: "paymentObject" }, outputs: { paymentAuthorized: "paymentAuthorized", onError: "onError" }, ngImport: i0, template: "<div class=\"flex flex-col gap-10\">\n @if (!paymentAccountDetails) {\n <form [formGroup]=\"transferForm\">\n <div class=\"flex flex-col gap-10\">\n <base-input\n formControlName=\"customerName\"\n label=\"Customer Name\"\n [required]=\"true\"\n [validationError]=\"getError('customerName', 'Customer Name') || ''\"\n ></base-input>\n\n <base-button\n [label]=\"'Pay ' + formatAmountHandler\"\n type=\"primary\"\n [caller]=\"caller\"\n customClass=\"w-full\"\n [loading]=\"isMakingPayment\"\n (onClick)=\"payHandler()\"\n ></base-button>\n </div>\n </form>\n }\n\n @if (paymentAccountDetails) {\n <div class=\"flex flex-col gap-10\">\n <div\n class=\"p-4 rounded-lg flex flex-col gap-6\"\n [ngClass]=\"{\n 'bg-[#FAFDFF] border border-[#F0FAFF]': caller === 'miden',\n 'bg-[#EFF7FF]': caller === 'buzapay',\n }\"\n >\n <base-label-info label=\"Bank Name\" [value]=\"paymentAccountDetails.bank\"></base-label-info>\n <base-label-info\n label=\"Account Name\"\n [value]=\"paymentAccountDetails.accountName\"\n ></base-label-info>\n <div class=\"flex items-center justify-between\">\n <base-label-info\n label=\"Account Number\"\n [value]=\"paymentAccountDetails.accountNumber\"\n ></base-label-info>\n <base-copy color=\"#9DBFDE\" [copyText]=\"paymentAccountDetails.accountNumber\"></base-copy>\n </div>\n <div class=\"flex items-center justify-between\">\n <base-label-info label=\"Amount\" [value]=\"formatAmountHandler\"></base-label-info>\n <base-copy color=\"#9DBFDE\" [copyText]=\"formatAmountHandler\"></base-copy>\n </div>\n </div>\n\n @if (caller === 'buzapay') {\n <p class=\"w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy\">\n This account is for this transaction only and expires in\n <span class=\"text-orange-500\">{{ countDownTime }}</span>\n </p>\n } @else {\n <div class=\"p-4 rounded-lg bg-[#FAFDFF] flex items-center gap-3\">\n <base-circle-countdown\n [value]=\"remainingSeconds\"\n [total]=\"1800\"\n [middleText]=\"countDownTime\"\n [size]=\"40\"\n [stroke]=\"2\"\n style=\"color: #3b82f6\"\n ></base-circle-countdown>\n <p class=\"text-body-3xs font-medium text-light-copy\">\n This account is for this transaction only and expires in\n <span class=\"text-[#1383E8]\">{{ countDownTime }}...</span>\n </p>\n </div>\n }\n\n <div class=\"flex flex-col gap-4\">\n <base-button\n label=\"I have paid the money\"\n type=\"primary\"\n [caller]=\"caller\"\n customClass=\"w-full\"\n [loading]=\"isFetchingPaymentDetails\"\n (onClick)=\"getReferenceDetails()\"\n ></base-button>\n <p
|
|
3079
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: PayByTransferComponent, isStandalone: true, selector: "pay-by-transfer", inputs: { secretKey: "secretKey", environment: "environment", caller: "caller", paymentObject: "paymentObject" }, outputs: { paymentAuthorized: "paymentAuthorized", onError: "onError" }, ngImport: i0, template: "<div class=\"flex flex-col gap-10\">\n @if (!paymentAccountDetails) {\n <form [formGroup]=\"transferForm\">\n <div class=\"flex flex-col gap-10\">\n <base-input\n formControlName=\"customerName\"\n label=\"Customer Name\"\n [required]=\"true\"\n [validationError]=\"getError('customerName', 'Customer Name') || ''\"\n ></base-input>\n\n <base-button\n [label]=\"'Pay ' + formatAmountHandler\"\n type=\"primary\"\n [caller]=\"caller\"\n customClass=\"w-full\"\n [loading]=\"isMakingPayment\"\n (onClick)=\"payHandler()\"\n ></base-button>\n </div>\n </form>\n }\n\n @if (paymentAccountDetails) {\n <div class=\"flex flex-col gap-10\">\n <div\n class=\"p-4 rounded-lg flex flex-col gap-6\"\n [ngClass]=\"{\n 'bg-[#FAFDFF] border border-[#F0FAFF]': caller === 'miden',\n 'bg-[#EFF7FF]': caller === 'buzapay',\n }\"\n >\n <base-label-info label=\"Bank Name\" [value]=\"paymentAccountDetails.bank\"></base-label-info>\n <base-label-info\n label=\"Account Name\"\n [value]=\"paymentAccountDetails.accountName\"\n ></base-label-info>\n <div class=\"flex items-center justify-between\">\n <base-label-info\n label=\"Account Number\"\n [value]=\"paymentAccountDetails.accountNumber\"\n ></base-label-info>\n <base-copy color=\"#9DBFDE\" [copyText]=\"paymentAccountDetails.accountNumber\"></base-copy>\n </div>\n <div class=\"flex items-center justify-between\">\n <base-label-info label=\"Amount\" [value]=\"formatAmountHandler\"></base-label-info>\n <base-copy color=\"#9DBFDE\" [copyText]=\"formatAmountHandler\"></base-copy>\n </div>\n </div>\n\n @if (caller === 'buzapay') {\n <p class=\"w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy\">\n This account is for this transaction only and expires in\n <span class=\"text-orange-500\">{{ countDownTime }}</span>\n </p>\n } @else {\n <div class=\"p-4 rounded-lg bg-[#FAFDFF] flex items-center gap-3\">\n <base-circle-countdown\n [value]=\"remainingSeconds\"\n [total]=\"1800\"\n [middleText]=\"countDownTime\"\n [size]=\"40\"\n [stroke]=\"2\"\n style=\"color: #3b82f6\"\n ></base-circle-countdown>\n <p class=\"text-body-3xs font-medium text-light-copy\">\n This account is for this transaction only and expires in\n <span class=\"text-[#1383E8]\">{{ countDownTime }}...</span>\n </p>\n </div>\n }\n\n <div class=\"flex flex-col gap-4\">\n <base-button\n label=\"I have paid the money\"\n type=\"primary\"\n [caller]=\"caller\"\n customClass=\"w-full\"\n [loading]=\"isFetchingPaymentDetails\"\n (onClick)=\"getReferenceDetails()\"\n ></base-button>\n <p\n class=\"text-heading-text text-body-2xs font-medium text-center py-2 cursor-pointer\"\n (click)=\"resetPaymentAccountDetails()\"\n >\n Cancel Payment\n </p>\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "component", type: LabelInfoComponent, selector: "base-label-info", inputs: ["type", "label", "labelCustomClass", "valueImageSrc", "valueImageCustomClass", "valueImagePosition", "hasValueCopy", "value", "valueCustomClass", "alignRight"] }, { kind: "component", type: CopyComponent, selector: "base-copy", inputs: ["copyText", "color"] }, { kind: "component", type: ButtonComponent, selector: "base-button", inputs: ["label", "type", "caller", "size", "paddingClassX", "disabled", "loading", "customClass"], outputs: ["onClick"] }, { 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: InputComponent, selector: "base-input", inputs: ["label", "type", "placeholder", "validationError", "hint", "mask", "rules", "isAmountInput", "required", "disabled", "loading", "showCopyIcon", "preventPaste", "showBottomText"], outputs: ["onInputChange", "onInputBlur"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CircleCountdownComponent, selector: "base-circle-countdown", inputs: ["value", "total", "middleText", "size", "stroke"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2945
3080
|
}
|
|
2946
3081
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PayByTransferComponent, decorators: [{
|
|
2947
3082
|
type: Component,
|
|
@@ -2953,7 +3088,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2953
3088
|
InputComponent,
|
|
2954
3089
|
CommonModule,
|
|
2955
3090
|
CircleCountdownComponent,
|
|
2956
|
-
], template: "<div class=\"flex flex-col gap-10\">\n @if (!paymentAccountDetails) {\n <form [formGroup]=\"transferForm\">\n <div class=\"flex flex-col gap-10\">\n <base-input\n formControlName=\"customerName\"\n label=\"Customer Name\"\n [required]=\"true\"\n [validationError]=\"getError('customerName', 'Customer Name') || ''\"\n ></base-input>\n\n <base-button\n [label]=\"'Pay ' + formatAmountHandler\"\n type=\"primary\"\n [caller]=\"caller\"\n customClass=\"w-full\"\n [loading]=\"isMakingPayment\"\n (onClick)=\"payHandler()\"\n ></base-button>\n </div>\n </form>\n }\n\n @if (paymentAccountDetails) {\n <div class=\"flex flex-col gap-10\">\n <div\n class=\"p-4 rounded-lg flex flex-col gap-6\"\n [ngClass]=\"{\n 'bg-[#FAFDFF] border border-[#F0FAFF]': caller === 'miden',\n 'bg-[#EFF7FF]': caller === 'buzapay',\n }\"\n >\n <base-label-info label=\"Bank Name\" [value]=\"paymentAccountDetails.bank\"></base-label-info>\n <base-label-info\n label=\"Account Name\"\n [value]=\"paymentAccountDetails.accountName\"\n ></base-label-info>\n <div class=\"flex items-center justify-between\">\n <base-label-info\n label=\"Account Number\"\n [value]=\"paymentAccountDetails.accountNumber\"\n ></base-label-info>\n <base-copy color=\"#9DBFDE\" [copyText]=\"paymentAccountDetails.accountNumber\"></base-copy>\n </div>\n <div class=\"flex items-center justify-between\">\n <base-label-info label=\"Amount\" [value]=\"formatAmountHandler\"></base-label-info>\n <base-copy color=\"#9DBFDE\" [copyText]=\"formatAmountHandler\"></base-copy>\n </div>\n </div>\n\n @if (caller === 'buzapay') {\n <p class=\"w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy\">\n This account is for this transaction only and expires in\n <span class=\"text-orange-500\">{{ countDownTime }}</span>\n </p>\n } @else {\n <div class=\"p-4 rounded-lg bg-[#FAFDFF] flex items-center gap-3\">\n <base-circle-countdown\n [value]=\"remainingSeconds\"\n [total]=\"1800\"\n [middleText]=\"countDownTime\"\n [size]=\"40\"\n [stroke]=\"2\"\n style=\"color: #3b82f6\"\n ></base-circle-countdown>\n <p class=\"text-body-3xs font-medium text-light-copy\">\n This account is for this transaction only and expires in\n <span class=\"text-[#1383E8]\">{{ countDownTime }}...</span>\n </p>\n </div>\n }\n\n <div class=\"flex flex-col gap-4\">\n <base-button\n label=\"I have paid the money\"\n type=\"primary\"\n [caller]=\"caller\"\n customClass=\"w-full\"\n [loading]=\"isFetchingPaymentDetails\"\n (onClick)=\"getReferenceDetails()\"\n ></base-button>\n <p
|
|
3091
|
+
], template: "<div class=\"flex flex-col gap-10\">\n @if (!paymentAccountDetails) {\n <form [formGroup]=\"transferForm\">\n <div class=\"flex flex-col gap-10\">\n <base-input\n formControlName=\"customerName\"\n label=\"Customer Name\"\n [required]=\"true\"\n [validationError]=\"getError('customerName', 'Customer Name') || ''\"\n ></base-input>\n\n <base-button\n [label]=\"'Pay ' + formatAmountHandler\"\n type=\"primary\"\n [caller]=\"caller\"\n customClass=\"w-full\"\n [loading]=\"isMakingPayment\"\n (onClick)=\"payHandler()\"\n ></base-button>\n </div>\n </form>\n }\n\n @if (paymentAccountDetails) {\n <div class=\"flex flex-col gap-10\">\n <div\n class=\"p-4 rounded-lg flex flex-col gap-6\"\n [ngClass]=\"{\n 'bg-[#FAFDFF] border border-[#F0FAFF]': caller === 'miden',\n 'bg-[#EFF7FF]': caller === 'buzapay',\n }\"\n >\n <base-label-info label=\"Bank Name\" [value]=\"paymentAccountDetails.bank\"></base-label-info>\n <base-label-info\n label=\"Account Name\"\n [value]=\"paymentAccountDetails.accountName\"\n ></base-label-info>\n <div class=\"flex items-center justify-between\">\n <base-label-info\n label=\"Account Number\"\n [value]=\"paymentAccountDetails.accountNumber\"\n ></base-label-info>\n <base-copy color=\"#9DBFDE\" [copyText]=\"paymentAccountDetails.accountNumber\"></base-copy>\n </div>\n <div class=\"flex items-center justify-between\">\n <base-label-info label=\"Amount\" [value]=\"formatAmountHandler\"></base-label-info>\n <base-copy color=\"#9DBFDE\" [copyText]=\"formatAmountHandler\"></base-copy>\n </div>\n </div>\n\n @if (caller === 'buzapay') {\n <p class=\"w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy\">\n This account is for this transaction only and expires in\n <span class=\"text-orange-500\">{{ countDownTime }}</span>\n </p>\n } @else {\n <div class=\"p-4 rounded-lg bg-[#FAFDFF] flex items-center gap-3\">\n <base-circle-countdown\n [value]=\"remainingSeconds\"\n [total]=\"1800\"\n [middleText]=\"countDownTime\"\n [size]=\"40\"\n [stroke]=\"2\"\n style=\"color: #3b82f6\"\n ></base-circle-countdown>\n <p class=\"text-body-3xs font-medium text-light-copy\">\n This account is for this transaction only and expires in\n <span class=\"text-[#1383E8]\">{{ countDownTime }}...</span>\n </p>\n </div>\n }\n\n <div class=\"flex flex-col gap-4\">\n <base-button\n label=\"I have paid the money\"\n type=\"primary\"\n [caller]=\"caller\"\n customClass=\"w-full\"\n [loading]=\"isFetchingPaymentDetails\"\n (onClick)=\"getReferenceDetails()\"\n ></base-button>\n <p\n class=\"text-heading-text text-body-2xs font-medium text-center py-2 cursor-pointer\"\n (click)=\"resetPaymentAccountDetails()\"\n >\n Cancel Payment\n </p>\n </div>\n </div>\n }\n</div>\n" }]
|
|
2957
3092
|
}], ctorParameters: () => [{ type: CheckoutService }, { type: i0.ChangeDetectorRef }], propDecorators: { secretKey: [{
|
|
2958
3093
|
type: Input
|
|
2959
3094
|
}], environment: [{
|