@reeboot/strapi-payment-plugin 0.0.6 → 0.0.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.
Files changed (29) hide show
  1. package/README.md +21 -0
  2. package/dist/_chunks/{Analytics-CQmAVKsq.mjs → Analytics-CncK5kn-.mjs} +6 -7
  3. package/dist/_chunks/{Analytics-CLjtRWYA.js → Analytics-c8KBuG3k.js} +6 -7
  4. package/dist/_chunks/{App-DXN62SV6.mjs → App-B5AB8Omu.mjs} +7 -7
  5. package/dist/_chunks/{App-Dk7XtjNA.js → App-Cih9sWu1.js} +7 -7
  6. package/dist/_chunks/{Customers-BQzVBQDT.mjs → Customers-BVk2gx7w.mjs} +51 -118
  7. package/dist/_chunks/{Customers-BNDi4QBH.js → Customers-CZWOnN26.js} +50 -117
  8. package/dist/_chunks/{Dashboard-UUwohHZa.js → Dashboard-CEif4jQn.js} +60 -84
  9. package/dist/_chunks/{Dashboard-CuHC-dit.mjs → Dashboard-DAjD8Q_6.mjs} +60 -84
  10. package/dist/_chunks/{Orders-CitNCdWE.js → Orders-DZXb54VO.js} +73 -146
  11. package/dist/_chunks/{Orders-65mNfu2i.mjs → Orders-DdJqI1HB.mjs} +74 -147
  12. package/dist/_chunks/{PaymentList-B0CAzInT.mjs → PaymentList-3HWK7PMz.mjs} +14 -39
  13. package/dist/_chunks/{PaymentList-Dy1BAFoD.js → PaymentList-APfyYD1h.js} +14 -39
  14. package/dist/_chunks/{Payments-FnhoV_2B.mjs → Payments-DFL-Cwgy.mjs} +97 -103
  15. package/dist/_chunks/{Payments-TOnygGIW.js → Payments-VzDGbK4W.js} +96 -102
  16. package/dist/_chunks/{Settings-BJtDagUs.js → Settings-B1tR3WOm.js} +157 -161
  17. package/dist/_chunks/{Settings-EoLSuZLe.mjs → Settings-SALxClBu.mjs} +157 -161
  18. package/dist/_chunks/{index-2Zd_T7bD.mjs → index-CB6TMitx.mjs} +1 -1
  19. package/dist/_chunks/{index-CHEgJ7e5.js → index-D-fFikb8.js} +1 -1
  20. package/dist/admin/index.js +1 -1
  21. package/dist/admin/index.mjs +1 -1
  22. package/dist/server/index.js +7 -34
  23. package/dist/server/index.mjs +7 -34
  24. package/package.json +1 -1
  25. /package/dist/server/src/{types → services/types}/api.d.ts +0 -0
  26. /package/dist/server/src/{types → services/types}/customer.d.ts +0 -0
  27. /package/dist/server/src/{types → services/types}/index.d.ts +0 -0
  28. /package/dist/server/src/{types → services/types}/order.d.ts +0 -0
  29. /package/dist/server/src/{types → services/types}/payment.d.ts +0 -0
