@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.
- package/README.md +21 -0
- package/dist/_chunks/{Analytics-CQmAVKsq.mjs → Analytics-CncK5kn-.mjs} +6 -7
- package/dist/_chunks/{Analytics-CLjtRWYA.js → Analytics-c8KBuG3k.js} +6 -7
- package/dist/_chunks/{App-DXN62SV6.mjs → App-B5AB8Omu.mjs} +7 -7
- package/dist/_chunks/{App-Dk7XtjNA.js → App-Cih9sWu1.js} +7 -7
- package/dist/_chunks/{Customers-BQzVBQDT.mjs → Customers-BVk2gx7w.mjs} +51 -118
- package/dist/_chunks/{Customers-BNDi4QBH.js → Customers-CZWOnN26.js} +50 -117
- package/dist/_chunks/{Dashboard-UUwohHZa.js → Dashboard-CEif4jQn.js} +60 -84
- package/dist/_chunks/{Dashboard-CuHC-dit.mjs → Dashboard-DAjD8Q_6.mjs} +60 -84
- package/dist/_chunks/{Orders-CitNCdWE.js → Orders-DZXb54VO.js} +73 -146
- package/dist/_chunks/{Orders-65mNfu2i.mjs → Orders-DdJqI1HB.mjs} +74 -147
- package/dist/_chunks/{PaymentList-B0CAzInT.mjs → PaymentList-3HWK7PMz.mjs} +14 -39
- package/dist/_chunks/{PaymentList-Dy1BAFoD.js → PaymentList-APfyYD1h.js} +14 -39
- package/dist/_chunks/{Payments-FnhoV_2B.mjs → Payments-DFL-Cwgy.mjs} +97 -103
- package/dist/_chunks/{Payments-TOnygGIW.js → Payments-VzDGbK4W.js} +96 -102
- package/dist/_chunks/{Settings-BJtDagUs.js → Settings-B1tR3WOm.js} +157 -161
- package/dist/_chunks/{Settings-EoLSuZLe.mjs → Settings-SALxClBu.mjs} +157 -161
- package/dist/_chunks/{index-2Zd_T7bD.mjs → index-CB6TMitx.mjs} +1 -1
- package/dist/_chunks/{index-CHEgJ7e5.js → index-D-fFikb8.js} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +17 -5
- package/dist/server/index.mjs +17 -5
- package/package.json +1 -1
- /package/dist/server/src/{types → services/types}/api.d.ts +0 -0
- /package/dist/server/src/{types → services/types}/customer.d.ts +0 -0
- /package/dist/server/src/{types → services/types}/index.d.ts +0 -0
- /package/dist/server/src/{types → services/types}/order.d.ts +0 -0
- /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-
|
|
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
|
|
213
|
-
|
|
215
|
+
const bc = data.data;
|
|
216
|
+
setSettings({
|
|
214
217
|
stripe: {
|
|
215
|
-
publishableKey:
|
|
216
|
-
secretKey:
|
|
217
|
-
webhookSecret:
|
|
218
|
-
apiVersion:
|
|
219
|
-
enabled:
|
|
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:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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
|
-
|
|
264
|
+
await put(`/${PLUGIN_ID}/admin/config`, {
|
|
282
265
|
stripe: settings.stripe,
|
|
283
266
|
payment: settings.payments,
|
|
284
|
-
logging: {
|
|
285
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
336
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick:
|
|
337
|
-
/* @__PURE__ */ jsx(
|
|
338
|
-
|
|
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(
|
|
367
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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.
|
|
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
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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
|
-
|
|
555
|
-
|
|
556
|
-
|
|
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,
|
|
550
|
+
/* @__PURE__ */ jsx(Grid.Item, { col: 12, children: /* @__PURE__ */ jsx(
|
|
565
551
|
TextInput,
|
|
566
552
|
{
|
|
567
|
-
label: formatMessage({
|
|
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__ */
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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
|
{
|
|
@@ -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-
|
|
40
|
+
const { App } = await Promise.resolve().then(() => require("./App-Cih9sWu1.js"));
|
|
41
41
|
return App;
|
|
42
42
|
}
|
|
43
43
|
});
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
1775
|
-
|
|
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
|
};
|
package/dist/server/index.mjs
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
1772
|
-
|
|
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
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|