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.
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Box, Flex, Typography, Select, Option, Checkbox, TextInput } from "@strapi/design-system";
2
+ import { Box, Flex, Typography, Select, Option, Checkbox, Stack } from "@strapi/design-system";
3
3
  import {
4
4
  APPLE_PAY_SUPPORTED_COUNTRIES,
5
5
  APPLE_PAY_SUPPORTED_CURRENCIES,
@@ -41,16 +41,16 @@ const ApplePayConfig = ({
41
41
  ...config,
42
42
  countryCode: value
43
43
  };
44
-
44
+
45
45
  // Auto-update currency if current currency is not supported in new country
46
46
  const newSupportedCurrencies = getSupportedCurrenciesForCountry(value);
47
47
  if (!newSupportedCurrencies.find(c => c.code === currencyCode)) {
48
48
  newConfig.currencyCode = newSupportedCurrencies[0]?.code || "USD";
49
49
  }
50
-
50
+
51
51
  // Auto-update networks based on country
52
52
  newConfig.supportedNetworks = getSupportedNetworksForCountry(value);
53
-
53
+
54
54
  onConfigChange(newConfig);
55
55
  };
56
56
 
@@ -66,7 +66,7 @@ const ApplePayConfig = ({
66
66
  const newNetworks = currentNetworks.includes(networkCode)
67
67
  ? currentNetworks.filter(n => n !== networkCode)
68
68
  : [...currentNetworks, networkCode];
69
-
69
+
70
70
  onConfigChange({
71
71
  ...config,
72
72
  supportedNetworks: newNetworks
@@ -78,7 +78,7 @@ const ApplePayConfig = ({
78
78
  const newCapabilities = currentCapabilities.includes(capabilityCode)
79
79
  ? currentCapabilities.filter(c => c !== capabilityCode)
80
80
  : [...currentCapabilities, capabilityCode];
81
-
81
+
82
82
  onConfigChange({
83
83
  ...config,
84
84
  merchantCapabilities: newCapabilities
@@ -86,82 +86,124 @@ const ApplePayConfig = ({
86
86
  };
87
87
 
88
88
  return (
89
- <Box padding={4}>
90
- <Flex direction="column" gap={4}>
91
- <Typography variant="omega" fontWeight="semiBold">
92
- Apple Pay Configuration
93
- </Typography>
94
-
95
- {/* Country Code */}
89
+ <Box>
90
+ <Stack spacing={6}>
96
91
  <Box>
97
- <Select
98
- label="Country Code *"
99
- name="countryCode"
100
- value={countryCode}
101
- onChange={handleCountryChange}
102
- hint="Select the country where your business operates"
103
- required
104
- >
105
- {APPLE_PAY_SUPPORTED_COUNTRIES.map(country => (
106
- <Option key={country.code} value={country.code}>
107
- {country.name} ({country.code})
108
- </Option>
109
- ))}
110
- </Select>
92
+ <Typography variant="delta" as="h3" fontWeight="bold" style={{ marginBottom: "6px" }}>
93
+ Apple Pay Configuration
94
+ </Typography>
95
+ <Typography variant="pi" textColor="neutral600">
96
+ Configure Apple Pay settings for your payment gateway
97
+ </Typography>
111
98
  </Box>
112
99
 
113
- {/* Currency Code */}
114
- <Box>
115
- <Select
116
- label="Currency Code *"
117
- name="currencyCode"
118
- value={currencyCode}
119
- onChange={handleCurrencyChange}
120
- hint={`Supported currencies for ${countryCode}. Some currencies may be restricted.`}
121
- required
122
- >
123
- {supportedCurrencies.map(currency => (
124
- <Option key={currency.code} value={currency.code}>
125
- {currency.name} ({currency.code}) {currency.symbol}
126
- </Option>
127
- ))}
128
- </Select>
129
- {supportedCurrencies.length === 0 && (
130
- <Typography variant="pi" textColor="danger600" style={{ marginTop: "4px" }}>
131
- No supported currencies for this country. Please select a different country.
132
- </Typography>
133
- )}
134
- </Box>
100
+ {/* Country and Currency */}
101
+ <Flex gap={4} wrap="wrap">
102
+ <Box style={{ flex: 1, minWidth: "300px" }}>
103
+ <Select
104
+ label="Country Code"
105
+ name="countryCode"
106
+ value={countryCode}
107
+ onChange={handleCountryChange}
108
+ hint="Select the country where your business operates"
109
+ required
110
+ >
111
+ {APPLE_PAY_SUPPORTED_COUNTRIES.map(country => (
112
+ <Option key={country.code} value={country.code}>
113
+ {country.name} ({country.code})
114
+ </Option>
115
+ ))}
116
+ </Select>
117
+ </Box>
118
+
119
+ <Box style={{ flex: 1, minWidth: "300px" }}>
120
+ <Select
121
+ label="Currency Code"
122
+ name="currencyCode"
123
+ value={currencyCode}
124
+ onChange={handleCurrencyChange}
125
+ hint={`Supported currencies for ${countryCode}`}
126
+ required
127
+ >
128
+ {supportedCurrencies.map(currency => (
129
+ <Option key={currency.code} value={currency.code}>
130
+ {currency.name} ({currency.code}) {currency.symbol}
131
+ </Option>
132
+ ))}
133
+ </Select>
134
+ {supportedCurrencies.length === 0 && (
135
+ <Typography variant="pi" textColor="danger600" style={{ marginTop: "4px" }}>
136
+ No supported currencies for this country. Please select a different country.
137
+ </Typography>
138
+ )}
139
+ </Box>
140
+ </Flex>
141
+
142
+ {/* Button Style and Type */}
143
+ <Flex gap={4} wrap="wrap">
144
+ <Box style={{ flex: 1, minWidth: "300px" }}>
145
+ <Select
146
+ label="Button Style"
147
+ name="buttonStyle"
148
+ value={buttonStyle}
149
+ onChange={(value) => onConfigChange({ ...config, buttonStyle: value })}
150
+ hint="Visual style of the Apple Pay button"
151
+ >
152
+ {APPLE_PAY_BUTTON_STYLES.map(style => (
153
+ <Option key={style.code} value={style.code}>
154
+ {style.name}
155
+ </Option>
156
+ ))}
157
+ </Select>
158
+ </Box>
159
+
160
+ <Box style={{ flex: 1, minWidth: "300px" }}>
161
+ <Select
162
+ label="Button Type"
163
+ name="buttonType"
164
+ value={buttonType}
165
+ onChange={(value) => onConfigChange({ ...config, buttonType: value })}
166
+ hint="Type of action the button represents"
167
+ >
168
+ {APPLE_PAY_BUTTON_TYPES.map(type => (
169
+ <Option key={type.code} value={type.code}>
170
+ {type.name}
171
+ </Option>
172
+ ))}
173
+ </Select>
174
+ </Box>
175
+ </Flex>
135
176
 
136
177
  {/* Supported Networks */}
137
178
  <Box>
138
- <Typography variant="pi" fontWeight="semiBold" style={{ marginBottom: "8px" }}>
139
- Supported Networks *
179
+ <Typography variant="pi" fontWeight="semiBold" style={{ marginLeft: "2px" }}>
180
+ Supported Networks
140
181
  </Typography>
141
- <Typography variant="sigma" textColor="neutral600" style={{ marginBottom: "12px" }}>
182
+ <Typography variant="pi" textColor="neutral600" style={{ marginLeft: "2px" }}>
142
183
  Select payment networks supported in {countryCode}
143
184
  </Typography>
144
- <Flex direction="column" gap={2}>
185
+ <Flex wrap="wrap" gap={4} style={{ marginTop: "12px" }}>
145
186
  {APPLE_PAY_SUPPORTED_NETWORKS.map(network => {
146
187
  const isSupported = supportedNetworksForCountry.includes(network.code);
147
188
  const isSelected = supportedNetworks?.includes(network.code);
148
-
189
+
149
190
  return (
150
- <Checkbox
151
- key={network.code}
152
- name={`network-${network.code}`}
153
- checked={isSelected}
154
- onChange={() => handleNetworkToggle(network.code)}
155
- disabled={!isSupported}
156
- hint={!isSupported ? `Not supported in ${countryCode}` : undefined}
157
- >
158
- {network.name} ({network.code})
159
- {!isSupported && (
160
- <Typography variant="sigma" textColor="neutral500" style={{ marginLeft: "8px" }}>
161
- (Not available in {countryCode})
162
- </Typography>
163
- )}
164
- </Checkbox>
191
+ <Box key={network.code} style={{ flex: "0 0 calc(50% - 8px)", minWidth: "250px" }}>
192
+ <Checkbox
193
+ name={`network-${network.code}`}
194
+ checked={isSelected}
195
+ onChange={() => handleNetworkToggle(network.code)}
196
+ disabled={!isSupported}
197
+ hint={!isSupported ? `Not supported in ${countryCode}` : undefined}
198
+ >
199
+ {network.name} ({network.code})
200
+ {!isSupported && (
201
+ <Typography variant="sigma" textColor="neutral500" style={{ marginLeft: "8px" }}>
202
+ (Not available)
203
+ </Typography>
204
+ )}
205
+ </Checkbox>
206
+ </Box>
165
207
  );
166
208
  })}
167
209
  </Flex>
@@ -174,25 +216,26 @@ const ApplePayConfig = ({
174
216
 
175
217
  {/* Merchant Capabilities */}
176
218
  <Box>
177
- <Typography variant="pi" fontWeight="semiBold" style={{ marginBottom: "8px" }}>
178
- Merchant Capabilities *
219
+ <Typography variant="pi" fontWeight="semiBold" style={{ marginLeft: "2px" }}>
220
+ Merchant Capabilities
179
221
  </Typography>
180
- <Typography variant="sigma" textColor="neutral600" style={{ marginBottom: "12px" }}>
222
+ <Typography variant="pi" textColor="neutral600" style={{ marginLeft: "2px" }}>
181
223
  Select payment capabilities. "3D Secure" is required for most payment methods.
182
224
  </Typography>
183
- <Flex direction="column" gap={2}>
225
+ <Flex wrap="wrap" gap={4} style={{ marginTop: "12px" }}>
184
226
  {APPLE_PAY_MERCHANT_CAPABILITIES.map(capability => {
185
227
  const isSelected = merchantCapabilities?.includes(capability.code);
186
-
228
+
187
229
  return (
188
- <Checkbox
189
- key={capability.code}
190
- name={`capability-${capability.code}`}
191
- checked={isSelected}
192
- onChange={() => handleCapabilityToggle(capability.code)}
193
- >
194
- {capability.name} - {capability.description}
195
- </Checkbox>
230
+ <Box key={capability.code} style={{ flex: "0 0 calc(50% - 8px)", minWidth: "250px" }}>
231
+ <Checkbox
232
+ name={`capability-${capability.code}`}
233
+ checked={isSelected}
234
+ onChange={() => handleCapabilityToggle(capability.code)}
235
+ >
236
+ {capability.name} - {capability.description}
237
+ </Checkbox>
238
+ </Box>
196
239
  );
197
240
  })}
198
241
  </Flex>
@@ -203,103 +246,119 @@ const ApplePayConfig = ({
203
246
  )}
204
247
  </Box>
205
248
 
206
- {/* Button Style */}
207
- <Box>
208
- <Select
209
- label="Button Style"
210
- name="buttonStyle"
211
- value={buttonStyle}
212
- onChange={(value) => onConfigChange({ ...config, buttonStyle: value })}
213
- hint="Visual style of the Apple Pay button"
214
- >
215
- {APPLE_PAY_BUTTON_STYLES.map(style => (
216
- <Option key={style.code} value={style.code}>
217
- {style.name}
218
- </Option>
219
- ))}
220
- </Select>
221
- </Box>
222
-
223
- {/* Button Type */}
224
- <Box>
225
- <Select
226
- label="Button Type"
227
- name="buttonType"
228
- value={buttonType}
229
- onChange={(value) => onConfigChange({ ...config, buttonType: value })}
230
- hint="Type of action the button represents"
231
- >
232
- {APPLE_PAY_BUTTON_TYPES.map(type => (
233
- <Option key={type.code} value={type.code}>
234
- {type.name}
235
- </Option>
236
- ))}
237
- </Select>
238
- </Box>
239
-
240
249
  {/* Payment Options */}
241
- <Box>
242
- <Typography variant="pi" fontWeight="semiBold" style={{ marginBottom: "8px" }}>
250
+ {/* <Box>
251
+ <Typography variant="pi" fontWeight="semiBold" style={{ marginLeft: "2px", marginBottom: "6px" }}>
243
252
  Payment Options
244
253
  </Typography>
245
- <Flex direction="column" gap={2}>
246
- <Checkbox
247
- name="requestPayerName"
248
- checked={requestPayerName}
249
- onChange={(checked) => onConfigChange({ ...config, requestPayerName: checked })}
250
- >
251
- Request Payer Name
252
- </Checkbox>
253
- <Checkbox
254
- name="requestBillingAddress"
255
- checked={requestBillingAddress}
256
- onChange={(checked) => onConfigChange({ ...config, requestBillingAddress: checked })}
257
- >
258
- Request Billing Address
259
- </Checkbox>
260
- <Checkbox
261
- name="requestPayerEmail"
262
- checked={requestPayerEmail}
263
- onChange={(checked) => onConfigChange({ ...config, requestPayerEmail: checked })}
264
- >
265
- Request Payer Email
266
- </Checkbox>
267
- <Checkbox
268
- name="requestPayerPhone"
269
- checked={requestPayerPhone}
270
- onChange={(checked) => onConfigChange({ ...config, requestPayerPhone: checked })}
271
- >
272
- Request Payer Phone
273
- </Checkbox>
274
- <Checkbox
275
- name="requestShipping"
276
- checked={requestShipping}
277
- onChange={(checked) => onConfigChange({ ...config, requestShipping: checked })}
278
- >
279
- Request Shipping Address
280
- </Checkbox>
254
+ <Typography variant="pi" textColor="neutral600" style={{ marginLeft: "2px" }}>
255
+ Select the information you want to collect during payment
256
+ </Typography>
257
+ <Flex wrap="wrap" gap={4} style={{ marginTop: "12px" }}>
258
+ <Box style={{ flex: "0 0 calc(33.333% - 11px)", minWidth: "200px" }}>
259
+ <Checkbox
260
+ name="requestPayerName"
261
+ checked={requestPayerName}
262
+ onChange={(checked) => onConfigChange({ ...config, requestPayerName: checked })}
263
+ >
264
+ Request Payer Name
265
+ </Checkbox>
266
+ </Box>
267
+ <Box style={{ flex: "0 0 calc(33.333% - 11px)", minWidth: "200px" }}>
268
+ <Checkbox
269
+ name="requestBillingAddress"
270
+ checked={requestBillingAddress}
271
+ onChange={(checked) => onConfigChange({ ...config, requestBillingAddress: checked })}
272
+ >
273
+ Request Billing Address
274
+ </Checkbox>
275
+ </Box>
276
+ <Box style={{ flex: "0 0 calc(33.333% - 11px)", minWidth: "200px" }}>
277
+ <Checkbox
278
+ name="requestPayerEmail"
279
+ checked={requestPayerEmail}
280
+ onChange={(checked) => onConfigChange({ ...config, requestPayerEmail: checked })}
281
+ >
282
+ Request Payer Email
283
+ </Checkbox>
284
+ </Box>
285
+ <Box style={{ flex: "0 0 calc(33.333% - 11px)", minWidth: "200px" }}>
286
+ <Checkbox
287
+ name="requestPayerPhone"
288
+ checked={requestPayerPhone}
289
+ onChange={(checked) => onConfigChange({ ...config, requestPayerPhone: checked })}
290
+ >
291
+ Request Payer Phone
292
+ </Checkbox>
293
+ </Box>
294
+ <Box style={{ flex: "0 0 calc(33.333% - 11px)", minWidth: "200px" }}>
295
+ <Checkbox
296
+ name="requestShipping"
297
+ checked={requestShipping}
298
+ onChange={(checked) => onConfigChange({ ...config, requestShipping: checked })}
299
+ >
300
+ Request Shipping Address
301
+ </Checkbox>
302
+ </Box>
281
303
  </Flex>
282
- </Box>
304
+ </Box> */}
283
305
 
284
306
  {/* Merchant Identifier Info */}
285
- <Box padding={3} background="neutral100" borderRadius="4px">
286
- <Typography variant="pi" fontWeight="semiBold" style={{ marginBottom: "4px" }}>
307
+ <Box>
308
+ <Typography variant="pi" fontWeight="semiBold" style={{ marginLeft: "2px" }}>
287
309
  Merchant Identifier
288
310
  </Typography>
289
- <Typography variant="sigma" textColor="neutral600">
290
- {settings?.mid || settings?.portalid
311
+ <Typography variant="pi" textColor="neutral600">
312
+ {settings?.mid || settings?.portalid
291
313
  ? `Using: ${settings.mid || settings.portalid}`
292
314
  : "Merchant identifier will be obtained from Payone after domain verification. See documentation for setup instructions."
293
315
  }
294
316
  </Typography>
295
317
  </Box>
296
- </Flex>
318
+
319
+ {/* Domain Verification File Alert */}
320
+ <Box marginTop={4}>
321
+ <Box padding={3} background="warning100" borderRadius="4px" borderColor="warning200" borderWidth="1px" borderStyle="solid">
322
+ <Typography variant="pi" fontWeight="bold" textColor="warning700" marginBottom={2}>
323
+ ⚠️ Domain Verification File Required
324
+ </Typography>
325
+ <Typography variant="pi" textColor="neutral700" marginBottom={2}>
326
+ <strong>Download the Apple Pay domain verification file</strong> from your Payone merchant portal:
327
+ </Typography>
328
+ <Box padding={2} background="neutral0" borderRadius="4px" marginTop={2} marginBottom={2}>
329
+ <Typography variant="pi" style={{ fontSize: "12px" }}>
330
+ <strong>Download URL:</strong> Download the domain verification file from Payone documentation:{" "}
331
+ <a
332
+ href="https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev"
333
+ target="_blank"
334
+ rel="noopener noreferrer"
335
+ style={{ color: "#0066ff", textDecoration: "underline" }}
336
+ >
337
+ https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev
338
+ </a>
339
+ {" "}or log into your Payone Merchant Interface (PMI) → Configuration → Payment Portals → Apple Pay → Download domain verification file
340
+ </Typography>
341
+ </Box>
342
+ <Typography variant="pi" textColor="neutral700" marginBottom={2}>
343
+ <strong>Place the file at:</strong>
344
+ </Typography>
345
+ <Box padding={2} background="neutral0" borderRadius="4px" marginTop={2} marginBottom={2}>
346
+ <Typography variant="pi" style={{ fontFamily: "monospace", fontSize: "12px" }}>
347
+ <strong>Strapi:</strong> <code>public/.well-known/apple-developer-merchantid-domain-association</code><br/>
348
+ <strong>Frontend:</strong> <code>public/.well-known/apple-developer-merchantid-domain-association</code>
349
+ </Typography>
350
+ </Box>
351
+ <Typography variant="pi" textColor="neutral700" marginTop={2}>
352
+ The file must be accessible at: <code>https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association</code>
353
+ </Typography>
354
+ <Typography variant="pi" fontWeight="bold" textColor="danger600" marginTop={2}>
355
+ ⚠️ Without this file, Apple Pay will NOT work on your domain!
356
+ </Typography>
357
+ </Box>
358
+ </Box>
359
+ </Stack>
297
360
  </Box>
298
361
  );
299
362
  };
300
363
 
301
- export default ApplePayConfig;
302
-
303
-
304
-
305
-
364
+ export default ApplePayConfig;
@@ -0,0 +1,81 @@
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 ApplePayConfig from "./ApplePayConfig";
12
+
13
+ const ApplePayConfigPanel = ({
14
+ settings,
15
+ onInputChange,
16
+ isSaving,
17
+ onSave
18
+ }) => {
19
+ const [applePayConfig, setApplePayConfig] = useState(settings?.applePayConfig || {});
20
+
21
+ useEffect(() => {
22
+ setApplePayConfig(settings?.applePayConfig || {});
23
+ }, [settings?.applePayConfig]);
24
+
25
+ return (
26
+ <Box
27
+ className="payment-container"
28
+ paddingTop={8}
29
+ paddingBottom={8}
30
+ paddingLeft={8}
31
+ paddingRight={8}
32
+ >
33
+ <Flex direction="column" alignItems="stretch" gap={8}>
34
+ <Box>
35
+ <Typography variant="beta" as="h2" fontWeight="bold" className="payment-title" style={{ fontSize: '20px', marginBottom: '4px' }}>
36
+ Apple Pay Configuration
37
+ </Typography>
38
+ <Typography variant="pi" textColor="neutral600" marginTop={2} className="payment-subtitle" style={{ fontSize: '14px' }}>
39
+ Configure Apple Pay settings for your payment gateway
40
+ </Typography>
41
+ </Box>
42
+
43
+ <Box>
44
+ <Card className="payment-card">
45
+ <CardBody padding={6}>
46
+ <ApplePayConfig
47
+ config={applePayConfig}
48
+ onConfigChange={(newConfig) => {
49
+ setApplePayConfig(newConfig);
50
+ onInputChange("applePayConfig", newConfig);
51
+ }}
52
+ settings={settings}
53
+ />
54
+ </CardBody>
55
+ </Card>
56
+ </Box>
57
+
58
+ <Box paddingTop={4}>
59
+ <Flex direction="row" gap={4} alignItems="center">
60
+ <Button
61
+ loading={isSaving}
62
+ onClick={onSave}
63
+ startIcon={<Check />}
64
+ size="L"
65
+ variant="default"
66
+ className="payment-button payment-button-success"
67
+ >
68
+ Save Apple Pay Configuration
69
+ </Button>
70
+ <Typography variant="sigma" textColor="neutral600">
71
+ Note: Apple Pay configuration is used for Apple Pay payment requests. Make sure to configure the correct merchant identifier, supported networks, and capabilities for your region.
72
+ </Typography>
73
+ </Flex>
74
+ </Box>
75
+ </Flex>
76
+ </Box>
77
+ );
78
+ };
79
+
80
+ export default ApplePayConfigPanel;
81
+
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { useEffect } from "react";
2
2
  import {
3
3
  Box,
4
4
  Button,
@@ -23,6 +23,16 @@ const ConfigurationPanel = ({
23
23
  onTestConnection,
24
24
  onInputChange
25
25
  }) => {
26
+ const mode = (settings?.mode || "test").toLowerCase();
27
+
28
+ useEffect(() => {
29
+ if (settings?.mode) {
30
+ const currentMode = (settings.mode || "test").toLowerCase();
31
+ console.log("[ConfigurationPanel] Mode updated:", currentMode);
32
+ }
33
+ }, [settings?.mode]);
34
+
35
+
26
36
  return (
27
37
  <Box
28
38
  className="payment-container"
@@ -104,8 +114,8 @@ const ConfigurationPanel = ({
104
114
  className="payment-input"
105
115
  style={{ flex: 1, minWidth: "300px" }}
106
116
  >
107
- <Option value="test">Test Environment</Option>
108
- <Option value="live">Live Environment</Option>
117
+ <Option value="test">Test</Option>
118
+ <Option value="live">Live</Option>
109
119
  </Select>
110
120
 
111
121
  <TextInput
@@ -169,9 +179,15 @@ const ConfigurationPanel = ({
169
179
  loading={isTesting}
170
180
  startIcon={<Play />}
171
181
  className="payment-button payment-button-success"
182
+ disabled={mode === 'live'}
172
183
  >
173
184
  {isTesting ? "Testing Connection..." : "Test Connection"}
174
185
  </Button>
186
+ {mode === 'live' && (
187
+ <Typography variant="pi" textColor="neutral600" style={{ marginTop: "8px" }}>
188
+ Test Connection is disabled in live mode for security reasons.
189
+ </Typography>
190
+ )}
175
191
 
176
192
  {testResult && (
177
193
  <Alert