@@ -4,7 +4,7 @@ import { Modal, Typography, Box, Tabs, Flex, Button, Alert, Grid, Card, Badge, T
4
4
  import { useIntl } from "react-intl";
5
5
  import { useFetchClient } from "@strapi/strapi/admin";
6
6
  import { Duplicate, Code, Key, EyeStriked, Eye, Globe } from "@strapi/icons";
7
- import { P as PLUGIN_ID } from "./index-2Zd_T7bD.mjs";
7
+ import { P as PLUGIN_ID } from "./index-CB6TMitx.mjs";
8
8
  const IntegrationModal = ({ onClose, publishableKey }) => {
9
9
  const [copied, setCopied] = useState(null);
10
10
  const copyToClipboard = (text, type) => {
@@ -197,10 +197,13 @@ const Settings = () => {
197
197
  const [saving, setSaving] = useState(false);
198
198
  const [error, setError] = useState(null);
199
199
  const [success, setSuccess] = useState(null);
200
+ const [testStatus, setTestStatus] = useState("idle");
201
+ const [testMessage, setTestMessage] = useState("");
200
202
  const [hasChanges, setHasChanges] = useState(false);
201
203
  const [showIntegrationModal, setShowIntegrationModal] = useState(false);
202
204
  const [showSecretKey, setShowSecretKey] = useState(false);
203
205
  const [showWebhookSecret, setShowWebhookSecret] = useState(false);
206
+ const [showResetConfirm, setShowResetConfirm] = useState(false);
204
207
  useEffect(() => {
205
208
  fetchSettings();
206
209
  }, []);
@@ -209,51 +212,34 @@ const Settings = () => {
209
212
  setLoading(true);
210
213
  const { data } = await get(`/${PLUGIN_ID}/admin/config`);
211
214
  if (data.success && data.data) {
212
- const backendConfig = data.data;
213
- const initialSettings = {
215
+ const bc = data.data;
216
+ setSettings({
214
217
  stripe: {
215
- publishableKey: backendConfig.stripe?.publishableKey || "",
216
- secretKey: backendConfig.stripe?.secretKey || "",
217
- webhookSecret: backendConfig.stripe?.webhookSecret || "",
218
- apiVersion: backendConfig.stripe?.apiVersion || "2023-10-16",
219
- enabled: backendConfig.stripe?.enabled ?? true
218
+ publishableKey: bc.stripe?.publishableKey || "",
219
+ secretKey: bc.stripe?.secretKey || "",
220
+ webhookSecret: bc.stripe?.webhookSecret || "",
221
+ apiVersion: bc.stripe?.apiVersion || "2024-06-20",
222
+ enabled: bc.stripe?.enabled ?? true
220
223
  },
221
224
  payments: {
222
- defaultCurrency: backendConfig.payment?.defaultCurrency || "usd",
223
- supportedCurrencies: backendConfig.payment?.supportedCurrencies || ["usd"],
224
- enableRefunds: backendConfig.payment?.enableRefunds ?? true,
225
- enablePartialRefunds: backendConfig.payment?.enablePartialRefunds ?? true,
226
- refundWindow: backendConfig.payment?.refundWindow || 30,
227
- captureMethod: backendConfig.payment?.captureMethod || "automatic",
228
- confirmationMethod: backendConfig.payment?.confirmationMethod || "automatic"
229
- },
230
- webhooks: {
231
- enabled: true,
232
- endpoints: {
233
- paymentSucceeded: "",
234
- paymentFailed: "",
235
- refundCreated: "",
236
- invoiceCreated: ""
237
- },
238
- retries: 3,
239
- timeout: 30
225
+ defaultCurrency: bc.payment?.defaultCurrency || "usd",
226
+ enableRefunds: bc.payment?.enableRefunds ?? true,
227
+ enablePartialRefunds: bc.payment?.enablePartialRefunds ?? true,
228
+ refundWindow: bc.payment?.refundWindow || 30,
229
+ captureMethod: bc.payment?.captureMethod || "automatic"
240
230
  },
241
231
  ui: {
242
232
  showPaymentStatus: true,
243
233
  showCustomerInfo: true,
244
234
  enableNotifications: true,
245
- theme: "auto",
246
235
  compactView: false
247
236
  },
248
237
  security: {
249
- enableIpFiltering: false,
250
- allowedIps: [],
251
238
  requireAuthentication: true,
252
239
  enableAuditLog: true,
253
240
  sessionTimeout: 60
254
241
  }
255
- };
256
- setSettings(initialSettings);
242
+ });
257
243
  }
258
244
  setLoading(false);
259
245
  } catch (err) {
@@ -265,10 +251,7 @@ const Settings = () => {
265
251
  if (!settings) return;
266
252
  setSettings((prev) => ({
267
253
  ...prev,
268
- [section]: {
269
- ...prev[section],
270
- [key]: value
271
- }
254
+ [section]: { ...prev[section], [key]: value }
272
255
  }));
273
256
  setHasChanges(true);
274
257
  setSuccess(null);
@@ -278,14 +261,11 @@ const Settings = () => {
278
261
  setSaving(true);
279
262
  setError(null);
280
263
  if (!settings) return;
281
- const payload = {
264
+ await put(`/${PLUGIN_ID}/admin/config`, {
282
265
  stripe: settings.stripe,
283
266
  payment: settings.payments,
284
- logging: {
285
- enableWebhookLogging: true
286
- }
287
- };
288
- await put(`/${PLUGIN_ID}/admin/config`, payload);
267
+ logging: { enableWebhookLogging: true }
268
+ });
289
269
  setHasChanges(false);
290
270
  setSuccess("Settings saved successfully");
291
271
  setTimeout(() => setSuccess(null), 3e3);
@@ -295,32 +275,41 @@ const Settings = () => {
295
275
  setSaving(false);
296
276
  }
297
277
  };
298
- const resetSettings = () => {
299
- if (confirm("Are you sure you want to reset all settings to default? This action cannot be undone.")) {
300
- fetchSettings();
301
- setHasChanges(false);
302
- }
303
- };
304
278
  const testConnection = async () => {
305
279
  try {
306
280
  setSaving(true);
281
+ setTestStatus("idle");
307
282
  const { data } = await get(`/${PLUGIN_ID}/admin/config`);
308
283
  if (data.success) {
309
- alert("Connection to backend successful!");
284
+ setTestStatus("success");
285
+ setTestMessage("Connection to backend successful!");
310
286
  } else {
311
287
  throw new Error("Failed to connect");
312
288
  }
313
289
  } catch (err) {
314
- alert("Connection test failed. Please check your API keys and server logs.");
290
+ setTestStatus("error");
291
+ setTestMessage("Connection test failed. Check your API keys and server logs.");
315
292
  } finally {
316
293
  setSaving(false);
294
+ setTimeout(() => setTestStatus("idle"), 4e3);
317
295
  }
318
296
  };
297
+ const copyToClipboard = (text) => {
298
+ navigator.clipboard.writeText(text);
299
+ };
319
300
  if (loading) {
320
301
  return /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", alignItems: "center", style: { minHeight: "400px" }, children: /* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({ id: "payment-plugin.settings.loading", defaultMessage: "Loading settings..." }) }) }) });
321
302
  }
322
303
  if (!settings) {
323
- return /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(Alert, { variant: "danger", children: formatMessage({ id: "payment-plugin.settings.error", defaultMessage: "Failed to load settings" }) }) });
304
+ return /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(
305
+ Alert,
306
+ {
307
+ variant: "danger",
308
+ closeLabel: formatMessage({ id: "payment-plugin.alert.close", defaultMessage: "Close alert" }),
309
+ onClose: () => setError(null),
310
+ children: formatMessage({ id: "payment-plugin.settings.error", defaultMessage: "Failed to load settings" })
311
+ }
312
+ ) });
324
313
  }
325
314
  return /* @__PURE__ */ jsxs(Box, { children: [
326
315
  /* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
@@ -331,45 +320,46 @@ const Settings = () => {
331
320
  defaultMessage: "Configure your payment plugin settings"
332
321
  }) })
333
322
  ] }),
334
- /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
335
- hasChanges && /* @__PURE__ */ jsx(Box, { marginRight: 2, children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "warning600", children: "Unsaved changes" }) }),
336
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: resetSettings, children: formatMessage({ id: "payment-plugin.settings.reset", defaultMessage: "Reset" }) }),
337
- /* @__PURE__ */ jsx(
338
- Button,
339
- {
340
- variant: "secondary",
341
- onClick: testConnection,
342
- disabled: saving,
343
- children: formatMessage({ id: "payment-plugin.settings.testConnection", defaultMessage: "Test Connection" })
344
- }
345
- ),
346
- /* @__PURE__ */ jsx(
347
- Button,
348
- {
349
- onClick: saveSettings,
350
- disabled: !hasChanges || saving,
351
- loading: saving,
352
- children: formatMessage({ id: "payment-plugin.settings.save", defaultMessage: "Save Settings" })
353
- }
354
- ),
355
- /* @__PURE__ */ jsx(
356
- Button,
357
- {
358
- variant: "tertiary",
359
- startIcon: /* @__PURE__ */ jsx(Code, {}),
360
- onClick: () => setShowIntegrationModal(true),
361
- children: formatMessage({ id: "payment-plugin.settings.integration", defaultMessage: "Integration Guide" })
362
- }
363
- )
323
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
324
+ hasChanges && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "warning600", children: "Unsaved changes" }),
325
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setShowResetConfirm(true), children: formatMessage({ id: "payment-plugin.settings.reset", defaultMessage: "Reset" }) }),
326
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: testConnection, disabled: saving, children: formatMessage({ id: "payment-plugin.settings.testConnection", defaultMessage: "Test Connection" }) }),
327
+ /* @__PURE__ */ jsx(Button, { onClick: saveSettings, disabled: !hasChanges || saving, loading: saving, children: formatMessage({ id: "payment-plugin.settings.save", defaultMessage: "Save Settings" }) }),
328
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", startIcon: /* @__PURE__ */ jsx(Code, {}), onClick: () => setShowIntegrationModal(true), children: formatMessage({ id: "payment-plugin.settings.integration", defaultMessage: "Integration Guide" }) })
364
329
  ] })
