PluginProbe
PayPlug for WooCommerce (Official) / 2.18.0
PayPlug for WooCommerce (Official) v2.18.0
3.0.0 2.18.0 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 1.0.22 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.1.0 1.10.0 1.10.1 1.2.1 1.2.10 1.2.11 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 All 101 releases
payplug / src / Controller / PayplugGenericGateway.php

PayplugGenericGateway.php in PayPlug for WooCommerce (Official) 2.18.0, at src/Controller/PayplugGenericGateway.php

533 lines 19.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Payplug\PayplugWoocommerce\Controller;
4
5 use Automattic\WooCommerce\Utilities\OrderUtil;
6 use Payplug\Exception\HttpException;
7 use Payplug\Payplug;
8 use Payplug\PayplugWoocommerce\Gateway\PayplugAddressData;
9 use Payplug\PayplugWoocommerce\Gateway\PayplugGateway;
10 use Payplug\PayplugWoocommerce\Interfaces\PayplugGatewayBuilder;
11 use Payplug\PayplugWoocommerce\PayplugWoocommerceHelper;
12 use Payplug\Resource\Payment as PaymentResource;
13 use Payplug\Resource\Refund as RefundResource;
14
15 class PayplugGenericGateway extends PayplugGateway implements PayplugGatewayBuilder
16 {
17 /**
18 * @var string
19 */
20 public $image;
21
22 /**
23 * @var array
24 */
25 protected $allowed_country_codes;
26
27 public function __construct()
28 {
29 parent::__construct();
30 add_action('woocommerce_after_order_itemmeta', [$this, 'hide_wc_refund_button']);
31 }
32
33 /**
34 * Generic code to fetch payment gateway specific image
35 *
36 * @return string
37 */
38 public function get_icon()
39 {
40
41 //get object $image
42 $icons = apply_filters('payplug_payment_icons', [
43 'payplug' => sprintf('<img src="%s" alt="%s" class="payplug-payment-icon" />', esc_url(PAYPLUG_GATEWAY_PLUGIN_URL . '/assets/images/checkout/' . $this->image), $this->id . ' Icon'),
44 ]);
45
46 $icons_str = '';
47 foreach ($icons as $icon) {
48 $icons_str .= $icon;
49 }
50
51 return $icons_str;
52 }
53
54 /**
55 * @return void
56 */
57 public function display_notice()
58 {
59 $error_message = 'payplug_' . $this->id . '_unauthorized_message'; ?>
60 <div class="notice notice-error is-dismissible">
61 <p><?php echo __($error_message, 'payplug'); ?></p>
62 </div>
63 <?php
64 }
65
66 public function checkGateway()
67 {
68 //check if module is enabled
69 if (!isset($this->settings['enabled']) || !$this->settings['enabled']) {
70 return false;
71 }
72
73 // todo: delete this usage to avoid call to getAccount resource each checkout loading
74 $account = PayplugWoocommerceHelper::generic_get_account_data_from_options($this->id);
75 $options = PayplugWoocommerceHelper::get_payplug_options();
76
77 if (!$this->check_api_gateway_enable($account)) {
78 return false;
79 }
80
81 if (!isset($options['payment_methods']) || empty($options['payment_methods'])) {
82 return false;
83 }
84
85 if (!$options['payment_methods']['configuration'][$this->id]['active']) {
86 return false;
87 }
88
89 if (!is_admin() && !PayplugWoocommerceHelper::is_checkout_block()) {
90 if (empty(WC()->cart) && !is_admin()) {
91 return false;
92 }
93
94 //for backend orders
95 if (!empty(get_query_var('order-pay'))) {
96 $order = wc_get_order((int) get_query_var('order-pay'));
97 $items = $order->get_items();
98 $country_code_shipping = $order->get_shipping_country();
99 $country_code_billing = $order->get_billing_country();
100 $this->order_items_to_cart(WC()->cart, $items);
101 }
102
103 if (empty($country_code_billing) || empty($country_code_shipping)) {
104 $country_code_shipping = method_exists(WC()->customer, 'get_shipping_country') ? WC()->customer->get_shipping_country() : null;
105 $country_code_billing = method_exists(WC()->customer, 'get_billing_country') ? WC()->customer->get_billing_country() : null;
106 }
107
108 if (!$this->check_billing_country_permissions($account, $country_code_billing)) {
109 return false;
110 }
111 }
112
113 return true;
114 }
115
116 /**
117 * check if payment is enable and customer has permissions
118 *
119 * @param $account
120 *
121 * @return bool
122 */
123 protected function check_api_gateway_enable($account)
124 {
125 if (
126 isset($account['payment_methods']) &&
127 empty($account['payment_methods'][$this->id]) &&
128 !$account['payment_methods'][$this->id]['enabled']
129 ) {
130 return false;
131 }
132
133 return true;
134 }
135
136 /**
137 * Check if billing country can use this payment method
138 *
139 * @param $account
140 * @param $billing_code
141 *
142 * @return bool
143 */
144 public function check_billing_country_permissions($account, $billing_code)
145 {
146 $this->allowed_country_codes = !empty($account['payment_methods'][$this->id]['allowed_countries']) ? $account['payment_methods'][$this->id]['allowed_countries'] : null;
147
148 if (is_array($this->allowed_country_codes)) {
149 if (in_array('ALL', $this->allowed_country_codes) || empty($this->allowed_country_codes)) {
150 return true;
151 }
152
153 //check if country is allowed
154 if (in_array($billing_code, $this->allowed_country_codes)) {
155 return true;
156 } else {
157 return false;
158 }
159 }
160
161 return true;
162 }
163
164 /**
165 * if payment was generated by an intend, we shouldn't generate another one and try to pay it, this would generate duplications
166 *
167 * @param $order
168 *
169 * @throws \Exception
170 *
171 * @return array|null
172 */
173 private function process_standard_intent_payment($order)
174 {
175 $embedded_mode = $this->settings['payment_methods']['configuration']['payplug']['embedded_mode'];
176 if (!is_wc_endpoint_url('order-pay') &&
177 empty($_POST['payplug_non_blocks']) &&
178 PayplugWoocommerceHelper::is_checkout_block() &&
179 (
180 ($this->id === 'payplug' && in_array($embedded_mode, ['integrated', 'popup'])) ||
181 ($this->id === 'american_express' && 'popup' == $embedded_mode)
182 ) &&
183 !empty($order->get_transaction_id())) {
184 $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
185
186 try {
187 $payment = $this->payplug_api->payment_retrieve($order->get_transaction_id());
188 if (ob_get_length() > 0) {
189 ob_clean();
190 }
191
192 // Save transaction id for the order
193 PayplugWoocommerceHelper::is_pre_30()
194 ? update_post_meta($order_id, '_transaction_id', $payment->id)
195 : $order->set_transaction_id($payment->id);
196
197 if (is_callable([$order, 'save'])) {
198 $order->save();
199 }
200
201 /**
202 * Fires once a payment has been created.
203 *
204 * @param int $order_id Order ID
205 * @param PaymentResource $payment Payment resource
206 */
207 \do_action('payplug_gateway_payment_created', $order_id, $payment);
208
209 $metadata = PayplugWoocommerceHelper::extract_transaction_metadata($payment);
210 PayplugWoocommerceHelper::save_transaction_metadata($order, $metadata);
211
212 PayplugGateway::log(sprintf('Payment intent created for order #%s', $order_id));
213
214 $return_url = esc_url_raw($order->get_checkout_order_received_url());
215
216 wp_send_json_success(
217 [
218 'payment_id' => $payment->id,
219 'result' => 'success',
220 'redirect' => !empty($payment->hosted_payment->payment_url) ? $payment->hosted_payment->payment_url : $return_url,
221 'cancel' => !empty($payment->hosted_payment->cancel_url) ? $payment->hosted_payment->cancel_url : null,
222 ]
223 );
224
225 return ['stt' => 'OK'];
226 } catch (HttpException $e) {
227 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
228 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
229 } catch (\Exception $e) {
230 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
231 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
232 }
233 }
234
235 return null;
236 }
237
238 public function process_standard_payment($order, $amount, $customer_id)
239 {
240 $intent = $this->process_standard_intent_payment($order);
241 if (!empty($intent)) {
242 return $intent;
243 }
244
245 $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
246
247 try {
248
249 //if there's no auth to process payment
250 if (!$this->checkGateway()) {
251 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
252 }
253
254 $address_data = PayplugAddressData::from_order($order);
255 $return_url = esc_url_raw($order->get_checkout_order_received_url());
256
257 if (!(substr($return_url, 0, 4) === 'http')) {
258 $return_url = get_site_url() . $return_url;
259 }
260 $payment_data = [
261 'amount' => $amount,
262 'currency' => get_woocommerce_currency(),
263 'payment_method' => $this->id,
264 'billing' => $address_data->get_billing(),
265 'shipping' => $address_data->get_shipping(),
266 'hosted_payment' => [
267 'return_url' => $return_url,
268 'cancel_url' => esc_url_raw($order->get_cancel_order_url_raw()),
269 ],
270 'notification_url' => esc_url_raw(WC()->api_request_url('PayplugGateway')),
271 'metadata' => [
272 'order_id' => $order_id,
273 'customer_id' => ((int) $customer_id > 0) ? $customer_id : 'guest',
274 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
275 ],
276 'save_card' => false,
277 'force_3ds' => false,
278 ];
279 if (!empty($payment_data['billing']['landline_phone_number'])) {
280 $payment_data['billing']['mobile_phone_number'] = $payment_data['billing']['landline_phone_number'];
281 }
282
283 if (PayplugWoocommerceHelper::is_checkout_block() && is_checkout()) {
284 $payment_data['metadata']['woocommerce_block'] = 'CHECKOUT';
285 } elseif (PayplugWoocommerceHelper::is_cart_block() && is_cart()) {
286 $payment_data['metadata']['woocommerce_block'] = 'CART';
287 }
288 /**
289 * Filter the payment data before it's used
290 *
291 * @param array $payment_data
292 * @param int $order_id
293 * @param array $customer_details
294 * @param PayplugAddressData $address_data
295 */
296 $payment_data = apply_filters('payplug_gateway_payment_data', $payment_data, $order_id, [], $address_data);
297 $payment = $this->payplug_api->payment_create($payment_data);
298
299 // Save transaction id for the order
300 PayplugWoocommerceHelper::is_pre_30()
301 ? update_post_meta($order_id, '_transaction_id', $payment->id)
302 : $order->set_transaction_id($payment->id);
303
304 $order->set_payment_method($this->id);
305 $order->set_payment_method_title($this->method_title);
306
307 if (is_callable([$order, 'save'])) {
308 $order->save();
309 }
310
311 /**
312 * Fires once a payment has been created.
313 *
314 * @param int $order_id Order ID
315 * @param PaymentResource $payment Payment resource
316 */
317 \do_action('payplug_gateway_payment_created', $order_id, $payment);
318
319 $metadata = PayplugWoocommerceHelper::extract_transaction_metadata($payment);
320 PayplugWoocommerceHelper::save_transaction_metadata($order, $metadata);
321
322 PayplugGateway::log(sprintf('Payment creation complete for order #%s', $order_id));
323
324 return [
325 'result' => 'success',
326 'redirect' => $payment->hosted_payment->payment_url,
327 'cancel' => $payment->hosted_payment->cancel_url,
328 ];
329 } catch (HttpException $e) {
330 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
331 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
332 } catch (\Exception $e) {
333 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
334 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
335 }
336 }
337
338 /**
339 * Process refund for an order paid with PayPlug gateway.
340 *
341 * @param int $order_id
342 * @param null $amount
343 * @param string $reason
344 *
345 * @return bool|\WP_Error
346 */
347 public function process_refund($order_id, $amount = null, $reason = '')
348 {
349 PayplugGateway::log(sprintf('Processing refund for order #%s', $order_id));
350
351 if (!$this->user_logged_in()) {
352 PayplugGateway::log(__('You must be logged in with your PayPlug account.', 'payplug'), 'error');
353
354 return new \WP_Error('process_refund_error', __('You must be logged in with your PayPlug account.', 'payplug'));
355 }
356
357 $order = wc_get_order($order_id);
358 if (!$order instanceof \WC_Order) {
359 PayplugGateway::log(sprintf('The order #%s does not exist.', $order_id), 'error');
360
361 return new \WP_Error('process_refund_error', sprintf(__('The order %s does not exist.', 'payplug'), $order_id));
362 }
363
364 if ($order->get_status() === 'cancelled') {
365 PayplugGateway::log(sprintf('The order #%s cannot be refund.', $order_id), 'error');
366
367 return new \WP_Error('process_refund_error', sprintf(__('The order %s cannot be refund.', 'payplug'), $order_id));
368 }
369
370 $transaction_id = PayplugWoocommerceHelper::is_pre_30() ? get_post_meta($order_id, '_transaction_id', true) : $order->get_transaction_id();
371 if (empty($transaction_id)) {
372 PayplugGateway::log(sprintf('The order #%s does not have PayPlug transaction ID associated with it.', $order_id), 'error');
373
374 return new \WP_Error('process_refund_error', __('No PayPlug transaction was found for this order. The refund could not be processed.', 'payplug'));
375 }
376
377 /**
378 * PPRO gateways feature!
379 */
380 if (isset($this->enable_refund) && $this->enable_refund === false) {
381 add_action('admin_head', [$this, 'hide_wc_refund_button']);
382 PayplugGateway::log(__('payplug_refund_disabled_error', 'payplug'), 'error');
383
384 return new \WP_Error('process_refund_error', __('payplug_refund_disabled_error', 'payplug'));
385 }
386
387 $customer_id = PayplugWoocommerceHelper::is_pre_30() ? $order->customer_user : $order->get_customer_id();
388 $data = [
389 'metadata' => [
390 'order_id' => $order_id,
391 'customer_id' => ((int) $customer_id > 0) ? $customer_id : 'guest',
392 'refund_from' => 'woocommerce',
393 ],
394 ];
395
396 if (!is_null($amount)) {
397 $data['amount'] = PayplugWoocommerceHelper::get_payplug_amount($amount);
398 }
399
400 if (!empty($reason)) {
401 $data['metadata']['reason'] = $reason;
402 }
403
404 /**
405 * Filter the refund data before it's used.
406 *
407 * @param array $data
408 * @param int $order_id
409 * @param string $transaction_id
410 */
411 $data = apply_filters('payplug_gateway_refund_data', $data, $order_id, $transaction_id);
412
413 try {
414 $refund = $this->payplug_api->refund_create($transaction_id, $data);
415
416 if ($refund->object === 'error') {
417 PayplugGateway::log(__('payplug_ppro_flag_error', 'payplug'), 'error');
418
419 return new \WP_Error('process_refund_error', __('payplug_ppro_flag_error', 'payplug'));
420 }
421
422 /**
423 * Fires once a refund has been created.
424 *
425 * @param int $order_id Order ID
426 * @param RefundResource $refund Refund resource
427 * @param string $transaction_id Transaction id
428 */
429 \do_action('payplug_gateway_refund_created', $order_id, $refund, $transaction_id);
430
431 $refund_meta_key = sprintf('_pr_%s', wc_clean($refund->id));
432 if (PayplugWoocommerceHelper::is_pre_30()) {
433 update_post_meta($order_id, $refund_meta_key, $refund->id);
434 } else {
435 $order->add_meta_data($refund_meta_key, $refund->id, true);
436 $order->save();
437 }
438
439 $note = sprintf(__('Refund %s : Refunded %s', 'payplug'), wc_clean($refund->id), wc_price(((int) $refund->amount) / 100));
440 if (!empty($refund->metadata['reason'])) {
441 $note .= sprintf(' (%s)', esc_html($refund->metadata['reason']));
442 }
443 $order->add_order_note($note);
444
445 try {
446 $payment = $this->payplug_api->payment_retrieve($transaction_id);
447 $metadata = PayplugWoocommerceHelper::extract_transaction_metadata($payment);
448 PayplugWoocommerceHelper::save_transaction_metadata($order, $metadata);
449 } catch (\Exception $e) {
450 }
451
452 PayplugGateway::log('Refund process complete for the order.');
453
454 return true;
455 } catch (HttpException $e) {
456 PayplugGateway::log(sprintf('Refund request error for the order %s from PayPlug API : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
457
458 return new \WP_Error('process_refund_error', __('The transaction could not be refunded. Please try again.', 'payplug'));
459 } catch (\Exception $e) {
460 PayplugGateway::log(sprintf('Refund request error for the order %s : %s', $order_id, wc_clean($e->getMessage())), 'error');
461
462 return new \WP_Error('process_refund_error', __('The transaction could not be refunded. Please try again.', 'payplug'));
463 }
464 }
465
466 /**
467 * Avoid usage of button refund on the BO
468 *
469 * @return false|void
470 */
471 public function hide_wc_refund_button()
472 {
473 global $post;
474
475 $payment_methods = [];
476
477 if (class_exists('OrderUtil') && OrderUtil::custom_orders_table_usage_is_enabled()) {
478 $order_id = !empty($_GET['id']) ? $_GET['id'] : null;
479 } else {
480 if (!empty($post->ID)) {
481 $order_id = $post->ID;
482 } elseif (!empty($_GET['id'])) {
483 $order_id = $_GET['id'];
484 } else {
485 $order_id = null;
486 }
487 }
488
489 if (empty($order_id)) {
490 return false;
491 }
492
493 $order = new \WC_Order($order_id);
494 if (in_array($order->get_payment_method(), $payment_methods)) {
495 ?>
496 <script>
497 jQuery(function () {
498 jQuery('.refund-items').attr("disabled", true);
499 });
500 </script>
501 <?php
502 }
503 }
504
505 /**
506 * refund not possible for PPRO payments
507 *
508 * @return void
509 */
510 public function refund_not_available($order)
511 {
512 if ($this->id === $order->get_payment_method() && isset($this->enable_refund) && $this->enable_refund === false) {
513 echo "<p style='color: red;'>" . __('payplug_refund_disabled_error', 'payplug') . '</p>';
514 }
515 }
516
517 /**
518 * Empty the cart and add all order_items
519 *
520 * @param $cart
521 * @param $items
522 *
523 * @return void
524 */
525 private function order_items_to_cart($cart, $items)
526 {
527 $cart->empty_cart();
528 foreach ($items as $item) {
529 $cart->add_to_cart($item->get_product_id(), $item->get_quantity(), $item->get_variation_id());
530 }
531 }
532 }
533