@tagadapay/plugin-sdk 3.1.12 → 3.1.24

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.
Files changed (144) hide show
  1. package/build-cdn.js +397 -11
  2. package/dist/data/iso3166.d.ts +23 -33
  3. package/dist/data/iso3166.js +134 -198
  4. package/dist/data/languages.d.ts +5 -64
  5. package/dist/data/languages.js +23 -143
  6. package/dist/external-tracker.js +623 -3426
  7. package/dist/external-tracker.min.js +2 -25
  8. package/dist/external-tracker.min.js.map +4 -4
  9. package/dist/react/config/payment.d.ts +14 -4
  10. package/dist/react/config/payment.js +47 -9
  11. package/dist/react/hooks/useCheckout.d.ts +3 -0
  12. package/dist/react/hooks/useCheckout.js +4 -1
  13. package/dist/react/hooks/useISOData.js +1 -1
  14. package/dist/react/hooks/usePaymentPolling.d.ts +3 -3
  15. package/dist/react/hooks/usePluginConfig.js +9 -10
  16. package/dist/react/providers/TagadaProvider.js +1 -1
  17. package/dist/tagada-react-sdk-minimal.min.js +36 -0
  18. package/dist/tagada-react-sdk-minimal.min.js.map +7 -0
  19. package/dist/tagada-react-sdk.js +37821 -0
  20. package/dist/tagada-react-sdk.min.js +78 -0
  21. package/dist/tagada-react-sdk.min.js.map +7 -0
  22. package/dist/tagada-sdk.js +16044 -0
  23. package/dist/tagada-sdk.min.js +32 -0
  24. package/dist/tagada-sdk.min.js.map +7 -0
  25. package/dist/v2/cdn-react-minimal.d.ts +23 -0
  26. package/dist/v2/cdn-react-minimal.js +26 -0
  27. package/dist/v2/core/client.d.ts +4 -2
  28. package/dist/v2/core/client.js +5 -4
  29. package/dist/v2/core/config/environment.js +2 -1
  30. package/dist/v2/core/errors.d.ts +75 -0
  31. package/dist/v2/core/errors.js +104 -0
  32. package/dist/v2/core/funnelClient.d.ts +100 -10
  33. package/dist/v2/core/funnelClient.js +121 -27
  34. package/dist/v2/core/isoData.d.ts +4 -4
  35. package/dist/v2/core/isoData.js +7 -7
  36. package/dist/v2/core/pixelMapping.d.ts +49 -0
  37. package/dist/v2/core/pixelMapping.js +363 -0
  38. package/dist/v2/core/resources/apiClient.d.ts +2 -0
  39. package/dist/v2/core/resources/apiClient.js +52 -9
  40. package/dist/v2/core/resources/checkout.d.ts +99 -30
  41. package/dist/v2/core/resources/checkout.js +14 -0
  42. package/dist/v2/core/resources/customer.d.ts +20 -19
  43. package/dist/v2/core/resources/expressPaymentMethods.d.ts +1 -0
  44. package/dist/v2/core/resources/funnel.d.ts +17 -17
  45. package/dist/v2/core/resources/payments.d.ts +89 -13
  46. package/dist/v2/core/resources/payments.js +27 -9
  47. package/dist/v2/core/resources/postPurchases.d.ts +17 -0
  48. package/dist/v2/core/resources/postPurchases.js +20 -0
  49. package/dist/v2/core/types.d.ts +50 -12
  50. package/dist/v2/core/types.js +0 -3
  51. package/dist/v2/core/utils/checkout.d.ts +2 -2
  52. package/dist/v2/core/utils/checkout.js +7 -2
  53. package/dist/v2/core/utils/currency.d.ts +14 -0
  54. package/dist/v2/core/utils/currency.js +40 -0
  55. package/dist/v2/core/utils/deviceInfo.d.ts +0 -10
  56. package/dist/v2/core/utils/deviceInfo.js +152 -76
  57. package/dist/v2/core/utils/index.d.ts +1 -0
  58. package/dist/v2/core/utils/index.js +2 -0
  59. package/dist/v2/core/utils/order.d.ts +13 -9
  60. package/dist/v2/core/utils/pluginConfig.d.ts +8 -0
  61. package/dist/v2/core/utils/pluginConfig.js +36 -12
  62. package/dist/v2/index.d.ts +6 -3
  63. package/dist/v2/index.js +4 -2
  64. package/dist/v2/react/components/FunnelScriptInjector.js +166 -77
  65. package/dist/v2/react/components/StripeExpressButton.d.ts +13 -0
  66. package/dist/v2/react/components/StripeExpressButton.js +171 -0
  67. package/dist/v2/react/components/WhopCheckout.d.ts +24 -0
  68. package/dist/v2/react/components/WhopCheckout.js +237 -0
  69. package/dist/v2/react/hooks/__examples__/FunnelContextExample.js +1 -1
  70. package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.d.ts +14 -0
  71. package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.js +181 -0
  72. package/dist/v2/react/hooks/payment-actions/useErrorAction.d.ts +9 -0
  73. package/dist/v2/react/hooks/payment-actions/useErrorAction.js +21 -0
  74. package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.d.ts +14 -0
  75. package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.js +187 -0
  76. package/dist/v2/react/hooks/payment-actions/useKessPayAction.d.ts +11 -0
  77. package/dist/v2/react/hooks/payment-actions/useKessPayAction.js +91 -0
  78. package/dist/v2/react/hooks/payment-actions/useMasterCardAction.d.ts +24 -0
  79. package/dist/v2/react/hooks/payment-actions/useMasterCardAction.js +221 -0
  80. package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.d.ts +15 -0
  81. package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.js +142 -0
  82. package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.d.ts +3 -0
  83. package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.js +31 -0
  84. package/dist/v2/react/hooks/payment-actions/useRedirectAction.d.ts +10 -0
  85. package/dist/v2/react/hooks/payment-actions/useRedirectAction.js +35 -0
  86. package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.d.ts +14 -0
  87. package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.js +192 -0
  88. package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.d.ts +14 -0
  89. package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.js +81 -0
  90. package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.d.ts +11 -0
  91. package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.js +84 -0
  92. package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.d.ts +14 -0
  93. package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.js +36 -0
  94. package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.d.ts +31 -0
  95. package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.js +212 -0
  96. package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.d.ts +14 -0
  97. package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.js +207 -0
  98. package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.d.ts +12 -0
  99. package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.js +101 -0
  100. package/dist/v2/react/hooks/useApplePayCheckout.js +8 -8
  101. package/dist/v2/react/hooks/useCheckoutQuery.d.ts +16 -0
  102. package/dist/v2/react/hooks/useCheckoutQuery.js +63 -10
  103. package/dist/v2/react/hooks/useFunnel.d.ts +15 -4
  104. package/dist/v2/react/hooks/useFunnel.js +8 -4
  105. package/dist/v2/react/hooks/useGeoLocation.d.ts +2 -1
  106. package/dist/v2/react/hooks/useGeoLocation.js +4 -2
  107. package/dist/v2/react/hooks/useGoogleAutocomplete.d.ts +2 -0
  108. package/dist/v2/react/hooks/useGoogleAutocomplete.js +29 -15
  109. package/dist/v2/react/hooks/useISOData.d.ts +2 -5
  110. package/dist/v2/react/hooks/useISOData.js +26 -27
  111. package/dist/v2/react/hooks/usePaymentPolling.d.ts +3 -3
  112. package/dist/v2/react/hooks/usePaymentQuery.d.ts +18 -5
  113. package/dist/v2/react/hooks/usePaymentQuery.js +63 -1015
  114. package/dist/v2/react/hooks/usePaymentRetrieve.d.ts +3 -2
  115. package/dist/v2/react/hooks/usePaymentRetrieve.js +3 -1
  116. package/dist/v2/react/hooks/usePixelTracking.d.ts +5 -48
  117. package/dist/v2/react/hooks/usePixelTracking.js +283 -504
  118. package/dist/v2/react/hooks/usePostPurchasesQuery.js +34 -2
  119. package/dist/v2/react/hooks/useRemappableParams.d.ts +2 -6
  120. package/dist/v2/react/hooks/useRemappableParams.js +23 -23
  121. package/dist/v2/react/hooks/useSetPaymentMethod.d.ts +16 -0
  122. package/dist/v2/react/hooks/useSetPaymentMethod.js +33 -0
  123. package/dist/v2/react/hooks/useShippingRatesQuery.js +13 -5
  124. package/dist/v2/react/hooks/useStepConfig.d.ts +23 -6
  125. package/dist/v2/react/hooks/useStepConfig.js +14 -7
  126. package/dist/v2/react/hooks/useTranslation.js +23 -8
  127. package/dist/v2/react/hooks/useWhopPaymentPolling.d.ts +30 -0
  128. package/dist/v2/react/hooks/useWhopPaymentPolling.js +61 -0
  129. package/dist/v2/react/index.d.ts +15 -1
  130. package/dist/v2/react/index.js +7 -0
  131. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +3 -1
  132. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +12 -2
  133. package/dist/v2/react/providers/TagadaProvider.js +74 -5
  134. package/dist/v2/standalone/external-tracker.d.ts +52 -46
  135. package/dist/v2/standalone/external-tracker.js +205 -98
  136. package/dist/v2/standalone/index.d.ts +40 -0
  137. package/dist/v2/standalone/index.js +148 -1
  138. package/dist/v2/standalone/payment-service.d.ts +134 -0
  139. package/dist/v2/standalone/payment-service.js +928 -0
  140. package/package.json +6 -4
  141. package/dist/react/utils/__tests__/urlUtils.test.d.ts +0 -1
  142. package/dist/react/utils/__tests__/urlUtils.test.js +0 -189
  143. package/dist/v2/core/__tests__/pathRemapping.test.d.ts +0 -11
  144. package/dist/v2/core/__tests__/pathRemapping.test.js +0 -776
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Hook for handling Finix fraud detection
3
+ */
4
+ import { useCallback } from 'react';
5
+ export function useFinixRadarAction({ paymentsResource, startPolling, setError, setIsLoading, hookOptionsRef, }) {
6
+ const handleFinixRadar = useCallback(async (payment, actionData, options = {}, handlePaymentAction) => {
7
+ const radarConfig = actionData.metadata?.radar;
8
+ if (!radarConfig) {
9
+ console.error('Finix radar config missing from payment action');
10
+ return;
11
+ }
12
+ try {
13
+ // Dynamically load Finix SDK if not already loaded
14
+ if (typeof window !== 'undefined' && typeof window.Finix?.Auth !== 'function') {
15
+ const existingScript = document.querySelector('script[src="https://js.finix.com/v/1/finix.js"]');
16
+ if (!existingScript) {
17
+ const script = document.createElement('script');
18
+ script.src = 'https://js.finix.com/v/1/finix.js';
19
+ script.async = true;
20
+ document.head.appendChild(script);
21
+ await new Promise((resolve, reject) => {
22
+ script.onload = () => {
23
+ console.log('Finix SDK loaded successfully');
24
+ resolve();
25
+ };
26
+ script.onerror = () => reject(new Error('Failed to load Finix SDK'));
27
+ });
28
+ }
29
+ else {
30
+ // Wait for existing script to load
31
+ await new Promise((resolve, reject) => {
32
+ const checkFinix = () => {
33
+ if (typeof window.Finix?.Auth === 'function') {
34
+ resolve();
35
+ }
36
+ else {
37
+ setTimeout(checkFinix, 100);
38
+ }
39
+ };
40
+ checkFinix();
41
+ setTimeout(() => reject(new Error('Timeout waiting for Finix SDK')), 10000);
42
+ });
43
+ }
44
+ }
45
+ // Get session key from Finix using callback to ensure initialization is complete
46
+ const sessionKey = await new Promise((resolve, reject) => {
47
+ const timeoutId = setTimeout(() => {
48
+ reject(new Error('Timeout waiting for Finix Auth initialization'));
49
+ }, 10000);
50
+ // Initialize Finix Auth with callback
51
+ const FinixAuth = window.Finix.Auth(radarConfig.environment, radarConfig.merchantId, () => {
52
+ // Callback fired when Finix Auth is ready
53
+ clearTimeout(timeoutId);
54
+ const key = FinixAuth.getSessionKey();
55
+ console.log('Finix Auth initialized, session key:', key);
56
+ if (key) {
57
+ resolve(key);
58
+ }
59
+ else {
60
+ reject(new Error('No session key returned from Finix after initialization'));
61
+ }
62
+ });
63
+ // Also try getting session key immediately in case it's already ready
64
+ const immediateKey = FinixAuth.getSessionKey();
65
+ if (immediateKey) {
66
+ clearTimeout(timeoutId);
67
+ console.log('Finix session key obtained immediately:', immediateKey);
68
+ resolve(immediateKey);
69
+ }
70
+ });
71
+ console.log('Finix fraud session key obtained:', sessionKey);
72
+ // Save radar session to database
73
+ await paymentsResource.saveRadarSession({
74
+ orderId: radarConfig.orderId,
75
+ finixRadarSessionId: sessionKey,
76
+ finixRadarSessionData: {
77
+ sessionKey,
78
+ merchantId: radarConfig.merchantId,
79
+ environment: radarConfig.environment,
80
+ createdAt: new Date().toISOString(),
81
+ },
82
+ });
83
+ console.log('Finix radar session saved to database');
84
+ // Resume payment by calling completePaymentAfterAction
85
+ const resumedPayment = await paymentsResource.completePaymentAfterAction(payment.id);
86
+ console.log('Payment resumed after Finix radar:', resumedPayment);
87
+ // Handle the resumed payment response
88
+ if (resumedPayment.status === 'declined' || resumedPayment.status === 'failed') {
89
+ // Payment declined or failed - extract error message from response
90
+ const errorMsg = resumedPayment.error?.message
91
+ || resumedPayment.error?.processorMessage
92
+ || 'Payment declined';
93
+ console.error('❌ [usePayment] Payment declined after Finix radar:', errorMsg);
94
+ setError(errorMsg);
95
+ setIsLoading(false);
96
+ options.onFailure?.(errorMsg);
97
+ options.onPaymentFailed?.({
98
+ code: resumedPayment.error?.code || 'PAYMENT_DECLINED',
99
+ message: errorMsg,
100
+ payment: resumedPayment,
101
+ });
102
+ // Hook-level callback (universal handler)
103
+ if (hookOptionsRef.current?.onPaymentFailed) {
104
+ hookOptionsRef.current.onPaymentFailed(errorMsg, {
105
+ isRedirectReturn: false,
106
+ });
107
+ }
108
+ }
109
+ else if (resumedPayment.status === 'succeeded') {
110
+ // Payment succeeded
111
+ setIsLoading(false);
112
+ const response = {
113
+ paymentId: resumedPayment.id,
114
+ payment: resumedPayment,
115
+ order: resumedPayment.order,
116
+ };
117
+ // Hook-level callback (universal handler)
118
+ if (hookOptionsRef.current?.onPaymentCompleted) {
119
+ await hookOptionsRef.current.onPaymentCompleted(resumedPayment, {
120
+ isRedirectReturn: false,
121
+ order: response.order,
122
+ });
123
+ }
124
+ options.onSuccess?.(response);
125
+ options.onPaymentSuccess?.(response);
126
+ }
127
+ else if (resumedPayment.requireAction !== 'none' && resumedPayment.requireActionData) {
128
+ // Payment requires another action (e.g., 3DS)
129
+ await handlePaymentAction(resumedPayment, options);
130
+ }
131
+ else {
132
+ // Start polling for final status
133
+ startPolling(resumedPayment.id, {
134
+ onRequireAction: (updatedPayment) => {
135
+ void handlePaymentAction(updatedPayment, options);
136
+ },
137
+ onSuccess: async (successPayment) => {
138
+ setIsLoading(false);
139
+ const response = {
140
+ paymentId: successPayment.id,
141
+ payment: successPayment,
142
+ order: successPayment.order,
143
+ };
144
+ // Hook-level callback (universal handler)
145
+ if (hookOptionsRef.current?.onPaymentCompleted) {
146
+ await hookOptionsRef.current.onPaymentCompleted(successPayment, {
147
+ isRedirectReturn: false,
148
+ order: response.order,
149
+ });
150
+ }
151
+ options.onSuccess?.(response);
152
+ options.onPaymentSuccess?.(response);
153
+ },
154
+ onFailure: async (errorMsg) => {
155
+ setError(errorMsg);
156
+ setIsLoading(false);
157
+ // Hook-level callback (universal handler)
158
+ if (hookOptionsRef.current?.onPaymentFailed) {
159
+ await hookOptionsRef.current.onPaymentFailed(errorMsg, {
160
+ isRedirectReturn: false,
161
+ });
162
+ }
163
+ options.onFailure?.(errorMsg);
164
+ options.onPaymentFailed?.({
165
+ code: 'PAYMENT_FAILED',
166
+ message: errorMsg,
167
+ payment,
168
+ });
169
+ },
170
+ });
171
+ }
172
+ }
173
+ catch (radarError) {
174
+ const errorMsg = radarError instanceof Error ? radarError.message : 'Finix fraud detection failed';
175
+ console.error('Finix radar error:', radarError);
176
+ setError(errorMsg);
177
+ setIsLoading(false);
178
+ options.onFailure?.(errorMsg);
179
+ options.onPaymentFailed?.({
180
+ code: 'FINIX_RADAR_FAILED',
181
+ message: errorMsg,
182
+ payment,
183
+ });
184
+ }
185
+ }, [paymentsResource, startPolling, setError, setIsLoading, hookOptionsRef]);
186
+ return { handleFinixRadar };
187
+ }
@@ -0,0 +1,11 @@
1
+ import type { Payment, PaymentOptions } from '../../../core/resources/payments';
2
+ import type { UsePaymentOptions } from '../usePaymentQuery';
3
+ interface UseKessPayActionParams {
4
+ setError: (error: string | null) => void;
5
+ setIsLoading: (loading: boolean) => void;
6
+ hookOptionsRef: React.MutableRefObject<UsePaymentOptions | undefined>;
7
+ }
8
+ export declare function useKessPayAction({ setError, setIsLoading, hookOptionsRef, }: UseKessPayActionParams): {
9
+ handleKessPayAuth: (payment: Payment, actionData: any, options?: PaymentOptions) => Promise<void>;
10
+ };
11
+ export {};
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Hook for handling KessPay 3DS authentication
3
+ */
4
+ import { useCallback, useRef } from 'react';
5
+ export function useKessPayAction({ setError, setIsLoading, hookOptionsRef, }) {
6
+ const challengeInProgressRef = useRef(false);
7
+ const handleKessPayAuth = useCallback(async (payment, actionData, options = {}) => {
8
+ if (challengeInProgressRef.current) {
9
+ console.log('KessPay 3DS challenge already in progress');
10
+ return;
11
+ }
12
+ const threeDSData = actionData?.metadata?.threeds;
13
+ if (!threeDSData?.challengeHtml) {
14
+ const errorMsg = 'Missing KessPay 3DS challenge HTML';
15
+ console.error(errorMsg);
16
+ setError(errorMsg);
17
+ setIsLoading(false);
18
+ options.onFailure?.(errorMsg);
19
+ options.onPaymentFailed?.({
20
+ code: 'KESSPAY_MISSING_DATA',
21
+ message: errorMsg,
22
+ payment,
23
+ });
24
+ return;
25
+ }
26
+ try {
27
+ challengeInProgressRef.current = true;
28
+ setIsLoading(false); // Stop loading before redirect
29
+ console.log('🔐 [KessPay] Starting 3DS authentication:', {
30
+ sessionId: threeDSData.sessionId,
31
+ orderId: threeDSData.orderId,
32
+ hasHtml: !!threeDSData.challengeHtml,
33
+ });
34
+ // Create a temporary document to execute the challenge HTML
35
+ // This will trigger the auto-submit form and redirect
36
+ const tempDoc = document.implementation.createHTMLDocument('KessPay 3DS Challenge');
37
+ tempDoc.body.innerHTML = threeDSData.challengeHtml;
38
+ // Find and submit the form directly
39
+ const form = tempDoc.querySelector('form');
40
+ if (form) {
41
+ // Create a new form in the current document and submit it
42
+ const redirectForm = document.createElement('form');
43
+ redirectForm.method = form.method || 'POST';
44
+ redirectForm.action = form.action || '';
45
+ redirectForm.style.display = 'none';
46
+ // Copy all form inputs
47
+ const inputs = form.querySelectorAll('input');
48
+ inputs.forEach(input => {
49
+ const newInput = document.createElement('input');
50
+ newInput.type = input.type;
51
+ newInput.name = input.name;
52
+ newInput.value = input.value;
53
+ redirectForm.appendChild(newInput);
54
+ });
55
+ // Add form to document and submit
56
+ document.body.appendChild(redirectForm);
57
+ redirectForm.submit();
58
+ console.log('🔐 [KessPay] Redirecting to 3DS challenge...');
59
+ }
60
+ else {
61
+ // Fallback: write the HTML directly to current document
62
+ // This should trigger the auto-submit script
63
+ document.open();
64
+ document.write(threeDSData.challengeHtml);
65
+ document.close();
66
+ }
67
+ // Note: Success callback will be triggered after redirect return
68
+ // Payment status will be updated via webhook
69
+ }
70
+ catch (error) {
71
+ challengeInProgressRef.current = false;
72
+ const errorMsg = error instanceof Error ? error.message : 'Failed to process KessPay 3DS authentication';
73
+ console.error('🔐 [KessPay] 3DS authentication error:', error);
74
+ setError(errorMsg);
75
+ setIsLoading(false);
76
+ options.onFailure?.(errorMsg);
77
+ options.onPaymentFailed?.({
78
+ code: 'KESSPAY_AUTH_FAILED',
79
+ message: errorMsg,
80
+ payment,
81
+ });
82
+ // Hook-level callback (universal handler)
83
+ if (hookOptionsRef.current?.onPaymentFailed) {
84
+ hookOptionsRef.current.onPaymentFailed(errorMsg, {
85
+ isRedirectReturn: false,
86
+ });
87
+ }
88
+ }
89
+ }, [setError, setIsLoading, hookOptionsRef]);
90
+ return { handleKessPayAuth };
91
+ }
@@ -0,0 +1,24 @@
1
+ import type { Payment, PaymentOptions } from '../../../core/resources/payments';
2
+ import type { PaymentsResource } from '../../../core/resources/payments';
3
+ import type { UsePaymentOptions } from '../usePaymentQuery';
4
+ interface UseMasterCardActionParams {
5
+ paymentsResource: PaymentsResource;
6
+ startPolling: any;
7
+ setError: (error: string | null) => void;
8
+ setIsLoading: (loading: boolean) => void;
9
+ hookOptionsRef: React.MutableRefObject<UsePaymentOptions | undefined>;
10
+ }
11
+ declare global {
12
+ interface Window {
13
+ ThreeDS: {
14
+ configure: (config: any) => void;
15
+ isConfigured: () => boolean;
16
+ initiateAuthentication: (orderId: string, transactionId: string, callback: (result: any) => void, optionalParams?: any) => void;
17
+ authenticatePayer: (orderId: string, transactionId: string, callback: (result: any) => void, optionalParams?: any) => void;
18
+ };
19
+ }
20
+ }
21
+ export declare function useMasterCardAction({ paymentsResource, startPolling, setError, setIsLoading, hookOptionsRef, }: UseMasterCardActionParams): {
22
+ handleMasterCardAuth: (payment: Payment, actionData: any, options: PaymentOptions | undefined, handlePaymentAction: any) => Promise<void>;
23
+ };
24
+ export {};
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Hook for handling MasterCard 3DS authentication
3
+ */
4
+ import { useCallback, useRef, useState } from 'react';
5
+ import { useThreedsModal } from '../useThreedsModal';
6
+ export function useMasterCardAction({ paymentsResource, startPolling, setError, setIsLoading, hookOptionsRef, }) {
7
+ const challengeInProgressRef = useRef(false);
8
+ const [isShowingChallenge, setIsShowingChallenge] = useState(false);
9
+ const { createThreedsModal, closeThreedsModal } = useThreedsModal();
10
+ // Load MasterCard 3DS script
11
+ const loadScript = useCallback(async (scriptUrl) => {
12
+ return new Promise((resolve, reject) => {
13
+ if (window.ThreeDS) {
14
+ resolve();
15
+ return;
16
+ }
17
+ const existingScript = document.querySelector(`script[src="${scriptUrl}"]`);
18
+ if (existingScript) {
19
+ existingScript.addEventListener('load', () => resolve());
20
+ existingScript.addEventListener('error', () => reject(new Error('Failed to load 3DS script')));
21
+ return;
22
+ }
23
+ const script = document.createElement('script');
24
+ script.src = scriptUrl;
25
+ script.onload = () => resolve();
26
+ script.onerror = () => reject(new Error('Failed to load 3DS script'));
27
+ document.head.appendChild(script);
28
+ });
29
+ }, []);
30
+ const handleMasterCardAuth = useCallback(async (payment, actionData, options = {}, handlePaymentAction) => {
31
+ if (challengeInProgressRef.current) {
32
+ console.log('MasterCard 3DS challenge already in progress');
33
+ return;
34
+ }
35
+ const threeDSData = actionData?.metadata?.threeds;
36
+ if (!threeDSData?.sessionId || !threeDSData?.merchantId) {
37
+ const errorMsg = 'Missing MasterCard 3DS authentication data';
38
+ console.error(errorMsg);
39
+ setError(errorMsg);
40
+ setIsLoading(false);
41
+ options.onFailure?.(errorMsg);
42
+ options.onPaymentFailed?.({
43
+ code: 'MASTERCARD_MISSING_DATA',
44
+ message: errorMsg,
45
+ payment,
46
+ });
47
+ return;
48
+ }
49
+ try {
50
+ challengeInProgressRef.current = true;
51
+ setIsLoading(false);
52
+ console.log('[MasterCard 3DS] Starting authentication:', {
53
+ sessionId: threeDSData.sessionId,
54
+ orderId: threeDSData.orderId,
55
+ transactionId: threeDSData.transactionId,
56
+ });
57
+ // Load the MasterCard 3DS script
58
+ await loadScript(threeDSData.scriptUrl);
59
+ // Create hidden container for 3DS iframe
60
+ const containerId = 'mastercard-3ds-container';
61
+ let container = document.getElementById(containerId);
62
+ if (!container) {
63
+ container = document.createElement('div');
64
+ container.id = containerId;
65
+ container.style.cssText = 'position: absolute; top: -9999px; left: -9999px; width: 1px; height: 1px; overflow: hidden;';
66
+ document.body.appendChild(container);
67
+ }
68
+ // Configure ThreeDS API
69
+ console.log('[MasterCard 3DS] Configuring ThreeDS API');
70
+ await new Promise((resolve, reject) => {
71
+ window.ThreeDS.configure({
72
+ merchantId: threeDSData.merchantId,
73
+ sessionId: threeDSData.sessionId,
74
+ containerId,
75
+ callback: function () {
76
+ if (window.ThreeDS.isConfigured()) {
77
+ console.log('[MasterCard 3DS] Configuration completed');
78
+ resolve();
79
+ }
80
+ else {
81
+ reject(new Error('ThreeDS configuration failed'));
82
+ }
83
+ },
84
+ configuration: {
85
+ userLanguage: 'en-US',
86
+ wsVersion: threeDSData.version ? parseInt(threeDSData.version, 10) : 72,
87
+ },
88
+ });
89
+ });
90
+ // Authenticate payer
91
+ const authResult = await new Promise((resolve) => {
92
+ window.ThreeDS.authenticatePayer(threeDSData.orderId, threeDSData.transactionId, (payerResult) => {
93
+ console.log('[MasterCard 3DS] authenticatePayer result:', payerResult);
94
+ resolve(payerResult);
95
+ });
96
+ });
97
+ // Check if challenge HTML is present
98
+ const challengeHtml = authResult?.htmlRedirectCode || authResult?.restApiResponse?.authentication?.redirect?.html;
99
+ if (challengeHtml) {
100
+ setIsShowingChallenge(true);
101
+ // Create modal for challenge
102
+ const modal = createThreedsModal({
103
+ containerId: 'mastercard-3ds-modal',
104
+ mode: 'auto-fit',
105
+ onClose: () => {
106
+ console.log('[MasterCard 3DS] Modal closed by user');
107
+ setIsShowingChallenge(false);
108
+ challengeInProgressRef.current = false;
109
+ const errorMsg = 'User closed the authentication modal';
110
+ setError(errorMsg);
111
+ options.onFailure?.(errorMsg);
112
+ options.onPaymentFailed?.({
113
+ code: 'MASTERCARD_CANCELLED',
114
+ message: errorMsg,
115
+ payment,
116
+ });
117
+ },
118
+ });
119
+ const contentElement = modal.getContentElement();
120
+ if (contentElement) {
121
+ contentElement.innerHTML = challengeHtml;
122
+ // Auto-submit form if present
123
+ setTimeout(() => {
124
+ const frictionlessForm = contentElement.querySelector('#threedsFrictionLessRedirectForm');
125
+ const challengeForm = contentElement.querySelector('#threedsChallengeRedirectForm');
126
+ const form = frictionlessForm ?? challengeForm;
127
+ if (form) {
128
+ console.log('[MasterCard 3DS] Auto-submitting form');
129
+ form.submit();
130
+ // For frictionless flow, close modal and complete payment
131
+ if (frictionlessForm) {
132
+ setTimeout(async () => {
133
+ closeThreedsModal('mastercard-3ds-modal');
134
+ setIsShowingChallenge(false);
135
+ challengeInProgressRef.current = false;
136
+ // Complete payment after frictionless 3DS
137
+ if (threeDSData.paymentId) {
138
+ const resumedPayment = await paymentsResource.completePaymentAfterAction(threeDSData.paymentId);
139
+ await handlePaymentAction(resumedPayment, options);
140
+ }
141
+ }, 1000);
142
+ }
143
+ else {
144
+ // Challenge flow - listen for completion
145
+ const handleIframeMessage = async (event) => {
146
+ const messageData = event.data;
147
+ let isComplete = false;
148
+ if (typeof messageData === 'string') {
149
+ isComplete = messageData.toLowerCase().includes('complete') ||
150
+ messageData.toLowerCase().includes('success');
151
+ }
152
+ else if (typeof messageData === 'object' && messageData !== null) {
153
+ isComplete = messageData.result === 'SUCCESS' ||
154
+ messageData.transStatus === 'Y' ||
155
+ messageData.type === '3DSAuthenticationComplete';
156
+ }
157
+ if (isComplete) {
158
+ console.log('[MasterCard 3DS] Challenge completed');
159
+ window.removeEventListener('message', handleIframeMessage);
160
+ closeThreedsModal('mastercard-3ds-modal');
161
+ setIsShowingChallenge(false);
162
+ challengeInProgressRef.current = false;
163
+ // Complete payment after challenge
164
+ if (threeDSData.paymentId) {
165
+ const resumedPayment = await paymentsResource.completePaymentAfterAction(threeDSData.paymentId);
166
+ await handlePaymentAction(resumedPayment, options);
167
+ }
168
+ }
169
+ };
170
+ window.addEventListener('message', handleIframeMessage);
171
+ // Timeout after 5 minutes
172
+ setTimeout(() => {
173
+ window.removeEventListener('message', handleIframeMessage);
174
+ closeThreedsModal('mastercard-3ds-modal');
175
+ setIsShowingChallenge(false);
176
+ challengeInProgressRef.current = false;
177
+ const errorMsg = '3DS authentication timed out';
178
+ setError(errorMsg);
179
+ options.onFailure?.(errorMsg);
180
+ }, 300000);
181
+ }
182
+ }
183
+ }, 100);
184
+ }
185
+ }
186
+ else {
187
+ // No challenge required - frictionless flow
188
+ console.log('[MasterCard 3DS] No challenge required');
189
+ challengeInProgressRef.current = false;
190
+ if (threeDSData.paymentId) {
191
+ const resumedPayment = await paymentsResource.completePaymentAfterAction(threeDSData.paymentId);
192
+ await handlePaymentAction(resumedPayment, options);
193
+ }
194
+ }
195
+ // Cleanup container
196
+ const cleanupContainer = document.getElementById('mastercard-3ds-container');
197
+ if (cleanupContainer && document.body.contains(cleanupContainer)) {
198
+ document.body.removeChild(cleanupContainer);
199
+ }
200
+ }
201
+ catch (error) {
202
+ challengeInProgressRef.current = false;
203
+ const errorMsg = error instanceof Error ? error.message : 'MasterCard 3DS authentication failed';
204
+ console.error('[MasterCard 3DS] Error:', error);
205
+ setError(errorMsg);
206
+ setIsLoading(false);
207
+ options.onFailure?.(errorMsg);
208
+ options.onPaymentFailed?.({
209
+ code: 'MASTERCARD_AUTH_FAILED',
210
+ message: errorMsg,
211
+ payment,
212
+ });
213
+ if (hookOptionsRef.current?.onPaymentFailed) {
214
+ hookOptionsRef.current.onPaymentFailed(errorMsg, {
215
+ isRedirectReturn: false,
216
+ });
217
+ }
218
+ }
219
+ }, [paymentsResource, loadScript, createThreedsModal, closeThreedsModal, setError, setIsLoading, hookOptionsRef]);
220
+ return { handleMasterCardAuth };
221
+ }
@@ -0,0 +1,15 @@
1
+ import type { Payment, PaymentOptions } from '../../../core/resources/payments';
2
+ import type { PaymentsResource } from '../../../core/resources/payments';
3
+ import type { UsePaymentOptions } from '../usePaymentQuery';
4
+ interface UsePaymentActionHandlerParams {
5
+ paymentsResource: PaymentsResource;
6
+ startChallenge: any;
7
+ startPolling: any;
8
+ setIsLoading: (loading: boolean) => void;
9
+ setError: (error: string | null) => void;
10
+ hookOptionsRef: React.MutableRefObject<UsePaymentOptions | undefined>;
11
+ }
12
+ export declare function usePaymentActionHandler({ paymentsResource, startChallenge, startPolling, setIsLoading, setError, hookOptionsRef, }: UsePaymentActionHandlerParams): {
13
+ handlePaymentAction: (payment: Payment, options?: PaymentOptions) => Promise<void>;
14
+ };
15
+ export {};