strapi-plugin-payone-provider 1.5.0 → 1.5.2
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 +179 -22
- package/admin/src/pages/App/components/AppHeader.js +22 -4
- package/admin/src/pages/App/components/AppTabs.js +23 -1
- package/admin/src/pages/App/components/ApplePayButton.js +46 -13
- package/admin/src/pages/App/components/ApplePayConfig.js +224 -165
- package/admin/src/pages/App/components/ApplePayConfigPanel.js +81 -0
- package/admin/src/pages/App/components/ConfigurationPanel.js +19 -3
- package/admin/src/pages/App/components/DocsPanel.js +1057 -0
- package/admin/src/pages/App/components/GooglePayConfig.js +217 -0
- package/admin/src/pages/App/components/GooglePayConfigPanel.js +82 -0
- package/admin/src/pages/App/components/GooglePaybutton.js +1 -1
- package/admin/src/pages/App/components/PaymentActionsPanel.js +18 -6
- package/admin/src/pages/App/components/paymentActions/AuthorizationForm.js +41 -12
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.js +106 -2
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.js +38 -20
- package/admin/src/pages/App/index.js +70 -1
- package/admin/src/pages/hooks/useSettings.js +2 -0
- package/admin/src/pages/utils/googlePayConstants.js +79 -0
- package/package.json +1 -1
- package/APPLE_PAY_INTEGRATION.md +0 -472
- package/CSP_SETUP.md +0 -184
- package/HTTPS_REQUIREMENT.md +0 -136
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Flex, Typography, Select, Option, Checkbox, Stack } from "@strapi/design-system";
|
|
3
|
+
import {
|
|
4
|
+
GOOGLE_PAY_SUPPORTED_COUNTRIES,
|
|
5
|
+
GOOGLE_PAY_SUPPORTED_CURRENCIES,
|
|
6
|
+
GOOGLE_PAY_SUPPORTED_NETWORKS,
|
|
7
|
+
GOOGLE_PAY_AUTH_METHODS,
|
|
8
|
+
DEFAULT_GOOGLE_PAY_CONFIG
|
|
9
|
+
} from "../../utils/googlePayConstants";
|
|
10
|
+
|
|
11
|
+
const GooglePayConfig = ({
|
|
12
|
+
config,
|
|
13
|
+
onConfigChange,
|
|
14
|
+
settings
|
|
15
|
+
}) => {
|
|
16
|
+
const {
|
|
17
|
+
countryCode = DEFAULT_GOOGLE_PAY_CONFIG.countryCode,
|
|
18
|
+
currencyCode = DEFAULT_GOOGLE_PAY_CONFIG.currencyCode,
|
|
19
|
+
allowedCardNetworks = DEFAULT_GOOGLE_PAY_CONFIG.allowedCardNetworks,
|
|
20
|
+
allowedAuthMethods = DEFAULT_GOOGLE_PAY_CONFIG.allowedAuthMethods,
|
|
21
|
+
merchantName = DEFAULT_GOOGLE_PAY_CONFIG.merchantName
|
|
22
|
+
} = config || {};
|
|
23
|
+
|
|
24
|
+
const handleCountryChange = (value) => {
|
|
25
|
+
onConfigChange({
|
|
26
|
+
...config,
|
|
27
|
+
countryCode: value
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const handleCurrencyChange = (value) => {
|
|
32
|
+
onConfigChange({
|
|
33
|
+
...config,
|
|
34
|
+
currencyCode: value
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const handleNetworkToggle = (networkCode) => {
|
|
39
|
+
const currentNetworks = allowedCardNetworks || [];
|
|
40
|
+
const newNetworks = currentNetworks.includes(networkCode)
|
|
41
|
+
? currentNetworks.filter(n => n !== networkCode)
|
|
42
|
+
: [...currentNetworks, networkCode];
|
|
43
|
+
|
|
44
|
+
onConfigChange({
|
|
45
|
+
...config,
|
|
46
|
+
allowedCardNetworks: newNetworks
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleAuthMethodToggle = (authMethodCode) => {
|
|
51
|
+
const currentMethods = allowedAuthMethods || [];
|
|
52
|
+
const newMethods = currentMethods.includes(authMethodCode)
|
|
53
|
+
? currentMethods.filter(m => m !== authMethodCode)
|
|
54
|
+
: [...currentMethods, authMethodCode];
|
|
55
|
+
|
|
56
|
+
onConfigChange({
|
|
57
|
+
...config,
|
|
58
|
+
allowedAuthMethods: newMethods
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Box>
|
|
64
|
+
<Stack spacing={6}>
|
|
65
|
+
<Box>
|
|
66
|
+
<Typography variant="delta" as="h3" fontWeight="bold" style={{ marginBottom: "6px" }}>
|
|
67
|
+
Google Pay Configuration
|
|
68
|
+
</Typography>
|
|
69
|
+
<Typography variant="pi" textColor="neutral600">
|
|
70
|
+
Configure Google Pay settings for your payment gateway
|
|
71
|
+
</Typography>
|
|
72
|
+
</Box>
|
|
73
|
+
|
|
74
|
+
{/* Country and Currency */}
|
|
75
|
+
<Flex gap={4} wrap="wrap">
|
|
76
|
+
<Box style={{ flex: 1, minWidth: "300px" }}>
|
|
77
|
+
<Select
|
|
78
|
+
label="Country Code"
|
|
79
|
+
name="countryCode"
|
|
80
|
+
value={countryCode}
|
|
81
|
+
onChange={handleCountryChange}
|
|
82
|
+
hint="Select the country where your business operates"
|
|
83
|
+
required
|
|
84
|
+
>
|
|
85
|
+
{GOOGLE_PAY_SUPPORTED_COUNTRIES.map(country => (
|
|
86
|
+
<Option key={country.code} value={country.code}>
|
|
87
|
+
{country.name} ({country.code})
|
|
88
|
+
</Option>
|
|
89
|
+
))}
|
|
90
|
+
</Select>
|
|
91
|
+
</Box>
|
|
92
|
+
|
|
93
|
+
<Box style={{ flex: 1, minWidth: "300px" }}>
|
|
94
|
+
<Select
|
|
95
|
+
label="Currency Code"
|
|
96
|
+
name="currencyCode"
|
|
97
|
+
value={currencyCode}
|
|
98
|
+
onChange={handleCurrencyChange}
|
|
99
|
+
hint="Select the currency for transactions"
|
|
100
|
+
required
|
|
101
|
+
>
|
|
102
|
+
{GOOGLE_PAY_SUPPORTED_CURRENCIES.map(currency => (
|
|
103
|
+
<Option key={currency.code} value={currency.code}>
|
|
104
|
+
{currency.name} ({currency.code}) {currency.symbol}
|
|
105
|
+
</Option>
|
|
106
|
+
))}
|
|
107
|
+
</Select>
|
|
108
|
+
</Box>
|
|
109
|
+
</Flex>
|
|
110
|
+
|
|
111
|
+
{/* Merchant Name */}
|
|
112
|
+
<Box>
|
|
113
|
+
<Typography variant="pi" fontWeight="semiBold" style={{ marginLeft: "2px" }}>
|
|
114
|
+
Merchant Name
|
|
115
|
+
</Typography>
|
|
116
|
+
<Typography variant="pi" textColor="neutral600" style={{ marginLeft: "2px" }}>
|
|
117
|
+
The name of your business as it will appear in Google Pay
|
|
118
|
+
</Typography>
|
|
119
|
+
<input
|
|
120
|
+
type="text"
|
|
121
|
+
value={merchantName}
|
|
122
|
+
onChange={(e) => onConfigChange({ ...config, merchantName: e.target.value })}
|
|
123
|
+
style={{
|
|
124
|
+
width: "100%",
|
|
125
|
+
padding: "8px 12px",
|
|
126
|
+
marginTop: "8px",
|
|
127
|
+
border: "1px solid #dcdce4",
|
|
128
|
+
borderRadius: "4px",
|
|
129
|
+
fontSize: "14px"
|
|
130
|
+
}}
|
|
131
|
+
placeholder="Your Store Name"
|
|
132
|
+
/>
|
|
133
|
+
</Box>
|
|
134
|
+
|
|
135
|
+
{/* Allowed Card Networks */}
|
|
136
|
+
<Box>
|
|
137
|
+
<Typography variant="pi" fontWeight="semiBold" style={{ marginLeft: "2px" }}>
|
|
138
|
+
Allowed Card Networks
|
|
139
|
+
</Typography>
|
|
140
|
+
<Typography variant="pi" textColor="neutral600" style={{ marginLeft: "2px" }}>
|
|
141
|
+
Select payment card networks to accept
|
|
142
|
+
</Typography>
|
|
143
|
+
<Flex wrap="wrap" gap={4} style={{ marginTop: "12px" }}>
|
|
144
|
+
{GOOGLE_PAY_SUPPORTED_NETWORKS.map(network => {
|
|
145
|
+
const isSelected = allowedCardNetworks?.includes(network.code);
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<Box key={network.code} style={{ flex: "0 0 calc(50% - 8px)", minWidth: "250px" }}>
|
|
149
|
+
<Checkbox
|
|
150
|
+
name={`network-${network.code}`}
|
|
151
|
+
checked={isSelected}
|
|
152
|
+
onChange={() => handleNetworkToggle(network.code)}
|
|
153
|
+
>
|
|
154
|
+
{network.name} ({network.code})
|
|
155
|
+
</Checkbox>
|
|
156
|
+
</Box>
|
|
157
|
+
);
|
|
158
|
+
})}
|
|
159
|
+
</Flex>
|
|
160
|
+
{allowedCardNetworks?.length === 0 && (
|
|
161
|
+
<Typography variant="pi" textColor="danger600" style={{ marginTop: "8px" }}>
|
|
162
|
+
At least one card network must be selected
|
|
163
|
+
</Typography>
|
|
164
|
+
)}
|
|
165
|
+
</Box>
|
|
166
|
+
|
|
167
|
+
{/* Allowed Authentication Methods */}
|
|
168
|
+
<Box>
|
|
169
|
+
<Typography variant="pi" fontWeight="semiBold" style={{ marginLeft: "2px" }}>
|
|
170
|
+
Allowed Authentication Methods
|
|
171
|
+
</Typography>
|
|
172
|
+
<Typography variant="pi" textColor="neutral600" style={{ marginLeft: "2px" }}>
|
|
173
|
+
Select authentication methods for card payments
|
|
174
|
+
</Typography>
|
|
175
|
+
<Flex wrap="wrap" gap={4} style={{ marginTop: "12px" }}>
|
|
176
|
+
{GOOGLE_PAY_AUTH_METHODS.map(method => {
|
|
177
|
+
const isSelected = allowedAuthMethods?.includes(method.code);
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<Box key={method.code} style={{ flex: "0 0 calc(50% - 8px)", minWidth: "250px" }}>
|
|
181
|
+
<Checkbox
|
|
182
|
+
name={`auth-method-${method.code}`}
|
|
183
|
+
checked={isSelected}
|
|
184
|
+
onChange={() => handleAuthMethodToggle(method.code)}
|
|
185
|
+
>
|
|
186
|
+
{method.name} - {method.description}
|
|
187
|
+
</Checkbox>
|
|
188
|
+
</Box>
|
|
189
|
+
);
|
|
190
|
+
})}
|
|
191
|
+
</Flex>
|
|
192
|
+
{allowedAuthMethods?.length === 0 && (
|
|
193
|
+
<Typography variant="pi" textColor="danger600" style={{ marginTop: "8px" }}>
|
|
194
|
+
At least one authentication method must be selected
|
|
195
|
+
</Typography>
|
|
196
|
+
)}
|
|
197
|
+
</Box>
|
|
198
|
+
|
|
199
|
+
{/* Gateway Merchant ID Info */}
|
|
200
|
+
<Box>
|
|
201
|
+
<Typography variant="pi" fontWeight="semiBold" style={{ marginLeft: "2px" }}>
|
|
202
|
+
Gateway Merchant ID
|
|
203
|
+
</Typography>
|
|
204
|
+
<Typography variant="pi" textColor="neutral600">
|
|
205
|
+
{settings?.mid || settings?.portalid
|
|
206
|
+
? `Using: ${settings.mid || settings.portalid}`
|
|
207
|
+
: "Gateway merchant ID will be obtained from your Payone Merchant ID (MID) or Portal ID. Make sure these are configured in the main Configuration tab."
|
|
208
|
+
}
|
|
209
|
+
</Typography>
|
|
210
|
+
</Box>
|
|
211
|
+
</Stack>
|
|
212
|
+
</Box>
|
|
213
|
+
);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export default GooglePayConfig;
|
|
217
|
+
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Card,
|
|
5
|
+
CardBody,
|
|
6
|
+
Flex,
|
|
7
|
+
Typography,
|
|
8
|
+
Button
|
|
9
|
+
} from "@strapi/design-system";
|
|
10
|
+
import { Check } from "@strapi/icons";
|
|
11
|
+
import GooglePayConfig from "./GooglePayConfig";
|
|
12
|
+
|
|
13
|
+
const GooglePayConfigPanel = ({
|
|
14
|
+
settings,
|
|
15
|
+
onInputChange,
|
|
16
|
+
isSaving,
|
|
17
|
+
onSave,
|
|
18
|
+
onBack
|
|
19
|
+
}) => {
|
|
20
|
+
const [googlePayConfig, setGooglePayConfig] = useState(settings?.googlePayConfig || {});
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
setGooglePayConfig(settings?.googlePayConfig || {});
|
|
24
|
+
}, [settings?.googlePayConfig]);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<Box
|
|
28
|
+
className="payment-container"
|
|
29
|
+
paddingTop={8}
|
|
30
|
+
paddingBottom={8}
|
|
31
|
+
paddingLeft={8}
|
|
32
|
+
paddingRight={8}
|
|
33
|
+
>
|
|
34
|
+
<Flex direction="column" alignItems="stretch" gap={8}>
|
|
35
|
+
<Box>
|
|
36
|
+
<Typography variant="beta" as="h2" fontWeight="bold" className="payment-title" style={{ fontSize: '20px', marginBottom: '4px' }}>
|
|
37
|
+
Google Pay Configuration
|
|
38
|
+
</Typography>
|
|
39
|
+
<Typography variant="pi" textColor="neutral600" marginTop={2} className="payment-subtitle" style={{ fontSize: '14px' }}>
|
|
40
|
+
Configure Google Pay settings for your payment gateway
|
|
41
|
+
</Typography>
|
|
42
|
+
</Box>
|
|
43
|
+
|
|
44
|
+
<Box>
|
|
45
|
+
<Card className="payment-card">
|
|
46
|
+
<CardBody padding={6}>
|
|
47
|
+
<GooglePayConfig
|
|
48
|
+
config={googlePayConfig}
|
|
49
|
+
onConfigChange={(newConfig) => {
|
|
50
|
+
setGooglePayConfig(newConfig);
|
|
51
|
+
onInputChange("googlePayConfig", newConfig);
|
|
52
|
+
}}
|
|
53
|
+
settings={settings}
|
|
54
|
+
/>
|
|
55
|
+
</CardBody>
|
|
56
|
+
</Card>
|
|
57
|
+
</Box>
|
|
58
|
+
|
|
59
|
+
<Box paddingTop={4}>
|
|
60
|
+
<Flex direction="row" gap={4} alignItems="center">
|
|
61
|
+
<Button
|
|
62
|
+
loading={isSaving}
|
|
63
|
+
onClick={onSave}
|
|
64
|
+
startIcon={<Check />}
|
|
65
|
+
size="L"
|
|
66
|
+
variant="default"
|
|
67
|
+
className="payment-button payment-button-success"
|
|
68
|
+
>
|
|
69
|
+
Save Google Pay Configuration
|
|
70
|
+
</Button>
|
|
71
|
+
<Typography variant="sigma" textColor="neutral600">
|
|
72
|
+
Note: Google Pay configuration is used for Google Pay payment requests. Make sure to configure the correct card networks, authentication methods, and merchant information for your region.
|
|
73
|
+
</Typography>
|
|
74
|
+
</Flex>
|
|
75
|
+
</Box>
|
|
76
|
+
</Flex>
|
|
77
|
+
</Box>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default GooglePayConfigPanel;
|
|
82
|
+
|
|
@@ -291,7 +291,7 @@ const GooglePayButton = ({
|
|
|
291
291
|
</Typography>
|
|
292
292
|
</>
|
|
293
293
|
)}
|
|
294
|
-
<Box ref={buttonContainerRef} style={{ minHeight: "40px", width: "100%", display: "flex", justifyContent: "flex-start" }} />
|
|
294
|
+
<Box ref={buttonContainerRef} style={{ minHeight: "40px", width: "100%", maxWidth: "200px", display: "flex", justifyContent: "flex-start", }} />
|
|
295
295
|
</Flex>
|
|
296
296
|
</Box>
|
|
297
297
|
);
|
|
@@ -45,8 +45,12 @@ const PaymentActionsPanel = ({
|
|
|
45
45
|
cardexpiredate,
|
|
46
46
|
setCardexpiredate,
|
|
47
47
|
cardcvc2,
|
|
48
|
-
setCardcvc2
|
|
48
|
+
setCardcvc2,
|
|
49
|
+
onNavigateToConfig
|
|
49
50
|
}) => {
|
|
51
|
+
const mode = (settings?.mode || 'test').toLowerCase();
|
|
52
|
+
const isLiveMode = mode === 'live';
|
|
53
|
+
|
|
50
54
|
return (
|
|
51
55
|
<Box
|
|
52
56
|
className="payment-container"
|
|
@@ -56,13 +60,18 @@ const PaymentActionsPanel = ({
|
|
|
56
60
|
paddingRight={8}
|
|
57
61
|
>
|
|
58
62
|
<Flex direction="column" alignItems="stretch" gap={6}>
|
|
59
|
-
<Box>
|
|
63
|
+
<Box style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: '8px' }}>
|
|
60
64
|
<Typography variant="beta" as="h2" className="payment-title" style={{ fontSize: '20px', marginBottom: '4px' }}>
|
|
61
65
|
Payment Actions
|
|
62
66
|
</Typography>
|
|
63
67
|
<Typography variant="pi" textColor="neutral600" className="payment-subtitle" style={{ fontSize: '14px' }}>
|
|
64
68
|
Process payments, captures, and refunds with multiple payment methods
|
|
65
69
|
</Typography>
|
|
70
|
+
{isLiveMode && (
|
|
71
|
+
<Typography variant="pi" textColor="danger600" style={{ fontSize: '14px', marginTop: '8px', fontWeight: 'bold' }}>
|
|
72
|
+
⚠️ Payment Actions are disabled in live mode for security reasons. Please use test mode for testing.
|
|
73
|
+
</Typography>
|
|
74
|
+
)}
|
|
66
75
|
</Box>
|
|
67
76
|
|
|
68
77
|
<PaymentMethodSelector
|
|
@@ -70,11 +79,12 @@ const PaymentActionsPanel = ({
|
|
|
70
79
|
setPaymentMethod={setPaymentMethod}
|
|
71
80
|
captureMode={captureMode}
|
|
72
81
|
setCaptureMode={setCaptureMode}
|
|
82
|
+
onNavigateToConfig={onNavigateToConfig}
|
|
73
83
|
/>
|
|
74
84
|
|
|
75
85
|
<hr className="payment-divider" />
|
|
76
86
|
|
|
77
|
-
<Box className="payment-form-section">
|
|
87
|
+
<Box className="payment-form-section" style={{ opacity: isLiveMode ? 0.5 : 1, pointerEvents: isLiveMode ? 'none' : 'auto' }}>
|
|
78
88
|
<PreauthorizationForm
|
|
79
89
|
paymentAmount={paymentAmount}
|
|
80
90
|
setPaymentAmount={setPaymentAmount}
|
|
@@ -96,12 +106,13 @@ const PaymentActionsPanel = ({
|
|
|
96
106
|
setCardexpiredate={setCardexpiredate}
|
|
97
107
|
cardcvc2={cardcvc2}
|
|
98
108
|
setCardcvc2={setCardcvc2}
|
|
109
|
+
isLiveMode={isLiveMode}
|
|
99
110
|
/>
|
|
100
111
|
</Box>
|
|
101
112
|
|
|
102
113
|
<hr className="payment-divider" />
|
|
103
114
|
|
|
104
|
-
<Box className="payment-form-section">
|
|
115
|
+
<Box className="payment-form-section" style={{ opacity: isLiveMode ? 0.5 : 1, pointerEvents: isLiveMode ? 'none' : 'auto' }}>
|
|
105
116
|
<AuthorizationForm
|
|
106
117
|
paymentAmount={paymentAmount}
|
|
107
118
|
setPaymentAmount={setPaymentAmount}
|
|
@@ -123,12 +134,13 @@ const PaymentActionsPanel = ({
|
|
|
123
134
|
setCardexpiredate={setCardexpiredate}
|
|
124
135
|
cardcvc2={cardcvc2}
|
|
125
136
|
setCardcvc2={setCardcvc2}
|
|
137
|
+
isLiveMode={isLiveMode}
|
|
126
138
|
/>
|
|
127
139
|
</Box>
|
|
128
140
|
|
|
129
141
|
<hr className="payment-divider" />
|
|
130
142
|
|
|
131
|
-
<Box className="payment-form-section">
|
|
143
|
+
<Box className="payment-form-section" style={{ opacity: isLiveMode ? 0.5 : 1, pointerEvents: isLiveMode ? 'none' : 'auto' }}>
|
|
132
144
|
<CaptureForm
|
|
133
145
|
paymentAmount={paymentAmount}
|
|
134
146
|
setPaymentAmount={setPaymentAmount}
|
|
@@ -141,7 +153,7 @@ const PaymentActionsPanel = ({
|
|
|
141
153
|
|
|
142
154
|
<hr className="payment-divider" />
|
|
143
155
|
|
|
144
|
-
<Box className="payment-form-section">
|
|
156
|
+
<Box className="payment-form-section" style={{ opacity: isLiveMode ? 0.5 : 1, pointerEvents: isLiveMode ? 'none' : 'auto' }}>
|
|
145
157
|
<RefundForm
|
|
146
158
|
paymentAmount={paymentAmount}
|
|
147
159
|
setPaymentAmount={setPaymentAmount}
|
|
@@ -25,7 +25,8 @@ const AuthorizationForm = ({
|
|
|
25
25
|
cardexpiredate,
|
|
26
26
|
setCardexpiredate,
|
|
27
27
|
cardcvc2,
|
|
28
|
-
setCardcvc2
|
|
28
|
+
setCardcvc2,
|
|
29
|
+
isLiveMode = false
|
|
29
30
|
}) => {
|
|
30
31
|
const handleGooglePayToken = (token, paymentData) => {
|
|
31
32
|
if (!token) {
|
|
@@ -41,12 +42,18 @@ const AuthorizationForm = ({
|
|
|
41
42
|
}
|
|
42
43
|
};
|
|
43
44
|
|
|
44
|
-
const handleApplePayToken = (token, paymentData) => {
|
|
45
|
+
const handleApplePayToken = async (token, paymentData) => {
|
|
45
46
|
if (!token) {
|
|
46
|
-
return;
|
|
47
|
+
return Promise.reject(new Error("Token is missing"));
|
|
47
48
|
}
|
|
48
49
|
setApplePayToken(token);
|
|
49
|
-
|
|
50
|
+
try {
|
|
51
|
+
await onAuthorization(token);
|
|
52
|
+
return Promise.resolve();
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error("[Apple Pay] Error in authorization:", error);
|
|
55
|
+
return Promise.reject(error);
|
|
56
|
+
}
|
|
50
57
|
};
|
|
51
58
|
|
|
52
59
|
const handleApplePayError = (error) => {
|
|
@@ -116,13 +123,33 @@ const AuthorizationForm = ({
|
|
|
116
123
|
settings={settings}
|
|
117
124
|
/>
|
|
118
125
|
) : paymentMethod === "apl" ? (
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
+
<Box>
|
|
127
|
+
<ApplePayButton
|
|
128
|
+
amount={paymentAmount}
|
|
129
|
+
currency="EUR"
|
|
130
|
+
onTokenReceived={handleApplePayToken}
|
|
131
|
+
onError={handleApplePayError}
|
|
132
|
+
settings={settings}
|
|
133
|
+
/>
|
|
134
|
+
{applePayToken && (
|
|
135
|
+
<Box marginTop={3} style={{ width: "100%", display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "8px" }}>
|
|
136
|
+
<Typography variant="pi" textColor="success600" style={{ marginBottom: "8px", fontWeight: "bold" }}>
|
|
137
|
+
✓ Apple Pay token received. You can now process the authorization:
|
|
138
|
+
</Typography>
|
|
139
|
+
<Button
|
|
140
|
+
variant="default"
|
|
141
|
+
onClick={() => onAuthorization(applePayToken)}
|
|
142
|
+
loading={isProcessingPayment}
|
|
143
|
+
startIcon={<Play />}
|
|
144
|
+
style={{ maxWidth: '200px' }}
|
|
145
|
+
disabled={!paymentAmount.trim() || !authReference.trim() || isLiveMode}
|
|
146
|
+
className="payment-button payment-button-primary"
|
|
147
|
+
>
|
|
148
|
+
Process Authorization
|
|
149
|
+
</Button>
|
|
150
|
+
</Box>
|
|
151
|
+
)}
|
|
152
|
+
</Box>
|
|
126
153
|
) : (
|
|
127
154
|
<Button
|
|
128
155
|
variant="default"
|
|
@@ -135,7 +162,9 @@ const AuthorizationForm = ({
|
|
|
135
162
|
!paymentAmount.trim() ||
|
|
136
163
|
(paymentMethod === "cc" &&
|
|
137
164
|
settings?.enable3DSecure !== false &&
|
|
138
|
-
(!cardtype || !cardpan || !cardexpiredate || !cardcvc2))
|
|
165
|
+
(!cardtype || !cardpan || !cardexpiredate || !cardcvc2)) ||
|
|
166
|
+
(paymentMethod === "apl" && !applePayToken) ||
|
|
167
|
+
isLiveMode
|
|
139
168
|
}
|
|
140
169
|
>
|
|
141
170
|
Process Authorization
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Box, Flex, Select, Option } from "@strapi/design-system";
|
|
2
|
+
import { Box, Flex, Select, Option, Typography, Link, Alert } from "@strapi/design-system";
|
|
3
|
+
import pluginId from "../../../../pluginId";
|
|
3
4
|
import {
|
|
4
5
|
getPaymentMethodOptions,
|
|
5
6
|
supportsCaptureMode,
|
|
@@ -11,7 +12,8 @@ const PaymentMethodSelector = ({
|
|
|
11
12
|
paymentMethod,
|
|
12
13
|
setPaymentMethod,
|
|
13
14
|
captureMode,
|
|
14
|
-
setCaptureMode
|
|
15
|
+
setCaptureMode,
|
|
16
|
+
onNavigateToConfig
|
|
15
17
|
}) => {
|
|
16
18
|
return (
|
|
17
19
|
<Box>
|
|
@@ -29,6 +31,108 @@ const PaymentMethodSelector = ({
|
|
|
29
31
|
</Option>
|
|
30
32
|
))}
|
|
31
33
|
</Select>
|
|
34
|
+
{paymentMethod === "apl" && onNavigateToConfig && (
|
|
35
|
+
<>
|
|
36
|
+
<Alert closeLabel="Close" title="⚠️ Important: Middleware Configuration Required" variant="warning">
|
|
37
|
+
<Typography variant="pi" marginTop={2}>
|
|
38
|
+
<strong>Apple Pay requires middleware configuration</strong> to work properly. You must configure Content Security Policy (CSP) in <code>config/middlewares.js</code> to allow Apple Pay scripts, otherwise Apple Pay will NOT work.
|
|
39
|
+
</Typography>
|
|
40
|
+
<Typography variant="pi" marginTop={2}>
|
|
41
|
+
Required CSP directives for Apple Pay:
|
|
42
|
+
</Typography>
|
|
43
|
+
<Box marginTop={2} padding={2} background="neutral100" borderRadius="4px">
|
|
44
|
+
<Typography variant="pi" style={{ fontFamily: "monospace", fontSize: "12px" }}>
|
|
45
|
+
'script-src': ['https://applepay.cdn-apple.com', 'https://www.apple.com']<br/>
|
|
46
|
+
'connect-src': ['https://applepay.cdn-apple.com', 'https://www.apple.com']<br/>
|
|
47
|
+
'frame-src': ['https://applepay.cdn-apple.com']
|
|
48
|
+
</Typography>
|
|
49
|
+
</Box>
|
|
50
|
+
<Typography variant="pi" marginTop={2} fontWeight="bold">
|
|
51
|
+
⚠️ Without this configuration, Apple Pay will NOT work!
|
|
52
|
+
</Typography>
|
|
53
|
+
</Alert>
|
|
54
|
+
<Alert closeLabel="Close" title="📥 Apple Pay Domain Verification File Required" variant="default">
|
|
55
|
+
<Typography variant="pi" marginTop={2}>
|
|
56
|
+
<strong>Download the Apple Pay domain verification file</strong> from your Payone merchant portal and place it in:
|
|
57
|
+
</Typography>
|
|
58
|
+
<Box marginTop={2} padding={2} background="neutral100" borderRadius="4px">
|
|
59
|
+
<Typography variant="pi" style={{ fontFamily: "monospace", fontSize: "12px" }}>
|
|
60
|
+
<strong>Strapi:</strong> <code>public/.well-known/apple-developer-merchantid-domain-association</code><br/>
|
|
61
|
+
<strong>Frontend:</strong> <code>public/.well-known/apple-developer-merchantid-domain-association</code>
|
|
62
|
+
</Typography>
|
|
63
|
+
</Box>
|
|
64
|
+
<Typography variant="pi" marginTop={2}>
|
|
65
|
+
<strong>Download URL:</strong> Download the domain verification file from Payone documentation:{" "}
|
|
66
|
+
<Link
|
|
67
|
+
href="https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev"
|
|
68
|
+
target="_blank"
|
|
69
|
+
rel="noopener noreferrer"
|
|
70
|
+
style={{ color: "#0066ff", textDecoration: "underline" }}
|
|
71
|
+
>
|
|
72
|
+
https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev
|
|
73
|
+
</Link>
|
|
74
|
+
</Typography>
|
|
75
|
+
<Typography variant="pi" marginTop={2}>
|
|
76
|
+
<strong>Alternative:</strong> Log into your Payone Merchant Interface (PMI) → Configuration → Payment Portals → Apple Pay → Download domain verification file
|
|
77
|
+
</Typography>
|
|
78
|
+
<Typography variant="pi" marginTop={2} fontWeight="bold" textColor="danger600">
|
|
79
|
+
⚠️ Without this file, Apple Pay will NOT work on your domain!
|
|
80
|
+
</Typography>
|
|
81
|
+
</Alert>
|
|
82
|
+
<Box padding={3} background="neutral100" borderRadius="4px">
|
|
83
|
+
<Typography variant="pi" textColor="neutral600">
|
|
84
|
+
Configure Apple Pay settings:{" "}
|
|
85
|
+
<Link
|
|
86
|
+
href={`/plugins/${pluginId}/apple-pay-config`}
|
|
87
|
+
onClick={(e) => {
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
onNavigateToConfig("apple-pay");
|
|
90
|
+
}}
|
|
91
|
+
style={{ cursor: "pointer", textDecoration: "underline", color: "#0066ff" }}
|
|
92
|
+
>
|
|
93
|
+
/plugins/{pluginId}/apple-pay-config
|
|
94
|
+
</Link>
|
|
95
|
+
</Typography>
|
|
96
|
+
</Box>
|
|
97
|
+
</>
|
|
98
|
+
)}
|
|
99
|
+
{paymentMethod === "gpp" && onNavigateToConfig && (
|
|
100
|
+
<>
|
|
101
|
+
<Alert closeLabel="Close" title="⚠️ Important: Middleware Configuration Required" variant="warning">
|
|
102
|
+
<Typography variant="pi" marginTop={2}>
|
|
103
|
+
<strong>Google Pay requires middleware configuration</strong> to work properly. You must configure Content Security Policy (CSP) in <code>config/middlewares.js</code> to allow Google Pay scripts, otherwise Google Pay will NOT work.
|
|
104
|
+
</Typography>
|
|
105
|
+
<Typography variant="pi" marginTop={2}>
|
|
106
|
+
Required CSP directives for Google Pay:
|
|
107
|
+
</Typography>
|
|
108
|
+
<Box marginTop={2} padding={2} background="neutral100" borderRadius="4px">
|
|
109
|
+
<Typography variant="pi" style={{ fontFamily: "monospace", fontSize: "12px" }}>
|
|
110
|
+
'script-src': ['https://pay.google.com']<br/>
|
|
111
|
+
'connect-src': ['https://pay.google.com']<br/>
|
|
112
|
+
'frame-src': ['https://pay.google.com']
|
|
113
|
+
</Typography>
|
|
114
|
+
</Box>
|
|
115
|
+
<Typography variant="pi" marginTop={2} fontWeight="bold">
|
|
116
|
+
⚠️ Without this configuration, Google Pay will NOT work!
|
|
117
|
+
</Typography>
|
|
118
|
+
</Alert>
|
|
119
|
+
<Box padding={3} background="neutral100" borderRadius="4px">
|
|
120
|
+
<Typography variant="pi" textColor="neutral600">
|
|
121
|
+
Configure Google Pay settings:{" "}
|
|
122
|
+
<Link
|
|
123
|
+
href={`/plugins/${pluginId}/google-pay-config`}
|
|
124
|
+
onClick={(e) => {
|
|
125
|
+
e.preventDefault();
|
|
126
|
+
onNavigateToConfig("google-pay");
|
|
127
|
+
}}
|
|
128
|
+
style={{ cursor: "pointer", textDecoration: "underline", color: "#0066ff" }}
|
|
129
|
+
>
|
|
130
|
+
/plugins/{pluginId}/google-pay-config
|
|
131
|
+
</Link>
|
|
132
|
+
</Typography>
|
|
133
|
+
</Box>
|
|
134
|
+
</>
|
|
135
|
+
)}
|
|
32
136
|
{supportsCaptureMode(paymentMethod) && (
|
|
33
137
|
<Select
|
|
34
138
|
label="Capture Mode"
|