365
330
  ] }) }),
366
- error && /* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsx(Alert, { variant: "danger", onClose: () => setError(null), children: error }) }),
367
- success && /* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsx(Alert, { variant: "success", onClose: () => setSuccess(null), children: success }) }),
331
+ error && /* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsx(
332
+ Alert,
333
+ {
334
+ variant: "danger",
335
+ closeLabel: formatMessage({ id: "payment-plugin.alert.close", defaultMessage: "Close alert" }),
336
+ onClose: () => setError(null),
337
+ children: error
338
+ }
339
+ ) }),
340
+ success && /* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsx(
341
+ Alert,
342
+ {
343
+ variant: "success",
344
+ closeLabel: formatMessage({ id: "payment-plugin.alert.close", defaultMessage: "Close alert" }),
345
+ onClose: () => setSuccess(null),
346
+ children: success
347
+ }
348
+ ) }),
349
+ testStatus !== "idle" && /* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsx(
350
+ Alert,
351
+ {
352
+ variant: testStatus === "success" ? "success" : "danger",
353
+ closeLabel: formatMessage({ id: "payment-plugin.alert.close", defaultMessage: "Close alert" }),
354
+ onClose: () => setTestStatus("idle"),
355
+ children: testMessage
356
+ }
357
+ ) }),
368
358
  /* @__PURE__ */ jsxs(Grid.Root, { gap: 6, children: [
369
359
  /* @__PURE__ */ jsx(Grid.Item, { col: 12, children: /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Box, { padding: 5, children: [
370
360
  /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, children: [
371
361
  /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
372
- /* @__PURE__ */ jsx(Box, { color: "primary600", children: /* @__PURE__ */ jsx(Key, { width: "1.5rem", height: "1.5rem" }) }),
362
+ /* @__PURE__ */ jsx(Key, { width: "1.5rem", height: "1.5rem" }),
373
363
  /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: formatMessage({ id: "payment-plugin.settings.stripe", defaultMessage: "Stripe API Configuration" }) })
374
364
  ] }),
375
365
  /* @__PURE__ */ jsx(Badge, { variant: settings.stripe.enabled ? "success" : "neutral", children: settings.stripe.enabled ? "Stripe Active" : "Stripe Disabled" })
@@ -386,10 +376,8 @@ const Settings = () => {
386
376
  Button,
387
377
  {
388
378
  variant: "ghost",
389
- onClick: () => {
390
- navigator.clipboard.writeText(settings.stripe.publishableKey);
391
- alert("Copied to clipboard");
392
- },
379
+ onClick: () => copyToClipboard(settings.stripe.publishableKey),
380
+ "aria-label": "Copy publishable key",
393
381
  children: /* @__PURE__ */ jsx(Duplicate, { width: "1rem", height: "1rem" })
394
382
  }
395
383
  )
@@ -409,6 +397,7 @@ const Settings = () => {
409
397
  {
410
398
  variant: "ghost",
411
399
  onClick: () => setShowSecretKey(!showSecretKey),
400
+ "aria-label": showSecretKey ? "Hide secret key" : "Show secret key",
412
401
  children: showSecretKey ? /* @__PURE__ */ jsx(EyeStriked, { width: "1rem", height: "1rem" }) : /* @__PURE__ */ jsx(Eye, { width: "1rem", height: "1rem" })
413
402
  }
414
403
  ),
@@ -416,10 +405,8 @@ const Settings = () => {
416
405
  Button,
417
406
  {
418
407
  variant: "ghost",
419
- onClick: () => {
420
- navigator.clipboard.writeText(settings.stripe.secretKey);
421
- alert("Copied to clipboard");
422
- },
408
+ onClick: () => copyToClipboard(settings.stripe.secretKey),
409
+ "aria-label": "Copy secret key",
423
410
  children: /* @__PURE__ */ jsx(Duplicate, { width: "1rem", height: "1rem" })
424
411
  }
425
412
  )
@@ -440,6 +427,7 @@ const Settings = () => {
440
427
  {
441
428
  variant: "ghost",
442
429
  onClick: () => setShowWebhookSecret(!showWebhookSecret),
430
+ "aria-label": showWebhookSecret ? "Hide webhook secret" : "Show webhook secret",
443
431
  children: showWebhookSecret ? /* @__PURE__ */ jsx(EyeStriked, { width: "1rem", height: "1rem" }) : /* @__PURE__ */ jsx(Eye, { width: "1rem", height: "1rem" })
444
432
  }
445
433
  ),
@@ -447,10 +435,8 @@ const Settings = () => {
447
435
  Button,
448
436
  {
449
437
  variant: "ghost",
450
- onClick: () => {
451
- navigator.clipboard.writeText(settings.stripe.webhookSecret);
452
- alert("Copied to clipboard");
453
- },
438
+ onClick: () => copyToClipboard(settings.stripe.webhookSecret),
439
+ "aria-label": "Copy webhook secret",
454
440
  children: /* @__PURE__ */ jsx(Duplicate, { width: "1rem", height: "1rem" })
455
441
  }
456
442
  )
@@ -474,13 +460,13 @@ const Settings = () => {
474
460
  /* @__PURE__ */ jsx(
475
461
  Switch,
476
462
  {
477
- label: formatMessage({ id: "payment-plugin.settings.enabled", defaultMessage: "Enable Stripe Payments" }),
478
- selected: settings.stripe.enabled,
479
- onChange: () => handleSettingChange("stripe", "enabled", !settings.stripe.enabled)
463
+ checked: settings.stripe.enabled,
464
+ onCheckedChange: (checked) => handleSettingChange("stripe", "enabled", checked),
465
+ "aria-label": formatMessage({ id: "payment-plugin.settings.enabled", defaultMessage: "Enable Stripe Payments" })
480
466
  }
481
467
  ),
482
468
  /* @__PURE__ */ jsxs(Box, { children: [
483
- /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({ id: "payment-plugin.settings.enabled", defaultMessage: "Payment Gateway Status" }) }),
469
+ /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({ id: "payment-plugin.settings.gatewayStatus", defaultMessage: "Payment Gateway Status" }) }),
484
470
  /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: settings.stripe.enabled ? "Your plugin is currently accepting payments through Stripe." : "Stripe payments are disabled. Customers will not be able to checkout." })
485
471
  ] })
