PluginProbe
MultiSafepay plugin for WooCommerce / trunk
MultiSafepay plugin for WooCommerce vtrunk
6.11.1 6.12.0 6.13.0 6.2.0 6.2.1 6.3.0 6.3.1 6.4.0 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.6.0 6.6.1 6.6.2 6.7.0 6.7.1 6.7.2 6.7.3 6.8.0 6.8.1 6.8.2 6.8.3 6.9.0 All 84 releases
multisafepay / src / Services / PaymentMethodService.php

PaymentMethodService.php in MultiSafepay plugin for WooCommerce trunk, at src/Services/PaymentMethodService.php

359 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php declare(strict_types=1);
2
3 namespace MultiSafepay\WooCommerce\Services;
4
5 use Exception;
6 use MultiSafepay\Api\PaymentMethodManager;
7 use MultiSafepay\Api\PaymentMethods\PaymentMethod;
8 use MultiSafepay\Exception\ApiException;
9 use MultiSafepay\Exception\InvalidDataInitializationException;
10 use MultiSafepay\WooCommerce\PaymentMethods\Base\BaseGiftCardPaymentMethod;
11 use MultiSafepay\WooCommerce\PaymentMethods\Base\BasePaymentMethod;
12 use MultiSafepay\WooCommerce\PaymentMethods\Base\BaseBrandedPaymentMethod;
13 use MultiSafepay\WooCommerce\Utils\Logger;
14 use Psr\Http\Client\ClientExceptionInterface;
15
16 /**
17 * Class PaymentMethodsService
18 *
19 * @package MultiSafepay\WooCommerce\Services
20 */
21 class PaymentMethodService {
22
23 /**
24 * Time in seconds, in which the stored value in cache with information about all gateways will expire.
25 */
26 public const EXPIRATION_TIME_FOR_PAYMENT_METHODS_API_REQUEST = 86400;
27
28 /**
29 * Time in seconds, in which the stored value in cache with information about all gateways with QR will expire.
30 */
31 public const EXPIRATION_TIME_FOR_PAYMENT_METHODS_WITH_QR = 60;
32
33 /**
34 * @var PaymentMethodManager
35 */
36 public $payment_method_manager;
37
38 /**
39 * @var Logger
40 */
41 private $logger;
42
43 /**
44 * In-request cache for WooCommerce gateway objects.
45 *
46 * This avoids rebuilding gateway objects multiple times in the same request
47 * while still relying on transients for API-level caching.
48 *
49 * @var array
50 */
51 private $woocommerce_payment_gateways = array();
52
53 /**
54 * @var bool
55 */
56 private $woocommerce_payment_gateways_loaded = false;
57
58 /**
59 * @param Logger|null $logger
60 */
61 public function __construct( ?Logger $logger = null ) {
62 $this->logger = $logger ?? new Logger();
63 try {
64 $this->payment_method_manager = ( new SdkService() )->get_payment_method_manager();
65 } catch ( ApiException $api_exception ) {
66 $this->logger->log_error( $api_exception->getMessage() );
67 }
68 }
69
70 /**
71 * Check if the current page is the WooCommerce settings page for payment methods
72 *
73 * @return bool
74 *
75 * @phpcs:disable WordPress.Security.NonceVerification.Recommended
76 */
77 public function is_settings_payments_page(): bool {
78 $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
79 $tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : '';
80 return is_admin() && ( 'wc-settings' === $page ) && ( 'checkout' === $tab );
81 }
82
83 /**
84 * Return an array with the information of each payment method from the API
85 * If the result is cached by transient api, will be returned from there,
86 * except when the call comes from admin side, in which case it will
87 * regenerate the transient.
88 *
89 * @see https://developer.wordpress.org/reference/functions/set_transient/
90 *
91 * @return array
92 */
93 public function get_multisafepay_payment_methods_from_api(): array {
94 $multisafepay_payment_methods_in_cache = get_transient( 'multisafepay_payment_methods' );
95 $admin_area = $this->is_settings_payments_page();
96
97 if ( ( false !== $multisafepay_payment_methods_in_cache ) && ! $admin_area ) {
98 return $multisafepay_payment_methods_in_cache;
99 }
100
101 if ( null === $this->payment_method_manager ) {
102 $this->logger->log_error( 'SDK is not initialized' );
103 return array();
104 }
105
106 try {
107 $multisafepay_payment_methods = $this->payment_method_manager->getPaymentMethodsAsArray(
108 true,
109 array(
110 'group_cards' => ( (bool) get_option(
111 'multisafepay_group_credit_cards',
112 self::is_multisafepay_credit_card_woocommerce_payment_gateway_enabled()
113 ) ),
114 )
115 );
116 } catch ( Exception |ApiException |InvalidDataInitializationException |ClientExceptionInterface $exception ) {
117 $this->logger->log_error( $exception->getMessage() );
118 return array();
119 }
120
121 set_transient( 'multisafepay_payment_methods', $multisafepay_payment_methods, self::EXPIRATION_TIME_FOR_PAYMENT_METHODS_API_REQUEST );
122
123 return $multisafepay_payment_methods;
124 }
125
126 /**
127 * Return an array with WC_Payment_Gateway objects, created from the results of the API.
128 *
129 * This method memoizes the gateway objects in-memory for the current request.
130 * The API response is already cached in transients, but object creation is still
131 * relatively expensive and this method is called multiple times in callbacks
132 * (for example: original gateway + wallet gateway lookup).
133 *
134 * @return array
135 */
136 public function get_woocommerce_payment_gateways() : array {
137 // Reuse the same in-memory gateway objects for all lookups in this request.
138 if ( $this->woocommerce_payment_gateways_loaded ) {
139 return $this->woocommerce_payment_gateways;
140 }
141
142 $woocommerce_payment_gateways = array();
143 $multisafepay_payment_methods = $this->get_multisafepay_payment_methods_from_api();
144 foreach ( $multisafepay_payment_methods as $multisafepay_payment_method ) {
145 if ( isset( $multisafepay_payment_method['type'] ) ) {
146 $woocommerce_payment_gateways = $this->create_woocommerce_payment_gateways( $multisafepay_payment_method, $woocommerce_payment_gateways );
147 }
148 }
149
150 $this->woocommerce_payment_gateways = $woocommerce_payment_gateways;
151 $this->woocommerce_payment_gateways_loaded = true;
152
153 return $this->woocommerce_payment_gateways;
154 }
155
156 /**
157 * @param array $multisafepay_payment_method
158 * @param array $woocommerce_payment_gateways
159 * @return array
160 */
161 public function create_woocommerce_payment_gateways( array $multisafepay_payment_method, array $woocommerce_payment_gateways ) : array {
162 $payment_method_id = self::get_legacy_woocommerce_payment_gateway_ids( $multisafepay_payment_method['id'] );
163
164 try {
165 $payment_method = new PaymentMethod( $multisafepay_payment_method );
166 } catch ( InvalidDataInitializationException $exception ) {
167 $this->logger->log_error( $exception->getMessage() );
168 return $woocommerce_payment_gateways;
169 }
170
171 if ( 'payment-method' === $multisafepay_payment_method['type'] ) {
172 $woocommerce_payment_gateways[ $payment_method_id ] = new BasePaymentMethod( $payment_method );
173 $woocommerce_payment_gateways = $this->create_branded_woocommerce_payment_gateways( $multisafepay_payment_method, $woocommerce_payment_gateways, $payment_method );
174 }
175
176 if ( 'coupon' === $multisafepay_payment_method['type'] ) {
177 $woocommerce_payment_gateways[ $payment_method_id ] = new BaseGiftCardPaymentMethod( $payment_method );
178 }
179
180 return $woocommerce_payment_gateways;
181 }
182
183 /**
184 * @param array $multisafepay_payment_method
185 * @param array $woocommerce_payment_gateways
186 * @param PaymentMethod $payment_method
187 * @return array
188 */
189 public function create_branded_woocommerce_payment_gateways( array $multisafepay_payment_method, array $woocommerce_payment_gateways, PaymentMethod $payment_method ) : array {
190 foreach ( $multisafepay_payment_method['brands'] as $brand ) {
191 if ( ! empty( $brand['allowed_countries'] ) && ! get_option( 'multisafepay_group_credit_cards', false ) ) {
192 $brand['id'] .= '_' . $multisafepay_payment_method['id'];
193 $brand['name'] .= ' - ' . $multisafepay_payment_method['name'];
194 $payment_method_id = self::get_legacy_woocommerce_payment_gateway_ids( $brand['id'] );
195 $woocommerce_payment_gateways[ $payment_method_id ] = new BaseBrandedPaymentMethod( $payment_method, $brand );
196 }
197 }
198
199 return $woocommerce_payment_gateways;
200 }
201
202 /**
203 * Return the WooCommerce payment method object by WooCommerce gateway id.
204 *
205 * Since gateways are indexed by id when created, this is an O(1) lookup and
206 * avoids iterating through the full list on every call.
207 *
208 * @param string $woocommerce_payment_gateway_id
209 * @return BasePaymentMethod|null
210 */
211 public function get_woocommerce_payment_gateway_by_id( string $woocommerce_payment_gateway_id ): ?BasePaymentMethod {
212 $woocommerce_payment_gateways = $this->get_woocommerce_payment_gateways();
213 if ( isset( $woocommerce_payment_gateways[ $woocommerce_payment_gateway_id ] ) ) {
214 return $woocommerce_payment_gateways[ $woocommerce_payment_gateway_id ];
215 }
216
217 return null;
218 }
219
220 /**
221 * Return an array with the WooCommerce payment method object ids
222 *
223 * @return array
224 */
225 public function get_woocommerce_payment_gateway_ids(): array {
226 $gateways_ids = array();
227 foreach ( $this->get_multisafepay_payment_methods_from_api() as $payment_method ) {
228 $gateways_ids[] = self::get_legacy_woocommerce_payment_gateway_ids( $payment_method['id'] );
229 }
230 return $gateways_ids;
231 }
232
233 /**
234 * Return the WooCommerce payment method object by MultiSafepay gateway code.
235 *
236 * The gateway code is first converted to the internal WooCommerce id format,
237 * then resolved through direct array access against the memoized gateway list.
238 * This avoids repeated list rebuilds and linear scans in hot paths.
239 *
240 * @param string $code
241 * @return ?BasePaymentMethod
242 */
243 public function get_woocommerce_payment_gateway_by_multisafepay_gateway_code( string $code ): ?BasePaymentMethod {
244 $woocommerce_payment_gateway_id = self::get_legacy_woocommerce_payment_gateway_ids( $code );
245 $woocommerce_payment_gateways = $this->get_woocommerce_payment_gateways();
246
247 // Direct array access avoids iterating over all gateways on each lookup.
248 if ( isset( $woocommerce_payment_gateways[ $woocommerce_payment_gateway_id ] ) ) {
249 return $woocommerce_payment_gateways[ $woocommerce_payment_gateway_id ];
250 }
251
252 return null;
253 }
254
255 /**
256 * Get all active MultiSafepay payment methods which supports payment component
257 *
258 * @return array
259 */
260 public function get_woocommerce_payment_gateway_ids_with_payment_component_support(): array {
261 $payment_methods_with_payment_component = array();
262 foreach ( $this->get_enabled_woocommerce_payment_gateways() as $woocommerce_payment_gateway ) {
263 if ( $woocommerce_payment_gateway->is_payment_component_enabled() ) {
264 $payment_methods_with_payment_component[] = $woocommerce_payment_gateway->get_payment_method_id();
265 }
266 }
267 return $payment_methods_with_payment_component;
268 }
269
270 /**
271 * Check if any of the active MultiSafepay payment methods supports payment component with QR
272 *
273 * @return bool
274 */
275 public function is_any_woocommerce_payment_gateway_with_payment_component_qr_enabled(): bool {
276 $is_any_woocommerce_payment_gateway_with_payment_component_qr_enabled = get_transient( 'is_multisafepay_payment_component_qr_enabled' );
277
278 if ( ( false !== $is_any_woocommerce_payment_gateway_with_payment_component_qr_enabled ) ) {
279 return (bool) $is_any_woocommerce_payment_gateway_with_payment_component_qr_enabled;
280 }
281
282 /** @var BasePaymentMethod $woocommerce_payment_gateway */
283 foreach ( $this->get_enabled_woocommerce_payment_gateways() as $woocommerce_payment_gateway ) {
284 if ( $woocommerce_payment_gateway->is_qr_enabled() || $woocommerce_payment_gateway->is_qr_only_enabled() ) {
285 set_transient( 'is_multisafepay_payment_component_qr_enabled', true, self::EXPIRATION_TIME_FOR_PAYMENT_METHODS_WITH_QR );
286 return true;
287 }
288 }
289
290 set_transient( 'is_multisafepay_payment_component_qr_enabled', false, self::EXPIRATION_TIME_FOR_PAYMENT_METHODS_WITH_QR );
291 return false;
292 }
293
294 /**
295 * Get all active MultiSafepay WooCommerce payment gateways
296 *
297 * @return array
298 */
299 public function get_enabled_woocommerce_payment_gateways(): array {
300 $enabled_payment_gateways = array();
301 foreach ( $this->get_woocommerce_payment_gateways() as $woocommerce_payment_gateway ) {
302 if ( 'yes' === $woocommerce_payment_gateway->enabled ) {
303 $enabled_payment_gateways[] = $woocommerce_payment_gateway;
304 }
305 }
306 return $enabled_payment_gateways;
307 }
308
309 /**
310 * Return the woocommerce_payment_gateway_ids considering those one previously set
311 * which don't match the new format
312 *
313 * @param string $code
314 * @return string
315 */
316 public static function get_legacy_woocommerce_payment_gateway_ids( string $code ): string {
317 $woocommerce_payment_gateway_id = 'multisafepay_' . str_replace( '-', '_', sanitize_title( strtolower( $code ) ) );
318
319 $legacy_woocommerce_payment_gateway_ids = array(
320 'multisafepay_alipayplus' => 'multisafepay_alipay_plus',
321 'multisafepay_amazonbtn' => 'multisafepay_amazonpay',
322 'multisafepay_mistercash' => 'multisafepay_bancontact',
323 'multisafepay_bnpl_instm' => 'multisafepay_payafterdelivery_installments',
324 'multisafepay_psafecard' => 'multisafepay_paysafecard',
325 'multisafepay_directbank' => 'multisafepay_sofort',
326 'multisafepay_babycad' => 'multisafepay_babycadeaubon',
327 'multisafepay_beautywell' => 'multisafepay_beautyandwellness',
328 'multisafepay_fashionchq' => 'multisafepay_fashioncheque',
329 'multisafepay_fashiongft' => 'multisafepay_fashiongiftcard',
330 'multisafepay_gezondheid' => 'multisafepay_gezondheidsbon',
331 'multisafepay_natnletuin' => 'multisafepay_nationaletuinbon',
332 'multisafepay_parfumcade' => 'multisafepay_parfumcadeaukaart',
333 'multisafepay_vvvgiftcrd' => 'multisafepay_vvvcadeaukaart',
334 );
335
336 return $legacy_woocommerce_payment_gateway_ids[ $woocommerce_payment_gateway_id ] ?? $woocommerce_payment_gateway_id;
337 }
338
339 /**
340 * For legacy reasons, this method returns if Credit Card WooCommerce Payment gateway is enabled,
341 * in which case this argument is used to return payment methods with argument group_cards as true
342 *
343 * @return bool
344 */
345 public static function is_multisafepay_credit_card_woocommerce_payment_gateway_enabled(): bool {
346
347 $multisafepay_credit_card_settings = get_option( 'woocommerce_multisafepay_creditcard_settings', false );
348
349 if ( ! $multisafepay_credit_card_settings ) {
350 return false;
351 }
352
353 $credit_card_woocommerce_payment_gateway_settings = maybe_unserialize( $multisafepay_credit_card_settings );
354
355 return isset( $credit_card_woocommerce_payment_gateway_settings['enabled'] ) &&
356 'yes' === $credit_card_woocommerce_payment_gateway_settings['enabled'];
357 }
358 }
359