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 +318 -113 1.2.5 → 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,84 +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 - if(is_array($this->oney_response)) {
72 - $this->description = <<<HTML
73 - <p>
74 - <div class="payplug-oney-flex">
75 - <div>{$f(__('Bring', 'payplug'))} :</div>
76 - <div>{$this->oney_response['x3_with_fees']['down_payment_amount']} {$currency}</div>
77 - </div>
78 - <div class="payplug-oney-flex">
79 - <div>{$f(__('1st monthly payment', 'payplug'))} :</div>
80 - <div>{$this->oney_response['x3_with_fees']['installments'][0]['amount']} {$currency}</div>
81 - </div>
82 - <div class="payplug-oney-flex">
83 - <div>{$f(__('2nd monthly payment', 'payplug'))} :</div>
84 - <div>{$this->oney_response['x3_with_fees']['installments'][1]['amount']} {$currency}</div>
85 - </div>
86 - </p>
87 -HTML;
88 - } else {
89 - $this->description = $this->oney_response;
90 - }
91 -
92 - $available_img = 'lg-3xoney-checkout.png';
93 - } else {
94 - $available_img = 'lg-3xoney-checkout-disabled.png';
95 - }
96 -
97 106 $icons = apply_filters('payplug_payment_icons', [
98 - '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)),
99 108 ]);
100 109 $icons_str = '';
101 110 foreach ($icons as $icon) {
102 111 $icons_str .= $icon;
103 112 }
113 +
104 114 return $icons_str;
105 115 }
106 116
107 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 + /**
108 158 * Check if Oney is available
109 - *
110 - * @return void
159 + *
160 + * @return bool|int true, false, or an ONEY_* status code
111 161 */
112 162 public function check_oney_is_available()
113 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 + {
114 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 +
115 227 $total_price = floatval($cart->total);
116 - $products_qty = (int) $cart->cart_contents_count;
117 -
118 - // Min and max
119 - if ($total_price < $this->min_oney_price || $total_price > $this->max_oney_price) {
120 - $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 +
121 234 return false;
122 235 }
123 236
124 237 // Cart check
125 238 if ($products_qty >= self::ONEY_PRODUCT_QUANTITY_MAXIMUM) {
126 - $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 +
127 241 return self::ONEY_UNAVAILABLE_CODE_CART_SIZE_TOO_HIGH;
128 242 }
129 243
130 244 // Country check
131 - $country_code_shipping = WC()->customer->get_shipping_country();
132 - $country_code_billing = WC()->customer->get_billing_country();
133 -
134 - if (!in_array($country_code_billing, $this->allowed_country_codes) || !in_array($country_code_shipping, $this->allowed_country_codes)) {
135 - $this->description = '<div class="payment_method_oney_x3_with_fees_disabled">'.__('Unavailable for the specified country.', 'payplug').'</div>';
136 - 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();
137 248 }
138 -
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 +
139 264 return true;
140 265 }
141 266
142 267 /**
@@ -162,10 +287,11 @@
162 287 * @param \WC_Order $order
163 288 * @param int $amount
164 289 * @param int $customer_id
165 290 *
291 + * @throws \Exception
292 + *
166 293 * @return array
167 - * @throws \Exception
168 294 */
169 295 public function process_standard_payment($order, $amount, $customer_id)
170 296 {
171 297 $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
@@ -179,25 +305,31 @@
179 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));
180 306 }
181 307
182 308 $country = PayplugWoocommerceHelper::is_pre_30() ? $order->billing_country : $order->get_billing_country();
183 - $phone = PayplugWoocommerceHelper::is_pre_30() ? $order->billing_phone : $order->get_billing_phone();
184 - $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();
185 311 $phone_number_util = PhoneNumberUtil::getInstance();
186 - $phone_number = $phone_number_util->parse( $phone, $country );
187 - 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)) {
188 314 throw new \Exception(__('Mobile phone number fullfilled is invalid. Please retry.', 'payplug'));
189 315 }
190 -
191 - if (!filter_var($billing_email, FILTER_VALIDATE_EMAIL) || strpos($billing_email,'+') !== false) {
192 - 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'));
193 319 }
194 320
195 321 $address_data = PayplugAddressData::from_order($order);
196 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 +
197 329 $cart_items = [];
198 330 $items = $order->get_items();
199 - foreach($items as $item) {
331 + foreach ($items as $item) {
200 332 $data = $item->get_data();
201 333 $total = floatval(round($data['total'], 2)) * 100;
202 334 $cart_items[] = [
203 335 'delivery_label' => 'storepickup',
@@ -202,39 +334,44 @@
202 334 $cart_items[] = [
203 335 'delivery_label' => 'storepickup',
204 336 'delivery_type' => 'storepickup',
205 337 'brand' => 'Woocommerce',
206 - 'merchant_item_id' => 'cart-'.$data['id'].'-'.$data['product_id'],
338 + 'merchant_item_id' => 'cart-' . $data['id'] . '-' . $data['product_id'],
207 339 'name' => $data['name'],
208 340 'expected_delivery_date' => date('Y-m-d'),
209 - 'total_amount' => $total,
210 - 'price' => round($total / $data['quantity']),
211 - 'quantity' => $data['quantity']
341 + 'total_amount' => (int) $total,
342 + 'price' => round($total / $data['quantity']),
343 + 'quantity' => $data['quantity'],
212 344 ];
213 345 }
214 346
215 347 $payment_data = [
216 348 'authorized_amount' => $amount,
217 - 'auto_capture' => true,
218 - 'currency' => get_woocommerce_currency(),
219 - 'payment_method' => $this->id,
220 - 'billing' => $address_data->get_billing(),
221 - 'shipping' => $address_data->get_shipping(),
222 - 'payment_context' => [
223 - "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,
224 356 ],
225 357 'notification_url' => esc_url_raw(WC()->api_request_url('PayplugGateway')),
226 - 'hosted_payment' => [
227 - 'return_url' => esc_url_raw($order->get_checkout_order_received_url()),
358 + 'hosted_payment' => [
359 + 'return_url' => $return_url,
228 360 'cancel_url' => esc_url_raw($order->get_cancel_order_url_raw()),
229 361 ],
230 - 'metadata' => [
231 - 'order_id' => $order_id,
362 + 'metadata' => [
363 + 'order_id' => $order_id,
232 364 'customer_id' => ((int) $customer_id > 0) ? $customer_id : 'guest',
233 - 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
365 + 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
234 366 ],
235 367 ];
236 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 + }
237 374
238 375 /**
239 376 * Filter the payment data before it's used
240 377 *
@@ -243,9 +380,9 @@
243 380 * @param array $customer_details
244 381 * @param PayplugAddressData $address_data
245 382 */
246 383 $payment_data = apply_filters('payplug_gateway_payment_data', $payment_data, $order_id, [], $address_data);
247 - $payment = $this->api->payment_create($payment_data);
384 + $payment = $this->payplug_api->payment_create($payment_data);
248 385
249 386 // Save transaction id for the order
250 387 PayplugWoocommerceHelper::is_pre_30()
251 388 ? update_post_meta($order_id, '_transaction_id', $payment->id)
@@ -268,11 +405,11 @@
268 405
269 406 PayplugGateway::log(sprintf('Payment creation complete for order #%s', $order_id));
270 407
271 408 return [
272 - 'result' => 'success',
409 + 'result' => 'success',
273 410 'redirect' => $payment->hosted_payment->payment_url,
274 - 'cancel' => $payment->hosted_payment->cancel_url,
411 + 'cancel' => $payment->hosted_payment->cancel_url,
275 412 ];
276 413 } catch (\HttpException $e) {
277 414 PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
278 415 throw new \Exception(__($e->getMessage(), 'payplug'));
@@ -281,48 +418,116 @@
281 418 throw new \Exception(__($e->getMessage(), 'payplug'));
282 419 }
283 420 }
284 421
285 -
286 422 /**
287 - * Check if the gatteway is allowed for the order amount
423 + * Check if the gatteway is allowed for the order amount
288 424 *
289 425 * @param array
426 + *
290 427 * @return array
291 428 */
292 429 public function check_gateway($gateways)
293 430 {
294 431 if (isset($gateways[$this->id]) && $gateways[$this->id]->id == $this->id) {
295 - if(!PayplugWoocommerceHelper::is_oney_available()) {
432 + //remove gateway if thresholds/country criteria are not met
433 + if ($this->check_oney_is_available() === false) {
296 434 unset($gateways[$this->id]);
297 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 + }
298 443 }
444 +
299 445 return $gateways;
300 446 }
301 447
302 448 /**
303 449 * Show Oney refund text
304 - *
450 + *
305 451 * @return void
306 452 */
307 - public function oney_refund_text($order)
453 + public function oney_refund_text($order): void
308 454 {
309 - 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) {
310 456 $order_metadata = $order->get_meta('_payplug_metadata');
311 - $payment = $this->api->payment_retrieve($order_metadata['transaction_id']);
312 - $today = current_time('Y-m-d H:i:s');
313 - $can_refund_date = date('Y-m-d H:i:s', $payment->__get('refundable_after'));
314 - if ($can_refund_date >= $today) {
315 - 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 + }
316 469 }
317 470 }
318 471 }
319 472
320 - 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)
321 482 {
322 - $description = $this->get_description();
323 - if (!empty($description)) {
324 - echo wpautop(wptexturize($description));
483 + if ($billing_country === $shipping_country) {
484 + return true;
325 485 }
486 +
487 + return false;
326 488 }
327 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;
532 + }
328 533 }