strapi-plugin-payone-provider 1.5.0 → 1.5.3
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 +93 -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 +58 -12
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.js +106 -2
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.js +55 -20
- package/admin/src/pages/App/index.js +70 -1
- package/admin/src/pages/hooks/usePaymentActions.js +38 -2
- 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
|
@@ -25,7 +25,8 @@ const PreauthorizationForm = ({
|
|
|
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,35 @@ const PreauthorizationForm = ({
|
|
|
41
42
|
}
|
|
42
43
|
};
|
|
43
44
|
|
|
44
|
-
const handleApplePayToken = (token, paymentData) => {
|
|
45
|
+
const handleApplePayToken = async (token, paymentData) => {
|
|
45
46
|
if (!token) {
|
|
46
|
-
|
|
47
|
+
console.error("[Apple Pay] Token is missing in handleApplePayToken");
|
|
48
|
+
return Promise.reject(new Error("Token is missing"));
|
|
47
49
|
}
|
|
50
|
+
|
|
51
|
+
console.log("[Apple Pay] handleApplePayToken called with token:", {
|
|
52
|
+
hasToken: !!token,
|
|
53
|
+
tokenLength: token?.length,
|
|
54
|
+
paymentData: !!paymentData
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// IMPORTANT: Set token in state immediately (synchronously)
|
|
58
|
+
// This ensures the token is saved before the dialog closes
|
|
48
59
|
setApplePayToken(token);
|
|
49
|
-
|
|
60
|
+
|
|
61
|
+
console.log("[Apple Pay] Token saved to state successfully");
|
|
62
|
+
|
|
63
|
+
// Don't call onPreauthorization immediately
|
|
64
|
+
// Let the user manually trigger the payment using the button
|
|
65
|
+
// This prevents the dialog from closing prematurely if there's an error
|
|
66
|
+
// The dialog will close with success, and the user will see the "Process Preauthorization" button
|
|
67
|
+
|
|
68
|
+
// Return success immediately so the dialog closes properly
|
|
69
|
+
// The actual payment processing will happen when the user clicks the button
|
|
70
|
+
return Promise.resolve({
|
|
71
|
+
success: true,
|
|
72
|
+
message: "Token received successfully. Please click 'Process Preauthorization' to complete the payment."
|
|
73
|
+
});
|
|
50
74
|
};
|
|
51
75
|
|
|
52
76
|
const handleApplePayError = (error) => {
|
|
@@ -122,21 +146,31 @@ const PreauthorizationForm = ({
|
|
|
122
146
|
onError={handleApplePayError}
|
|
123
147
|
settings={settings}
|
|
124
148
|
/>
|
|
125
|
-
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
149
|
+
{applePayToken && (
|
|
150
|
+
<Box marginTop={3} style={{ width: "100%", display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "8px" }}>
|
|
151
|
+
<Typography variant="pi" textColor="success600" style={{ marginBottom: "8px", fontWeight: "bold" }}>
|
|
152
|
+
✓ Apple Pay token received. You can now process the preauthorization:
|
|
153
|
+
</Typography>
|
|
154
|
+
<Button
|
|
155
|
+
variant="default"
|
|
156
|
+
onClick={() => onPreauthorization(applePayToken)}
|
|
157
|
+
loading={isProcessingPayment}
|
|
158
|
+
startIcon={<Play />}
|
|
159
|
+
style={{ maxWidth: '200px' }}
|
|
160
|
+
disabled={!paymentAmount.trim() || !preauthReference.trim() || isLiveMode}
|
|
161
|
+
className="payment-button payment-button-primary"
|
|
162
|
+
>
|
|
163
|
+
Process Preauthorization
|
|
164
|
+
</Button>
|
|
165
|
+
</Box>
|
|
166
|
+
)}
|
|
167
|
+
{!applePayToken && (
|
|
168
|
+
<Box marginTop={3} style={{ width: "100%", display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "8px" }}>
|
|
169
|
+
<Typography variant="pi" textColor="neutral600" style={{ marginBottom: "8px" }}>
|
|
170
|
+
Apple Pay is not available on localhost. You can test the payment flow without Apple Pay token:
|
|
171
|
+
</Typography>
|
|
172
|
+
</Box>
|
|
173
|
+
)}
|
|
140
174
|
</Box>
|
|
141
175
|
) : (
|
|
142
176
|
<Button
|
|
@@ -150,7 +184,8 @@ const PreauthorizationForm = ({
|
|
|
150
184
|
!paymentAmount.trim() ||
|
|
151
185
|
(paymentMethod === "cc" &&
|
|
152
186
|
settings?.enable3DSecure !== false &&
|
|
153
|
-
(!cardtype || !cardpan || !cardexpiredate || !cardcvc2))
|
|
187
|
+
(!cardtype || !cardpan || !cardexpiredate || !cardcvc2)) ||
|
|
188
|
+
isLiveMode
|
|
154
189
|
}
|
|
155
190
|
>
|
|
156
191
|
Process Preauthorization
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
|
+
import { useLocation, useHistory } from "react-router-dom";
|
|
2
3
|
import { Layout, ContentLayout, Box } from "@strapi/design-system";
|
|
3
4
|
import useSettings from "../hooks/useSettings";
|
|
4
5
|
import useTransactionHistory from "../hooks/useTransactionHistory";
|
|
5
6
|
import usePaymentActions from "../hooks/usePaymentActions";
|
|
6
7
|
import AppHeader from "./components/AppHeader";
|
|
7
8
|
import AppTabs from "./components/AppTabs";
|
|
9
|
+
import ApplePayConfigPanel from "./components/ApplePayConfigPanel";
|
|
10
|
+
import GooglePayConfigPanel from "./components/GooglePayConfigPanel";
|
|
8
11
|
import "./styles.css";
|
|
12
|
+
import pluginId from "../../pluginId";
|
|
9
13
|
|
|
10
14
|
const App = () => {
|
|
15
|
+
const location = useLocation();
|
|
16
|
+
const history = useHistory();
|
|
11
17
|
const [activeTab, setActiveTab] = useState(0);
|
|
12
18
|
|
|
13
19
|
// Custom hooks
|
|
@@ -15,6 +21,68 @@ const App = () => {
|
|
|
15
21
|
const transactionHistory = useTransactionHistory();
|
|
16
22
|
const paymentActions = usePaymentActions();
|
|
17
23
|
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (location.pathname.includes('/apple-pay-config') || location.pathname.includes('/google-pay-config')) {
|
|
26
|
+
} else {
|
|
27
|
+
const tabFromPath = location.pathname.includes('/history') ? 1 :
|
|
28
|
+
location.pathname.includes('/payment-actions') ? 2 :
|
|
29
|
+
location.pathname.includes('/documentation') ? 3 : 0;
|
|
30
|
+
setActiveTab(tabFromPath);
|
|
31
|
+
}
|
|
32
|
+
}, [location.pathname]);
|
|
33
|
+
|
|
34
|
+
const isApplePayConfigPage = location.pathname.includes('/apple-pay-config');
|
|
35
|
+
const isGooglePayConfigPage = location.pathname.includes('/google-pay-config');
|
|
36
|
+
|
|
37
|
+
if (isApplePayConfigPage) {
|
|
38
|
+
return (
|
|
39
|
+
<Layout>
|
|
40
|
+
<AppHeader
|
|
41
|
+
title="Apple Pay Configuration"
|
|
42
|
+
activeTab={null}
|
|
43
|
+
isSaving={settings.isSaving}
|
|
44
|
+
onSave={settings.handleSave}
|
|
45
|
+
onBack={() => history.push(`/plugins/${pluginId}`)}
|
|
46
|
+
/>
|
|
47
|
+
<ContentLayout>
|
|
48
|
+
<Box padding={6}>
|
|
49
|
+
<ApplePayConfigPanel
|
|
50
|
+
settings={settings.settings}
|
|
51
|
+
onInputChange={settings.handleInputChange}
|
|
52
|
+
isSaving={settings.isSaving}
|
|
53
|
+
onSave={settings.handleSave}
|
|
54
|
+
/>
|
|
55
|
+
</Box>
|
|
56
|
+
</ContentLayout>
|
|
57
|
+
</Layout>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isGooglePayConfigPage) {
|
|
62
|
+
return (
|
|
63
|
+
<Layout>
|
|
64
|
+
<AppHeader
|
|
65
|
+
title="Google Pay Configuration"
|
|
66
|
+
activeTab={null}
|
|
67
|
+
isSaving={settings.isSaving}
|
|
68
|
+
onSave={settings.handleSave}
|
|
69
|
+
onBack={() => history.push(`/plugins/${pluginId}`)}
|
|
70
|
+
/>
|
|
71
|
+
<ContentLayout>
|
|
72
|
+
<Box padding={6}>
|
|
73
|
+
<GooglePayConfigPanel
|
|
74
|
+
settings={settings.settings}
|
|
75
|
+
onInputChange={settings.handleInputChange}
|
|
76
|
+
isSaving={settings.isSaving}
|
|
77
|
+
onSave={settings.handleSave}
|
|
78
|
+
onBack={() => history.push(`/plugins/${pluginId}`)}
|
|
79
|
+
/>
|
|
80
|
+
</Box>
|
|
81
|
+
</ContentLayout>
|
|
82
|
+
</Layout>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
18
86
|
return (
|
|
19
87
|
<Layout>
|
|
20
88
|
<AppHeader
|
|
@@ -48,6 +116,7 @@ const App = () => {
|
|
|
48
116
|
selectedTransaction={transactionHistory.selectedTransaction}
|
|
49
117
|
onTransactionSelect={transactionHistory.handleTransactionSelect}
|
|
50
118
|
paymentActions={paymentActions}
|
|
119
|
+
history={history}
|
|
51
120
|
/>
|
|
52
121
|
</Box>
|
|
53
122
|
</ContentLayout>
|
|
@@ -83,6 +83,12 @@ const usePaymentActions = () => {
|
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
const handlePreauthorization = async (tokenParam = null) => {
|
|
86
|
+
console.log("[Payment] handlePreauthorization called", {
|
|
87
|
+
hasToken: !!tokenParam,
|
|
88
|
+
paymentMethod,
|
|
89
|
+
amount: paymentAmount
|
|
90
|
+
});
|
|
91
|
+
|
|
86
92
|
setIsProcessingPayment(true);
|
|
87
93
|
setPaymentError(null);
|
|
88
94
|
setPaymentResult(null);
|
|
@@ -211,16 +217,31 @@ const usePaymentActions = () => {
|
|
|
211
217
|
|
|
212
218
|
setPaymentResult(responseData);
|
|
213
219
|
|
|
220
|
+
console.log("[Payment] Preauthorization result:", {
|
|
221
|
+
status,
|
|
222
|
+
hasError: !!errorCode,
|
|
223
|
+
errorCode,
|
|
224
|
+
errorMessage
|
|
225
|
+
});
|
|
226
|
+
|
|
214
227
|
if (status === "APPROVED") {
|
|
215
228
|
handlePaymentSuccess("Preauthorization completed successfully");
|
|
229
|
+
// Return success result for Apple Pay callback
|
|
230
|
+
return { success: true, data: responseData };
|
|
216
231
|
} else {
|
|
232
|
+
const errorMsg = errorMessage || `Unexpected status: ${status}`;
|
|
217
233
|
handlePaymentError(
|
|
218
|
-
{ message:
|
|
234
|
+
{ message: errorMsg },
|
|
219
235
|
`Preauthorization completed with status: ${status}`
|
|
220
236
|
);
|
|
237
|
+
// Return error result for Apple Pay callback
|
|
238
|
+
throw new Error(errorMsg);
|
|
221
239
|
}
|
|
222
240
|
} catch (error) {
|
|
241
|
+
console.error("[Payment] Preauthorization error:", error);
|
|
223
242
|
handlePaymentError(error, "Preauthorization failed");
|
|
243
|
+
// Re-throw error so Apple Pay callback knows it failed
|
|
244
|
+
throw error;
|
|
224
245
|
} finally {
|
|
225
246
|
setIsProcessingPayment(false);
|
|
226
247
|
}
|
|
@@ -356,16 +377,31 @@ const usePaymentActions = () => {
|
|
|
356
377
|
|
|
357
378
|
setPaymentResult(responseData);
|
|
358
379
|
|
|
380
|
+
console.log("[Payment] Authorization result:", {
|
|
381
|
+
status,
|
|
382
|
+
hasError: !!errorCode,
|
|
383
|
+
errorCode,
|
|
384
|
+
errorMessage
|
|
385
|
+
});
|
|
386
|
+
|
|
359
387
|
if (status === "APPROVED") {
|
|
360
388
|
handlePaymentSuccess("Authorization completed successfully");
|
|
389
|
+
// Return success result for Apple Pay callback
|
|
390
|
+
return { success: true, data: responseData };
|
|
361
391
|
} else {
|
|
392
|
+
const errorMsg = errorMessage || `Unexpected status: ${status}`;
|
|
362
393
|
handlePaymentError(
|
|
363
|
-
{ message:
|
|
394
|
+
{ message: errorMsg },
|
|
364
395
|
`Authorization completed with status: ${status}`
|
|
365
396
|
);
|
|
397
|
+
// Return error result for Apple Pay callback
|
|
398
|
+
throw new Error(errorMsg);
|
|
366
399
|
}
|
|
367
400
|
} catch (error) {
|
|
401
|
+
console.error("[Payment] Authorization error:", error);
|
|
368
402
|
handlePaymentError(error, "Authorization failed");
|
|
403
|
+
// Re-throw error so Apple Pay callback knows it failed
|
|
404
|
+
throw error;
|
|
369
405
|
} finally {
|
|
370
406
|
setIsProcessingPayment(false);
|
|
371
407
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Pay Constants
|
|
3
|
+
* Based on Google Pay documentation and Payone requirements
|
|
4
|
+
* https://developers.google.com/pay/api/web/overview
|
|
5
|
+
* https://docs.payone.com/display/public/PLATFORM/Google+Pay
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Google Pay supported card networks
|
|
9
|
+
export const GOOGLE_PAY_SUPPORTED_NETWORKS = [
|
|
10
|
+
{ code: "MASTERCARD", name: "Mastercard" },
|
|
11
|
+
{ code: "VISA", name: "Visa" },
|
|
12
|
+
{ code: "AMEX", name: "American Express" },
|
|
13
|
+
{ code: "DISCOVER", name: "Discover" },
|
|
14
|
+
{ code: "JCB", name: "JCB" }
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
// Google Pay supported authentication methods
|
|
18
|
+
export const GOOGLE_PAY_AUTH_METHODS = [
|
|
19
|
+
{ code: "PAN_ONLY", name: "PAN Only", description: "Basic card authentication" },
|
|
20
|
+
{ code: "CRYPTOGRAM_3DS", name: "3D Secure", description: "3D Secure authentication" }
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// Google Pay supported countries
|
|
24
|
+
export const GOOGLE_PAY_SUPPORTED_COUNTRIES = [
|
|
25
|
+
{ code: "US", name: "United States" },
|
|
26
|
+
{ code: "GB", name: "United Kingdom" },
|
|
27
|
+
{ code: "CA", name: "Canada" },
|
|
28
|
+
{ code: "AU", name: "Australia" },
|
|
29
|
+
{ code: "DE", name: "Germany" },
|
|
30
|
+
{ code: "FR", name: "France" },
|
|
31
|
+
{ code: "IT", name: "Italy" },
|
|
32
|
+
{ code: "ES", name: "Spain" },
|
|
33
|
+
{ code: "NL", name: "Netherlands" },
|
|
34
|
+
{ code: "BE", name: "Belgium" },
|
|
35
|
+
{ code: "CH", name: "Switzerland" },
|
|
36
|
+
{ code: "AT", name: "Austria" },
|
|
37
|
+
{ code: "IE", name: "Ireland" },
|
|
38
|
+
{ code: "SE", name: "Sweden" },
|
|
39
|
+
{ code: "NO", name: "Norway" },
|
|
40
|
+
{ code: "DK", name: "Denmark" },
|
|
41
|
+
{ code: "FI", name: "Finland" },
|
|
42
|
+
{ code: "PL", name: "Poland" },
|
|
43
|
+
{ code: "BR", name: "Brazil" },
|
|
44
|
+
{ code: "MX", name: "Mexico" },
|
|
45
|
+
{ code: "JP", name: "Japan" },
|
|
46
|
+
{ code: "SG", name: "Singapore" },
|
|
47
|
+
{ code: "NZ", name: "New Zealand" },
|
|
48
|
+
{ code: "IN", name: "India" }
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
// Google Pay supported currencies
|
|
52
|
+
export const GOOGLE_PAY_SUPPORTED_CURRENCIES = [
|
|
53
|
+
{ code: "USD", name: "US Dollar", symbol: "$" },
|
|
54
|
+
{ code: "EUR", name: "Euro", symbol: "€" },
|
|
55
|
+
{ code: "GBP", name: "British Pound", symbol: "£" },
|
|
56
|
+
{ code: "CAD", name: "Canadian Dollar", symbol: "C$" },
|
|
57
|
+
{ code: "AUD", name: "Australian Dollar", symbol: "A$" },
|
|
58
|
+
{ code: "JPY", name: "Japanese Yen", symbol: "¥" },
|
|
59
|
+
{ code: "CHF", name: "Swiss Franc", symbol: "CHF" },
|
|
60
|
+
{ code: "SEK", name: "Swedish Krona", symbol: "kr" },
|
|
61
|
+
{ code: "NOK", name: "Norwegian Krone", symbol: "kr" },
|
|
62
|
+
{ code: "DKK", name: "Danish Krone", symbol: "kr" },
|
|
63
|
+
{ code: "PLN", name: "Polish Zloty", symbol: "zł" },
|
|
64
|
+
{ code: "BRL", name: "Brazilian Real", symbol: "R$" },
|
|
65
|
+
{ code: "MXN", name: "Mexican Peso", symbol: "$" },
|
|
66
|
+
{ code: "SGD", name: "Singapore Dollar", symbol: "S$" },
|
|
67
|
+
{ code: "NZD", name: "New Zealand Dollar", symbol: "NZ$" },
|
|
68
|
+
{ code: "INR", name: "Indian Rupee", symbol: "₹" }
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
// Default Google Pay configuration
|
|
72
|
+
export const DEFAULT_GOOGLE_PAY_CONFIG = {
|
|
73
|
+
countryCode: "US",
|
|
74
|
+
currencyCode: "USD",
|
|
75
|
+
allowedCardNetworks: ["MASTERCARD", "VISA"],
|
|
76
|
+
allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
|
|
77
|
+
merchantName: "Your Store Name"
|
|
78
|
+
};
|
|
79
|
+
|