486
472
  ] }) }) })
@@ -537,9 +523,9 @@ const Settings = () => {
537
523
  /* @__PURE__ */ jsx(
538
524
  Switch,
539
525
  {
540
- label: formatMessage({ id: "payment-plugin.settings.requireAuth", defaultMessage: "Require Authentication" }),
541
- selected: settings.security.requireAuthentication,
542
- onChange: () => handleSettingChange("security", "requireAuthentication", !settings.security.requireAuthentication)
526
+ checked: settings.security.requireAuthentication,
527
+ onCheckedChange: (checked) => handleSettingChange("security", "requireAuthentication", checked),
528
+ "aria-label": formatMessage({ id: "payment-plugin.settings.requireAuth", defaultMessage: "Require Authentication" })
543
529
  }
544
530
  ),
545
531
  /* @__PURE__ */ jsxs(Box, { children: [
@@ -551,9 +537,9 @@ const Settings = () => {
551
537
  /* @__PURE__ */ jsx(
552
538
  Switch,
553
539
  {
554
- label: formatMessage({ id: "payment-plugin.settings.auditLog", defaultMessage: "Enable Audit Log" }),
555
- selected: settings.security.enableAuditLog,
556
- onChange: () => handleSettingChange("security", "enableAuditLog", !settings.security.enableAuditLog)
540
+ checked: settings.security.enableAuditLog,
541
+ onCheckedChange: (checked) => handleSettingChange("security", "enableAuditLog", checked),
542
+ "aria-label": formatMessage({ id: "payment-plugin.settings.auditLog", defaultMessage: "Enable Audit Log" })
557
543
  }
558
544
  ),
559
545
  /* @__PURE__ */ jsxs(Box, { children: [
@@ -561,10 +547,13 @@ const Settings = () => {
561
547
  /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Detailed logs of all transaction attempts and configuration changes." })
562
548
  ] })
563
549
  ] }) }),
564
- /* @__PURE__ */ jsx(Grid.Item, { col: 12, marginTop: 2, children: /* @__PURE__ */ jsx(
550
+ /* @__PURE__ */ jsx(Grid.Item, { col: 12, children: /* @__PURE__ */ jsx(
565
551
  TextInput,
566
552
  {
567
- label: formatMessage({ id: "payment-plugin.settings.sessionTimeout", defaultMessage: "Checkout Session Timeout (Minutes)" }),
553
+ label: formatMessage({
554
+ id: "payment-plugin.settings.sessionTimeout",
555
+ defaultMessage: "Checkout Session Timeout (Minutes)"
556
+ }),
568
557
  type: "number",
569
558
  value: settings.security.sessionTimeout.toString(),
570
559
  onChange: (e) => handleSettingChange("security", "sessionTimeout", parseInt(e.target.value) || 60)
@@ -574,62 +563,69 @@ const Settings = () => {
574
563
  ] }) }) }),
575
564
  /* @__PURE__ */ jsx(Grid.Item, { col: 12, children: /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Box, { padding: 5, children: [
576
565
  /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", marginBottom: 4, children: formatMessage({ id: "payment-plugin.settings.ui", defaultMessage: "Admin Interface Customization" }) }),
577
- /* @__PURE__ */ jsxs(Grid.Root, { gap: 4, children: [
578
- /* @__PURE__ */ jsx(Grid.Item, { col: 3, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
579
- /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, children: [
580
- /* @__PURE__ */ jsx(
581
- Switch,
582
- {
583
- checked: settings.ui.showPaymentStatus,
584
- onChange: (checked) => handleSettingChange("ui", "showPaymentStatus", checked)
585
- }
586
- ),
587
- /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({ id: "payment-plugin.settings.showStatus", defaultMessage: "Payment Status" }) })
588
- ] }),
589
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Show status badges in lists" })
590
- ] }) }),
591
- /* @__PURE__ */ jsx(Grid.Item, { col: 3, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
592
- /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, children: [
593
- /* @__PURE__ */ jsx(
594
- Switch,
595
- {
596
- checked: settings.ui.showCustomerInfo,
597
- onChange: (checked) => handleSettingChange("ui", "showCustomerInfo", checked)
598
- }
599
- ),
600
- /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({ id: "payment-plugin.settings.showCustomerInfo", defaultMessage: "Customer Data" }) })
601
- ] }),
602
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Display sensitive customer info" })
603
- ] }) }),
604
- /* @__PURE__ */ jsx(Grid.Item, { col: 3, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
605
- /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, children: [
606
- /* @__PURE__ */ jsx(
607
- Switch,
608
- {
609
- checked: settings.ui.enableNotifications,
610
- onChange: (checked) => handleSettingChange("ui", "enableNotifications", checked)
611
- }
612
- ),
613
- /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({ id: "payment-plugin.settings.notifications", defaultMessage: "Notifications" }) })
614
- ] }),
615
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Browser alerts for success" })
616
- ] }) }),
617
- /* @__PURE__ */ jsx(Grid.Item, { col: 3, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
618
- /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, children: [
619
- /* @__PURE__ */ jsx(
620
- Switch,
621
- {
622
- checked: settings.ui.compactView,
623
- onChange: (checked) => handleSettingChange("ui", "compactView", checked)
624
- }
625
- ),
626
- /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: formatMessage({ id: "payment-plugin.settings.compactView", defaultMessage: "Compact Mode" }) })
627
- ] }),
628
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Dense layout for tables" })
629
- ] }) })
630
- ] })
566
+ /* @__PURE__ */ jsx(Grid.Root, { gap: 4, children: [
567
+ {
568
+ key: "showPaymentStatus",
569
+ label: formatMessage({ id: "payment-plugin.settings.showStatus", defaultMessage: "Payment Status" }),
570
+ hint: "Show status badges in lists",
571
+ value: settings.ui.showPaymentStatus
572
+ },
573
+ {
574
+ key: "showCustomerInfo",
575
+ label: formatMessage({ id: "payment-plugin.settings.showCustomerInfo", defaultMessage: "Customer Data" }),
576
+ hint: "Display sensitive customer info",
577
+ value: settings.ui.showCustomerInfo
578
+ },
579
+ {
580
+ key: "enableNotifications",
581
+ label: formatMessage({ id: "payment-plugin.settings.notifications", defaultMessage: "Notifications" }),
582
+ hint: "Browser alerts for success",
583
+ value: settings.ui.enableNotifications
584
+ },
585
+ {
586
+ key: "compactView",
587
+ label: formatMessage({ id: "payment-plugin.settings.compactView", defaultMessage: "Compact Mode" }),
588
+ hint: "Dense layout for tables",
589
+ value: settings.ui.compactView
590
+ }
591
+ ].map(({ key, label, hint, value }) => /* @__PURE__ */ jsx(Grid.Item, { col: 3, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
592
+ /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, children: [
593
+ /* @__PURE__ */ jsx(
594
+ Switch,
595
+ {
596
+ checked: value,
597
+ onCheckedChange: (checked) => handleSettingChange("ui", key, checked),
598
+ "aria-label": label
599
+ }
600
+ ),
601
+ /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: label })
602
+ ] }),
603
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: hint })
604
+ ] }) }, key)) })
631
605
  ] }) }) })
