strapi-plugin-payone-provider 1.6.1 → 1.6.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/admin/src/pages/App/components/ApplePayBtn.jsx +15 -13
- package/admin/src/pages/App/components/PaymentActionsPanel.jsx +68 -17
- package/admin/src/pages/App/components/paymentActions/AuthorizationForm.jsx +4 -12
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.jsx +163 -86
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.jsx +21 -11
- package/admin/src/pages/hooks/usePaymentActions.js +0 -172
- package/admin/src/pages/utils/paymentUtils.js +2 -2
- package/package.json +1 -1
- package/server/bootstrap.js +0 -19
- package/server/services/transactionService.js +0 -28
- package/admin/src/components/Initializer/index.js +0 -16
- package/admin/src/components/PluginIcon/index.js +0 -6
- package/admin/src/pages/App/components/AppHeader.js +0 -55
- package/admin/src/pages/App/components/AppTabs.js +0 -158
- package/admin/src/pages/App/components/ApplePayButton.js +0 -950
- package/admin/src/pages/App/components/ApplePayConfig.js +0 -364
- package/admin/src/pages/App/components/ApplePayConfigPanel.js +0 -81
- package/admin/src/pages/App/components/ConfigurationPanel.js +0 -280
- package/admin/src/pages/App/components/DocsPanel.js +0 -1057
- package/admin/src/pages/App/components/GooglePayConfig.js +0 -217
- package/admin/src/pages/App/components/GooglePayConfigPanel.js +0 -82
- package/admin/src/pages/App/components/GooglePaybutton.js +0 -300
- package/admin/src/pages/App/components/HistoryPanel.js +0 -285
- package/admin/src/pages/App/components/PaymentActionsPanel.js +0 -190
- package/admin/src/pages/App/components/StatusBadge.js +0 -24
- package/admin/src/pages/App/components/TransactionHistoryItem.js +0 -377
- package/admin/src/pages/App/components/icons/BankIcon.js +0 -10
- package/admin/src/pages/App/components/icons/ChevronDownIcon.js +0 -9
- package/admin/src/pages/App/components/icons/ChevronUpIcon.js +0 -9
- package/admin/src/pages/App/components/icons/CreditCardIcon.js +0 -9
- package/admin/src/pages/App/components/icons/ErrorIcon.js +0 -10
- package/admin/src/pages/App/components/icons/InfoIcon.js +0 -9
- package/admin/src/pages/App/components/icons/PaymentIcon.js +0 -10
- package/admin/src/pages/App/components/icons/PendingIcon.js +0 -9
- package/admin/src/pages/App/components/icons/PersonIcon.js +0 -9
- package/admin/src/pages/App/components/icons/SuccessIcon.js +0 -9
- package/admin/src/pages/App/components/icons/WalletIcon.js +0 -9
- package/admin/src/pages/App/components/icons/index.js +0 -11
- package/admin/src/pages/App/components/paymentActions/AuthorizationForm.js +0 -195
- package/admin/src/pages/App/components/paymentActions/CaptureForm.js +0 -65
- package/admin/src/pages/App/components/paymentActions/CardDetailsInput.js +0 -191
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.js +0 -156
- package/admin/src/pages/App/components/paymentActions/PaymentResult.js +0 -148
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.js +0 -199
- package/admin/src/pages/App/components/paymentActions/RefundForm.js +0 -90
- package/admin/src/pages/App/index.js +0 -127
|
@@ -1,217 +0,0 @@
|
|
|
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
|
-
|
|
@@ -1,82 +0,0 @@
|
|
|
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
|
-
|
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
-
import { Box, Flex, Typography } from "@strapi/design-system";
|
|
3
|
-
import { injectGooglePayScript } from "../../utils/injectGooglePayScript";
|
|
4
|
-
|
|
5
|
-
const GooglePayButton = ({
|
|
6
|
-
amount,
|
|
7
|
-
currency = "EUR",
|
|
8
|
-
onTokenReceived,
|
|
9
|
-
onError,
|
|
10
|
-
settings
|
|
11
|
-
}) => {
|
|
12
|
-
const [isReady, setIsReady] = useState(false);
|
|
13
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
14
|
-
const buttonContainerRef = useRef(null);
|
|
15
|
-
const paymentsClientRef = useRef(null);
|
|
16
|
-
|
|
17
|
-
const baseRequest = {
|
|
18
|
-
apiVersion: 2,
|
|
19
|
-
apiVersionMinor: 0
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const getGooglePayConfig = (settings) => {
|
|
23
|
-
const gatewayMerchantId = settings?.mid || settings?.portalid || '';
|
|
24
|
-
|
|
25
|
-
const allowedCardNetworks = ["MASTERCARD", "VISA"];
|
|
26
|
-
const allowedAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"];
|
|
27
|
-
|
|
28
|
-
const tokenizationSpecification = {
|
|
29
|
-
type: 'PAYMENT_GATEWAY',
|
|
30
|
-
parameters: {
|
|
31
|
-
'gateway': 'payonegmbh',
|
|
32
|
-
'gatewayMerchantId': gatewayMerchantId
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const baseCardPaymentMethod = {
|
|
37
|
-
type: "CARD",
|
|
38
|
-
parameters: {
|
|
39
|
-
allowedCardNetworks,
|
|
40
|
-
allowedAuthMethods
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const cardPaymentMethod = {
|
|
45
|
-
...baseCardPaymentMethod,
|
|
46
|
-
tokenizationSpecification
|
|
47
|
-
};
|
|
48
|
-
return {
|
|
49
|
-
baseCardPaymentMethod,
|
|
50
|
-
cardPaymentMethod,
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
injectGooglePayScript();
|
|
56
|
-
|
|
57
|
-
const checkGooglePay = () => {
|
|
58
|
-
try {
|
|
59
|
-
return typeof window !== 'undefined' &&
|
|
60
|
-
typeof window.google !== 'undefined' &&
|
|
61
|
-
window.google.payments?.api?.PaymentsClient;
|
|
62
|
-
} catch (e) {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
if (checkGooglePay()) {
|
|
68
|
-
initializeGooglePay();
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const handleScriptLoaded = () => {
|
|
73
|
-
setTimeout(() => {
|
|
74
|
-
if (checkGooglePay()) {
|
|
75
|
-
initializeGooglePay();
|
|
76
|
-
}
|
|
77
|
-
}, 500);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const handleScriptError = () => {
|
|
81
|
-
setIsLoading(false);
|
|
82
|
-
if (onError) {
|
|
83
|
-
onError(new Error("Failed to load Google Pay script. Please check CSP settings."));
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
window.addEventListener("googlePayScriptLoaded", handleScriptLoaded);
|
|
88
|
-
window.addEventListener("googlePayScriptError", handleScriptError);
|
|
89
|
-
|
|
90
|
-
const checkInterval = setInterval(() => {
|
|
91
|
-
if (checkGooglePay()) {
|
|
92
|
-
clearInterval(checkInterval);
|
|
93
|
-
initializeGooglePay();
|
|
94
|
-
}
|
|
95
|
-
}, 200);
|
|
96
|
-
|
|
97
|
-
const timeout = setTimeout(() => {
|
|
98
|
-
clearInterval(checkInterval);
|
|
99
|
-
if (!checkGooglePay()) {
|
|
100
|
-
setIsLoading(false);
|
|
101
|
-
if (onError) {
|
|
102
|
-
onError(new Error("Google Pay API is not available. Please check if the script is loaded and CSP allows pay.google.com"));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}, 15000);
|
|
106
|
-
|
|
107
|
-
return () => {
|
|
108
|
-
window.removeEventListener("googlePayScriptLoaded", handleScriptLoaded);
|
|
109
|
-
window.removeEventListener("googlePayScriptError", handleScriptError);
|
|
110
|
-
clearInterval(checkInterval);
|
|
111
|
-
clearTimeout(timeout);
|
|
112
|
-
};
|
|
113
|
-
}, [settings, amount, currency]);
|
|
114
|
-
|
|
115
|
-
const initializeGooglePay = () => {
|
|
116
|
-
if (!settings || (!settings.mid && !settings.portalid)) {
|
|
117
|
-
setIsLoading(false);
|
|
118
|
-
if (onError) {
|
|
119
|
-
onError(new Error("Google Pay settings missing. Please configure mid or portalid in settings."));
|
|
120
|
-
}
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
if (typeof window === 'undefined' || typeof window.google === 'undefined' || !window.google.payments?.api?.PaymentsClient) {
|
|
126
|
-
setIsLoading(false);
|
|
127
|
-
if (onError) {
|
|
128
|
-
onError(new Error("Google Pay API is not loaded. Please check browser console for CSP errors."));
|
|
129
|
-
}
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const environment = settings?.mode === "live" ? "PRODUCTION" : "TEST";
|
|
135
|
-
paymentsClientRef.current = new window.google.payments.api.PaymentsClient({
|
|
136
|
-
environment: environment
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
const config = getGooglePayConfig(settings);
|
|
140
|
-
|
|
141
|
-
const isReadyToPayRequest = Object.assign({}, baseRequest);
|
|
142
|
-
isReadyToPayRequest.allowedPaymentMethods = [config.baseCardPaymentMethod];
|
|
143
|
-
|
|
144
|
-
paymentsClientRef.current.isReadyToPay(isReadyToPayRequest)
|
|
145
|
-
.then((response) => {
|
|
146
|
-
if (response.result) {
|
|
147
|
-
setIsReady(true);
|
|
148
|
-
const tryAddButton = () => {
|
|
149
|
-
if (buttonContainerRef.current) {
|
|
150
|
-
addGooglePayButton(config);
|
|
151
|
-
} else {
|
|
152
|
-
setTimeout(tryAddButton, 100);
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
setTimeout(tryAddButton, 100);
|
|
156
|
-
} else {
|
|
157
|
-
setIsLoading(false);
|
|
158
|
-
if (onError) {
|
|
159
|
-
onError(new Error("Google Pay is not available on this device"));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
})
|
|
163
|
-
.catch((err) => {
|
|
164
|
-
setIsLoading(false);
|
|
165
|
-
if (onError) {
|
|
166
|
-
onError(err);
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
} catch (error) {
|
|
170
|
-
setIsLoading(false);
|
|
171
|
-
if (onError) {
|
|
172
|
-
onError(error);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const addGooglePayButton = (config) => {
|
|
178
|
-
if (!buttonContainerRef.current) {
|
|
179
|
-
setTimeout(() => {
|
|
180
|
-
if (buttonContainerRef.current) {
|
|
181
|
-
addGooglePayButton(config);
|
|
182
|
-
} else {
|
|
183
|
-
setIsLoading(false);
|
|
184
|
-
}
|
|
185
|
-
}, 500);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (!paymentsClientRef.current) {
|
|
190
|
-
setIsLoading(false);
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
buttonContainerRef.current.innerHTML = "";
|
|
195
|
-
|
|
196
|
-
const gatewayMerchantId = settings?.mid || settings?.portalid || '';
|
|
197
|
-
const paymentDataRequest = Object.assign({}, baseRequest);
|
|
198
|
-
paymentDataRequest.allowedPaymentMethods = [config.cardPaymentMethod];
|
|
199
|
-
paymentDataRequest.transactionInfo = {
|
|
200
|
-
totalPriceStatus: "FINAL",
|
|
201
|
-
totalPrice: (parseFloat(amount) / 100).toFixed(2),
|
|
202
|
-
currencyCode: currency
|
|
203
|
-
};
|
|
204
|
-
paymentDataRequest.merchantInfo = {
|
|
205
|
-
merchantId: gatewayMerchantId,
|
|
206
|
-
merchantName: settings?.merchantName || 'Demo Shop'
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
try {
|
|
210
|
-
const button = paymentsClientRef.current.createButton({
|
|
211
|
-
onClick: () => handleGooglePayClick(paymentDataRequest),
|
|
212
|
-
buttonColor: "black",
|
|
213
|
-
buttonType: "pay",
|
|
214
|
-
buttonSizeMode: "fill"
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
if (buttonContainerRef.current) {
|
|
218
|
-
buttonContainerRef.current.appendChild(button);
|
|
219
|
-
setIsLoading(false);
|
|
220
|
-
setIsReady(true);
|
|
221
|
-
} else {
|
|
222
|
-
setIsLoading(false);
|
|
223
|
-
}
|
|
224
|
-
} catch (error) {
|
|
225
|
-
setIsLoading(false);
|
|
226
|
-
if (onError) {
|
|
227
|
-
onError(error);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
const handleGooglePayClick = async (paymentDataRequest) => {
|
|
233
|
-
try {
|
|
234
|
-
if (!paymentsClientRef.current) {
|
|
235
|
-
throw new Error("Google Pay client not initialized");
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const paymentData = await paymentsClientRef.current.loadPaymentData(paymentDataRequest);
|
|
239
|
-
const rawToken = paymentData.paymentMethodData?.tokenizationData?.token;
|
|
240
|
-
|
|
241
|
-
if (!rawToken) {
|
|
242
|
-
throw new Error("Google Pay token is missing from payment data");
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let token = rawToken;
|
|
246
|
-
|
|
247
|
-
try {
|
|
248
|
-
const tokenObj = JSON.parse(token);
|
|
249
|
-
if (!tokenObj.signature || !tokenObj.protocolVersion || !tokenObj.signedMessage) {
|
|
250
|
-
throw new Error("Google Pay token is missing required fields");
|
|
251
|
-
}
|
|
252
|
-
token = btoa(unescape(encodeURIComponent(rawToken)));
|
|
253
|
-
} catch (e) {
|
|
254
|
-
if (typeof token === 'string') {
|
|
255
|
-
token = btoa(unescape(encodeURIComponent(token)));
|
|
256
|
-
} else {
|
|
257
|
-
throw new Error(`Invalid Google Pay token format: ${e.message}`);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (onTokenReceived) {
|
|
262
|
-
onTokenReceived(token, paymentData);
|
|
263
|
-
}
|
|
264
|
-
} catch (error) {
|
|
265
|
-
if (onError) {
|
|
266
|
-
onError(error);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
return (
|
|
272
|
-
<Box width="100%">
|
|
273
|
-
<Flex direction="column" gap={3} alignItems="stretch">
|
|
274
|
-
{isLoading && (
|
|
275
|
-
<Typography variant="pi" textColor="neutral600" style={{ textAlign: "left" }}>
|
|
276
|
-
Loading Google Pay...
|
|
277
|
-
</Typography>
|
|
278
|
-
)}
|
|
279
|
-
{!isLoading && !isReady && (
|
|
280
|
-
<Typography variant="pi" textColor="neutral600" style={{ textAlign: "left" }}>
|
|
281
|
-
Google Pay is not available
|
|
282
|
-
</Typography>
|
|
283
|
-
)}
|
|
284
|
-
{!isLoading && isReady && (
|
|
285
|
-
<>
|
|
286
|
-
<Typography variant="sigma" textColor="neutral700" fontWeight="semiBold" style={{ textAlign: "left" }}>
|
|
287
|
-
Google Pay Payment
|
|
288
|
-
</Typography>
|
|
289
|
-
<Typography variant="pi" textColor="neutral600" style={{ textAlign: "left" }}>
|
|
290
|
-
Click the button below to pay with Google Pay. The token will be automatically sent to Payone.
|
|
291
|
-
</Typography>
|
|
292
|
-
</>
|
|
293
|
-
)}
|
|
294
|
-
<Box ref={buttonContainerRef} style={{ minHeight: "40px", width: "100%", maxWidth: "200px", display: "flex", justifyContent: "flex-start", }} />
|
|
295
|
-
</Flex>
|
|
296
|
-
</Box>
|
|
297
|
-
);
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
export default GooglePayButton;
|