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/Gateway/PayplugGateway.php +66 -18 2.18.0 → 3.1.0 View file →
@@ -25,9 +25,9 @@
25 25 class PayplugGateway extends WC_Payment_Gateway_CC
26 26 {
27 27 use ServiceGetter;
28 28
29 - const OPTION_NAME = 'payplug_config';
29 + public const OPTION_NAME = 'payplug_config';
30 30
31 31 /**
32 32 * @var string
33 33 */
@@ -91,14 +91,14 @@
91 91
92 92 /**
93 93 * @var float
94 94 */
95 - const MIN_AMOUNT = 0.99;
95 + public const MIN_AMOUNT = 0.99;
96 96
97 97 /**
98 98 * @var float
99 99 */
100 - const MAX_AMOUNT = 20000;
100 + public const MAX_AMOUNT = 20000;
101 101
102 102 /**
103 103 * @var string
104 104 */
@@ -109,9 +109,9 @@
109 109 public $oney_thresholds_min;
110 110 public $max_oney_price;
111 111 public $oney_thresholds_max;
112 112
113 - const ENABLE_ON_TEST_MODE = true;
113 + public const ENABLE_ON_TEST_MODE = true;
114 114
115 115 /**
116 116 * Logging method.
117 117 *
@@ -118,9 +118,9 @@
118 118 * @param string $message Log message.
119 119 * @param string $level Optional. Default 'info'.
120 120 * emergency|alert|critical|error|warning|notice|info|debug
121 121 */
122 - public static function log($message, $level = 'info')
122 + public static function log($message, $level = 'info'): void
123 123 {
124 124 if (!self::$log_enabled) {
125 125 return;
126 126 }
@@ -239,9 +239,9 @@
239 239 * Validate order payment when the user is redirected to the success confirmation page.
240 240 *
241 241 * @throws \WC_Data_Exception
242 242 */
243 - public function validate_payment($id = null, $save_request = true, $ipn = false)
243 + public function validate_payment($id = null, $save_request = true, $ipn = false): void
244 244 {
245 245 global $wp;
246 246
247 247 if (!$ipn) {
@@ -328,9 +328,17 @@
328 328 */
329 329 public function is_available()
330 330 {
331 331 if ('yes' == $this->enabled) {
332 - return $this->requirements->satisfy_requirements() && !empty($this->get_api_key($this->get_current_mode()));
332 + $available = $this->requirements->satisfy_requirements() && !empty($this->get_api_key($this->get_current_mode()));
333 +
334 + // $this->enabled only reflects the country/context check as it was at gateway construction time,
335 + // so re-run it here to catch context that only becomes known later in the request (e.g. order-pay).
336 + if ($available && method_exists($this, 'checkGateway')) {
337 + $available = $this->checkGateway();
338 + }
339 +
340 + return $available;
333 341 }
334 342
335 343 return parent::is_available();
336 344 }
@@ -337,9 +345,9 @@
337 345
338 346 /**
339 347 * Load gateway settings.
340 348 */
341 - public function init_settings()
349 + public function init_settings(): void
342 350 {
343 351 parent::init_settings();
344 352 $enabled = !empty($this->settings['enabled']) && (bool) $this->settings['enabled'];
345 353 $this->enabled = $enabled ? 'yes' : 'no';
@@ -347,9 +355,9 @@
347 355
348 356 /**
349 357 * Register gateway settings.
350 358 */
351 - public function init_form_fields()
359 + public function init_form_fields(): void
352 360 {
353 361 $anchor = esc_html_x(__('More informations', 'payplug'), 'modal', 'payplug');
354 362 $domain = __('support.payplug.com/hc/fr/articles/4408142346002', 'payplug');
355 363 $link = sprintf(' <a href="https://%s" target="_blank">%s</a>', $domain, $anchor);
@@ -544,14 +552,16 @@
544 552
545 553 /**
546 554 * Set global configuration for PayPlug instance.
547 555 */
548 - public function init_payplug()
556 + public function init_payplug(): void
549 557 {
550 558 $this->payplug_api = new PayplugApi($this);
551 559 $this->payplug_api->init();
552 560
553 - $this->permissions = new PayplugPermissions($this);
561 + // init() just resolved this for the same mode - reuse it instead of asking
562 + // Service\Api::get_bearer_token() to do so again right after.
563 + $this->permissions = new PayplugPermissions($this, $this->payplug_api->get_current_bearer_token());
554 564 $this->response = new PayplugResponse($this);
555 565
556 566 // Register IPN handler
557 567 new PayplugIpnResponse($this);
@@ -628,9 +638,9 @@
628 638
629 639 /**
630 640 * extra payment fields
631 641 */
632 - public function payment_fields()
642 + public function payment_fields(): void
633 643 {
634 644 $description = $this->get_description();
635 645
636 646 if (!empty($description)) {
@@ -645,9 +655,9 @@
645 655
646 656 /**
647 657 * Handle admin display.
648 658 */
649 - public function admin_options()
659 + public function admin_options(): void
650 660 {
651 661 /************ VUE Code *************/
652 662 wp_enqueue_script('chunk-vendors.js', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/dist/js/chunk-vendors-' . PAYPLUG_GATEWAY_VERSION . '.js', [], PAYPLUG_GATEWAY_VERSION);
653 663 wp_enqueue_script('app.js', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/dist/js/app-' . PAYPLUG_GATEWAY_VERSION . '.js', [], PAYPLUG_GATEWAY_VERSION);
@@ -710,8 +720,32 @@
710 720 return $this->process_standard_payment($order, $amount, $customer_id);
711 721 }
712 722
713 723 /**
724 + * Whether the current request is repaying an existing order (order-pay page, or one of
725 + * the order-pay AJAX flows). The order_key/order_pay_key posted by those AJAX flows must
726 + * match the order's own key: their mere presence isn't proof of anything, since any
727 + * request can set them.
728 + *
729 + * @param \WC_Order|null $order
730 + *
731 + * @return bool
732 + */
733 + protected function is_order_pay_request($order): bool
734 + {
735 + if (is_wc_endpoint_url('order-pay')) {
736 + return true;
737 + }
738 +
739 + $posted_key = $_POST['order_pay_key'] ?? $_POST['order_key'] ?? '';
740 + if (empty($posted_key)) {
741 + return false;
742 + }
743 +
744 + return $order instanceof \WC_Order && hash_equals($order->get_order_key(), wc_clean(wp_unslash($posted_key)));
745 + }
746 +
747 + /**
714 748 * if payment was generated by an intend, we shouldn't generate another one and try to pay it, this would generate duplications
715 749 *
716 750 * @param $order
717 751 *
@@ -720,16 +754,22 @@
720 754 * @return array|null
721 755 */
722 756 private function process_standard_intent_payment($order)
723 757 {
758 + // This can run from AJAX endpoints whose own request URL never carries the order-pay
759 + // query var, so is_wc_endpoint_url() alone can't detect that context here: fall back
760 + // to the order_key/order_pay_key sent by the order-pay AJAX flows.
761 + $is_order_pay = $this->is_order_pay_request($order);
762 +
724 763 //no order-pay page, no ajax_on_order_review_page
725 - if (!is_wc_endpoint_url('order-pay') &&
764 + if (!$is_order_pay &&
726 765 PayplugWoocommerceHelper::is_checkout_block() &&
727 766 (
728 767 ('payplug' == $this->id && in_array($this->embedded_mode, ['integrated', 'popup'])) ||
729 768 ('american_express' == $this->id && 'popup' == $this->embedded_mode)
730 769 ) &&
731 - $_GET['wc-ajax'] !== 'payplug_order_review_url'
770 + ($_GET['wc-ajax'] ?? '') !== 'payplug_order_review_url' &&
771 + !empty($order->get_transaction_id())
732 772 ) {
733 773 $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
734 774
735 775 try {
@@ -766,16 +806,24 @@
766 806 self::log(sprintf('Payment intent created for order #%s', $order_id));
767 807
768 808 $return_url = esc_url_raw($order->get_checkout_order_received_url());
769 809
770 - wp_send_json_success([
810 + $result = [
771 811 'payment_id' => $payment->id,
772 812 'result' => 'success',
773 813 'redirect' => !empty($payment->hosted_payment->payment_url) ? $payment->hosted_payment->payment_url : $return_url,
774 814 'cancel' => !empty($payment->hosted_payment->cancel_url) ? $payment->hosted_payment->cancel_url : null,
775 - ]);
815 + ];
776 816
777 - return ['stt' => 'OK'];
817 + // wp_send_json_success() calls die(), which is only safe for the classic
818 + // wc-ajax request this was written for: the Store API checkout flow (used by
819 + // the checkout block) calls process_payment() through the REST framework,
820 + // and killing the process mid-request there produces a broken response.
821 + if (wp_doing_ajax()) {
822 + wp_send_json_success($result);
823 + }
824 +
825 + return $result;
778 826 } catch (HttpException $e) {
779 827 self::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
780 828 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
781 829 } catch (\Exception $e) {