strapi-plugin-payone-provider 1.4.2 → 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 +25 -1
- package/admin/src/pages/App/components/ApplePayButton.js +737 -0
- package/admin/src/pages/App/components/ApplePayConfig.js +364 -0
- 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 +24 -6
- package/admin/src/pages/App/components/paymentActions/AuthorizationForm.js +60 -4
- package/admin/src/pages/App/components/paymentActions/CaptureForm.js +1 -0
- package/admin/src/pages/App/components/paymentActions/CardDetailsInput.js +18 -16
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.js +106 -2
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.js +64 -4
- package/admin/src/pages/App/components/paymentActions/RefundForm.js +1 -0
- package/admin/src/pages/App/index.js +70 -1
- package/admin/src/pages/hooks/usePaymentActions.js +13 -2
- package/admin/src/pages/hooks/useSettings.js +2 -0
- package/admin/src/pages/utils/applePayConstants.js +222 -0
- package/admin/src/pages/utils/googlePayConstants.js +79 -0
- package/admin/src/pages/utils/paymentUtils.js +22 -74
- package/package.json +1 -1
- package/server/bootstrap.js +5 -1
- package/server/config/index.js +5 -1
- package/server/controllers/payone.js +10 -0
- package/server/routes/index.js +17 -0
- package/server/services/applePayService.js +261 -0
- package/server/services/payone.js +10 -0
- package/server/utils/paymentMethodParams.js +19 -2
package/README.md
CHANGED
|
@@ -85,6 +85,159 @@ After installation, you need to configure your Payone credentials:
|
|
|
85
85
|
5. Click **"Test Connection"** to verify your credentials
|
|
86
86
|
6. Click **"Save Configuration"** to store your settings
|
|
87
87
|
|
|
88
|
+
### Apple Pay Configuration
|
|
89
|
+
|
|
90
|
+
To configure Apple Pay settings:
|
|
91
|
+
|
|
92
|
+
1. Navigate to **Payone Provider** in the sidebar menu
|
|
93
|
+
2. Go to **Payment Actions** tab
|
|
94
|
+
3. Select **Apple Pay** as the payment method
|
|
95
|
+
4. Click on the Apple Pay configuration link: `/plugins/strapi-plugin-payone-provider/apple-pay-config`
|
|
96
|
+
5. Configure the following settings:
|
|
97
|
+
- **Country Code**: Select the country where your business operates
|
|
98
|
+
- **Currency Code**: Select the currency for transactions
|
|
99
|
+
- **Supported Networks**: Select payment card networks (Visa, Mastercard, Amex, etc.)
|
|
100
|
+
- **Merchant Capabilities**: Select payment capabilities (3D Secure is recommended)
|
|
101
|
+
- **Button Style & Type**: Customize the Apple Pay button appearance
|
|
102
|
+
6. Click **"Save Apple Pay Configuration"** to store your settings
|
|
103
|
+
|
|
104
|
+
> ⚠️ **Important**: Apple Pay requires a registered domain with HTTPS. It does NOT work on localhost. For testing, use a production domain with HTTPS or test on a device with Safari (iOS/macOS).
|
|
105
|
+
|
|
106
|
+
#### Apple Pay Domain Verification File (.well-known)
|
|
107
|
+
|
|
108
|
+
Apple Pay requires a domain verification file to be placed on your server. This file must be accessible at:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Steps to set up the domain verification file:**
|
|
115
|
+
|
|
116
|
+
1. **Download the file from Payone:**
|
|
117
|
+
|
|
118
|
+
- Download the domain verification file from Payone documentation: [https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev](https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev)
|
|
119
|
+
- Alternatively, log into your Payone Merchant Interface (PMI)
|
|
120
|
+
- Navigate to **Configuration** → **Payment Portals** → **Apple Pay**
|
|
121
|
+
- Download the `apple-developer-merchantid-domain-association` file
|
|
122
|
+
|
|
123
|
+
2. **Place the file in Strapi:**
|
|
124
|
+
|
|
125
|
+
- Create the directory: `public/.well-known/` (if it doesn't exist)
|
|
126
|
+
- Place the file at: `public/.well-known/apple-developer-merchantid-domain-association`
|
|
127
|
+
|
|
128
|
+
3. **Place the file in your Frontend (if separate):**
|
|
129
|
+
|
|
130
|
+
- Create the directory: `public/.well-known/` (if it doesn't exist)
|
|
131
|
+
- Place the file at: `public/.well-known/apple-developer-merchantid-domain-association`
|
|
132
|
+
|
|
133
|
+
4. **Verify accessibility:**
|
|
134
|
+
- The file must be accessible via HTTPS at: `https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association`
|
|
135
|
+
- Test by visiting the URL in your browser - you should see the file content
|
|
136
|
+
|
|
137
|
+
> ⚠️ **Critical**: Without this file, Apple Pay will NOT work on your domain. The file must be accessible via HTTPS and must match exactly what Payone provides.
|
|
138
|
+
|
|
139
|
+
#### Middleware Configuration for Apple Pay
|
|
140
|
+
|
|
141
|
+
Apple Pay requires Content Security Policy (CSP) configuration in `config/middlewares.js` to allow Apple Pay scripts. Without this configuration, Apple Pay will NOT work.
|
|
142
|
+
|
|
143
|
+
**Required CSP directives:**
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
module.exports = [
|
|
147
|
+
"strapi::logger",
|
|
148
|
+
"strapi::errors",
|
|
149
|
+
{
|
|
150
|
+
name: "strapi::security",
|
|
151
|
+
config: {
|
|
152
|
+
contentSecurityPolicy: {
|
|
153
|
+
useDefaults: true,
|
|
154
|
+
directives: {
|
|
155
|
+
"script-src": [
|
|
156
|
+
"'self'",
|
|
157
|
+
"'unsafe-inline'",
|
|
158
|
+
"'unsafe-eval'",
|
|
159
|
+
"https://applepay.cdn-apple.com", // Apple Pay SDK
|
|
160
|
+
"https://www.apple.com", // Apple Pay manifest
|
|
161
|
+
],
|
|
162
|
+
"connect-src": [
|
|
163
|
+
"'self'",
|
|
164
|
+
"https:",
|
|
165
|
+
"https://applepay.cdn-apple.com", // Apple Pay API
|
|
166
|
+
"https://www.apple.com", // Apple Pay manifest
|
|
167
|
+
],
|
|
168
|
+
"frame-src": [
|
|
169
|
+
"'self'",
|
|
170
|
+
"https://applepay.cdn-apple.com", // Apple Pay iframe
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
// ... other middlewares
|
|
177
|
+
];
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
> ⚠️ **Important**: Without this middleware configuration, Apple Pay scripts will be blocked and Apple Pay will NOT work!
|
|
181
|
+
|
|
182
|
+
### Google Pay Configuration
|
|
183
|
+
|
|
184
|
+
To configure Google Pay settings:
|
|
185
|
+
|
|
186
|
+
1. Navigate to **Payone Provider** in the sidebar menu
|
|
187
|
+
2. Go to **Payment Actions** tab
|
|
188
|
+
3. Select **Google Pay** as the payment method
|
|
189
|
+
4. Click on the Google Pay configuration link: `/plugins/strapi-plugin-payone-provider/google-pay-config`
|
|
190
|
+
5. Configure the following settings:
|
|
191
|
+
- **Country Code**: Select the country where your business operates
|
|
192
|
+
- **Currency Code**: Select the currency for transactions
|
|
193
|
+
- **Merchant Name**: Enter your business name as it will appear in Google Pay
|
|
194
|
+
- **Allowed Card Networks**: Select payment card networks (Mastercard, Visa, Amex, etc.)
|
|
195
|
+
- **Allowed Authentication Methods**: Select authentication methods (PAN Only, 3D Secure)
|
|
196
|
+
6. Click **"Save Google Pay Configuration"** to store your settings
|
|
197
|
+
|
|
198
|
+
> ℹ️ **Note**: The Gateway Merchant ID will be automatically obtained from your Payone Merchant ID (MID) or Portal ID configured in the main Configuration tab.
|
|
199
|
+
|
|
200
|
+
#### Middleware Configuration for Google Pay
|
|
201
|
+
|
|
202
|
+
Google Pay requires Content Security Policy (CSP) configuration in `config/middlewares.js` to allow Google Pay scripts. Without this configuration, Google Pay will NOT work.
|
|
203
|
+
|
|
204
|
+
**Required CSP directives:**
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
module.exports = [
|
|
208
|
+
"strapi::logger",
|
|
209
|
+
"strapi::errors",
|
|
210
|
+
{
|
|
211
|
+
name: "strapi::security",
|
|
212
|
+
config: {
|
|
213
|
+
contentSecurityPolicy: {
|
|
214
|
+
useDefaults: true,
|
|
215
|
+
directives: {
|
|
216
|
+
"script-src": [
|
|
217
|
+
"'self'",
|
|
218
|
+
"'unsafe-inline'",
|
|
219
|
+
"'unsafe-eval'",
|
|
220
|
+
"https://pay.google.com", // Google Pay SDK
|
|
221
|
+
],
|
|
222
|
+
"connect-src": [
|
|
223
|
+
"'self'",
|
|
224
|
+
"https:",
|
|
225
|
+
"https://pay.google.com", // Google Pay API
|
|
226
|
+
],
|
|
227
|
+
"frame-src": [
|
|
228
|
+
"'self'",
|
|
229
|
+
"https://pay.google.com", // Google Pay iframe
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
// ... other middlewares
|
|
236
|
+
];
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
> ⚠️ **Important**: Without this middleware configuration, Google Pay scripts will be blocked and Google Pay will NOT work!
|
|
240
|
+
|
|
88
241
|
## 🚀 Getting Started
|
|
89
242
|
|
|
90
243
|
### 1. Test Your Connection
|
|
@@ -590,7 +743,7 @@ Google Pay integration requires obtaining an encrypted payment token from Google
|
|
|
590
743
|
|
|
591
744
|
```javascript
|
|
592
745
|
const paymentsClient = new google.payments.api.PaymentsClient({
|
|
593
|
-
environment:
|
|
746
|
+
environment: "TEST", // or "PRODUCTION" for live
|
|
594
747
|
});
|
|
595
748
|
|
|
596
749
|
const baseRequest = {
|
|
@@ -598,19 +751,19 @@ const baseRequest = {
|
|
|
598
751
|
apiVersionMinor: 0,
|
|
599
752
|
};
|
|
600
753
|
|
|
601
|
-
const allowedCardNetworks = [
|
|
602
|
-
const allowedAuthMethods = [
|
|
754
|
+
const allowedCardNetworks = ["MASTERCARD", "VISA"];
|
|
755
|
+
const allowedAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"];
|
|
603
756
|
|
|
604
757
|
const tokenizationSpecification = {
|
|
605
|
-
type:
|
|
758
|
+
type: "PAYMENT_GATEWAY",
|
|
606
759
|
parameters: {
|
|
607
|
-
gateway:
|
|
608
|
-
gatewayMerchantId:
|
|
760
|
+
gateway: "payonegmbh",
|
|
761
|
+
gatewayMerchantId: "YOUR_PAYONE_MERCHANT_ID", // Use your Payone MID or Portal ID
|
|
609
762
|
},
|
|
610
763
|
};
|
|
611
764
|
|
|
612
765
|
const cardPaymentMethod = {
|
|
613
|
-
type:
|
|
766
|
+
type: "CARD",
|
|
614
767
|
parameters: {
|
|
615
768
|
allowedCardNetworks,
|
|
616
769
|
allowedAuthMethods,
|
|
@@ -634,45 +787,47 @@ paymentsClient.isReadyToPay(isReadyToPayRequest).then(function (response) {
|
|
|
634
787
|
const paymentDataRequest = Object.assign({}, baseRequest);
|
|
635
788
|
paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
|
|
636
789
|
paymentDataRequest.transactionInfo = {
|
|
637
|
-
totalPriceStatus:
|
|
638
|
-
totalPrice:
|
|
639
|
-
currencyCode:
|
|
790
|
+
totalPriceStatus: "FINAL",
|
|
791
|
+
totalPrice: "10.00",
|
|
792
|
+
currencyCode: "EUR",
|
|
640
793
|
};
|
|
641
794
|
paymentDataRequest.merchantInfo = {
|
|
642
|
-
merchantId:
|
|
643
|
-
merchantName:
|
|
795
|
+
merchantId: "YOUR_GOOGLE_MERCHANT_ID", // Optional: from Google Console
|
|
796
|
+
merchantName: "Your Merchant Name",
|
|
644
797
|
};
|
|
645
798
|
|
|
646
799
|
const button = paymentsClient.createButton({
|
|
647
800
|
onClick: async () => {
|
|
648
801
|
try {
|
|
649
|
-
const paymentData = await paymentsClient.loadPaymentData(
|
|
802
|
+
const paymentData = await paymentsClient.loadPaymentData(
|
|
803
|
+
paymentDataRequest
|
|
804
|
+
);
|
|
650
805
|
const token = paymentData.paymentMethodData.tokenizationData.token;
|
|
651
806
|
|
|
652
807
|
// Token is a JSON string, encode it to Base64 for Payone
|
|
653
808
|
const base64Token = btoa(unescape(encodeURIComponent(token)));
|
|
654
809
|
|
|
655
810
|
// Send to your backend
|
|
656
|
-
await fetch(
|
|
657
|
-
method:
|
|
811
|
+
await fetch("/api/strapi-plugin-payone-provider/preauthorization", {
|
|
812
|
+
method: "POST",
|
|
658
813
|
headers: {
|
|
659
|
-
|
|
660
|
-
Authorization:
|
|
814
|
+
"Content-Type": "application/json",
|
|
815
|
+
Authorization: "Bearer YOUR_TOKEN",
|
|
661
816
|
},
|
|
662
817
|
body: JSON.stringify({
|
|
663
818
|
amount: 1000,
|
|
664
|
-
currency:
|
|
665
|
-
reference:
|
|
819
|
+
currency: "EUR",
|
|
820
|
+
reference: "PAY1234567890ABCDEF",
|
|
666
821
|
googlePayToken: base64Token,
|
|
667
822
|
}),
|
|
668
823
|
});
|
|
669
824
|
} catch (error) {
|
|
670
|
-
console.error(
|
|
825
|
+
console.error("Google Pay error:", error);
|
|
671
826
|
}
|
|
672
827
|
},
|
|
673
828
|
});
|
|
674
829
|
|
|
675
|
-
document.getElementById(
|
|
830
|
+
document.getElementById("google-pay-button").appendChild(button);
|
|
676
831
|
```
|
|
677
832
|
|
|
678
833
|
**Token Format**
|
|
@@ -684,7 +839,9 @@ The token from Google Pay is a JSON string with the following structure:
|
|
|
684
839
|
"signature": "MEUCIFr4ETGzv0uLZX3sR+i1ScARXnRBrncyYFDX/TI/VSLCAiEAvC/Q4dqXMQhwcSdg/ZvXj8+up0wXsfHja3V/6z48/vk=",
|
|
685
840
|
"intermediateSigningKey": {
|
|
686
841
|
"signedKey": "{\"keyValue\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7PWUi+e6WPUhNmTSQ2WN006oWlcWy0FtBWizw9sph1wvX9XcXUNRLcfcsmCBfI5IsKQkjAmYxpCSB+L5sIudLw\\u003d\\u003d\",\"keyExpiration\":\"1722393105282\"}",
|
|
687
|
-
"signatures": [
|
|
842
|
+
"signatures": [
|
|
843
|
+
"MEUCIQCpU30A3g2pP93IBE5NxgO9ZcJlGF9YPzCZS7H4/IR1CQIgF6+I5t8olT8YsRDUcj7w3R1bvX4ZCcyFXE2+YXa+3H0="
|
|
844
|
+
]
|
|
688
845
|
},
|
|
689
846
|
"protocolVersion": "ECv2",
|
|
690
847
|
"signedMessage": "{\"encryptedMessage\":\"...\",\"ephemeralPublicKey\":\"...\",\"tag\":\"...\"}"
|
|
@@ -1,22 +1,40 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { HeaderLayout, Box, Typography, Button } from "@strapi/design-system";
|
|
3
|
-
import { Check } from "@strapi/icons";
|
|
3
|
+
import { Check, ArrowLeft } from "@strapi/icons";
|
|
4
|
+
import { useHistory, useLocation } from "react-router-dom";
|
|
5
|
+
import pluginId from "../../../pluginId";
|
|
4
6
|
|
|
5
7
|
const AppHeader = ({ activeTab, isSaving, onSave }) => {
|
|
8
|
+
const history = useHistory();
|
|
9
|
+
const location = useLocation();
|
|
10
|
+
const isApplePayConfigPage = location.pathname.includes('/apple-pay-config');
|
|
11
|
+
|
|
6
12
|
return (
|
|
7
13
|
<HeaderLayout
|
|
8
14
|
title={
|
|
9
15
|
<Box>
|
|
10
16
|
<Typography variant="alpha" as="h1" fontWeight="bold" className="payment-title">
|
|
11
|
-
Payone Provider
|
|
17
|
+
{isApplePayConfigPage ? "Apple Pay Configuration" : "Payone Provider"}
|
|
12
18
|
</Typography>
|
|
13
19
|
<Typography variant="pi" marginTop={2} className="payment-subtitle">
|
|
14
|
-
|
|
20
|
+
{isApplePayConfigPage
|
|
21
|
+
? "Configure Apple Pay settings for your payment gateway"
|
|
22
|
+
: "Configure your Payone integration and manage payment transactions"
|
|
23
|
+
}
|
|
15
24
|
</Typography>
|
|
16
25
|
</Box>
|
|
17
26
|
}
|
|
18
27
|
primaryAction={
|
|
19
|
-
|
|
28
|
+
isApplePayConfigPage ? (
|
|
29
|
+
<Button
|
|
30
|
+
onClick={() => history.push(`/plugins/${pluginId}`)}
|
|
31
|
+
startIcon={<ArrowLeft />}
|
|
32
|
+
size="L"
|
|
33
|
+
variant="secondary"
|
|
34
|
+
>
|
|
35
|
+
Back to Main
|
|
36
|
+
</Button>
|
|
37
|
+
) : activeTab === 0 ? (
|
|
20
38
|
<Button
|
|
21
39
|
loading={isSaving}
|
|
22
40
|
onClick={onSave}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Tabs, Tab, TabGroup, TabPanels, TabPanel } from "@strapi/design-system";
|
|
3
|
+
import pluginId from "../../../pluginId";
|
|
3
4
|
import ConfigurationPanel from "./ConfigurationPanel";
|
|
4
5
|
import HistoryPanel from "./HistoryPanel";
|
|
5
6
|
import PaymentActionsPanel from "./PaymentActionsPanel";
|
|
7
|
+
import DocsPanel from "./DocsPanel";
|
|
6
8
|
|
|
7
9
|
const AppTabs = ({
|
|
8
10
|
activeTab,
|
|
@@ -30,8 +32,18 @@ const AppTabs = ({
|
|
|
30
32
|
selectedTransaction,
|
|
31
33
|
onTransactionSelect,
|
|
32
34
|
// Payment actions props
|
|
33
|
-
paymentActions
|
|
35
|
+
paymentActions,
|
|
36
|
+
history
|
|
34
37
|
}) => {
|
|
38
|
+
const handleNavigateToConfig = (configType = "apple-pay") => {
|
|
39
|
+
if (history) {
|
|
40
|
+
if (configType === "google-pay") {
|
|
41
|
+
history.push(`/plugins/${pluginId}/google-pay-config`);
|
|
42
|
+
} else {
|
|
43
|
+
history.push(`/plugins/${pluginId}/apple-pay-config`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
35
47
|
return (
|
|
36
48
|
<TabGroup
|
|
37
49
|
label="Payone Provider Tabs"
|
|
@@ -53,6 +65,11 @@ const AppTabs = ({
|
|
|
53
65
|
>
|
|
54
66
|
Payment Actions
|
|
55
67
|
</Tab>
|
|
68
|
+
<Tab
|
|
69
|
+
className={`payment-tab ${activeTab === 3 ? 'payment-tab-active' : ''}`}
|
|
70
|
+
>
|
|
71
|
+
Documentation
|
|
72
|
+
</Tab>
|
|
56
73
|
</Tabs>
|
|
57
74
|
<TabPanels>
|
|
58
75
|
<TabPanel>
|
|
@@ -115,6 +132,8 @@ const AppTabs = ({
|
|
|
115
132
|
settings={settings}
|
|
116
133
|
googlePayToken={paymentActions.googlePayToken}
|
|
117
134
|
setGooglePayToken={paymentActions.setGooglePayToken}
|
|
135
|
+
applePayToken={paymentActions.applePayToken}
|
|
136
|
+
setApplePayToken={paymentActions.setApplePayToken}
|
|
118
137
|
cardtype={paymentActions.cardtype}
|
|
119
138
|
setCardtype={paymentActions.setCardtype}
|
|
120
139
|
cardpan={paymentActions.cardpan}
|
|
@@ -123,8 +142,13 @@ const AppTabs = ({
|
|
|
123
142
|
setCardexpiredate={paymentActions.setCardexpiredate}
|
|
124
143
|
cardcvc2={paymentActions.cardcvc2}
|
|
125
144
|
setCardcvc2={paymentActions.setCardcvc2}
|
|
145
|
+
onNavigateToConfig={handleNavigateToConfig}
|
|
126
146
|
/>
|
|
127
147
|
</TabPanel>
|
|
148
|
+
|
|
149
|
+
<TabPanel>
|
|
150
|
+
<DocsPanel />
|
|
151
|
+
</TabPanel>
|
|
128
152
|
</TabPanels>
|
|
129
153
|
</TabGroup>
|
|
130
154
|
);
|