@reeboot/strapi-payment-plugin 0.0.5 → 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 +17 -5
  23. package/dist/server/index.mjs +17 -5
  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
  };
@@ -408,7 +408,8 @@ const stripeController = {
408
408
  async handleWebhook(ctx) {
409
409
  try {
410
410
  const signature = ctx.request.headers["stripe-signature"];
411
- const unparsedBody = ctx.request.body?.[Symbol.for("unparsedBody")];
411
+ const body = ctx.request.body;
412
+ const unparsedBody = body?.[Symbol.for("unparsedBody")] || body?.[Symbol.for("koa-body-unparsed-body")] || ctx.request.rawBody || ctx.rawBody;
412
413
  const rawBody = unparsedBody || ctx.request.body;
413
414
  if (!signature) {
414
415
  return ctx.badRequest("Missing Stripe signature");
@@ -418,6 +419,10 @@ const stripeController = {
418
419
  await stripeService2.handleWebhook(event);
419
420
  ctx.body = { received: true };
420
421
  } catch (error) {
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
+ }
421
426
  strapi.log.error("Failed to handle webhook", { error: error.message, stack: error.stack });
422
427
  ctx.badRequest(`Webhook Error: ${error.message}`);
423
428
  }
@@ -1764,15 +1769,22 @@ const stripeService = ({ strapi: strapi2 }) => {
1764
1769
  const stripe2 = await initializeStripe();
1765
1770
  const config2 = await getCombinedConfig();
1766
1771
  const stripeConfig = config2.stripe || {};
1767
- const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET || stripeConfig.webhookSecret;
1772
+ const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET || stripeConfig.webhookSecret || (process.env.STRIPE_SECRET_KEY?.startsWith("whsec_") ? process.env.STRIPE_SECRET_KEY : null);
1773
+ const logger = getLogger();
1768
1774
  if (!webhookSecret) {
1769
1775
  throw new Error("Stripe webhook secret not configured. Please set STRIPE_WEBHOOK_SECRET environment variable.");
1770
1776
  }
1771
1777
  try {
1772
- return stripe2.webhooks.constructEvent(payload, signature, webhookSecret);
1778
+ let verifiedPayload = payload;
1779
+ if (typeof payload === "object" && !Buffer.isBuffer(payload)) {
1780
+ verifiedPayload = JSON.stringify(payload);
1781
+ }
1782
+ return stripe2.webhooks.constructEvent(verifiedPayload, signature, webhookSecret);
1773
1783
  } catch (error) {
1774
- const logger = getLogger();
1775
- logger.error("Failed to construct webhook event", { error });
1784
+ logger.error("Failed to construct webhook event", {
1785
+ message: error.message,
1786
+ type: error.type
1787
+ });
1776
1788
  throw error;
1777
1789
  }
1778
1790
  };
@@ -405,7 +405,8 @@ const stripeController = {
405
405
  async handleWebhook(ctx) {
406
406
  try {
407
407
  const signature = ctx.request.headers["stripe-signature"];
408
- const unparsedBody = ctx.request.body?.[Symbol.for("unparsedBody")];
408
+ const body = ctx.request.body;
409
+ const unparsedBody = body?.[Symbol.for("unparsedBody")] || body?.[Symbol.for("koa-body-unparsed-body")] || ctx.request.rawBody || ctx.rawBody;
409
410
  const rawBody = unparsedBody || ctx.request.body;
410
411
  if (!signature) {
411
412
  return ctx.badRequest("Missing Stripe signature");
@@ -415,6 +416,10 @@ const stripeController = {
415
416
  await stripeService2.handleWebhook(event);
416
417
  ctx.body = { received: true };
417
418
  } catch (error) {
419
+ if (error.message.includes("No signatures found matching") || error.message.includes("Webhook payload must be provided as a string or a Buffer")) {
420
+ strapi.log.error('Stripe Webhook Error: Payload is not raw. Ensure "includeUnparsed: true" is set in config/middlewares.ts for "strapi::body".');
421
+ return ctx.badRequest("Webhook verification failed: Payload must be raw. Check your Strapi configuration for strapi::body middleware.");
422
+ }
418
423
  strapi.log.error("Failed to handle webhook", { error: error.message, stack: error.stack });
419
424
  ctx.badRequest(`Webhook Error: ${error.message}`);
420
425
  }
@@ -1761,15 +1766,22 @@ const stripeService = ({ strapi: strapi2 }) => {
1761
1766
  const stripe2 = await initializeStripe();
1762
1767
  const config2 = await getCombinedConfig();
1763
1768
  const stripeConfig = config2.stripe || {};
1764
- const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET || stripeConfig.webhookSecret;
1769
+ const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET || stripeConfig.webhookSecret || (process.env.STRIPE_SECRET_KEY?.startsWith("whsec_") ? process.env.STRIPE_SECRET_KEY : null);
1770
+ const logger = getLogger();
1765
1771
  if (!webhookSecret) {
1766
1772
  throw new Error("Stripe webhook secret not configured. Please set STRIPE_WEBHOOK_SECRET environment variable.");
1767
1773
  }
1768
1774
  try {
1769
- return stripe2.webhooks.constructEvent(payload, signature, webhookSecret);
1775
+ let verifiedPayload = payload;
1776
+ if (typeof payload === "object" && !Buffer.isBuffer(payload)) {
1777
+ verifiedPayload = JSON.stringify(payload);
1778
+ }
1779
+ return stripe2.webhooks.constructEvent(verifiedPayload, signature, webhookSecret);
1770
1780
  } catch (error) {
1771
- const logger = getLogger();
1772
- logger.error("Failed to construct webhook event", { error });
1781
+ logger.error("Failed to construct webhook event", {
1782
+ message: error.message,
1783
+ type: error.type
1784
+ });
1773
1785
  throw error;
1774
1786
  }
1775
1787
  };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.5",
2
+ "version": "0.0.7",
3
3
  "keywords": [],
4
4
  "type": "commonjs",
5
5
  "exports": {