strapi-plugin-payone-provider 1.6.7 → 5.6.9
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 +24 -11
- package/admin/src/components/Initializer/index.jsx +3 -3
- package/admin/src/components/PluginIcon/index.jsx +3 -3
- package/admin/src/index.js +33 -11
- package/admin/src/pages/App/components/AppHeader.jsx +17 -32
- package/admin/src/pages/App/components/AppTabs.jsx +36 -156
- package/admin/src/pages/App/components/ApplePayBtn.jsx +9 -11
- package/admin/src/pages/App/components/ApplePayConfig.jsx +221 -161
- package/admin/src/pages/App/components/ApplePayConfigPanel.jsx +33 -45
- package/admin/src/pages/App/components/DocsPanel.jsx +66 -1726
- package/admin/src/pages/App/components/GooglePayConfig.jsx +136 -169
- package/admin/src/pages/App/components/GooglePayConfigPanel.jsx +37 -55
- package/admin/src/pages/App/components/GooglePaybutton.jsx +101 -43
- package/admin/src/pages/App/components/RenderInput.jsx +94 -0
- package/admin/src/pages/App/components/StatusBadge.jsx +27 -16
- package/admin/src/pages/App/components/configuration/ConfigurationFields.jsx +255 -0
- package/admin/src/pages/App/components/configuration/ConfigurationPanel.jsx +54 -0
- package/admin/src/pages/App/components/configuration/TestConnection.jsx +130 -0
- package/admin/src/pages/App/components/docs/ApplePaySection.jsx +260 -0
- package/admin/src/pages/App/components/docs/BaseUrlSection.jsx +53 -0
- package/admin/src/pages/App/components/docs/CaptureRefundSection.jsx +113 -0
- package/admin/src/pages/App/components/docs/CodeBlock.jsx +59 -0
- package/admin/src/pages/App/components/docs/CreditCardSection.jsx +93 -0
- package/admin/src/pages/App/components/docs/GooglePaySection.jsx +248 -0
- package/admin/src/pages/App/components/docs/PayPalSection.jsx +116 -0
- package/admin/src/pages/App/components/docs/PaymentMethodsSection.jsx +55 -0
- package/admin/src/pages/App/components/docs/TableOfContents.jsx +47 -0
- package/admin/src/pages/App/components/docs/TestCredentialsSection.jsx +304 -0
- package/admin/src/pages/App/components/docs/ThreeDSecureSection.jsx +188 -0
- package/admin/src/pages/App/components/icons/BankIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/ChevronDownIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/ChevronUpIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/CreditCardIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/ErrorIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/InfoIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/MarkCircle.jsx +19 -0
- package/admin/src/pages/App/components/icons/PaymentIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/PendingIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/PersonIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/SuccessIcon.jsx +1 -1
- package/admin/src/pages/App/components/icons/WalletIcon.jsx +1 -1
- package/admin/src/pages/App/components/payment-actions/ApplePayPanel.jsx +51 -0
- package/admin/src/pages/App/components/payment-actions/AuthorizationForm.jsx +341 -0
- package/admin/src/pages/App/components/payment-actions/CaptureForm.jsx +128 -0
- package/admin/src/pages/App/components/{paymentActions → payment-actions}/CardDetailsInput.jsx +77 -72
- package/admin/src/pages/App/components/payment-actions/PaymentActionsPanel.jsx +194 -0
- package/admin/src/pages/App/components/payment-actions/PaymentMethodSelector.jsx +313 -0
- package/admin/src/pages/App/components/payment-actions/PaymentResult.jsx +133 -0
- package/admin/src/pages/App/components/payment-actions/PreauthorizationForm.jsx +280 -0
- package/admin/src/pages/App/components/payment-actions/RefundForm.jsx +121 -0
- package/admin/src/pages/App/components/transaction-history/FiltersPanel.jsx +145 -0
- package/admin/src/pages/App/components/transaction-history/HistoryPanel.jsx +50 -0
- package/admin/src/pages/App/components/transaction-history/TransactionTable.jsx +163 -0
- package/admin/src/pages/App/components/transaction-history/details/TransactionDetails.jsx +156 -0
- package/admin/src/pages/App/components/{TransactionHistoryItem.jsx → transaction-history/details/TransactionHistoryItem.jsx} +16 -28
- package/admin/src/pages/App/index.jsx +27 -67
- package/admin/src/pages/App/styles.css +46 -169
- package/admin/src/pages/constants/paymentConstants.js +52 -16
- package/admin/src/pages/hooks/use-system-theme.js +27 -0
- package/admin/src/pages/hooks/usePaymentActions.js +273 -210
- package/admin/src/pages/hooks/useSettings.js +87 -48
- package/admin/src/pages/hooks/useTransactionHistory.js +109 -47
- package/admin/src/pages/utils/api.js +57 -72
- package/admin/src/pages/utils/applePayConstants.js +2 -28
- package/admin/src/pages/utils/countryLanguageUtils.js +280 -0
- package/admin/src/pages/utils/getInputComponent.jsx +225 -0
- package/admin/src/pages/utils/googlePayConstants.js +2 -9
- package/admin/src/pages/utils/paymentUtils.js +13 -25
- package/admin/src/pages/utils/tooltipHelpers.js +18 -0
- package/admin/src/pages/utils/transactionTableUtils.js +60 -0
- package/package.json +7 -12
- package/server/config/index.js +18 -2
- package/server/controllers/payone.js +80 -31
- package/server/policies/is-auth.js +9 -3
- package/server/policies/isSuperAdmin.js +7 -5
- package/server/services/paymentService.js +6 -22
- package/server/services/payone.js +3 -3
- package/server/services/settingsService.js +13 -3
- package/server/services/testConnectionService.js +11 -73
- package/server/services/transactionService.js +61 -32
- package/server/utils/normalize.js +0 -12
- package/server/utils/paymentMethodParams.js +0 -1
- package/server/utils/responseParser.js +9 -14
- package/strapi-admin.js +3 -1
- package/admin/src/pages/App/components/ConfigurationPanel.jsx +0 -517
- package/admin/src/pages/App/components/HistoryPanel.jsx +0 -312
- package/admin/src/pages/App/components/PaymentActionsPanel.jsx +0 -280
- package/admin/src/pages/App/components/paymentActions/ApplePayPanel.jsx +0 -95
- package/admin/src/pages/App/components/paymentActions/AuthorizationForm.jsx +0 -197
- package/admin/src/pages/App/components/paymentActions/CaptureForm.jsx +0 -65
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.jsx +0 -306
- package/admin/src/pages/App/components/paymentActions/PaymentResult.jsx +0 -192
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.jsx +0 -142
- package/admin/src/pages/App/components/paymentActions/RefundForm.jsx +0 -90
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Box, Flex, Typography } from "@strapi/design-system";
|
|
3
|
+
import ConfigurationFields from "./ConfigurationFields";
|
|
4
|
+
import TestConnection from "./TestConnection";
|
|
5
|
+
|
|
6
|
+
const ConfigurationPanel = ({ settings }) => {
|
|
7
|
+
return (
|
|
8
|
+
<Flex direction="column" alignItems="stretch" gap={8} paddingTop={8}>
|
|
9
|
+
<Box>
|
|
10
|
+
<Typography
|
|
11
|
+
variant="beta"
|
|
12
|
+
as="h2"
|
|
13
|
+
fontWeight="bold"
|
|
14
|
+
className="payment-title"
|
|
15
|
+
style={{ fontSize: "20px", marginBottom: "4px" }}
|
|
16
|
+
>
|
|
17
|
+
Payone API Configuration
|
|
18
|
+
</Typography>
|
|
19
|
+
<Typography
|
|
20
|
+
variant="pi"
|
|
21
|
+
textColor="neutral600"
|
|
22
|
+
marginTop={2}
|
|
23
|
+
className="payment-subtitle"
|
|
24
|
+
style={{ fontSize: "14px" }}
|
|
25
|
+
>
|
|
26
|
+
Configure your Payone payment gateway settings
|
|
27
|
+
</Typography>
|
|
28
|
+
</Box>
|
|
29
|
+
|
|
30
|
+
<ConfigurationFields
|
|
31
|
+
settings={settings.settings}
|
|
32
|
+
onInputChange={settings.handleInputChange}
|
|
33
|
+
onPaymentMethodToggle={settings.handlePaymentMethodToggle}
|
|
34
|
+
onNavigateToConfig={settings.onNavigateToConfig}
|
|
35
|
+
/>
|
|
36
|
+
|
|
37
|
+
<TestConnection
|
|
38
|
+
settings={settings.settings}
|
|
39
|
+
isTesting={settings.isTesting}
|
|
40
|
+
testResult={settings.testResult}
|
|
41
|
+
onTestConnection={settings.handleTestConnection}
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
<Box paddingTop={4}>
|
|
45
|
+
<Typography variant="sigma" textColor="neutral600">
|
|
46
|
+
Note: These settings are used for all Payone API requests. Make sure
|
|
47
|
+
to use the correct credentials for your selected mode.
|
|
48
|
+
</Typography>
|
|
49
|
+
</Box>
|
|
50
|
+
</Flex>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default ConfigurationPanel;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Button,
|
|
5
|
+
Card,
|
|
6
|
+
CardBody,
|
|
7
|
+
Flex,
|
|
8
|
+
Typography,
|
|
9
|
+
Alert,
|
|
10
|
+
} from "@strapi/design-system";
|
|
11
|
+
import { Play } from "@strapi/icons";
|
|
12
|
+
|
|
13
|
+
const TestConnection = ({
|
|
14
|
+
settings,
|
|
15
|
+
isTesting,
|
|
16
|
+
testResult,
|
|
17
|
+
onTestConnection,
|
|
18
|
+
}) => {
|
|
19
|
+
const mode = (settings?.mode || "test").toLowerCase();
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Card padding={8}>
|
|
23
|
+
<CardBody>
|
|
24
|
+
<Flex direction="column" alignItems="stretch" gap={6} paddingTop={6}>
|
|
25
|
+
<Box>
|
|
26
|
+
<Typography
|
|
27
|
+
variant="delta"
|
|
28
|
+
as="h3"
|
|
29
|
+
fontWeight="bold"
|
|
30
|
+
style={{ marginBottom: "16px" }}
|
|
31
|
+
>
|
|
32
|
+
Test Connection
|
|
33
|
+
</Typography>
|
|
34
|
+
|
|
35
|
+
{mode === "test" ? (
|
|
36
|
+
<Typography variant="pi" textColor="neutral600">
|
|
37
|
+
Verify your Payone configuration by testing the API connection
|
|
38
|
+
</Typography>
|
|
39
|
+
) : (
|
|
40
|
+
<Typography
|
|
41
|
+
variant="pi"
|
|
42
|
+
textColor="neutral600"
|
|
43
|
+
style={{ marginTop: "8px" }}
|
|
44
|
+
>
|
|
45
|
+
Test Connection is disabled in live mode.
|
|
46
|
+
</Typography>
|
|
47
|
+
)}
|
|
48
|
+
</Box>
|
|
49
|
+
|
|
50
|
+
<Button
|
|
51
|
+
variant="default"
|
|
52
|
+
onClick={onTestConnection}
|
|
53
|
+
loading={isTesting}
|
|
54
|
+
startIcon={<Play />}
|
|
55
|
+
className="payment-button payment-button-success"
|
|
56
|
+
disabled={mode === "live"}
|
|
57
|
+
style={{ maxWidth: "200px" }}
|
|
58
|
+
>
|
|
59
|
+
{isTesting ? "Testing Connection..." : "Test Connection"}
|
|
60
|
+
</Button>
|
|
61
|
+
|
|
62
|
+
{testResult && (
|
|
63
|
+
<Flex direction={"column"} alignItems={"stretch"} gap={2}>
|
|
64
|
+
<Typography
|
|
65
|
+
variant="pi"
|
|
66
|
+
fontWeight="medium"
|
|
67
|
+
style={{ marginBottom: "16px" }}
|
|
68
|
+
>
|
|
69
|
+
{testResult.message}
|
|
70
|
+
</Typography>
|
|
71
|
+
{testResult.details && Boolean(testResult.success) ? (
|
|
72
|
+
<Box paddingTop={3}>
|
|
73
|
+
<Card>
|
|
74
|
+
<CardBody padding={4}>
|
|
75
|
+
<Flex direction="column" alignItems="stretch" gap={2}>
|
|
76
|
+
{testResult.details.mode && (
|
|
77
|
+
<Typography variant="pi" textColor="neutral600">
|
|
78
|
+
<strong>Mode:</strong> {testResult.details.mode}
|
|
79
|
+
</Typography>
|
|
80
|
+
)}
|
|
81
|
+
{testResult.details.aid && (
|
|
82
|
+
<Typography variant="pi" textColor="neutral600">
|
|
83
|
+
<strong>AID:</strong> {testResult.details.aid}
|
|
84
|
+
</Typography>
|
|
85
|
+
)}
|
|
86
|
+
{testResult.details.portalid && (
|
|
87
|
+
<Typography variant="pi" textColor="neutral600">
|
|
88
|
+
<strong>Portal ID:</strong>{" "}
|
|
89
|
+
{testResult.details.portalid}
|
|
90
|
+
</Typography>
|
|
91
|
+
)}
|
|
92
|
+
</Flex>
|
|
93
|
+
</CardBody>
|
|
94
|
+
</Card>
|
|
95
|
+
</Box>
|
|
96
|
+
) : (
|
|
97
|
+
<Card>
|
|
98
|
+
<CardBody padding={4}>
|
|
99
|
+
<Flex direction="column" alignItems="stretch" gap={2}>
|
|
100
|
+
{testResult.error && (
|
|
101
|
+
<Typography variant="pi" textColor="neutral600">
|
|
102
|
+
<strong>Error Code:</strong>{" "}
|
|
103
|
+
{testResult.error.ErrorCode}
|
|
104
|
+
</Typography>
|
|
105
|
+
)}
|
|
106
|
+
{testResult.error.ErrorMessage && (
|
|
107
|
+
<Typography variant="pi" textColor="neutral600">
|
|
108
|
+
<strong>Error Message:</strong>{" "}
|
|
109
|
+
{testResult.error.ErrorMessage}
|
|
110
|
+
</Typography>
|
|
111
|
+
)}
|
|
112
|
+
{testResult.error.CustomerMessage && (
|
|
113
|
+
<Typography variant="pi" textColor="neutral600">
|
|
114
|
+
<strong>Customer Message:</strong>{" "}
|
|
115
|
+
{testResult.error.CustomerMessage}
|
|
116
|
+
</Typography>
|
|
117
|
+
)}
|
|
118
|
+
</Flex>
|
|
119
|
+
</CardBody>
|
|
120
|
+
</Card>
|
|
121
|
+
)}
|
|
122
|
+
</Flex>
|
|
123
|
+
)}
|
|
124
|
+
</Flex>
|
|
125
|
+
</CardBody>
|
|
126
|
+
</Card>
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export default TestConnection;
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Accordion, Box, Flex, Typography } from "@strapi/design-system";
|
|
3
|
+
import { Link } from "@strapi/design-system";
|
|
4
|
+
import CodeBlock from "./CodeBlock";
|
|
5
|
+
|
|
6
|
+
const ApplePaySection = () => {
|
|
7
|
+
return (
|
|
8
|
+
<Accordion.Item value="apple-pay" id="apple-pay">
|
|
9
|
+
<Accordion.Header>
|
|
10
|
+
<Accordion.Trigger>Apple Pay Integration</Accordion.Trigger>
|
|
11
|
+
</Accordion.Header>
|
|
12
|
+
<Accordion.Content>
|
|
13
|
+
<Flex direction="column" alignItems={"stretch"} gap={4} padding={4}>
|
|
14
|
+
<Typography variant="delta" as="h3" fontWeight="bold">
|
|
15
|
+
Apple Pay Integration
|
|
16
|
+
</Typography>
|
|
17
|
+
<Typography variant="pi" fontWeight="bold" textColor="danger600">
|
|
18
|
+
⚠️ Important: Apple Pay does NOT work on localhost
|
|
19
|
+
</Typography>
|
|
20
|
+
|
|
21
|
+
<Typography variant="pi" textColor="neutral600">
|
|
22
|
+
Apple Pay requires a registered domain with HTTPS. For testing, use a
|
|
23
|
+
production domain with HTTPS or test on a device with Safari
|
|
24
|
+
(iOS/macOS).
|
|
25
|
+
</Typography>
|
|
26
|
+
|
|
27
|
+
<Box>
|
|
28
|
+
<Flex direction="column" alignItems={"stretch"} gap={2}>
|
|
29
|
+
<Typography variant="pi" fontWeight="bold">
|
|
30
|
+
Step 1: Configure Strapi Middleware
|
|
31
|
+
</Typography>
|
|
32
|
+
<Typography variant="pi">
|
|
33
|
+
Add Apple Pay SDK to your <code>config/middlewares.js</code>:
|
|
34
|
+
</Typography>
|
|
35
|
+
</Flex>
|
|
36
|
+
|
|
37
|
+
<div style={{ marginTop: "12px" }}>
|
|
38
|
+
<CodeBlock>{`module.exports = [
|
|
39
|
+
'strapi::logger',
|
|
40
|
+
'strapi::errors',
|
|
41
|
+
{
|
|
42
|
+
name: 'strapi::security',
|
|
43
|
+
config: {
|
|
44
|
+
contentSecurityPolicy: {
|
|
45
|
+
useDefaults: true,
|
|
46
|
+
directives: {
|
|
47
|
+
'script-src': [
|
|
48
|
+
"'self'",
|
|
49
|
+
"'unsafe-inline'",
|
|
50
|
+
"'unsafe-eval'",
|
|
51
|
+
'https://applepay.cdn-apple.com',
|
|
52
|
+
'https://www.apple.com',
|
|
53
|
+
],
|
|
54
|
+
'connect-src': [
|
|
55
|
+
"'self'",
|
|
56
|
+
'https:',
|
|
57
|
+
'https://applepay.cdn-apple.com',
|
|
58
|
+
'https://www.apple.com',
|
|
59
|
+
],
|
|
60
|
+
'frame-src': [
|
|
61
|
+
"'self'",
|
|
62
|
+
'https://applepay.cdn-apple.com',
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
// ... other middlewares
|
|
69
|
+
];`}</CodeBlock>
|
|
70
|
+
</div>
|
|
71
|
+
</Box>
|
|
72
|
+
|
|
73
|
+
<Box>
|
|
74
|
+
<Flex direction="column" alignItems={"stretch"} gap={2}>
|
|
75
|
+
<Typography variant="pi" fontWeight="bold">
|
|
76
|
+
Step 2: Setup .well-known File
|
|
77
|
+
</Typography>
|
|
78
|
+
<Typography variant="pi">
|
|
79
|
+
Download the Apple Pay domain verification file from Payone
|
|
80
|
+
documentation:{" "}
|
|
81
|
+
<Link
|
|
82
|
+
href="https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev"
|
|
83
|
+
target="_blank"
|
|
84
|
+
rel="noopener noreferrer"
|
|
85
|
+
>
|
|
86
|
+
https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev
|
|
87
|
+
</Link>{" "}
|
|
88
|
+
or from your Payone merchant portal and place it:
|
|
89
|
+
</Typography>
|
|
90
|
+
</Flex>
|
|
91
|
+
<Flex
|
|
92
|
+
direction="column"
|
|
93
|
+
alignItems={"stretch"}
|
|
94
|
+
gap={2}
|
|
95
|
+
style={{ marginTop: "16px" }}
|
|
96
|
+
>
|
|
97
|
+
<Typography variant="pi">
|
|
98
|
+
<strong>In Strapi:</strong>{" "}
|
|
99
|
+
<code>
|
|
100
|
+
public/.well-known/apple-developer-merchantid-domain-association
|
|
101
|
+
</code>
|
|
102
|
+
</Typography>
|
|
103
|
+
<Typography variant="pi">
|
|
104
|
+
<strong>In Frontend:</strong>{" "}
|
|
105
|
+
<code>
|
|
106
|
+
public/.well-known/apple-developer-merchantid-domain-association
|
|
107
|
+
</code>
|
|
108
|
+
</Typography>
|
|
109
|
+
</Flex>
|
|
110
|
+
<Typography variant="pi" textColor="neutral600" marginTop={2}>
|
|
111
|
+
The file must be accessible at:{" "}
|
|
112
|
+
<code>
|
|
113
|
+
https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association
|
|
114
|
+
</code>
|
|
115
|
+
</Typography>
|
|
116
|
+
<Typography variant="pi" textColor="neutral600" marginTop={2}>
|
|
117
|
+
<strong>Alternative Download:</strong> Log into your Payone
|
|
118
|
+
Merchant Interface (PMI) → Configuration → Payment Portals → Apple
|
|
119
|
+
Pay → Download domain verification file
|
|
120
|
+
</Typography>
|
|
121
|
+
</Box>
|
|
122
|
+
<Box>
|
|
123
|
+
<Typography variant="pi" fontWeight="bold">
|
|
124
|
+
Step 3: Implement Apple Pay Button
|
|
125
|
+
</Typography>
|
|
126
|
+
<div style={{ marginTop: "12px" }}>
|
|
127
|
+
<CodeBlock>{`// Load Apple Pay SDK
|
|
128
|
+
<script src="https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js"></script>
|
|
129
|
+
|
|
130
|
+
// Check if Apple Pay is available
|
|
131
|
+
if (window.ApplePaySession && ApplePaySession.canMakePayments()) {
|
|
132
|
+
// Create payment request
|
|
133
|
+
const paymentRequest = {
|
|
134
|
+
countryCode: 'DE',
|
|
135
|
+
currencyCode: 'EUR',
|
|
136
|
+
supportedNetworks: ['visa', 'masterCard', 'amex'],
|
|
137
|
+
merchantCapabilities: ['supports3DS'],
|
|
138
|
+
total: {
|
|
139
|
+
label: 'Your Store',
|
|
140
|
+
amount: '10.00'
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// Create session
|
|
145
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
146
|
+
|
|
147
|
+
// Handle merchant validation
|
|
148
|
+
session.onmerchantvalidation = async (event) => {
|
|
149
|
+
const validationURL = event.validationURL;
|
|
150
|
+
|
|
151
|
+
// Call your backend to validate merchant
|
|
152
|
+
const response = await fetch('/api/strapi-plugin-payone-provider/validate-apple-pay-merchant', {
|
|
153
|
+
method: 'POST',
|
|
154
|
+
headers: {
|
|
155
|
+
'Content-Type': 'application/json',
|
|
156
|
+
'Authorization': 'Bearer YOUR_TOKEN'
|
|
157
|
+
},
|
|
158
|
+
body: JSON.stringify({
|
|
159
|
+
validationURL: validationURL,
|
|
160
|
+
displayName: 'Your Store Name',
|
|
161
|
+
domainName: window.location.hostname
|
|
162
|
+
})
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const merchantSession = await response.json();
|
|
166
|
+
session.completeMerchantValidation(merchantSession);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Handle payment authorization
|
|
170
|
+
session.onpaymentauthorized = async (event) => {
|
|
171
|
+
const payment = event.payment;
|
|
172
|
+
const token = payment.token;
|
|
173
|
+
|
|
174
|
+
// Send token to backend
|
|
175
|
+
const response = await fetch('/api/strapi-plugin-payone-provider/preauthorization', {
|
|
176
|
+
method: 'POST',
|
|
177
|
+
headers: {
|
|
178
|
+
'Content-Type': 'application/json',
|
|
179
|
+
'Authorization': 'Bearer YOUR_TOKEN'
|
|
180
|
+
},
|
|
181
|
+
body: JSON.stringify({
|
|
182
|
+
amount: 1000,
|
|
183
|
+
currency: 'EUR',
|
|
184
|
+
reference: 'ORD-00123-ABCD',
|
|
185
|
+
clearingtype: 'wlt',
|
|
186
|
+
wallettype: 'APL',
|
|
187
|
+
'add_paydata[paymentmethod_token_data]': JSON.stringify(token),
|
|
188
|
+
'add_paydata[paymentmethod]': 'APL',
|
|
189
|
+
'add_paydata[paymentmethod_type]': 'APPLEPAY',
|
|
190
|
+
'add_paydata[gatewayid]': 'payonegmbh',
|
|
191
|
+
firstname: payment.billingContact.givenName || 'John',
|
|
192
|
+
lastname: payment.billingContact.familyName || 'Doe',
|
|
193
|
+
email: payment.billingContact.emailAddress || 'john.doe@example.com',
|
|
194
|
+
street: payment.billingContact.addressLines?.[0] || 'Main Street 123',
|
|
195
|
+
zip: payment.billingContact.postalCode || '12345',
|
|
196
|
+
city: payment.billingContact.locality || 'Berlin',
|
|
197
|
+
country: payment.billingContact.countryCode || 'DE',
|
|
198
|
+
shipping_firstname: payment.shippingContact?.givenName || payment.billingContact.givenName || 'John',
|
|
199
|
+
shipping_lastname: payment.shippingContact?.familyName || payment.billingContact.familyName || 'Doe',
|
|
200
|
+
shipping_street: payment.shippingContact?.addressLines?.[0] || payment.billingContact.addressLines?.[0] || 'Main Street 123',
|
|
201
|
+
shipping_zip: payment.shippingContact?.postalCode || payment.billingContact.postalCode || '12345',
|
|
202
|
+
shipping_city: payment.shippingContact?.locality || payment.billingContact.locality || 'Berlin',
|
|
203
|
+
shipping_country: payment.shippingContact?.countryCode || payment.billingContact.countryCode || 'DE'
|
|
204
|
+
})
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const result = await response.json();
|
|
208
|
+
|
|
209
|
+
if (result.status === 'APPROVED') {
|
|
210
|
+
session.completePayment(ApplePaySession.STATUS_SUCCESS);
|
|
211
|
+
} else {
|
|
212
|
+
session.completePayment(ApplePaySession.STATUS_FAILURE);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// Show payment sheet
|
|
217
|
+
session.begin();
|
|
218
|
+
}`}</CodeBlock>
|
|
219
|
+
</div>
|
|
220
|
+
</Box>
|
|
221
|
+
<Box>
|
|
222
|
+
<Typography variant="pi" fontWeight="bold">
|
|
223
|
+
Token Parameters (Backend Request):
|
|
224
|
+
</Typography>
|
|
225
|
+
<div style={{ marginTop: "12px" }}>
|
|
226
|
+
<CodeBlock>{`{
|
|
227
|
+
"amount": 1000,
|
|
228
|
+
"currency": "EUR",
|
|
229
|
+
"reference": "ORD-00123-ABCD",
|
|
230
|
+
"clearingtype": "wlt",
|
|
231
|
+
"wallettype": "APL",
|
|
232
|
+
"add_paydata[paymentmethod_token_data]": "JSON_STRINGIFIED_TOKEN",
|
|
233
|
+
"add_paydata[paymentmethod]": "APL",
|
|
234
|
+
"add_paydata[paymentmethod_type]": "APPLEPAY",
|
|
235
|
+
"add_paydata[gatewayid]": "payonegmbh",
|
|
236
|
+
"add_paydata[gateway_merchantid]": "YOUR_MERCHANT_ID",
|
|
237
|
+
// ... customer and shipping info
|
|
238
|
+
}`}</CodeBlock>
|
|
239
|
+
</div>
|
|
240
|
+
</Box>
|
|
241
|
+
<Box>
|
|
242
|
+
<Typography variant="pi" textColor="neutral600">
|
|
243
|
+
📚 <strong>Payone Apple Pay Documentation:</strong>{" "}
|
|
244
|
+
<Link
|
|
245
|
+
href="https://docs.payone.com/display/public/PLATFORM/Apple+Pay"
|
|
246
|
+
target="_blank"
|
|
247
|
+
rel="noopener noreferrer"
|
|
248
|
+
>
|
|
249
|
+
https://docs.payone.com/display/public/PLATFORM/Apple+Pay
|
|
250
|
+
</Link>
|
|
251
|
+
</Typography>
|
|
252
|
+
</Box>
|
|
253
|
+
</Flex>
|
|
254
|
+
</Accordion.Content>
|
|
255
|
+
</Accordion.Item>
|
|
256
|
+
);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
export default ApplePaySection;
|
|
260
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Box, Card, CardBody, Flex, Typography } from "@strapi/design-system";
|
|
3
|
+
import CodeBlock from "./CodeBlock";
|
|
4
|
+
|
|
5
|
+
const BaseUrlSection = () => {
|
|
6
|
+
return (
|
|
7
|
+
<Card id="base-url">
|
|
8
|
+
<CardBody padding={6}>
|
|
9
|
+
<Flex direction="column" alignItems="stretch" gap={4}>
|
|
10
|
+
<Typography
|
|
11
|
+
variant="delta"
|
|
12
|
+
as="h3"
|
|
13
|
+
fontWeight="bold"
|
|
14
|
+
style={{ marginBottom: "12px" }}
|
|
15
|
+
>
|
|
16
|
+
Base URL & Authentication
|
|
17
|
+
</Typography>
|
|
18
|
+
<Box>
|
|
19
|
+
<Typography
|
|
20
|
+
variant="pi"
|
|
21
|
+
fontWeight="bold"
|
|
22
|
+
style={{ marginBottom: "16px" }}
|
|
23
|
+
>
|
|
24
|
+
Content API (Frontend):
|
|
25
|
+
</Typography>
|
|
26
|
+
<CodeBlock>/api/strapi-plugin-payone-provider</CodeBlock>
|
|
27
|
+
</Box>
|
|
28
|
+
<Box>
|
|
29
|
+
<Typography
|
|
30
|
+
variant="pi"
|
|
31
|
+
fontWeight="bold"
|
|
32
|
+
style={{ marginBottom: "16px" }}
|
|
33
|
+
>
|
|
34
|
+
Required Headers:
|
|
35
|
+
</Typography>
|
|
36
|
+
<CodeBlock>{`{
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
"Authorization": "Bearer YOUR_AUTH_TOKEN"
|
|
39
|
+
}`}</CodeBlock>
|
|
40
|
+
</Box>
|
|
41
|
+
<Typography variant="pi" textColor="neutral600">
|
|
42
|
+
<strong>Note:</strong> <code>YOUR_AUTH_TOKEN</code> is your Strapi
|
|
43
|
+
authentication token (JWT), not a Payone token. You can get this
|
|
44
|
+
token by logging into Strapi admin panel or using Strapi's
|
|
45
|
+
authentication API.
|
|
46
|
+
</Typography>
|
|
47
|
+
</Flex>
|
|
48
|
+
</CardBody>
|
|
49
|
+
</Card>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default BaseUrlSection;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Accordion, Box, Flex, Typography } from "@strapi/design-system";
|
|
3
|
+
import { Link } from "@strapi/design-system";
|
|
4
|
+
import CodeBlock from "./CodeBlock";
|
|
5
|
+
|
|
6
|
+
const CaptureRefundSection = () => {
|
|
7
|
+
return (
|
|
8
|
+
<Accordion.Item value="capture-refund" id="capture-refund">
|
|
9
|
+
<Accordion.Header>
|
|
10
|
+
<Accordion.Trigger>Capture & Refund Operations</Accordion.Trigger>
|
|
11
|
+
</Accordion.Header>
|
|
12
|
+
<Accordion.Content>
|
|
13
|
+
<Flex direction="column" alignItems={"stretch"} gap={4} padding={4}>
|
|
14
|
+
<Typography variant="delta" as="h3" fontWeight="bold">
|
|
15
|
+
Capture & Refund Operations
|
|
16
|
+
</Typography>
|
|
17
|
+
<Box>
|
|
18
|
+
<Typography variant="pi" fontWeight="bold">
|
|
19
|
+
Capture (Complete Preauthorized Transaction):
|
|
20
|
+
</Typography>
|
|
21
|
+
<div style={{ marginTop: "12px", marginBottom: "12px" }}>
|
|
22
|
+
<CodeBlock>{`POST /api/strapi-plugin-payone-provider/capture
|
|
23
|
+
|
|
24
|
+
{
|
|
25
|
+
"txid": "12345678",
|
|
26
|
+
"amount": 1000,
|
|
27
|
+
"currency": "EUR",
|
|
28
|
+
"reference": "CAPTURE-00123-ABCD",
|
|
29
|
+
"sequencenumber": 1,
|
|
30
|
+
"capturemode": "full" // For wallet payments: "full" or "partial"
|
|
31
|
+
}`}</CodeBlock>
|
|
32
|
+
</div>
|
|
33
|
+
<Typography variant="pi" textColor="neutral600">
|
|
34
|
+
<strong>Note:</strong> <code>capturemode</code> is only required
|
|
35
|
+
for wallet payments (PayPal, Google Pay, Apple Pay).
|
|
36
|
+
</Typography>
|
|
37
|
+
</Box>
|
|
38
|
+
<Box>
|
|
39
|
+
<Typography variant="pi" fontWeight="bold">
|
|
40
|
+
Refund (Return Funds):
|
|
41
|
+
</Typography>
|
|
42
|
+
<div style={{ marginTop: "12px", marginBottom: "12px" }}>
|
|
43
|
+
<CodeBlock>{`POST /api/strapi-plugin-payone-provider/refund
|
|
44
|
+
|
|
45
|
+
{
|
|
46
|
+
"txid": "12345678",
|
|
47
|
+
"amount": -1000, // Negative amount for refund
|
|
48
|
+
"currency": "EUR",
|
|
49
|
+
"reference": "REFUND-00123-ABCD",
|
|
50
|
+
"sequencenumber": 2
|
|
51
|
+
}`}</CodeBlock>
|
|
52
|
+
</div>
|
|
53
|
+
<Typography variant="pi" textColor="neutral600">
|
|
54
|
+
<strong>Note:</strong> Refund amount must be negative.{" "}
|
|
55
|
+
<code>sequencenumber</code> should be incremented for each
|
|
56
|
+
operation on the same transaction.
|
|
57
|
+
</Typography>
|
|
58
|
+
</Box>
|
|
59
|
+
<Box>
|
|
60
|
+
<Typography variant="pi" fontWeight="bold">
|
|
61
|
+
Sequence Numbers:
|
|
62
|
+
</Typography>
|
|
63
|
+
<Flex
|
|
64
|
+
direction="column"
|
|
65
|
+
marginTop={2}
|
|
66
|
+
alignItems={"stretch"}
|
|
67
|
+
gap={2}
|
|
68
|
+
>
|
|
69
|
+
<Typography variant="pi">
|
|
70
|
+
• <strong>Preauthorization:</strong> sequencenumber = 0
|
|
71
|
+
(default)
|
|
72
|
+
</Typography>
|
|
73
|
+
<Typography variant="pi">
|
|
74
|
+
• <strong>Capture:</strong> sequencenumber = 1 (first capture)
|
|
75
|
+
</Typography>
|
|
76
|
+
<Typography variant="pi">
|
|
77
|
+
• <strong>Refund:</strong> sequencenumber = 2 (first refund), 3
|
|
78
|
+
(second refund), etc.
|
|
79
|
+
</Typography>
|
|
80
|
+
</Flex>
|
|
81
|
+
</Box>
|
|
82
|
+
<Box marginTop={2}>
|
|
83
|
+
<Typography variant="pi" textColor="neutral600">
|
|
84
|
+
📚 <strong>Payone Capture Documentation:</strong>{" "}
|
|
85
|
+
<Link
|
|
86
|
+
href="https://docs.payone.com/display/public/PLATFORM/Capture"
|
|
87
|
+
target="_blank"
|
|
88
|
+
rel="noopener noreferrer"
|
|
89
|
+
>
|
|
90
|
+
https://docs.payone.com/display/public/PLATFORM/Capture
|
|
91
|
+
</Link>
|
|
92
|
+
</Typography>
|
|
93
|
+
</Box>
|
|
94
|
+
<Box marginTop={2}>
|
|
95
|
+
<Typography variant="pi" textColor="neutral600">
|
|
96
|
+
📚 <strong>Payone Refund Documentation:</strong>{" "}
|
|
97
|
+
<Link
|
|
98
|
+
href="https://docs.payone.com/display/public/PLATFORM/Refund"
|
|
99
|
+
target="_blank"
|
|
100
|
+
rel="noopener noreferrer"
|
|
101
|
+
>
|
|
102
|
+
https://docs.payone.com/display/public/PLATFORM/Refund
|
|
103
|
+
</Link>
|
|
104
|
+
</Typography>
|
|
105
|
+
</Box>
|
|
106
|
+
</Flex>
|
|
107
|
+
</Accordion.Content>
|
|
108
|
+
</Accordion.Item>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export default CaptureRefundSection;
|
|
113
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Box } from "@strapi/design-system";
|
|
3
|
+
|
|
4
|
+
const CodeBlock = ({ children }) => {
|
|
5
|
+
const [isDark, setIsDark] = React.useState(false);
|
|
6
|
+
|
|
7
|
+
React.useEffect(() => {
|
|
8
|
+
const checkTheme = () => {
|
|
9
|
+
if (typeof window !== "undefined") {
|
|
10
|
+
const bodyBg = window.getComputedStyle(document.body).backgroundColor;
|
|
11
|
+
const rgb = bodyBg.match(/\d+/g);
|
|
12
|
+
if (rgb && rgb.length >= 3) {
|
|
13
|
+
const brightness =
|
|
14
|
+
(parseInt(rgb[0]) * 299 +
|
|
15
|
+
parseInt(rgb[1]) * 587 +
|
|
16
|
+
parseInt(rgb[2]) * 114) /
|
|
17
|
+
1000;
|
|
18
|
+
setIsDark(brightness < 128);
|
|
19
|
+
} else {
|
|
20
|
+
const prefersDark =
|
|
21
|
+
window.matchMedia &&
|
|
22
|
+
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
23
|
+
setIsDark(prefersDark);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
checkTheme();
|
|
29
|
+
const mediaQuery =
|
|
30
|
+
window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)");
|
|
31
|
+
if (mediaQuery) {
|
|
32
|
+
mediaQuery.addEventListener("change", checkTheme);
|
|
33
|
+
return () => mediaQuery.removeEventListener("change", checkTheme);
|
|
34
|
+
}
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Box
|
|
39
|
+
padding={3}
|
|
40
|
+
borderRadius="4px"
|
|
41
|
+
style={{
|
|
42
|
+
backgroundColor: isDark ? "#1e1e1e" : "#f6f6f9",
|
|
43
|
+
color: isDark ? "#d4d4d4" : "#32324d",
|
|
44
|
+
fontFamily: "monospace",
|
|
45
|
+
fontSize: "14px",
|
|
46
|
+
overflow: "auto",
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
<pre
|
|
50
|
+
style={{ margin: 0, whiteSpace: "pre-wrap", wordBreak: "break-word" }}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</pre>
|
|
54
|
+
</Box>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default CodeBlock;
|
|
59
|
+
|