strapi-plugin-payone-provider 1.6.6 → 1.6.7

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.
@@ -8,6 +8,8 @@ import {
8
8
  Stack,
9
9
  Typography,
10
10
  TextInput,
11
+ Select,
12
+ Option,
11
13
  Divider,
12
14
  } from "@strapi/design-system";
13
15
  import { Search } from "@strapi/icons";
@@ -68,66 +70,69 @@ const HistoryPanel = ({
68
70
  <Stack spacing={4}>
69
71
  <Flex gap={4} wrap="wrap" alignItems="center">
70
72
  <TextInput
71
- label="Status"
72
- name="status"
73
- value={filters.status}
74
- onChange={(e) => onFilterChange("status", e.target.value)}
75
- placeholder="APPROVED, ERROR, etc."
73
+ label="Search"
74
+ name="search"
75
+ value={filters.search || ""}
76
+ onChange={(e) => onFilterChange("search", e.target.value)}
77
+ placeholder="Search by Status, Transaction ID, or Reference"
76
78
  className="payment-input"
77
- style={{ flex: 1, minWidth: "200px" }}
79
+ style={{ flex: 1, minWidth: "250px" }}
78
80
  />
79
- <TextInput
81
+ <Select
80
82
  label="Request Type"
81
83
  name="request_type"
82
- value={filters.request_type}
83
- onChange={(e) =>
84
- onFilterChange("request_type", e.target.value)
85
- }
86
- placeholder="preauthorization, authorization, etc."
87
- className="payment-input"
88
- style={{ flex: 1, minWidth: "200px" }}
89
- />
90
- <TextInput
91
- label="Transaction ID"
92
- name="txid"
93
- value={filters.txid}
94
- onChange={(e) => onFilterChange("txid", e.target.value)}
95
- placeholder="Enter TxId"
84
+ value={filters.request_type || ""}
85
+ onChange={(value) => onFilterChange("request_type", value)}
86
+ placeholder="Select request type"
96
87
  className="payment-input"
97
88
  style={{ flex: 1, minWidth: "200px" }}
98
- />
99
- <TextInput
100
- label="Reference"
101
- name="reference"
102
- value={filters.reference}
103
- onChange={(e) =>
104
- onFilterChange("reference", e.target.value)
89
+ >
90
+ <Option value="">All Types</Option>
91
+ <Option value="preauthorization">Preauthorization</Option>
92
+ <Option value="authorization">Authorization</Option>
93
+ <Option value="capture">Capture</Option>
94
+ <Option value="refund">Refund</Option>
95
+ </Select>
96
+ <Select
97
+ label="Payment Method"
98
+ name="payment_method"
99
+ value={filters.payment_method || ""}
100
+ onChange={(value) =>
101
+ onFilterChange("payment_method", value)
105
102
  }
106
- placeholder="Enter reference"
103
+ placeholder="Select payment method"
107
104
  className="payment-input"
108
105
  style={{ flex: 1, minWidth: "200px" }}
109
- />
106
+ >
107
+ <Option value="">All Methods</Option>
108
+ <Option value="credit_card">Credit Card</Option>
109
+ <Option value="paypal">PayPal</Option>
110
+ <Option value="google_pay">Google Pay</Option>
111
+ <Option value="apple_pay">Apple Pay</Option>
112
+ <Option value="sofort">Sofort Banking</Option>
113
+ <Option value="sepa">SEPA Direct Debit</Option>
114
+ </Select>
110
115
  <TextInput
111
116
  label="Date From"
112
117
  name="date_from"
113
- value={filters.date_from}
118
+ value={filters.date_from || ""}
114
119
  onChange={(e) =>
115
120
  onFilterChange("date_from", e.target.value)
116
121
  }
117
122
  placeholder="YYYY-MM-DD"
118
123
  type="date"
119
124
  className="payment-input"
120
- style={{ flex: 1, minWidth: "200px" }}
125
+ style={{ flex: 1, minWidth: "150px" }}
121
126
  />
122
127
  <TextInput
123
128
  label="Date To"
124
129
  name="date_to"
125
- value={filters.date_to}
130
+ value={filters.date_to || ""}
126
131
  onChange={(e) => onFilterChange("date_to", e.target.value)}
127
132
  placeholder="YYYY-MM-DD"
128
133
  type="date"
129
134
  className="payment-input"
130
- style={{ flex: 1, minWidth: "200px" }}
135
+ style={{ flex: 1, minWidth: "150px" }}
131
136
  />
132
137
  <Button
133
138
  variant="default"
@@ -51,7 +51,13 @@ const PaymentActionsPanel = ({
51
51
  const mode = (settings?.mode || "test").toLowerCase();
52
52
  const isLiveMode = mode === "live";
53
53
 
54
- if (isLiveMode) {
54
+ React.useEffect(() => {
55
+ if (isLiveMode && paymentMethod !== "apl") {
56
+ setPaymentMethod("apl");
57
+ }
58
+ }, [isLiveMode, paymentMethod]);
59
+
60
+ if (isLiveMode && paymentMethod !== "apl") {
55
61
  return (
56
62
  <Box
57
63
  style={{
@@ -99,6 +105,7 @@ const PaymentActionsPanel = ({
99
105
  cardcvc2={cardcvc2}
100
106
  setCardcvc2={setCardcvc2}
101
107
  onNavigateToConfig={onNavigateToConfig}
108
+ isLiveMode={isLiveMode}
102
109
  />
103
110
  );
104
111
  }
@@ -4,11 +4,30 @@ import PaymentMethodSelector from "./PaymentMethodSelector";
4
4
  import AuthorizationForm from "./AuthorizationForm";
5
5
 
6
6
  const ApplePayOnlyPanel = ({
7
+ paymentAmount,
8
+ setPaymentAmount,
9
+ authReference,
10
+ setAuthReference,
11
+ isProcessingPayment,
12
+ onAuthorization,
7
13
  paymentMethod,
14
+ settings,
15
+ setGooglePayToken,
8
16
  setPaymentMethod,
9
17
  captureMode,
10
18
  setCaptureMode,
11
19
  onNavigateToConfig,
20
+ isLiveMode,
21
+ setCardcvc2,
22
+ cardtype,
23
+ setCardtype,
24
+ cardpan,
25
+ setCardpan,
26
+ cardexpiredate,
27
+ setCardexpiredate,
28
+ cardcvc2,
29
+ applePayToken,
30
+ setApplePayToken,
12
31
  }) => {
13
32
  return (
14
33
  <Box
@@ -42,7 +61,32 @@ const ApplePayOnlyPanel = ({
42
61
  captureMode={captureMode}
43
62
  setCaptureMode={setCaptureMode}
44
63
  onNavigateToConfig={onNavigateToConfig}
45
- isLiveMode={false}
64
+ isLiveMode={isLiveMode}
65
+ />
66
+
67
+ <hr className="payment-divider" />
68
+
69
+ <AuthorizationForm
70
+ paymentAmount={paymentAmount}
71
+ setPaymentAmount={setPaymentAmount}
72
+ authReference={authReference}
73
+ setAuthReference={setAuthReference}
74
+ isProcessingPayment={isProcessingPayment}
75
+ onAuthorization={onAuthorization}
76
+ paymentMethod={paymentMethod}
77
+ settings={settings}
78
+ setGooglePayToken={setGooglePayToken}
79
+ applePayToken={applePayToken}
80
+ setApplePayToken={setApplePayToken}
81
+ cardtype={cardtype}
82
+ setCardtype={setCardtype}
83
+ cardpan={cardpan}
84
+ setCardpan={setCardpan}
85
+ cardexpiredate={cardexpiredate}
86
+ setCardexpiredate={setCardexpiredate}
87
+ cardcvc2={cardcvc2}
88
+ setCardcvc2={setCardcvc2}
89
+ isLiveMode={isLiveMode}
46
90
  />
47
91
  </Box>
48
92
  );
@@ -110,6 +110,7 @@ const App = () => {
110
110
  onSave={settings.handleSave}
111
111
  onTestConnection={settings.handleTestConnection}
112
112
  onInputChange={settings.handleInputChange}
113
+ onPaymentMethodToggle={settings.handlePaymentMethodToggle}
113
114
  filters={transactionHistory.filters}
114
115
  onFilterChange={transactionHistory.handleFilterChange}
115
116
  onFilterApply={transactionHistory.handleFilterApply}
@@ -41,6 +41,31 @@ const useSettings = () => {
41
41
  setSettings((prev) => ({ ...prev, [field]: value }));
42
42
  };
43
43
 
44
+ const handlePaymentMethodToggle = async (field, value) => {
45
+ let updatedSettings;
46
+ setSettings((prev) => {
47
+ updatedSettings = { ...prev, [field]: value };
48
+ return updatedSettings;
49
+ });
50
+
51
+ setIsSaving(true);
52
+ try {
53
+ await payoneRequests.updateSettings(updatedSettings);
54
+ toggleNotification({
55
+ type: "success",
56
+ message: "Payment method updated successfully"
57
+ });
58
+ } catch (error) {
59
+ setSettings((prev) => ({ ...prev, [field]: !value }));
60
+ toggleNotification({
61
+ type: "warning",
62
+ message: "Failed to update payment method"
63
+ });
64
+ } finally {
65
+ setIsSaving(false);
66
+ }
67
+ };
68
+
44
69
  const handleSave = async () => {
45
70
  setIsSaving(true);
46
71
  try {
@@ -103,6 +128,7 @@ const useSettings = () => {
103
128
  isTesting,
104
129
  testResult,
105
130
  handleInputChange,
131
+ handlePaymentMethodToggle,
106
132
  handleSave,
107
133
  handleTestConnection
108
134
  };
@@ -11,10 +11,9 @@ const useTransactionHistory = () => {
11
11
  const [selectedTransaction, setSelectedTransaction] = useState(null);
12
12
  const [currentPage, setCurrentPage] = useState(1);
13
13
  const [filters, setFilters] = useState({
14
- status: "",
14
+ search: "",
15
15
  request_type: "",
16
- txid: "",
17
- reference: "",
16
+ payment_method: "",
18
17
  date_from: "",
19
18
  date_to: ""
20
19
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-payone-provider",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
4
4
  "description": "Strapi plugin for Payone payment gateway integration",
5
5
  "license": "MIT",
6
6
  "maintainers": [
@@ -21,7 +21,13 @@ module.exports = async ({ strapi }) => {
21
21
  merchantName: "",
22
22
  displayName: "",
23
23
  domainName: "",
24
- merchantIdentifier: ""
24
+ merchantIdentifier: "",
25
+ enableCreditCard: true,
26
+ enablePayPal: true,
27
+ enableGooglePay: true,
28
+ enableApplePay: true,
29
+ enableSofort: true,
30
+ enableSepaDirectDebit: true
25
31
  }
26
32
  });
27
33
  }
@@ -56,8 +62,8 @@ module.exports = async ({ strapi }) => {
56
62
 
57
63
  router.get('/.well-known/apple-developer-merchantid-domain-association', async (ctx) => {
58
64
  try {
59
- const publicPath = path.join(process.cwd(), 'public');
60
- const wellKnownPath = path.join(publicPath, '.well-known');
65
+ const pluginRoot = path.resolve(__dirname, '..');
66
+ const wellKnownPath = path.join(pluginRoot, '.well-known');
61
67
  const possiblePaths = [
62
68
  path.join(wellKnownPath, 'apple-developer-merchantid-domain-association'),
63
69
  path.join(wellKnownPath, 'apple-developer-merchantid-domain-association.txt'),
@@ -45,6 +45,14 @@ module.exports = ({ strapi }) => ({
45
45
  portalid: settings?.portalid || null,
46
46
  accountId: settings?.aid || null,
47
47
  portalKey: settings?.key || null,
48
+ paymentMethods: {
49
+ creditCard: settings?.enableCreditCard,
50
+ paypal: settings?.enablePayPal,
51
+ googlePay: settings?.enableGooglePay,
52
+ applePay: settings?.enableApplePay,
53
+ sofort: settings?.enableSofort,
54
+ sepa: settings?.enableSepaDirectDebit,
55
+ },
48
56
  }
49
57
  };
50
58
  } catch (error) {
@@ -8,13 +8,35 @@ const POST_GATEWAY_URL = "https://api.pay1.de/post-gateway/";
8
8
 
9
9
  const parseResponse = (responseData) => {
10
10
  if (typeof responseData === 'string') {
11
+ if (responseData.trim().startsWith('{')) {
12
+ try {
13
+ return JSON.parse(responseData);
14
+ } catch (e) {
15
+ // Fall through to URL-encoded parsing
16
+ }
17
+ }
18
+
11
19
  const params = new URLSearchParams(responseData);
12
20
  const parsed = {};
13
21
  for (const [key, value] of params.entries()) {
14
22
  parsed[key] = value;
23
+ const normalizedKey = key.toLowerCase().replace(/\[/g, '_').replace(/\]/g, '');
24
+ if (normalizedKey !== key.toLowerCase()) {
25
+ parsed[normalizedKey] = value;
26
+ }
15
27
  }
16
28
  return parsed;
17
29
  }
30
+
31
+ if (typeof responseData === 'object' && responseData !== null) {
32
+ const result = { ...responseData };
33
+ if (result['add_paydata[applepay_payment_session]']) {
34
+ result.add_paydata = result.add_paydata || {};
35
+ result.add_paydata.applepay_payment_session = result['add_paydata[applepay_payment_session]'];
36
+ }
37
+ return result;
38
+ }
39
+
18
40
  return responseData;
19
41
  };
20
42
 
@@ -45,8 +67,6 @@ const initializeApplePaySession = async (strapi, params) => {
45
67
 
46
68
  const applePayConfig = settings?.applePayConfig || {};
47
69
  const currency = params.currency || applePayConfig.currencyCode || "EUR";
48
- const countryCode = params.countryCode || applePayConfig.countryCode || "DE";
49
-
50
70
  const merchantName = params.displayName || settings?.merchantName || "Store";
51
71
  const domain = params.domain || params.domainName || "localhost";
52
72
 
@@ -63,18 +83,14 @@ const initializeApplePaySession = async (strapi, params) => {
63
83
  const requestParams = buildClientRequestParams(settings, baseParams, strapi.log);
64
84
  const formData = toFormData(requestParams);
65
85
 
66
- let response;
67
- try {
68
- response = await axios.post(`${POST_GATEWAY_URL}Genericpayment`, formData, {
69
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
70
- timeout: 30000,
71
- validateStatus: function (status) {
72
- return status >= 200 && status < 600;
73
- }
74
- });
75
- } catch (axiosError) {
76
- throw axiosError;
77
- }
86
+ const response = await axios.post(`${POST_GATEWAY_URL}Genericpayment`, formData, {
87
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
88
+ timeout: 30000,
89
+ validateStatus: function (status) {
90
+ return status >= 200 && status < 600;
91
+ }
92
+ });
93
+
78
94
 
79
95
  if (response.status === 403) {
80
96
  const responseData = parseResponse(response.data);
@@ -88,12 +104,7 @@ const initializeApplePaySession = async (strapi, params) => {
88
104
 
89
105
  const detailedError = new Error("403 Forbidden: Authentication failed with Payone API. " +
90
106
  (errorCode ? `Error Code: ${errorCode}. ` : "") +
91
- (errorMessage ? `Error: ${errorMessage}. ` : "") +
92
- "Please check: 1) Your Payone credentials (aid, portalid, mid, key) in plugin settings, " +
93
- "2) Mode is set to 'live' (Apple Pay only works in live mode), " +
94
- "3) Your domain is registered with Payone Merchant Services, " +
95
- "4) Merchant ID (mid) matches your merchantIdentifier in PMI, " +
96
- "5) Apple Pay is enabled for your portal in PMI.");
107
+ (errorMessage ? `Error: ${errorMessage}. ` : ""));
97
108
  Object.assign(detailedError, { status: 403, response: response });
98
109
  throw detailedError;
99
110
  }
@@ -138,71 +149,7 @@ const initializeApplePaySession = async (strapi, params) => {
138
149
 
139
150
  return responseData;
140
151
  } catch (error) {
141
- const errorStatus = error.response?.status || error.status;
142
- const errorResponseData = error.response?.data;
143
-
144
- // Provide more specific error messages
145
- if (errorStatus === 403 || error.message?.includes('403')) {
146
- let responseData = {};
147
- let errorCode = null;
148
- let errorMessage = null;
149
-
150
- if (errorResponseData) {
151
- try {
152
- responseData = parseResponse(errorResponseData);
153
- errorCode = responseData.errorcode || responseData.ErrorCode;
154
- errorMessage = responseData.errormessage || responseData.ErrorMessage || responseData.customermessage || responseData.CustomerMessage;
155
- } catch (parseErr) {
156
- if (typeof errorResponseData === 'string') {
157
- errorMessage = errorResponseData;
158
- }
159
- }
160
- }
161
-
162
- if (errorCode || errorMessage) {
163
- strapi.log.error("[Apple Pay] 403 Forbidden from Payone:", {
164
- errorcode: errorCode,
165
- errormessage: errorMessage
166
- });
167
- }
168
-
169
- let detailedMessage = "403 Forbidden: Authentication failed with Payone API. ";
170
-
171
- if (errorCode) {
172
- detailedMessage += `Error Code: ${errorCode}. `;
173
- }
174
-
175
- if (errorMessage) {
176
- detailedMessage += `Error: ${errorMessage}. `;
177
- }
178
-
179
- detailedMessage += "Please check:\n" +
180
- "1. Your Payone credentials (aid, portalid, mid, key) in plugin settings\n" +
181
- "2. Mode is set to 'live' (Apple Pay only works in live mode according to Payone docs)\n" +
182
- "3. Your domain is registered with Payone Merchant Services\n" +
183
- "4. Merchant ID (mid) matches your merchantIdentifier in PMI\n" +
184
- "5. Apple Pay is enabled for your portal in PMI (CONFIGURATION → PAYMENT PORTALS → [Your Portal] → Payment type configuration tab)";
185
-
186
- throw new Error(detailedMessage);
187
- } else if (errorStatus === 401 || error.message?.includes('401')) {
188
- if (errorResponseData) {
189
- const responseData = parseResponse(errorResponseData);
190
- strapi.log.error("[Apple Pay] 401 Unauthorized from Payone:", {
191
- errorcode: responseData.errorcode || responseData.ErrorCode,
192
- errormessage: responseData.errormessage || responseData.ErrorMessage
193
- });
194
- }
195
- throw new Error("401 Unauthorized: Invalid credentials. Please verify your Payone key in plugin settings.");
196
- } else if (errorStatus && errorStatus >= 500) {
197
- const responseData = errorResponseData ? parseResponse(errorResponseData) : {};
198
- strapi.log.error("[Apple Pay] Payone server error:", {
199
- status: error.response?.status,
200
- errorcode: responseData.errorcode || responseData.ErrorCode,
201
- errormessage: responseData.errormessage || responseData.ErrorMessage
202
- });
203
- throw new Error(`Payone server error (${error.response?.status}): ${error.response?.statusText || 'Internal server error'}`);
204
- }
205
-
152
+ strapi.log.error("[Apple Pay] Error:", error instanceof Error ? error.message : error);
206
153
  throw error;
207
154
  }
208
155
  };
@@ -215,28 +162,89 @@ const validateApplePayMerchant = async (strapi, params) => {
215
162
  throw new Error("Payone settings are not properly configured. Please check your plugin settings (aid, portalid, mid, key).");
216
163
  }
217
164
 
218
- // Get currency and country from Apple Pay config
219
165
  const applePayConfig = settings?.applePayConfig || {};
220
- const currency = params.currency || applePayConfig.currencyCode || "EUR";
221
- const countryCode = params.countryCode || applePayConfig.countryCode || "DE";
222
166
 
223
- // Update params with config values
224
167
  if (!params.currency && applePayConfig.currencyCode) {
225
168
  params.currency = applePayConfig.currencyCode;
226
169
  }
170
+
227
171
  if (!params.countryCode && applePayConfig.countryCode) {
228
172
  params.countryCode = applePayConfig.countryCode;
229
173
  }
230
174
 
231
175
  const sessionResponse = await initializeApplePaySession(strapi, params);
232
176
 
233
- const applePaySessionBase64 = sessionResponse["add_paydata[applepay_payment_session]"] ||
234
- sessionResponse.add_paydata?.applepay_payment_session;
177
+ // Extract add_paydata[applepay_payment_session] from response
178
+ // Payone returns this in URL-encoded format: add_paydata[applepay_payment_session]=BASE64_STRING
179
+ const applePaySessionBase64 =
180
+ sessionResponse["add_paydata[applepay_payment_session]"] ||
181
+ sessionResponse["add_paydata_applepay_payment_session"] ||
182
+ sessionResponse.add_paydata?.applepay_payment_session ||
183
+ (sessionResponse.add_paydata && typeof sessionResponse.add_paydata === 'object'
184
+ ? sessionResponse.add_paydata["applepay_payment_session"]
185
+ : null);
186
+
187
+ strapi.log.info("[Apple Pay] Genericpayment response:", {
188
+ status: sessionResponse.status,
189
+ workorderid: sessionResponse.workorderid,
190
+ hasApplePaySession: !!applePaySessionBase64,
191
+ applePaySessionLength: applePaySessionBase64 ? applePaySessionBase64.length : 0,
192
+ responseKeys: Object.keys(sessionResponse),
193
+ hasAddPaydataKey: !!sessionResponse["add_paydata[applepay_payment_session]"],
194
+ hasAddPaydataObject: !!sessionResponse.add_paydata,
195
+ addPaydataKeys: sessionResponse.add_paydata ? Object.keys(sessionResponse.add_paydata) : null
196
+ });
197
+
198
+ if (!applePaySessionBase64) {
199
+ strapi.log.error("[Apple Pay] Missing applepay_payment_session in response:", {
200
+ status: sessionResponse.status,
201
+ responseKeys: Object.keys(sessionResponse),
202
+ responseSample: JSON.stringify(sessionResponse).substring(0, 1000),
203
+ addPaydataKeys: sessionResponse.add_paydata ? Object.keys(sessionResponse.add_paydata) : null
204
+ });
205
+ throw new Error("Missing applepay_payment_session in Payone response. Please check your Payone Apple Pay configuration in PMI.");
206
+ }
235
207
 
236
208
  if (sessionResponse.status === "OK" && applePaySessionBase64 && applePaySessionBase64.length > 0) {
237
209
  try {
238
- const merchantSessionJson = Buffer.from(applePaySessionBase64, 'base64').toString('utf-8');
239
- const merchantSession = JSON.parse(merchantSessionJson);
210
+ strapi.log.info("[Apple Pay] Extracting merchant session from Base64:", {
211
+ base64Length: applePaySessionBase64.length,
212
+ base64Preview: applePaySessionBase64.substring(0, 100) + "...",
213
+ base64End: applePaySessionBase64.substring(Math.max(0, applePaySessionBase64.length - 50))
214
+ });
215
+
216
+ // Decode Base64 to get merchant session JSON
217
+ let merchantSessionJson;
218
+ try {
219
+ merchantSessionJson = Buffer.from(applePaySessionBase64, 'base64').toString('utf-8');
220
+ strapi.log.info("[Apple Pay] Base64 decoded successfully, JSON length:", merchantSessionJson.length);
221
+ } catch (decodeError) {
222
+ strapi.log.error("[Apple Pay] Failed to decode Base64:", {
223
+ error: decodeError.message,
224
+ base64Length: applePaySessionBase64.length
225
+ });
226
+ throw new Error(`Failed to decode Base64 merchant session: ${decodeError.message}`);
227
+ }
228
+
229
+ // Parse JSON merchant session
230
+ let merchantSession;
231
+ try {
232
+ merchantSession = JSON.parse(merchantSessionJson);
233
+ strapi.log.info("[Apple Pay] Merchant session JSON parsed successfully");
234
+ } catch (parseError) {
235
+ strapi.log.error("[Apple Pay] Failed to parse merchant session JSON:", {
236
+ error: parseError.message,
237
+ jsonPreview: merchantSessionJson.substring(0, 500)
238
+ });
239
+ throw new Error(`Failed to parse merchant session JSON: ${parseError.message}`);
240
+ }
241
+
242
+ strapi.log.info("[Apple Pay] Merchant session extracted successfully:", {
243
+ hasMerchantIdentifier: !!merchantSession.merchantIdentifier,
244
+ hasEpochTimestamp: !!merchantSession.epochTimestamp,
245
+ hasExpiresAt: !!merchantSession.expiresAt,
246
+ merchantSessionKeys: Object.keys(merchantSession)
247
+ });
240
248
 
241
249
  if (merchantSession.epochTimestamp && merchantSession.epochTimestamp > 1000000000000) {
242
250
  merchantSession.epochTimestamp = Math.floor(merchantSession.epochTimestamp / 1000);
@@ -274,7 +282,9 @@ const validateApplePayMerchant = async (strapi, params) => {
274
282
  throw new Error(
275
283
  `Payone Apple Pay initialization failed: ${errorCode ? `Error ${errorCode}` : 'Unknown error'} - ${errorMessage || 'Please check your Payone Apple Pay configuration in PMI'}`
276
284
  );
285
+
277
286
  } catch (error) {
287
+ strapi.log.error("[Apple Pay] Error:", error instanceof Error ? error.message : error);
278
288
  throw error;
279
289
  }
280
290
  };
@@ -54,10 +54,19 @@ const getTransactionHistory = async (strapi, filters = {}) => {
54
54
  let transactionHistory =
55
55
  (await pluginStore.get({ key: "transactionHistory" })) || [];
56
56
 
57
- if (filters.status) {
58
- transactionHistory = transactionHistory.filter(
59
- (transaction) => transaction.status === filters.status
60
- );
57
+ if (filters.search) {
58
+ const searchLower = filters.search.toLowerCase().trim();
59
+ transactionHistory = transactionHistory.filter((transaction) => {
60
+ const status = (transaction.status || "").toLowerCase();
61
+ const txid = (transaction.txid || "").toLowerCase();
62
+ const reference = (transaction.reference || "").toLowerCase();
63
+
64
+ return (
65
+ status.includes(searchLower) ||
66
+ txid.includes(searchLower) ||
67
+ reference.includes(searchLower)
68
+ );
69
+ });
61
70
  }
62
71
 
63
72
  if (filters.request_type) {
@@ -66,16 +75,28 @@ const getTransactionHistory = async (strapi, filters = {}) => {
66
75
  );
67
76
  }
68
77
 
69
- if (filters.txid) {
70
- transactionHistory = transactionHistory.filter(
71
- (transaction) => transaction.txid === filters.txid
72
- );
73
- }
74
-
75
- if (filters.reference) {
76
- transactionHistory = transactionHistory.filter(
77
- (transaction) => transaction.reference === filters.reference
78
- );
78
+ if (filters.payment_method) {
79
+ transactionHistory = transactionHistory.filter((transaction) => {
80
+ const clearingtype = transaction.raw_request?.clearingtype || "";
81
+ const wallettype = transaction.raw_request?.wallettype || "";
82
+
83
+ switch (filters.payment_method) {
84
+ case "credit_card":
85
+ return clearingtype === "cc";
86
+ case "paypal":
87
+ return clearingtype === "wlt" && wallettype === "PPE";
88
+ case "google_pay":
89
+ return clearingtype === "wlt" && (wallettype === "GPY" || wallettype === "GOOGLEPAY");
90
+ case "apple_pay":
91
+ return clearingtype === "wlt" && (wallettype === "APL" || wallettype === "APPLEPAY");
92
+ case "sofort":
93
+ return clearingtype === "sb";
94
+ case "sepa":
95
+ return clearingtype === "elv";
96
+ default:
97
+ return false;
98
+ }
99
+ });
79
100
  }
80
101
 
81
102
  if (filters.date_from) {