632
606
  ] }),
607
+ showResetConfirm && /* @__PURE__ */ jsx(Modal.Root, { open: true, onOpenChange: () => setShowResetConfirm(false), children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
608
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", as: "h2", children: formatMessage({ id: "payment-plugin.settings.resetConfirm.title", defaultMessage: "Reset Settings?" }) }) }),
609
+ /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx(Typography, { children: formatMessage({
610
+ id: "payment-plugin.settings.resetConfirm.body",
611
+ defaultMessage: "This will reload settings from the server and discard all unsaved changes."
612
+ }) }) }),
613
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
614
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", onClick: () => setShowResetConfirm(false), children: formatMessage({ id: "payment-plugin.settings.cancel", defaultMessage: "Cancel" }) }),
615
+ /* @__PURE__ */ jsx(
616
+ Button,
617
+ {
618
+ variant: "danger-light",
619
+ onClick: () => {
620
+ setShowResetConfirm(false);
621
+ fetchSettings();
622
+ setHasChanges(false);
623
+ },
624
+ children: formatMessage({ id: "payment-plugin.settings.resetConfirm", defaultMessage: "Reset" })
625
+ }
626
+ )
627
+ ] })
628
+ ] }) }),
633
629
  showIntegrationModal && /* @__PURE__ */ jsx(
634
630
  IntegrationModal,
635
631
  {
@@ -36,7 +36,7 @@ const index = {
36
36
  defaultMessage: "Payment Management"
37
37
  },
38
38
  Component: async () => {
39
- const { App } = await import("./App-DXN62SV6.mjs");
39
+ const { App } = await import("./App-B5AB8Omu.mjs");
40
40
  return App;
41
41
  }
42
42
  });
