strapi-plugin-payone-provider 1.5.2 → 1.5.4

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.
@@ -1,5 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from "react";
2
2
  import { Box, Flex, Typography } from "@strapi/design-system";
3
+ import { request } from "@strapi/helper-plugin";
4
+ import pluginId from "../../../pluginId";
3
5
  import { DEFAULT_APPLE_PAY_CONFIG } from "../../utils/applePayConstants";
4
6
 
5
7
  /**
@@ -41,13 +43,41 @@ const ApplePayButton = ({
41
43
  try {
42
44
  console.log("[Apple Pay] Checking availability...");
43
45
 
44
- // Check if we're on HTTPS (required for Apple Pay JS API)
45
- const isSecure = typeof window !== 'undefined' &&
46
- (window.location.protocol === 'https:' ||
47
- window.location.hostname === 'localhost' ||
48
- window.location.hostname === '127.0.0.1');
46
+ // Check secure context using browser's native property
47
+ // This is the most reliable way to check if we're in a secure context
48
+ const isSecureContext = typeof window !== 'undefined' && window.isSecureContext;
49
+ const protocol = typeof window !== 'undefined' ? window.location.protocol : '';
50
+ const hostname = typeof window !== 'undefined' ? window.location.hostname : '';
51
+ const isLocalhost = hostname === 'localhost' || hostname === '127.0.0.1';
52
+
53
+ // For Apple Pay, we need a secure context (HTTPS or localhost)
54
+ // window.isSecureContext is true for:
55
+ // - HTTPS pages
56
+ // - localhost (even on HTTP)
57
+ // - 127.0.0.1 (even on HTTP)
58
+ // - file:// URLs
59
+ const isSecure = isSecureContext || isLocalhost;
49
60
 
50
- console.log("[Apple Pay] Secure context:", isSecure, "Protocol:", window.location?.protocol);
61
+ console.log("[Apple Pay] Secure context check:", {
62
+ isSecureContext: isSecureContext,
63
+ protocol: protocol,
64
+ hostname: hostname,
65
+ isLocalhost: isLocalhost,
66
+ isSecure: isSecure,
67
+ fullUrl: typeof window !== 'undefined' ? window.location.href : ''
68
+ });
69
+
70
+ // If not secure, log detailed information
71
+ if (!isSecure) {
72
+ console.error("[Apple Pay] NOT in secure context!", {
73
+ isSecureContext: isSecureContext,
74
+ protocol: protocol,
75
+ hostname: hostname,
76
+ isLocalhost: isLocalhost,
77
+ fullUrl: typeof window !== 'undefined' ? window.location.href : '',
78
+ reason: !isSecureContext ? "window.isSecureContext is false" : "Unknown"
79
+ });
80
+ }
51
81
 
52
82
  // First, check if Payment Request API is available
53
83
  // Payment Request API works on HTTP too, but Apple Pay JS API requires HTTPS
@@ -168,15 +198,23 @@ const ApplePayButton = ({
168
198
  }
169
199
  }
170
200
 
171
- // If canMakePayment is not available, assume it's available (for older browsers)
172
- // But only if we're in a secure context
173
- // Reuse isSecure from line 47
201
+ // If canMakePayment is not available, check secure context again
202
+ // Re-check secure context to ensure we have the latest state
203
+ const isSecureContextFinal = typeof window !== 'undefined' && window.isSecureContext;
204
+ const hostnameFinal = typeof window !== 'undefined' ? window.location.hostname : '';
205
+ const isLocalhostFinal = hostnameFinal === 'localhost' || hostnameFinal === '127.0.0.1';
206
+ const isSecureFinal = isSecureContextFinal || isLocalhostFinal;
174
207
 
175
- if (isSecure) {
208
+ if (isSecureFinal) {
176
209
  console.log("[Apple Pay] canMakePayment not available, assuming support (secure context)");
177
210
  return { available: true, method: 'paymentRequest' };
178
211
  } else {
179
212
  console.warn("[Apple Pay] canMakePayment not available and insecure context");
213
+ console.warn("[Apple Pay] Context details:", {
214
+ isSecureContext: isSecureContextFinal,
215
+ hostname: hostnameFinal,
216
+ isLocalhost: isLocalhostFinal
217
+ });
180
218
  return { available: false, method: null, error: 'insecure_context' };
181
219
  }
182
220
  } catch (error) {
@@ -189,9 +227,13 @@ const ApplePayButton = ({
189
227
  }
190
228
 
191
229
  // Fallback: Try Apple Pay JS API (only on HTTPS)
192
- // Reuse isSecure from line 47
230
+ // Re-check secure context
231
+ const isSecureContextFallback = typeof window !== 'undefined' && window.isSecureContext;
232
+ const hostnameFallback = typeof window !== 'undefined' ? window.location.hostname : '';
233
+ const isLocalhostFallback = hostnameFallback === 'localhost' || hostnameFallback === '127.0.0.1';
234
+ const isSecureFallback = isSecureContextFallback || isLocalhostFallback;
193
235
 
194
- if (typeof window !== 'undefined' && window.ApplePaySession && isSecure) {
236
+ if (typeof window !== 'undefined' && window.ApplePaySession && isSecureFallback) {
195
237
  try {
196
238
  const canMakePayments = ApplePaySession.canMakePayments();
197
239
  return { available: canMakePayments, method: 'applePayJS' };
@@ -461,16 +503,22 @@ const ApplePayButton = ({
461
503
  });
462
504
  }).catch(err => {
463
505
  console.error("[Apple Pay] Merchant session error:", err);
506
+ // Don't call onError here - let the dialog handle it
464
507
  });
465
508
 
509
+ // Complete with the merchant session promise
510
+ // If it fails, Apple Pay will handle it gracefully
466
511
  event.complete(merchantSessionPromise);
467
512
  } catch (error) {
468
513
  console.error("[Apple Pay] Merchant validation error:", error);
469
- if (onError) {
514
+ // Only call onError if it's defined
515
+ if (typeof onError === 'function') {
470
516
  onError(error);
471
517
  }
472
- // Complete with empty object - Payone will handle validation
473
- event.complete({});
518
+ // Complete with a promise that resolves to empty object
519
+ // This allows the dialog to continue even if validation fails
520
+ // Apple Pay will show an error but won't close immediately
521
+ event.complete(Promise.resolve({}));
474
522
  }
475
523
  };
476
524
 
@@ -504,7 +552,14 @@ const ApplePayButton = ({
504
552
  response = await request.show();
505
553
  } catch (error) {
506
554
  console.error("[Apple Pay] Error showing payment sheet:", error);
507
- if (onError) {
555
+ // Check if error is due to cancellation (user cancelled)
556
+ if (error.message && error.message.includes('Cancelled')) {
557
+ console.log("[Apple Pay] User cancelled the payment");
558
+ // Don't call onError for user cancellation
559
+ return;
560
+ }
561
+ // Only call onError if it's defined and it's not a cancellation
562
+ if (typeof onError === 'function') {
508
563
  onError(error);
509
564
  }
510
565
  return;
@@ -553,37 +608,85 @@ const ApplePayButton = ({
553
608
  }
554
609
 
555
610
  // Call the callback with the token BEFORE completing payment
556
- // This ensures the token is processed before the dialog closes
611
+ // This ensures the token is saved before the dialog closes
557
612
  console.log("[Apple Pay] Sending token to callback");
558
613
  let callbackSuccess = true;
614
+ let callbackError = null;
615
+
559
616
  if (onTokenReceived) {
560
617
  try {
561
- // If callback is async, wait for it
618
+ // Call the callback to save the token
619
+ // The callback should set the token in state and return success immediately
620
+ // It should NOT process the payment yet - that will happen when user clicks the button
562
621
  const callbackResult = onTokenReceived(tokenString, {
563
622
  paymentToken: paymentToken,
564
623
  billingContact: response.payerName || response.details?.billingContact,
565
624
  shippingContact: response.shippingAddress || response.details?.shippingAddress,
566
625
  shippingOption: response.shippingOption || response.details?.shippingOption
567
626
  });
568
-
569
- // If callback returns a promise, wait for it
627
+
628
+ // If callback returns a promise, wait for it to resolve or reject
570
629
  if (callbackResult && typeof callbackResult.then === 'function') {
571
- await callbackResult;
630
+ try {
631
+ const result = await callbackResult;
632
+ console.log("[Apple Pay] Token callback completed successfully:", result);
633
+ // Check if result indicates success
634
+ if (result && result.success === false) {
635
+ callbackSuccess = false;
636
+ callbackError = new Error(result.message || "Token callback returned failure");
637
+ }
638
+ } catch (error) {
639
+ console.error("[Apple Pay] Token callback promise rejected:", error);
640
+ callbackSuccess = false;
641
+ callbackError = error;
642
+ }
643
+ } else if (callbackResult === false) {
644
+ // If callback explicitly returns false, treat as failure
645
+ callbackSuccess = false;
646
+ console.warn("[Apple Pay] Token callback returned false");
647
+ } else {
648
+ // If callback returns a value (not a promise), assume success
649
+ console.log("[Apple Pay] Token callback returned synchronously");
572
650
  }
573
- } catch (callbackError) {
574
- console.error("[Apple Pay] Error in token callback:", callbackError);
651
+ } catch (error) {
652
+ console.error("[Apple Pay] Error in token callback:", error);
575
653
  callbackSuccess = false;
654
+ callbackError = error;
576
655
  }
656
+ } else {
657
+ console.warn("[Apple Pay] No onTokenReceived callback provided");
658
+ // If no callback, we should still complete the payment
659
+ // But mark as success since we can't determine the result
660
+ callbackSuccess = true;
577
661
  }
578
662
 
579
663
  // Complete payment with success or fail based on callback result
664
+ // IMPORTANT: Only call complete() after the callback has fully finished
580
665
  console.log("[Apple Pay] Completing payment with status:", callbackSuccess ? "success" : "fail");
666
+
581
667
  try {
582
- await response.complete(callbackSuccess ? "success" : "fail");
583
- console.log("[Apple Pay] Payment completed successfully");
668
+ // Use a small delay to ensure state updates are complete
669
+ // This prevents the dialog from closing before the token is saved
670
+ await new Promise(resolve => setTimeout(resolve, 200));
671
+
672
+ const completionStatus = callbackSuccess ? "success" : "fail";
673
+ await response.complete(completionStatus);
674
+ console.log("[Apple Pay] Payment completed with status:", completionStatus);
675
+
676
+ // If there was an error, notify the error handler
677
+ if (!callbackSuccess && callbackError && onError) {
678
+ onError(callbackError);
679
+ }
584
680
  } catch (completeError) {
585
681
  console.error("[Apple Pay] Error completing payment:", completeError);
586
- if (onError) {
682
+ // Try to complete with fail status if there's an error
683
+ try {
684
+ await response.complete("fail");
685
+ } catch (finalError) {
686
+ console.error("[Apple Pay] Failed to complete payment even with fail status:", finalError);
687
+ }
688
+ // Only call onError if it's defined
689
+ if (typeof onError === 'function') {
587
690
  onError(completeError);
588
691
  }
589
692
  }
@@ -594,7 +697,14 @@ const ApplePayButton = ({
594
697
  stack: error.stack,
595
698
  name: error.name
596
699
  });
597
- if (onError) {
700
+ // Check if error is due to cancellation (user cancelled)
701
+ if (error.message && error.message.includes('Cancelled')) {
702
+ console.log("[Apple Pay] User cancelled the payment");
703
+ // Don't call onError for user cancellation
704
+ return;
705
+ }
706
+ // Only call onError if it's defined and it's not a cancellation
707
+ if (typeof onError === 'function') {
598
708
  onError(error);
599
709
  }
600
710
  }
@@ -613,43 +723,45 @@ const ApplePayButton = ({
613
723
  });
614
724
 
615
725
  try {
616
- // Call Strapi backend to validate with Payone
617
- const response = await fetch('/api/strapi-plugin-payone-provider/validate-apple-pay-merchant', {
726
+ console.log("[Apple Pay] Making validation request using Strapi helper...");
727
+
728
+ // Use Strapi helper-plugin's request function which automatically handles authentication
729
+ // This uses the admin API route which requires admin authentication
730
+ const merchantSession = await request(`/${pluginId}/validate-apple-pay-merchant`, {
618
731
  method: 'POST',
619
- headers: {
620
- 'Content-Type': 'application/json',
621
- },
622
- body: JSON.stringify({
732
+ body: {
623
733
  validationURL,
624
734
  ...config
625
- })
735
+ }
626
736
  });
627
737
 
628
- console.log("[Apple Pay] Validation response status:", response.status);
738
+ console.log("[Apple Pay] Merchant session received from backend:", {
739
+ hasData: !!merchantSession.data,
740
+ merchantIdentifier: merchantSession.data?.merchantIdentifier
741
+ });
629
742
 
630
- if (response.ok) {
631
- const merchantSession = await response.json();
632
- console.log("[Apple Pay] Merchant session received from backend:", {
633
- hasData: !!merchantSession.data,
634
- merchantIdentifier: merchantSession.data?.merchantIdentifier
635
- });
636
- return merchantSession.data || merchantSession;
637
- } else {
638
- // If validation fails, return empty object - Payone will handle it
639
- const errorText = await response.text();
640
- console.warn("[Apple Pay] Merchant validation failed:", {
641
- status: response.status,
642
- statusText: response.statusText,
643
- error: errorText
644
- });
645
- return {};
646
- }
743
+ return merchantSession.data || merchantSession;
647
744
  } catch (error) {
648
745
  console.error("[Apple Pay] Merchant validation error:", {
649
746
  message: error.message,
747
+ status: error.response?.status,
748
+ statusText: error.response?.statusText,
749
+ data: error.response?.data,
650
750
  stack: error.stack
651
751
  });
652
- // Return empty object - Payone will handle validation
752
+
753
+ // Log specific error details
754
+ if (error.response?.status === 403) {
755
+ console.error("[Apple Pay] 403 Forbidden - Authentication failed. Make sure you are logged in as admin.");
756
+ } else if (error.response?.status === 401) {
757
+ console.error("[Apple Pay] 401 Unauthorized - Please log in again.");
758
+ } else if (error.response?.status >= 500) {
759
+ console.error("[Apple Pay] Server error - Check server logs for details.");
760
+ }
761
+
762
+ // If validation fails, return empty object
763
+ // This allows the dialog to continue, though Apple Pay may show an error
764
+ // The user can still proceed with payment if they want
653
765
  return {};
654
766
  }
655
767
  };
@@ -673,12 +785,6 @@ const ApplePayButton = ({
673
785
  )}
674
786
  {!isLoading && isAvailable && (
675
787
  <>
676
- <Typography variant="sigma" textColor="neutral700" fontWeight="semiBold" style={{ textAlign: "left" }}>
677
- Apple Pay Payment
678
- </Typography>
679
- <Typography variant="pi" textColor="neutral600" style={{ textAlign: "left" }}>
680
- Click the button below to pay with Apple Pay. The token will be automatically sent to Payone.
681
- </Typography>
682
788
  <Box ref={buttonContainerRef} style={{ minHeight: "40px", width: "100%", display: "flex", justifyContent: "flex-start" }}>
683
789
  {typeof window !== 'undefined' && window.customElements && window.customElements.get('apple-pay-button') ? (
684
790
  <apple-pay-button
@@ -44,16 +44,33 @@ const AuthorizationForm = ({
44
44
 
45
45
  const handleApplePayToken = async (token, paymentData) => {
46
46
  if (!token) {
47
+ console.error("[Apple Pay] Token is missing in handleApplePayToken");
47
48
  return Promise.reject(new Error("Token is missing"));
48
49
  }
50
+
51
+ console.log("[Apple Pay] handleApplePayToken called with token:", {
52
+ hasToken: !!token,
53
+ tokenLength: token?.length,
54
+ paymentData: !!paymentData
55
+ });
56
+
57
+ // IMPORTANT: Set token in state immediately (synchronously)
58
+ // This ensures the token is saved before the dialog closes
49
59
  setApplePayToken(token);
50
- try {
51
- await onAuthorization(token);
52
- return Promise.resolve();
53
- } catch (error) {
54
- console.error("[Apple Pay] Error in authorization:", error);
55
- return Promise.reject(error);
56
- }
60
+
61
+ console.log("[Apple Pay] Token saved to state successfully");
62
+
63
+ // Don't call onAuthorization immediately
64
+ // Let the user manually trigger the payment using the button
65
+ // This prevents the dialog from closing prematurely if there's an error
66
+ // The dialog will close with success, and the user will see the "Process Authorization" button
67
+
68
+ // Return success immediately so the dialog closes properly
69
+ // The actual payment processing will happen when the user clicks the button
70
+ return Promise.resolve({
71
+ success: true,
72
+ message: "Token received successfully. Please click 'Process Authorization' to complete the payment."
73
+ });
57
74
  };
58
75
 
59
76
  const handleApplePayError = (error) => {
@@ -44,16 +44,33 @@ const PreauthorizationForm = ({
44
44
 
45
45
  const handleApplePayToken = async (token, paymentData) => {
46
46
  if (!token) {
47
+ console.error("[Apple Pay] Token is missing in handleApplePayToken");
47
48
  return Promise.reject(new Error("Token is missing"));
48
49
  }
50
+
51
+ console.log("[Apple Pay] handleApplePayToken called with token:", {
52
+ hasToken: !!token,
53
+ tokenLength: token?.length,
54
+ paymentData: !!paymentData
55
+ });
56
+
57
+ // IMPORTANT: Set token in state immediately (synchronously)
58
+ // This ensures the token is saved before the dialog closes
49
59
  setApplePayToken(token);
50
- try {
51
- await onPreauthorization(token);
52
- return Promise.resolve();
53
- } catch (error) {
54
- console.error("[Apple Pay] Error in preauthorization:", error);
55
- return Promise.reject(error);
56
- }
60
+
61
+ console.log("[Apple Pay] Token saved to state successfully");
62
+
63
+ // Don't call onPreauthorization immediately
64
+ // Let the user manually trigger the payment using the button
65
+ // This prevents the dialog from closing prematurely if there's an error
66
+ // The dialog will close with success, and the user will see the "Process Preauthorization" button
67
+
68
+ // Return success immediately so the dialog closes properly
69
+ // The actual payment processing will happen when the user clicks the button
70
+ return Promise.resolve({
71
+ success: true,
72
+ message: "Token received successfully. Please click 'Process Preauthorization' to complete the payment."
73
+ });
57
74
  };
58
75
 
59
76
  const handleApplePayError = (error) => {
@@ -83,6 +83,12 @@ const usePaymentActions = () => {
83
83
  };
84
84
 
85
85
  const handlePreauthorization = async (tokenParam = null) => {
86
+ console.log("[Payment] handlePreauthorization called", {
87
+ hasToken: !!tokenParam,
88
+ paymentMethod,
89
+ amount: paymentAmount
90
+ });
91
+
86
92
  setIsProcessingPayment(true);
87
93
  setPaymentError(null);
88
94
  setPaymentResult(null);
@@ -211,16 +217,31 @@ const usePaymentActions = () => {
211
217
 
212
218
  setPaymentResult(responseData);
213
219
 
220
+ console.log("[Payment] Preauthorization result:", {
221
+ status,
222
+ hasError: !!errorCode,
223
+ errorCode,
224
+ errorMessage
225
+ });
226
+
214
227
  if (status === "APPROVED") {
215
228
  handlePaymentSuccess("Preauthorization completed successfully");
229
+ // Return success result for Apple Pay callback
230
+ return { success: true, data: responseData };
216
231
  } else {
232
+ const errorMsg = errorMessage || `Unexpected status: ${status}`;
217
233
  handlePaymentError(
218
- { message: `Unexpected status: ${status}` },
234
+ { message: errorMsg },
219
235
  `Preauthorization completed with status: ${status}`
220
236
  );
237
+ // Return error result for Apple Pay callback
238
+ throw new Error(errorMsg);
221
239
  }
222
240
  } catch (error) {
241
+ console.error("[Payment] Preauthorization error:", error);
223
242
  handlePaymentError(error, "Preauthorization failed");
243
+ // Re-throw error so Apple Pay callback knows it failed
244
+ throw error;
224
245
  } finally {
225
246
  setIsProcessingPayment(false);
226
247
  }
@@ -356,16 +377,31 @@ const usePaymentActions = () => {
356
377
 
357
378
  setPaymentResult(responseData);
358
379
 
380
+ console.log("[Payment] Authorization result:", {
381
+ status,
382
+ hasError: !!errorCode,
383
+ errorCode,
384
+ errorMessage
385
+ });
386
+
359
387
  if (status === "APPROVED") {
360
388
  handlePaymentSuccess("Authorization completed successfully");
389
+ // Return success result for Apple Pay callback
390
+ return { success: true, data: responseData };
361
391
  } else {
392
+ const errorMsg = errorMessage || `Unexpected status: ${status}`;
362
393
  handlePaymentError(
363
- { message: `Unexpected status: ${status}` },
394
+ { message: errorMsg },
364
395
  `Authorization completed with status: ${status}`
365
396
  );
397
+ // Return error result for Apple Pay callback
398
+ throw new Error(errorMsg);
366
399
  }
367
400
  } catch (error) {
401
+ console.error("[Payment] Authorization error:", error);
368
402
  handlePaymentError(error, "Authorization failed");
403
+ // Re-throw error so Apple Pay callback knows it failed
404
+ throw error;
369
405
  } finally {
370
406
  setIsProcessingPayment(false);
371
407
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-payone-provider",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "description": "Strapi plugin for Payone payment gateway integration",
5
5
  "license": "MIT",
6
6
  "maintainers": [
@@ -17,7 +17,7 @@ const getPayoneService = (strapi) => {
17
17
  * @param {Error} error - Error object
18
18
  */
