PluginProbe
PayPlug for WooCommerce (Official) / 3.1.0
PayPlug for WooCommerce (Official) v3.1.0
3.1.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 All 102 releases
← All changes | src/Controller/PayplugGenericGateway.php +60 -43 2.18.0 → 3.1.0 View file →
@@ -1,9 +1,8 @@
1 1 <?php
2 2
3 3 namespace Payplug\PayplugWoocommerce\Controller;
4 4
5 -use Automattic\WooCommerce\Utilities\OrderUtil;
6 5 use Payplug\Exception\HttpException;
7 6 use Payplug\Payplug;
8 7 use Payplug\PayplugWoocommerce\Gateway\PayplugAddressData;
9 8 use Payplug\PayplugWoocommerce\Gateway\PayplugGateway;
@@ -26,9 +25,9 @@
26 25
27 26 public function __construct()
28 27 {
29 28 parent::__construct();
30 - add_action('woocommerce_after_order_itemmeta', [$this, 'hide_wc_refund_button']);
29 + add_action('woocommerce_after_order_itemmeta', [$this, 'hide_wc_refund_button'], 10, 3);
31 30 }
32 31
33 32 /**
34 33 * Generic code to fetch payment gateway specific image
@@ -53,9 +52,9 @@
53 52
54 53 /**
55 54 * @return void
56 55 */
57 - public function display_notice()
56 + public function display_notice(): void
58 57 {
59 58 $error_message = 'payplug_' . $this->id . '_unauthorized_message'; ?>
60 59 <div class="notice notice-error is-dismissible">
61 60 <p><?php echo __($error_message, 'payplug'); ?></p>
@@ -85,10 +84,12 @@
85 84 if (!$options['payment_methods']['configuration'][$this->id]['active']) {
86 85 return false;
87 86 }
88 87
89 - if (!is_admin() && !PayplugWoocommerceHelper::is_checkout_block()) {
90 - if (empty(WC()->cart) && !is_admin()) {
88 + $is_order_pay = is_wc_endpoint_url('order-pay');
89 + $country_code_billing = null;
90 + if (!is_admin() && (!PayplugWoocommerceHelper::is_checkout_block() || $is_order_pay)) {
91 + if (empty(WC()->cart) && !is_admin() && !$is_order_pay) {
91 92 return false;
92 93 }
93 94
94 95 //for backend orders
@@ -94,19 +95,28 @@
94 95 //for backend orders
95 96 if (!empty(get_query_var('order-pay'))) {
96 97 $order = wc_get_order((int) get_query_var('order-pay'));
97 98 $items = $order->get_items();
98 - $country_code_shipping = $order->get_shipping_country();
99 99 $country_code_billing = $order->get_billing_country();
100 - $this->order_items_to_cart(WC()->cart, $items);
100 + // Skip cart population for subscription renewals: WC Subscriptions manages the cart
101 + // itself and adding items here would cause a double entry in the order summary.
102 + $is_renewal = function_exists('wcs_order_contains_renewal') && wcs_order_contains_renewal($order);
103 + if (!$is_renewal) {
104 + if (is_null(WC()->cart)) {
105 + wc_load_cart();
106 + }
107 + $this->order_items_to_cart(WC()->cart, $items);
108 + }
101 109 }
102 110
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;
111 + $source_before_fallback = $country_code_billing;
112 + if (empty($country_code_billing)) {
105 113 $country_code_billing = method_exists(WC()->customer, 'get_billing_country') ? WC()->customer->get_billing_country() : null;
106 114 }
107 115
108 - if (!$this->check_billing_country_permissions($account, $country_code_billing)) {
116 + $permission_result = $this->check_billing_country_permissions($account, $country_code_billing);
117 +
118 + if (!$permission_result) {
109 119 return false;
110 120 }
111 121 }
112 122
@@ -142,10 +152,14 @@
142 152 * @return bool
143 153 */
144 154 public function check_billing_country_permissions($account, $billing_code)
145 155 {
146 - $this->allowed_country_codes = !empty($account['payment_methods'][$this->id]['allowed_countries']) ? $account['payment_methods'][$this->id]['allowed_countries'] : null;
156 + if (!isset($account['payment_methods'][$this->id]['allowed_countries'])) {
157 + return true;
158 + }
147 159
160 + $this->allowed_country_codes = $account['payment_methods'][$this->id]['allowed_countries'];
161 +
148 162 if (is_array($this->allowed_country_codes)) {
149 163 if (in_array('ALL', $this->allowed_country_codes) || empty($this->allowed_country_codes)) {
150 164 return true;
151 165 }
@@ -157,9 +171,9 @@
157 171 return false;
158 172 }
159 173 }
160 174
161 - return true;
175 + return false;
162 176 }
163 177
164 178 /**
165 179 * if payment was generated by an intend, we shouldn't generate another one and try to pay it, this would generate duplications
@@ -172,9 +186,15 @@
172 186 */
173 187 private function process_standard_intent_payment($order)
174 188 {
175 189 $embedded_mode = $this->settings['payment_methods']['configuration']['payplug']['embedded_mode'];
176 - if (!is_wc_endpoint_url('order-pay') &&
190 +
191 + // This can run from AJAX endpoints whose own request URL never carries the order-pay
192 + // query var, so is_wc_endpoint_url() alone can't detect that context here: fall back
193 + // to the order_key/order_pay_key sent by the order-pay AJAX flows.
194 + $is_order_pay = $this->is_order_pay_request($order);
195 +
196 + if (!$is_order_pay &&
177 197 empty($_POST['payplug_non_blocks']) &&
178 198 PayplugWoocommerceHelper::is_checkout_block() &&
179 199 (
180 200 ($this->id === 'payplug' && in_array($embedded_mode, ['integrated', 'popup'])) ||
@@ -212,18 +232,24 @@
212 232 PayplugGateway::log(sprintf('Payment intent created for order #%s', $order_id));
213 233
214 234 $return_url = esc_url_raw($order->get_checkout_order_received_url());
215 235
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 - );
236 + $result = [
237 + 'payment_id' => $payment->id,
238 + 'result' => 'success',
239 + 'redirect' => !empty($payment->hosted_payment->payment_url) ? $payment->hosted_payment->payment_url : $return_url,
240 + 'cancel' => !empty($payment->hosted_payment->cancel_url) ? $payment->hosted_payment->cancel_url : null,
241 + ];
224 242
225 - return ['stt' => 'OK'];
243 + // wp_send_json_success() calls die(), which is only safe for the classic
244 + // wc-ajax request this was written for: the Store API checkout flow (used by
245 + // the checkout block) calls process_payment() through the REST framework,
246 + // and killing the process mid-request there produces a broken response.
247 + if (wp_doing_ajax()) {
248 + wp_send_json_success($result);
249 + }
250 +
251 + return $result;
226 252 } catch (HttpException $e) {
227 253 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
228 254 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
229 255 } catch (\Exception $e) {
@@ -377,9 +403,8 @@
377 403 /**
378 404 * PPRO gateways feature!
379 405 */
380 406 if (isset($this->enable_refund) && $this->enable_refund === false) {
381 - add_action('admin_head', [$this, 'hide_wc_refund_button']);
382 407 PayplugGateway::log(__('payplug_refund_disabled_error', 'payplug'), 'error');
383 408
384 409 return new \WP_Error('process_refund_error', __('payplug_refund_disabled_error', 'payplug'));
385 410 }
@@ -465,34 +490,26 @@
465 490
466 491 /**
467 492 * Avoid usage of button refund on the BO
468 493 *
494 + * @param int $item_id
495 + * @param \WC_Order_Item|null $item
496 + * @param mixed $product
497 + *
469 498 * @return false|void
470 499 */
471 - public function hide_wc_refund_button()
500 + public function hide_wc_refund_button($item_id, $item = null, $product = null)
472 501 {
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 - }
502 + if (!$item instanceof \WC_Order_Item) {
503 + return false;
487 504 }
488 505
489 - if (empty($order_id)) {
506 + $order = $item->get_order();
507 + if (!$order instanceof \WC_Order) {
490 508 return false;
491 509 }
492 510
493 - $order = new \WC_Order($order_id);
494 - if (in_array($order->get_payment_method(), $payment_methods)) {
511 + if ($order->get_payment_method() === $this->id && isset($this->enable_refund) && $this->enable_refund === false) {
495 512 ?>
496 513 <script>
497 514 jQuery(function () {
498 515 jQuery('.refund-items').attr("disabled", true);
@@ -506,9 +523,9 @@
506 523 * refund not possible for PPRO payments
507 524 *
508 525 * @return void
509 526 */
510 - public function refund_not_available($order)
527 + public function refund_not_available($order): void
511 528 {
512 529 if ($this->id === $order->get_payment_method() && isset($this->enable_refund) && $this->enable_refund === false) {
513 530 echo "<p style='color: red;'>" . __('payplug_refund_disabled_error', 'payplug') . '</p>';
514 531 }
@@ -521,9 +538,9 @@
521 538 * @param $items
522 539 *
523 540 * @return void
524 541 */
525 - private function order_items_to_cart($cart, $items)
542 + private function order_items_to_cart($cart, $items): void
526 543 {
527 544 $cart->empty_cart();
528 545 foreach ($items as $item) {
529 546 $cart->add_to_cart($item->get_product_id(), $item->get_quantity(), $item->get_variation_id());