@@ -37,7 +37,7 @@ const index = {
37
37
  defaultMessage: "Payment Management"
38
38
  },
39
39
  Component: async () => {
40
- const { App } = await Promise.resolve().then(() => require("./App-Dk7XtjNA.js"));
40
+ const { App } = await Promise.resolve().then(() => require("./App-Cih9sWu1.js"));
41
41
  return App;
42
42
  }
43
43
  });
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-CHEgJ7e5.js");
2
+ const index = require("../_chunks/index-D-fFikb8.js");
3
3
  module.exports = index.index;
@@ -1,4 +1,4 @@
1
- import { i } from "../_chunks/index-2Zd_T7bD.mjs";
1
+ import { i } from "../_chunks/index-CB6TMitx.mjs";
2
2
  export {
3
3
  i as default
4
4
  };
@@ -411,36 +411,20 @@ const stripeController = {
411
411
  const body = ctx.request.body;
412
412
  const unparsedBody = body?.[Symbol.for("unparsedBody")] || body?.[Symbol.for("koa-body-unparsed-body")] || ctx.request.rawBody || ctx.rawBody;
413
413
  const rawBody = unparsedBody || ctx.request.body;
414
- const debugInfo = {
415
- hasUnparsedBody: !!unparsedBody,
416
- unparsedBodyType: typeof unparsedBody,
417
- isBodyBuffer: Buffer.isBuffer(ctx.request.body),
418
- keys: body ? Object.keys(body) : [],
419
- symbols: body ? Object.getOwnPropertySymbols(body).map((s) => s.toString()) : []
420
- };
421
- strapi.log.info("Webhook Debug:", debugInfo);
422
414
  if (!signature) {
423
415
  return ctx.badRequest("Missing Stripe signature");
424
416
  }
425
- if (signature === "t=123,v1=abc") {
426
- ctx.body = { debug: debugInfo };
427
- return;
428
- }
429
417
  const stripeService2 = strapi.plugin("payment-plugin").service("stripe");
430
418
  const event = await stripeService2.constructEvent(rawBody, signature);
431
419
  await stripeService2.handleWebhook(event);
432
420
  ctx.body = { received: true };
433
421
  } catch (error) {
434
- const body = ctx.request.body;
435
- const symbols = body ? Object.getOwnPropertySymbols(body).map((s) => s.toString()) : [];
436
- const keys = body ? Object.keys(body) : [];
437
- strapi.log.error("Failed to handle webhook", {
438
- error: error.message,
439
- stack: error.stack,
440
- bodyKeys: keys,
441
- bodySymbols: symbols
442
- });
443
- ctx.badRequest(`Webhook Error: ${error.message} | Keys: ${keys.join(",")} | Symbols: ${symbols.join(",")}`);
422
+ if (error.message.includes("No signatures found matching") || error.message.includes("Webhook payload must be provided as a string or a Buffer")) {
423
+ strapi.log.error('Stripe Webhook Error: Payload is not raw. Ensure "includeUnparsed: true" is set in config/middlewares.ts for "strapi::body".');
424
+ return ctx.badRequest("Webhook verification failed: Payload must be raw. Check your Strapi configuration for strapi::body middleware.");
425
+ }
426
+ strapi.log.error("Failed to handle webhook", { error: error.message, stack: error.stack });
427
+ ctx.badRequest(`Webhook Error: ${error.message}`);
444
428
  }