19
19
  const handleError = (ctx, error) => {
20
- strapi.log.error("Payone controller error:", error);
20
+ ctx.strapi.log.error("Payone controller error:", error);
21
21
  ctx.throw(500, error);
22
22
  };
23
23
 
@@ -180,10 +180,28 @@ module.exports = ({ strapi }) => ({
180
180
 
181
181
  async validateApplePayMerchant(ctx) {
182
182
  try {
183
+ strapi.log.info("[Apple Pay] Merchant validation request received");
184
+ strapi.log.info("[Apple Pay] Request body:", JSON.stringify(ctx.request.body, null, 2));
185
+ strapi.log.info("[Apple Pay] User:", ctx.state.user ? {
186
+ id: ctx.state.user.id,
187
+ email: ctx.state.user.email,
188
+ roles: ctx.state.user.roles?.map(r => r.code)
189
+ } : "No user");
190
+
183
191
  const params = ctx.request.body;
184
192
  const result = await getPayoneService(strapi).validateApplePayMerchant(params);
193
+
194
+ strapi.log.info("[Apple Pay] Merchant validation result:", {
195
+ hasResult: !!result,
196
+ hasMerchantIdentifier: !!result.merchantIdentifier
197
+ });
198
+
185
199
  ctx.body = { data: result };
186
200
  } catch (error) {
201
+ strapi.log.error("[Apple Pay] Controller error:", {
202
+ message: error.message,
203
+ stack: error.stack
204
+ });
187
205
  handleError(ctx, error);
188
206
  }
189
207
  }
@@ -24,7 +24,7 @@ const initializeApplePaySession = async (strapi, params) => {
24
24
  try {
25
25
  strapi.log.info("[Apple Pay] Initializing Apple Pay session with Payone");
26
26
  strapi.log.info("[Apple Pay] Request params:", JSON.stringify(params, null, 2));
27
-
27
+
28
28
  const settings = await getSettings(strapi);
29
29
 
30
30
  if (!validateSettings(settings)) {
@@ -55,9 +55,9 @@ const initializeApplePaySession = async (strapi, params) => {
55
55
  const mode = settings.mode || "test"; // test or live
56
56
 
57
57
  // Get domain from params or settings or server config
58
- const domain = domainName || settings.domainName ||
59
- (strapi.config.get("server.url") ? new URL(strapi.config.get("server.url")).hostname : null) ||
60
- "localhost";
58
+ const domain = domainName || settings.domainName ||
59
+ (strapi.config.get("server.url") ? new URL(strapi.config.get("server.url")).hostname : null) ||
60
+ "localhost";
61
61
 
62
62
  // Build request parameters for Apple Pay session initialization
63
63
  // According to Payone documentation: request="genericpayment"
@@ -87,14 +87,38 @@ const initializeApplePaySession = async (strapi, params) => {
87
87
 
88
88
  const formData = toFormData(requestParams);
89
89
 
90
- const response = await axios.post(POST_GATEWAY_URL, formData, {
91
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
92
- timeout: 30000
90
+ strapi.log.info("[Apple Pay] Sending request to Payone API:", {
91
+ url: POST_GATEWAY_URL,
92
+ params: {
93
+ ...requestParams,
94
+ key: "***HIDDEN***" // Hide API key in logs
95
+ }
93
96
  });
94
97
 
98
+ let response;
99
+ try {
100
+ response = await axios.post(POST_GATEWAY_URL, formData, {
101
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
102
+ timeout: 30000
103
+ });
104
+ } catch (axiosError) {
105
+ strapi.log.error("[Apple Pay] Payone API request failed:", {
106
+ message: axiosError.message,
107
+ status: axiosError.response?.status,
108
+ statusText: axiosError.response?.statusText,
109
+ data: axiosError.response?.data,
110
+ config: {
111
+ url: axiosError.config?.url,
112
+ method: axiosError.config?.method
113
+ }
114
+ });
115
+ throw axiosError;
116
+ }
117
+
95
118
  strapi.log.info("[Apple Pay] Payone response received:", {
96
119
  status: response.status,
97
- statusText: response.statusText
120
+ statusText: response.statusText,
121
+ headers: response.headers
98
122
  });
99
123
 
100
124
  // Parse response
@@ -102,7 +126,7 @@ const initializeApplePaySession = async (strapi, params) => {
102
126
 
103
127
  strapi.log.info("[Apple Pay] Session initialization response:", JSON.stringify(responseData, null, 2));
104
128
  strapi.log.info("[Apple Pay] Response status:", responseData.status || responseData.Status);
105
-
129
+
106
130
  if (responseData.errorcode || responseData.ErrorCode) {
107
131
  strapi.log.warn("[Apple Pay] Response contains error:", {
108
132
  errorcode: responseData.errorcode || responseData.ErrorCode,
@@ -135,7 +159,7 @@ const validateApplePayMerchant = async (strapi, params) => {
135
159
  mid: params.mid,
136
160
  portalid: params.portalid
137
161
  }, null, 2));
138
-
162
+
139
163
  const settings = await getSettings(strapi);
140
164
 
141
165
  if (!validateSettings(settings)) {
@@ -155,11 +179,11 @@ const validateApplePayMerchant = async (strapi, params) => {
155
179
  const merchantName = displayName || settings.merchantName || settings.displayName || "Test Store";
156
180
  const merchantId = mid || settings.mid || settings.merchantIdentifier;
157
181
  const portalId = portalid || settings.portalid;
158
-
182
+
159
183
  // Get domain from params or settings or server config
160
- const domainName = domain || settings.domainName ||
161
- (strapi.config.get("server.url") ? new URL(strapi.config.get("server.url")).hostname : null) ||
162
- "localhost";
184
+ const domainName = domain || settings.domainName ||
185
+ (strapi.config.get("server.url") ? new URL(strapi.config.get("server.url")).hostname : null) ||
186
+ "localhost";
163
187
 
164
188
  // For Payone integration without developer account,
165
189
  // Payone handles merchant validation
@@ -174,24 +198,39 @@ const validateApplePayMerchant = async (strapi, params) => {
174
198
  strapi.log.info("[Apple Pay] Initializing session with params:", JSON.stringify(sessionParams, null, 2));
175
199
 
176
200
  // Initialize Apple Pay session with Payone
177
- const sessionResponse = await initializeApplePaySession(strapi, sessionParams);
201
+ let sessionResponse;
202
+ try {
203
+ sessionResponse = await initializeApplePaySession(strapi, sessionParams);
204
+ } catch (error) {
205
+ strapi.log.error("[Apple Pay] Failed to initialize session with Payone:", {
206
+ message: error.message,
207
+ status: error.response?.status,
208
+ data: error.response?.data
209
+ });
210
+ // Return empty object on error - Payment Request API will handle it
211
+ return {};
212
+ }
178
213
 
179
214
  strapi.log.info("[Apple Pay] Session initialization result:", {
180
215
  status: sessionResponse.status || sessionResponse.Status,
181
- hasMerchantIdentifier: !!(sessionResponse.merchantIdentifier || sessionResponse.merchantSessionIdentifier)
216
+ hasMerchantIdentifier: !!(sessionResponse.merchantIdentifier || sessionResponse.merchantSessionIdentifier),
217
+ fullResponse: JSON.stringify(sessionResponse, null, 2)
182
218
  });
183
219
 
184
220
  // If session initialization is successful, return merchant session
185
221
  // Payone will provide the merchant identifier and validation data
186
- if (sessionResponse.status === "APPROVED" || sessionResponse.status === "REDIRECT") {
222
+ // Check for both uppercase and lowercase status
223
+ const responseStatus = sessionResponse.status || sessionResponse.Status;
224
+ if (responseStatus === "APPROVED" || responseStatus === "REDIRECT" ||
225
+ responseStatus === "approved" || responseStatus === "redirect") {
187
226
  strapi.log.info("[Apple Pay] Session approved, creating merchant session object");
188
227
  // Get merchant identifier from Payone response or settings
189
- const merchantIdentifier = sessionResponse.merchantIdentifier ||
190
- sessionResponse.merchantSessionIdentifier ||
191
- settings.merchantIdentifier ||
192
- settings.mid ||
193
- settings.portalid ||
194
- `merchant.${domainName}`;
228
+ const merchantIdentifier = sessionResponse.merchantIdentifier ||
229
+ sessionResponse.merchantSessionIdentifier ||
230
+ settings.merchantIdentifier ||
231
+ settings.mid ||
232
+ settings.portalid ||
233
+ `merchant.${domainName}`;
195
234
 
196
235
  // Return merchant session object
197
236
  // In a real implementation, you would get this from Payone's response
@@ -249,8 +288,8 @@ const parseResponse = (responseData, logger) => {
249
288
  * Generate nonce for merchant session
250
289
  */
251
290
  const generateNonce = () => {
252
- return Math.random().toString(36).substring(2, 15) +
253
- Math.random().toString(36).substring(2, 15);
291
+ return Math.random().toString(36).substring(2, 15) +
292
+ Math.random().toString(36).substring(2, 15);
254
293
  };
255
294
 
256
295
  module.exports = {