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/PayplugGatewayOney3x.php +319 -108 1.2.4 → 3.1.0 View file →
@@ -1,12 +1,13 @@
1 1 <?php
2 2
3 3 namespace Payplug\PayplugWoocommerce\Gateway;
4 4
5 -use Payplug\PayplugWoocommerce\PayplugWoocommerceHelper;
6 -use Payplug\Authentication;
7 5 use libphonenumber\PhoneNumberType;
8 6 use libphonenumber\PhoneNumberUtil;
7 +use Payplug\PayplugWoocommerce\Controller\PayplugGenericGateway;
8 +use Payplug\PayplugWoocommerce\Gateway\Oney\OneyAccountMapper;
9 +use Payplug\PayplugWoocommerce\PayplugWoocommerceHelper;
9 10
10 11 // Exit if accessed directly
11 12 if (!defined('ABSPATH')) {
12 13 exit;
@@ -13,40 +14,79 @@
13 14 }
14 15
15 16 /**
16 17 * PayPlug WooCommerce Gateway.
17 - *
18 - * @package Payplug\PayplugWoocommerce\Gateway
19 18 */
20 -class PayplugGatewayOney3x extends PayplugGateway
19 +class PayplugGatewayOney3x extends PayplugGenericGateway
21 20 {
22 - const OPTION_NAME = "payplug_oney_config";
23 - const ONEY_UNAVAILABLE_CODE_COUNTRY_NOT_ALLOWED = 2;
24 - const ONEY_UNAVAILABLE_CODE_CART_SIZE_TOO_HIGH = 3;
25 - const ONEY_PRODUCT_QUANTITY_MAXIMUM = 1000;
21 + public const ONEY_UNAVAILABLE_CODE_COUNTRY_NOT_ALLOWED = 2;
22 + public const ONEY_UNAVAILABLE_CODE_CART_SIZE_TOO_HIGH = 3;
23 + public const ONEY_DISALBE_CHECKOUT_OPTIONS = 4;
26 24
25 + public const ONEY_PRODUCT_QUANTITY_MAXIMUM = 1000;
26 +
27 27 protected $oney_response;
28 - protected $min_oney_price;
29 - protected $max_oney_price;
30 - protected $allowed_country_codes;
28 + public const ENABLE_ON_TEST_MODE = true;
31 29
30 + public $allowed_country_codes = [];
31 +
32 32 public function __construct()
33 33 {
34 34 parent::__construct();
35 - $this->id = 'oney_x3_with_fees';
36 - $this->method_title = _x('PayPlug Oney 3x', 'Gateway method title', 'payplug');
35 + $this->id = 'oney_x3_with_fees';
36 + $this->method_title = _x('PayPlug Oney 3x', 'Gateway method title', 'payplug');
37 37 $this->method_description = __('Enable PayPlug Oney 3x for your customers.', 'payplug');
38 - $this->title = __('Pay by card in 3x with Oney', 'payplug');
38 + $this->title = __('Pay by card in 3x with Oney', 'payplug');
39 + $this->has_fields = true;
39 40
40 - if (is_admin()) {
41 - wp_register_style('payplug-admin-oney', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/css/payplug-admin-oney.css', [], PAYPLUG_GATEWAY_VERSION);
42 - wp_enqueue_style('payplug-admin-oney');
41 + add_action('woocommerce_order_item_add_action_buttons', [$this, 'oney_refund_text']);
42 + add_action('woocommerce_after_checkout_validation', [$this, 'validate_checkout'], 10);
43 +
44 + self::set_oney_configuration();
45 +
46 + // Unlike the other sub-gateways (Bancontact, AmericanExpress, PPRO methods...), Oney never
47 + // synced $this->enabled with the plugin's own "active" toggle, so disabling Oney from the
48 + // Payplug config left it shown as enabled on WooCommerce's native Payments settings page.
49 + if (!$this->checkGateway()) {
50 + $this->enabled = 'no';
43 51 }
44 52
45 - add_action('woocommerce_order_item_add_action_buttons', [$this, 'oney_refund_text']);
53 + if (is_checkout()) {
54 + if ($this->check_oney_is_available() === self::ONEY_DISALBE_CHECKOUT_OPTIONS) {
55 + $this->enabled = 'no';
56 + }
57 + }
58 + }
46 59
47 - if (is_checkout()) {
48 - $account = PayplugWoocommerceHelper::get_account_data_from_options(true);
60 + public function validate_checkout(): void
61 + {
62 + $posted_data = $this->get_post_data();
63 +
64 + // Was a single malformed string (missing quotes around each id) instead of a 4-element
65 + // array, so this guard never matched and the whole method was a silent no-op (PRE-3457
66 + // review / PRE-3457 follow-up fix).
67 + $oney_gateway_ids = ['oney_x3_with_fees', 'oney_x4_with_fees', 'oney_x3_without_fees', 'oney_x4_without_fees'];
68 +
69 + if (in_array($posted_data['payment_method'] ?? '', $oney_gateway_ids, true)) {
70 + if ($this->check_oney_is_available() === self::ONEY_UNAVAILABLE_CODE_COUNTRY_NOT_ALLOWED) {
71 + throw new \Exception(__('Unavailable for the specified country.'));
72 + } elseif ($this->check_oney_is_available() === self::ONEY_UNAVAILABLE_CODE_CART_SIZE_TOO_HIGH) {
73 + throw new \Exception(sprintf(__('The payment with Oney is unavailable because you have more than %s items in your cart.', 'payplug'), self::ONEY_PRODUCT_QUANTITY_MAXIMUM));
74 + } elseif (!$this->check_oney_is_available()) {
75 + throw new \Exception(sprintf(__('The total amount of your order should be between %s€ and %s€ to pay with Oney.', 'payplug'), $this->oney_thresholds_min, $this->oney_thresholds_max));
76 + }
77 + }
78 + }
79 +
80 + /**
81 + * Set oney settings
82 + *
83 + * @return void
84 + */
85 + private function set_oney_configuration(): void
86 + {
87 + $account = PayplugWoocommerceHelper::get_account_data_from_options();
88 + if ($account) {
49 89 $oney_configuration = $account['configuration']['oney'];
50 90 $this->min_oney_price = $oney_configuration['min_amounts']['EUR'] / 100;
51 91 $this->max_oney_price = $oney_configuration['max_amounts']['EUR'] / 100;
52 92 $this->allowed_country_codes = $oney_configuration['allowed_countries'];
@@ -59,79 +99,169 @@
59 99 * @return string
60 100 */
61 101 public function get_icon()
62 102 {
103 + $disable = $this->check_oney_is_available() === true ? '' : 'disable-checkout-icons';
104 + $available_img = 'x3_with_fees.svg';
63 105
64 - if ($this->check_oney_is_available() === true) {
65 - $total_price = floatval(WC()->cart->total);
66 - $this->oney_response = $this->api->simulate_oney_payment($total_price);
67 - $currency = get_woocommerce_currency_symbol(get_option('woocommerce_currency'));
68 - $f = function ($fn) {
69 - return $fn;
70 - };
71 - $this->description = <<<HTML
72 - <p>
73 - <div class="payplug-oney-flex">
74 - <div>{$f(__('Bring', 'payplug'))} :</div>
75 - <div>{$this->oney_response['x3_with_fees']['down_payment_amount']} {$currency}</div>
76 - </div>
77 - <div class="payplug-oney-flex">
78 - <div>{$f(__('1st monthly payment', 'payplug'))} :</div>
79 - <div>{$this->oney_response['x3_with_fees']['installments'][0]['amount']} {$currency}</div>
80 - </div>
81 - <div class="payplug-oney-flex">
82 - <div>{$f(__('2nd monthly payment', 'payplug'))} :</div>
83 - <div>{$this->oney_response['x3_with_fees']['installments'][1]['amount']} {$currency}</div>
84 - </div>
85 - </p>
86 -HTML;
87 - $available_img = 'lg-3xoney-checkout.png';
88 - } else {
89 - $available_img = 'lg-3xoney-checkout-disabled.png';
90 - }
91 -
92 106 $icons = apply_filters('payplug_payment_icons', [
93 - 'payplug' => sprintf('<img src="%s" alt="Oney 3x" class="payplug-payment-icon" />', esc_url(PAYPLUG_GATEWAY_PLUGIN_URL . '/assets/images/' . $available_img)),
107 + 'payplug' => sprintf('<img src="%s" alt="Oney 3x" class="payplug-payment-icon ' . $disable . '" />', esc_url(PAYPLUG_GATEWAY_PLUGIN_URL . '/assets/images/checkout/' . $available_img)),
94 108 ]);
95 109 $icons_str = '';
96 110 foreach ($icons as $icon) {
97 111 $icons_str .= $icon;
98 112 }
113 +
99 114 return $icons_str;
100 115 }
101 116
102 117 /**
118 + * Render the placeholder + config the official Oney widget uses to display the inline
119 + * payment-schedule section for this specific gateway (checkout obligation).
120 + */
121 + public function payment_fields(): void
122 + {
123 + if ($this->check_oney_is_available() !== true) {
124 + // check_oney_is_available() sets $this->description with the reason Oney can't be used.
125 + $description = $this->get_description();
126 +
127 + if (!empty($description)) {
128 + echo wpautop(wptexturize($description));
129 + }
130 +
131 + return;
132 + }
133 +
134 + $account = PayplugWoocommerceHelper::get_account_data_from_options();
135 + $oney_settings = $this->get_configuration()->get_option('payment_methods.configuration.oney');
136 + $country = PayplugWoocommerceHelper::getISOCountryCode();
137 + $mapper = OneyAccountMapper::map((array) $account, $oney_settings, $country);
138 + $code = $mapper->business_transaction_code_for_gateway($this->id);
139 +
140 + if (!$mapper->is_enabled() || !$code) {
141 + return;
142 + }
143 +
144 + printf(
145 + '<div id="oney-checkout-loading-%1$s" class="payplug-lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div><div id="oney-checkout-%1$s"></div><script type="application/json" id="oney-checkout-config-%1$s">%2$s</script>',
146 + esc_attr($this->id),
147 + wp_json_encode([
148 + 'merchant_guid' => $mapper->get_merchant_guid(),
149 + 'business_transaction_code' => $code,
150 + 'country' => $country,
151 + 'language' => strtoupper(substr(get_locale(), 0, 2)),
152 + 'payment_amount' => floatval(WC()->cart->total),
153 + ])
154 + );
155 + }
156 +
157 + /**
103 158 * Check if Oney is available
104 - *
105 - * @return void
159 + *
160 + * @return bool|int true, false, or an ONEY_* status code
106 161 */
107 162 public function check_oney_is_available()
108 163 {
164 + static $is_running = false;
165 + if ($is_running) {
166 + return false;
167 + }
168 + $is_running = true;
169 + try {
170 + $result = $this->do_check_oney_is_available();
171 + } finally {
172 + $is_running = false;
173 + }
174 +
175 + return $result;
176 + }
177 +
178 + private function do_check_oney_is_available()
179 + {
109 180 $cart = WC()->cart;
181 +
182 + //for backend orders
183 + if (!empty(get_query_var('order-pay'))) {
184 + $order = wc_get_order(get_query_var('order-pay'));
185 +
186 + //wc_get_order @return bool|WC_Order|WC_Order_Refund
187 + if ($order === false) {
188 + return false;
189 + }
190 +
191 + $items = $order->get_items();
192 +
193 + $country_code_shipping = $order->get_shipping_country();
194 + $country_code_billing = $order->get_billing_country();
195 +
196 + // Skip cart population for subscription renewals: WC Subscriptions manages the cart
197 + // itself and adding items here would cause a double entry in the order summary.
198 + $is_renewal = function_exists('wcs_order_contains_renewal') && wcs_order_contains_renewal($order);
199 + if (!$is_renewal) {
200 + $this->order_items_to_cart($cart, $items);
201 + }
202 + }
203 +
204 + $oney_cfg = $this->get_configuration()->get_option('payment_methods.configuration.oney');
205 + $account = PayplugWoocommerceHelper::get_account_data_from_options();
206 + $oney_account_cfg = ((array) $account)['configuration']['oney'] ?? [];
207 + // Same clamping OneyAccountMapper::map() uses for the badge/widget display, so
208 + // checkout validation and display never silently drift apart (PRE-3457 review).
209 + [$min_cents, $max_cents] = OneyAccountMapper::effective_bounds($oney_account_cfg, $oney_cfg);
210 + $oney_amount = [
211 + 'min' => $min_cents / 100,
212 + 'max' => $max_cents / 100,
213 + ];
214 + // validate_checkout() reads these to build its exception message - populate them
215 + // unconditionally (before any early return below) so they're never stale/unset there.
216 + $this->oney_thresholds_min = $oney_amount['min'];
217 + $this->oney_thresholds_max = $oney_amount['max'];
218 +
219 + if (empty($cart->total)) {
220 + return false;
221 + }
222 +
223 + if (empty($cart->cart_contents_count)) {
224 + return false;
225 + }
226 +
110 227 $total_price = floatval($cart->total);
111 - $products_qty = (int) $cart->cart_contents_count;
112 -
113 - // Min and max
114 - if ($total_price < $this->min_oney_price || $total_price > $this->max_oney_price) {
115 - $this->description = '<div class="payment_method_oney_x3_with_fees_disabled">'.sprintf(__('The total amount of your order should be between %s€ and %s€ to pay with Oney.', 'payplug'), $this->min_oney_price, $this->max_oney_price).'</div>';
228 + $products_qty = (int) $cart->cart_contents_count;
229 +
230 + // Min and max
231 + if ($total_price < $oney_amount['min'] || $total_price > $oney_amount['max']) {
232 + $this->description = '<div class="payment_method_oney_x3_with_fees_disabled">' . sprintf(__('The total amount of your order should be between %s€ and %s€ to pay with Oney.', 'payplug'), $oney_amount['min'], $oney_amount['max']) . '</div>';
233 +
116 234 return false;
117 235 }
118 236
119 237 // Cart check
120 238 if ($products_qty >= self::ONEY_PRODUCT_QUANTITY_MAXIMUM) {
121 - $this->description = '<div class="payment_method_oney_x3_with_fees_disabled">'.sprintf(__('The payment with Oney is unavailable because you have more than %s items in your cart.', 'payplug'), self::ONEY_PRODUCT_QUANTITY_MAXIMUM).'</div>';
239 + $this->description = '<div class="payment_method_oney_x3_with_fees_disabled">' . sprintf(__('The payment with Oney is unavailable because you have more than %s items in your cart.', 'payplug'), self::ONEY_PRODUCT_QUANTITY_MAXIMUM) . '</div>';
240 +
122 241 return self::ONEY_UNAVAILABLE_CODE_CART_SIZE_TOO_HIGH;
123 242 }
124 243
125 244 // Country check
126 - $country_code_shipping = WC()->customer->get_shipping_country();
127 - $country_code_billing = WC()->customer->get_billing_country();
128 -
129 - if (!in_array($country_code_billing, $this->allowed_country_codes) || !in_array($country_code_shipping, $this->allowed_country_codes)) {
130 - $this->description = '<div class="payment_method_oney_x3_with_fees_disabled">'.__('Unavailable for the specified country.', 'payplug').'</div>';
131 - return self::ONEY_UNAVAILABLE_CODE_COUNTRY_NOT_ALLOWED;
245 + if (empty($country_code_shipping) || empty($country_code_shipping)) {
246 + $country_code_shipping = WC()->customer->get_shipping_country();
247 + $country_code_billing = WC()->customer->get_billing_country();
132 248 }
133 -
249 +
250 + //WOOC-663 exception for the description to be visible
251 + //billing allowed?
252 + if ($this->allowed_country($country_code_billing, $this->allowed_country_codes)) {
253 +
254 + //if shipping is different from billing and billing is accepted
255 + if (!$this->validate_shipping_billing_country($country_code_shipping, $country_code_billing)) {
256 + $this->description = '<div class="payment_method_oney_x3_with_fees_disabled">' . __('Unavailable for the specified country.', 'payplug') . '</div>';
257 +
258 + return self::ONEY_UNAVAILABLE_CODE_COUNTRY_NOT_ALLOWED;
259 + }
260 + } else {
261 + return self::ONEY_DISALBE_CHECKOUT_OPTIONS;
262 + }
263 +
134 264 return true;
135 265 }
136 266
137 267 /**
@@ -157,10 +287,11 @@
157 287 * @param \WC_Order $order
158 288 * @param int $amount
159 289 * @param int $customer_id
160 290 *
291 + * @throws \Exception
292 + *
161 293 * @return array
162 - * @throws \Exception
163 294 */
164 295 public function process_standard_payment($order, $amount, $customer_id)
165 296 {
166 297 $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
@@ -174,25 +305,31 @@
174 305 throw new \Exception(sprintf(__('The payment with Oney is unavailable because you have more than %s items in your cart.', 'payplug'), self::ONEY_PRODUCT_QUANTITY_MAXIMUM));
175 306 }
176 307
177 308 $country = PayplugWoocommerceHelper::is_pre_30() ? $order->billing_country : $order->get_billing_country();
178 - $phone = PayplugWoocommerceHelper::is_pre_30() ? $order->billing_phone : $order->get_billing_phone();
179 - $billing_email = PayplugWoocommerceHelper::is_pre_30() ? $order->billing_email : $order->get_billing_email();
309 + $phone = PayplugWoocommerceHelper::is_pre_30() ? $order->billing_phone : $order->get_billing_phone();
310 + $billing_email = PayplugWoocommerceHelper::is_pre_30() ? $order->billing_email : $order->get_billing_email();
180 311 $phone_number_util = PhoneNumberUtil::getInstance();
181 - $phone_number = $phone_number_util->parse( $phone, $country );
182 - if ( PhoneNumberType::MOBILE !== $phone_number_util->getNumberType( $phone_number ) ) {
312 + $phone_number = $phone_number_util->parse($phone, $country);
313 + if (PhoneNumberType::MOBILE !== $phone_number_util->getNumberType($phone_number)) {
183 314 throw new \Exception(__('Mobile phone number fullfilled is invalid. Please retry.', 'payplug'));
184 315 }
185 -
186 - if (!filter_var($billing_email, FILTER_VALIDATE_EMAIL) || strpos($billing_email,'+') !== false) {
187 - throw new \Exception(__("Your email address is too long and the + character is not valid, please change it to another address (max 100 characters).", 'payplug'));
316 +
317 + if (!filter_var($billing_email, FILTER_VALIDATE_EMAIL) || strpos($billing_email, '+') !== false) {
318 + throw new \Exception(__('Your email address is too long and the + character is not valid, please change it to another address (max 100 characters).', 'payplug'));
188 319 }
189 320
190 321 $address_data = PayplugAddressData::from_order($order);
191 322
323 + $return_url = esc_url_raw($order->get_checkout_order_received_url());
324 +
325 + if (!(substr($return_url, 0, 4) === 'http')) {
326 + $return_url = get_site_url() . $return_url;
327 + }
328 +
192 329 $cart_items = [];
193 330 $items = $order->get_items();
194 - foreach($items as $item) {
331 + foreach ($items as $item) {
195 332 $data = $item->get_data();
196 333 $total = floatval(round($data['total'], 2)) * 100;
197 334 $cart_items[] = [
198 335 'delivery_label' => 'storepickup',
@@ -197,39 +334,44 @@
197 334 $cart_items[] = [
198 335 'delivery_label' => 'storepickup',
199 336 'delivery_type' => 'storepickup',
200 337 'brand' => 'Woocommerce',
201 - 'merchant_item_id' => 'cart-'.$data['id'].'-'.$data['product_id'],
338 + 'merchant_item_id' => 'cart-' . $data['id'] . '-' . $data['product_id'],
202 339 'name' => $data['name'],
203 340 'expected_delivery_date' => date('Y-m-d'),
204 - 'total_amount' => $total,
205 - 'price' => round($total / $data['quantity']),
206 - 'quantity' => $data['quantity']
341 + 'total_amount' => (int) $total,
342 + 'price' => round($total / $data['quantity']),
343 + 'quantity' => $data['quantity'],
207 344 ];
208 345 }
209 346
210 347 $payment_data = [
211 348 'authorized_amount' => $amount,
212 - 'auto_capture' => true,
213 - 'currency' => get_woocommerce_currency(),
214 - 'payment_method' => $this->id,
215 - 'billing' => $address_data->get_billing(),
216 - 'shipping' => $address_data->get_shipping(),
217 - 'payment_context' => [
218 - "cart" => $cart_items
349 + 'auto_capture' => true,
350 + 'currency' => get_woocommerce_currency(),
351 + 'payment_method' => $this->id,
352 + 'billing' => $address_data->get_billing(),
353 + 'shipping' => $address_data->get_shipping(),
354 + 'payment_context' => [
355 + 'cart' => $cart_items,
219 356 ],
220 357 'notification_url' => esc_url_raw(WC()->api_request_url('PayplugGateway')),
221 - 'hosted_payment' => [
222 - 'return_url' => esc_url_raw($order->get_checkout_order_received_url()),
358 + 'hosted_payment' => [
359 + 'return_url' => $return_url,
223 360 'cancel_url' => esc_url_raw($order->get_cancel_order_url_raw()),
224 361 ],
225 - 'metadata' => [
226 - 'order_id' => $order_id,
362 + 'metadata' => [
363 + 'order_id' => $order_id,
227 364 'customer_id' => ((int) $customer_id > 0) ? $customer_id : 'guest',
228 - 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
365 + 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
229 366 ],
230 367 ];
231 368
369 + if (PayplugWoocommerceHelper::is_checkout_block() && is_checkout()) {
370 + $payment_data['metadata']['woocommerce_block'] = 'CHECKOUT';
371 + } elseif (PayplugWoocommerceHelper::is_cart_block() && is_cart()) {
372 + $payment_data['metadata']['woocommerce_block'] = 'CART';
373 + }
232 374
233 375 /**
234 376 * Filter the payment data before it's used
235 377 *
@@ -238,9 +380,9 @@
238 380 * @param array $customer_details
239 381 * @param PayplugAddressData $address_data
240 382 */
241 383 $payment_data = apply_filters('payplug_gateway_payment_data', $payment_data, $order_id, [], $address_data);
242 - $payment = $this->api->payment_create($payment_data);
384 + $payment = $this->payplug_api->payment_create($payment_data);
243 385
244 386 // Save transaction id for the order
245 387 PayplugWoocommerceHelper::is_pre_30()
246 388 ? update_post_meta($order_id, '_transaction_id', $payment->id)
@@ -263,11 +405,11 @@
263 405
264 406 PayplugGateway::log(sprintf('Payment creation complete for order #%s', $order_id));
265 407
266 408 return [
267 - 'result' => 'success',
409 + 'result' => 'success',
268 410 'redirect' => $payment->hosted_payment->payment_url,
269 - 'cancel' => $payment->hosted_payment->cancel_url,
411 + 'cancel' => $payment->hosted_payment->cancel_url,
270 412 ];
271 413 } catch (\HttpException $e) {
272 414 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
273 415 throw new \Exception(__($e->getMessage(), 'payplug'));
@@ -276,47 +418,116 @@
276 418 throw new \Exception(__($e->getMessage(), 'payplug'));
277 419 }
278 420 }
279 421
280 -
281 422 /**
282 - * Check if the gatteway is allowed for the order amount
423 + * Check if the gatteway is allowed for the order amount
283 424 *
284 425 * @param array
426 + *
285 427 * @return array
286 428 */
287 429 public function check_gateway($gateways)
288 430 {
289 431 if (isset($gateways[$this->id]) && $gateways[$this->id]->id == $this->id) {
290 - if(!PayplugWoocommerceHelper::is_oney_available()) {
432 + //remove gateway if thresholds/country criteria are not met
433 + if ($this->check_oney_is_available() === false) {
291 434 unset($gateways[$this->id]);
292 435 }
436 +
437 + //remove gateway if account doesn't have permission
438 + if (!PayplugWoocommerceHelper::is_oney_available()) {
439 + unset($gateways[$this->id]);
440 + } else {
441 + $gateways = parent::check_gateway($gateways);
442 + }
293 443 }
444 +
294 445 return $gateways;
295 446 }
296 447
297 448 /**
298 449 * Show Oney refund text
299 - *
450 + *
300 451 * @return void
301 452 */
302 - public function oney_refund_text($order)
453 + public function oney_refund_text($order): void
303 454 {
304 - if ($this->id === $order->get_payment_method() && parent::can_refund_order($order) && $order->get_status() !== "refunded") {
455 + if ($this->id === $order->get_payment_method() && parent::can_refund_order($order) && $order->get_status() !== 'refunded' && $this->payplug_api) {
305 456 $order_metadata = $order->get_meta('_payplug_metadata');
306 - $payment = $this->api->payment_retrieve($order_metadata['transaction_id']);
307 - $today = current_time('Y-m-d H:i:s');
308 - $can_refund_date = date('Y-m-d H:i:s', $payment->__get('refundable_after'));
309 - if ($can_refund_date >= $today) {
310 - echo "<p style='color: red;'>" . __('Refund will be possible 48 hours after the last payment or refund transaction.', 'payplug') . "</p>";
457 +
458 + if (is_array($order_metadata) && !empty($order_metadata['transaction_id'])) {
459 + try {
460 + $payment = $this->payplug_api->payment_retrieve($order_metadata['transaction_id']);
461 + $today = current_time('Y-m-d H:i:s');
462 + $can_refund_date = date('Y-m-d H:i:s', $payment->__get('refundable_after'));
463 + if ($can_refund_date >= $today) {
464 + echo "<p style='color: red;'>" . __('Refund will be possible 48 hours after the last payment or refund transaction.', 'payplug') . '</p>';
465 + }
466 + } catch (\Exception $e) {
467 + PayplugGateway::log(sprintf('Could not retrieve refundable_after for Oney order: %s', $e->getMessage()), 'error');
468 + }
311 469 }
312 470 }
313 471 }
314 472
315 - public function payment_fields()
473 + /**
474 + * Billing and shipping addresses should have the same country and allowed by Oney
475 + * https://payplug-prod.atlassian.net/browse/WOOC-227
476 + *
477 + * @param $order
478 + *
479 + * @return bool
480 + */
481 + public function validate_shipping_billing_country($shipping_country, $billing_country)
316 482 {
317 - $description = $this->get_description();
318 - if (!empty($description)) {
319 - echo wpautop(wptexturize($description));
483 + if ($billing_country === $shipping_country) {
484 + return true;
320 485 }
486 +
487 + return false;
488 + }
489 +
490 + /**
491 + * Country of billing or shipping at oney payments should be on the allowedCountry that comes from pauyplug-api /account
492 + *
493 + * @param string $country
494 + * @param array $allowed
495 + *
496 + * @return bool
497 + */
498 + public function allowed_country($country, $allowed)
499 + {
500 + if (in_array($country, $allowed)) {
501 + return true;
502 + }
503 +
504 + return false;
505 + }
506 +
507 + /**
508 + * Empty the cart and add all order_items
509 + *
510 + * @param $cart
511 + * @param $items
512 + *
513 + * @return void
514 + */
515 + private function order_items_to_cart($cart, $items): void
516 + {
517 + $cart->empty_cart();
518 + foreach ($items as $item) {
519 + $cart->add_to_cart($item->get_product_id(), $item->get_quantity(), $item->get_variation_id());
520 + }
521 + }
522 +
523 + public function checkGateway()
524 + {
525 + $options = PayplugWoocommerceHelper::get_payplug_options();
526 +
527 + // Now called unconditionally from the constructor (not just at checkout via
528 + // is_available()), so a legacy account whose stored config predates the oney block
529 + // (never went through Upgrade::run_upgrade()) would otherwise throw "undefined array
530 + // key" warnings on every admin page that builds the WC gateway list (PRE-3597 review).
531 + return $options['payment_methods']['configuration']['oney']['active'] ?? false;
321 532 }
322 533 }