445
429
  },
446
430
  /**
@@ -1787,30 +1771,19 @@ const stripeService = ({ strapi: strapi2 }) => {
1787
1771
  const stripeConfig = config2.stripe || {};
1788
1772
  const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET || stripeConfig.webhookSecret || (process.env.STRIPE_SECRET_KEY?.startsWith("whsec_") ? process.env.STRIPE_SECRET_KEY : null);
1789
1773
  const logger = getLogger();
1790
- logger.info("Attempting to construct webhook event", {
1791
- hasPayload: !!payload,
1792
- payloadType: typeof payload,
1793
- isBuffer: Buffer.isBuffer(payload),
1794
- hasSignature: !!signature,
1795
- hasSecret: !!webhookSecret,
1796
- secretPrefix: webhookSecret ? webhookSecret.substring(0, 6) : "none"
1797
- });
1798
1774
  if (!webhookSecret) {
1799
1775
  throw new Error("Stripe webhook secret not configured. Please set STRIPE_WEBHOOK_SECRET environment variable.");
1800
1776
  }
1801
1777
  try {
1802
1778
  let verifiedPayload = payload;
1803
1779
  if (typeof payload === "object" && !Buffer.isBuffer(payload)) {
1804
- logger.warn("Webhook payload is an object, verification will likely fail. Expected raw body.");
1805
1780
  verifiedPayload = JSON.stringify(payload);
1806
1781
  }
1807
1782
  return stripe2.webhooks.constructEvent(verifiedPayload, signature, webhookSecret);
1808
1783
  } catch (error) {
1809
1784
  logger.error("Failed to construct webhook event", {
1810
1785
  message: error.message,
1811
- type: error.type,
1812
- // Don't log full stack to keep logs cleaner but enough info for debugging
1813
- shortStack: error.stack?.split("\n").slice(0, 3).join("\n")
1786
+ type: error.type
1814
1787
  });
1815
1788
  throw error;
1816
1789
  }