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 +677 -796 1.2.11 → 3.1.0 View file →
@@ -10,25 +10,57 @@
10 10 use Payplug\Authentication;
11 11 use Payplug\Exception\ConfigurationException;
12 12 use Payplug\Exception\HttpException;
13 13 use Payplug\Payplug;
14 -use Payplug\PayplugWoocommerce\Admin\Ajax;
14 +use Payplug\PayplugWoocommerce\Helper\Lock;
15 15 use Payplug\PayplugWoocommerce\PayplugWoocommerceHelper;
16 +use Payplug\PayplugWoocommerce\Traits\ServiceGetter;
16 17 use Payplug\Resource\Payment as PaymentResource;
17 18 use Payplug\Resource\Refund as RefundResource;
18 19 use WC_Payment_Gateway_CC;
19 20 use WC_Payment_Tokens;
20 21
21 -
22 22 /**
23 23 * PayPlug WooCommerce Gateway.
24 - *
25 - * @package Payplug\PayplugWoocommerce\Gateway
26 24 */
27 25 class PayplugGateway extends WC_Payment_Gateway_CC
28 26 {
27 + use ServiceGetter;
29 28
29 + public const OPTION_NAME = 'payplug_config';
30 +
30 31 /**
32 + * @var string
33 + */
34 + public $mode;
35 + /**
36 + * @var bool
37 + */
38 + public $debug;
39 + /**
40 + * @var string
41 + */
42 + public $email;
43 + /**
44 + * @var string
45 + */
46 + public $embedded_mode;
47 + /**
48 + * @var bool
49 + */
50 + public $save_card;
51 +
52 + /**
53 + * @var string
54 + */
55 + public $oney_type;
56 +
57 + /**
58 + * @var string
59 + */
60 + public $oney_product_animation;
61 +
62 + /**
31 63 * @var PayplugGatewayRequirements
32 64 */
33 65 private $requirements;
34 66
@@ -44,9 +76,9 @@
44 76
45 77 /**
46 78 * @var PayplugApi
47 79 */
48 - public $api;
80 + public $payplug_api;
49 81
50 82 /**
51 83 * @var \WC_Logger
52 84 */
@@ -59,23 +91,36 @@
59 91
60 92 /**
61 93 * @var float
62 94 */
63 - const MIN_AMOUNT = 0.99;
95 + public const MIN_AMOUNT = 0.99;
64 96
65 97 /**
66 98 * @var float
67 99 */
68 - const MAX_AMOUNT = 20000;
100 + public const MAX_AMOUNT = 20000;
69 101
70 102 /**
103 + * @var string
104 + */
105 + private $payplug_merchant_country = 'FR';
106 +
107 + protected $oney_response;
108 + public $min_oney_price;
109 + public $oney_thresholds_min;
110 + public $max_oney_price;
111 + public $oney_thresholds_max;
112 +
113 + public const ENABLE_ON_TEST_MODE = true;
114 +
115 + /**
71 116 * Logging method.
72 117 *
73 118 * @param string $message Log message.
74 119 * @param string $level Optional. Default 'info'.
75 - * emergency|alert|critical|error|warning|notice|info|debug
120 + * emergency|alert|critical|error|warning|notice|info|debug
76 121 */
77 - public static function log($message, $level = 'info')
122 + public static function log($message, $level = 'info'): void
78 123 {
79 124 if (!self::$log_enabled) {
80 125 return;
81 126 }
@@ -85,61 +130,80 @@
85 130 }
86 131
87 132 PayplugWoocommerceHelper::is_pre_30()
88 133 ? self::$log->add('payplug_gateway', $message)
89 - : self::$log->log($level, $message, array('source' => 'payplug_gateway'));
134 + : self::$log->log($level, $message, ['source' => 'payplug_gateway']);
90 135 }
91 136
137 + /**
138 + * Construct method
139 + *
140 + * @return void
141 + */
92 142 public function __construct()
93 143 {
94 - $this->id = 'payplug';
95 - $this->icon = '';
96 - $this->has_fields = false;
97 - $this->method_title = _x('PayPlug', 'Gateway method title', 'payplug');
98 - $this->method_description = __('Enable PayPlug for your customers.', 'payplug');
99 - $this->supports = array(
144 + //required plugin id
145 + $this->id = 'payplug';
146 + $this->supports = [
100 147 'products',
101 148 'refunds',
102 149 'tokenization',
103 - );
104 - $this->new_method_label = __('Pay with another credit card', 'payplug');
150 + ];
105 151
152 + $payplug_gateways = ['payplug', 'american_express', 'apple_pay', 'bancontact', 'oney_x3_with_fees', 'oney_x3_without_fees', 'oney_x4_with_fees', 'oney_x4_without_fees', 'satispay', 'ideal', 'mybank', 'wero', 'bizum', 'scalapay'];
153 +
154 + //save buttom admin
155 + if ((!empty($_GET['section'])) && (in_array($_GET['section'], $payplug_gateways))) {
156 + $GLOBALS['hide_save_button'] = true;
157 + }
158 +
106 159 $this->init_settings();
107 160 $this->requirements = new PayplugGatewayRequirements($this);
108 161 if ($this->user_logged_in()) {
109 162 $this->init_payplug();
110 163 }
164 +
165 + $this->mode = (bool) $this->get_configuration()->get_option('mode') ? 'live' : 'test';
166 + $this->debug = (bool) $this->get_configuration()->get_option('debug');
167 + $this->email = (string) $this->get_configuration()->get_option('email');
168 +
169 + //admin form
111 170 $this->init_form_fields();
112 171
113 - $this->title = $this->get_option('title');
114 - $this->description = $this->get_option('description');
115 - $this->mode = 'yes' === $this->get_option('mode', 'no') ? 'live' : 'test';
116 - $this->debug = 'yes' === $this->get_option('debug', 'no');
117 - $this->email = $this->get_option('email');
118 - $this->payment_method = $this->get_option('payment_method');
119 - $this->oneclick = 'yes' === $this->get_option('oneclick', 'no');
120 -
121 172 add_filter('woocommerce_get_customer_payment_tokens', [$this, 'filter_tokens'], 10, 3);
122 173
123 174 self::$log_enabled = $this->debug;
124 175
125 - // Ensure the description is not empty to correctly display users's save cards
126 - if (empty($this->description) && 0 !== count($this->get_tokens())) {
127 - $this->description = ' ';
176 + add_filter('woocommerce_get_order_item_totals', [$this, 'customize_gateway_title'], 10, 2);
177 + add_action('woocommerce_thankyou', [$this, 'validate_payment']);
178 + add_action('the_post', [$this, 'validate_payment']);
179 + add_action('woocommerce_available_payment_gateways', [$this, 'check_gateway']);
180 + }
181 +
182 + /**
183 + * @param $option
184 + * @param $value
185 + *
186 + * @return bool|void
187 + */
188 + public function update_option($option, $value = '')
189 + {
190 + if ($this->needs_setup()) {
191 + wp_send_json_error('needs_setup');
192 + wp_die();
128 193 }
129 194
130 - if ('test' === $this->mode) {
131 - $this->description .= " \n";
195 + parent::update_option($option, $value);
196 + }
132 197
133 - $this->description .= __('You are in TEST MODE. In test mode you can use the card 4242424242424242 with any valid expiration date and CVC.', 'payplug');
134 - $this->description = trim($this->description);
135 - }
136 -
137 - add_filter('woocommerce_get_order_item_totals', [$this, 'customize_gateway_title'], 10, 2);
138 - add_action('wp_enqueue_scripts', [$this, 'scripts']);
139 - add_action('woocommerce_update_options_payment_gateways_' . $this->id, [$this, 'process_admin_options']);
140 - add_action('the_post', [$this, 'validate_payment']);
141 - add_action('woocommerce_available_payment_gateways', [$this, 'check_gateway']);
198 + /**
199 + * this payment gateway cannot be updated on the wooco payment settings
200 + *
201 + * @return bool
202 + */
203 + public function needs_setup()
204 + {
205 + return true;
142 206 }
143 207
144 208 /**
145 209 * Customize gateway title in emails.
@@ -152,9 +216,14 @@
152 216 * @author Clément Boirie
153 217 */
154 218 public function customize_gateway_title($total_rows, $order)
155 219 {
156 - $payment_method = PayplugWoocommerceHelper::is_pre_30() ? $order->payment_method : $order->get_payment_method();
220 + $get_payment_method = $this->id;
221 + if (method_exists($order, 'get_payment_method')) {
222 + $get_payment_method = $order->get_payment_method();
223 + }
224 +
225 + $payment_method = PayplugWoocommerceHelper::is_pre_30() ? $order->payment_method : $get_payment_method;
157 226 if (
158 227 $this->id !== $payment_method
159 228 || !isset($total_rows['payment_method'])
160 229 ) {
@@ -170,16 +239,39 @@
170 239 * Validate order payment when the user is redirected to the success confirmation page.
171 240 *
172 241 * @throws \WC_Data_Exception
173 242 */
174 - public function validate_payment()
243 + public function validate_payment($id = null, $save_request = true, $ipn = false): void
175 244 {
176 - if (!is_wc_endpoint_url('order-received') || empty($_GET['key'])) {
177 - return;
245 + global $wp;
246 +
247 + if (!$ipn) {
248 + if (!is_wc_endpoint_url('order-received') || (empty($_GET['key']) && empty($id))) {
249 + return;
250 + }
178 251 }
179 252
180 - $order_id = wc_get_order_id_by_order_key(wc_clean($_GET['key']));
253 + if (!empty($_GET['order-received'])) {
254 + $order_id = (int) ($_GET['order-received']);
255 + } elseif (!empty($id) && !is_object($id)) {
256 + $order_id = (int) $id;
257 + }
258 +
259 + if (empty($order_id) && (isset($wp->query_vars['order-received']))) {
260 + $order_id = apply_filters(
261 + 'woocommerce_thankyou_order_id',
262 + absint($wp->query_vars['order-received'])
263 + );
264 + }
265 +
181 266 if (empty($order_id)) {
267 + if (empty($_GET['key']) && empty($id) && !is_object($id)) {
268 + return;
269 + }
270 + $order_id = wc_get_order_id_by_order_key(wc_clean((!empty($_GET['key']) ? $_GET['key'] : (int) $id)));
271 + }
272 +
273 + if (empty($order_id)) {
182 274 return;
183 275 }
184 276
185 277 $order = wc_get_order($order_id);
@@ -187,59 +279,49 @@
187 279 return;
188 280 }
189 281
190 282 $payment_method = PayplugWoocommerceHelper::is_pre_30() ? $order->payment_method : $order->get_payment_method();
191 - if (!in_array($payment_method, ['payplug', 'oney_x3_with_fees', 'oney_x4_with_fees'])) {
283 + if (!in_array($payment_method, ['payplug', 'oney_x3_with_fees', 'oney_x4_with_fees', 'oney_x3_without_fees', 'oney_x4_without_fees', 'bancontact', 'apple_pay', 'american_express', 'satispay', 'mybank', 'ideal', 'wero', 'bizum', 'scalapay'])) {
192 284 return;
193 285 }
194 286
287 + if ($payment_method === $this->id) {
288 + $transaction_id = PayplugWoocommerceHelper::is_pre_30() ? get_post_meta($order_id, '_transaction_id', true) : $order->get_transaction_id();
289 + if (empty($transaction_id)) {
290 + self::log(sprintf('Order #%s : Missing transaction id.', $order_id), 'error');
195 291
196 - $transaction_id = PayplugWoocommerceHelper::is_pre_30() ? get_post_meta($order_id, '_transaction_id', true) : $order->get_transaction_id();
197 - if (empty($transaction_id)) {
198 - PayplugGateway::log(sprintf('Order #%s : Missing transaction id.', $order_id), 'error');
292 + return;
293 + }
199 294
200 - return;
201 - }
295 + $lock_id = Lock::handle_insert($save_request, $transaction_id);
296 + if (!$lock_id) {
297 + return;
298 + }
202 299
203 - try {
204 - $payment = $this->api->payment_retrieve($transaction_id);
205 - } catch (\Exception $e) {
206 - PayplugGateway::log(
207 - sprintf(
208 - 'Order #%s : An error occurred while retrieving the payment data with the message : %s',
209 - $order_id,
210 - $e->getMessage()
211 - )
212 - );
300 + try {
301 + $payment = $this->payplug_api->payment_retrieve($transaction_id);
302 + } catch (\Exception $e) {
303 + self::log(
304 + sprintf(
305 + 'Order #%s : An error occurred while retrieving the payment data with the message : %s',
306 + $order_id,
307 + $e->getMessage()
308 + )
309 + );
213 310
214 - return;
215 - }
311 + return;
312 + }
216 313
217 - $this->response->process_payment($payment);
218 - }
314 + $this->response->process_payment($payment);
219 315
220 - /**
221 - * Get payment icons.
222 - *
223 - * @return string
224 - */
225 - public function get_icon()
226 - {
316 + \Payplug\PayplugWoocommerce\Model\Lock::delete_lock($lock_id);
317 + $waiting_requests = \Payplug\PayplugWoocommerce\Model\Lock::get_lock_by_payment_id($transaction_id);
227 318
228 - $src = ('it_IT' === get_locale())
229 - ? PAYPLUG_GATEWAY_PLUGIN_URL . '/assets/images/logos_scheme_PostePay.svg'
230 - : PAYPLUG_GATEWAY_PLUGIN_URL . '/assets/images/logos_scheme_CB.svg';
231 -
232 - $icons = apply_filters('payplug_payment_icons', [
233 - 'payplug' => sprintf('<img src="%s" alt="Visa & Mastercard" class="payplug-payment-icon" />', esc_url($src)),
234 - ]);
235 -
236 - $icons_str = '';
237 - foreach ($icons as $icon) {
238 - $icons_str .= $icon;
319 + if ($waiting_requests) {
320 + \Payplug\PayplugWoocommerce\Model\Lock::delete_lock_by_payment_id($transaction_id);
321 + $this->validate_payment($order_id, false);
322 + }
239 323 }
240 -
241 - return $icons_str;
242 324 }
243 325
244 326 /**
245 327 * Check if this gateway is enabled
@@ -245,10 +327,18 @@
245 327 * Check if this gateway is enabled
246 328 */
247 329 public function is_available()
248 330 {
249 - if ('yes' === $this->enabled) {
250 - return $this->requirements->satisfy_requirements() && !empty($this->get_api_key($this->get_current_mode()));
331 + if ('yes' == $this->enabled) {
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;
251 341 }
252 342
253 343 return parent::is_available();
254 344 }
@@ -255,139 +345,201 @@
255 345
256 346 /**
257 347 * Load gateway settings.
258 348 */
259 - public function init_settings()
349 + public function init_settings(): void
260 350 {
261 351 parent::init_settings();
262 - $this->enabled = !empty($this->settings['enabled']) && 'yes' === $this->settings['enabled'] ? 'yes' : 'no';
352 + $enabled = !empty($this->settings['enabled']) && (bool) $this->settings['enabled'];
353 + $this->enabled = $enabled ? 'yes' : 'no';
263 354 }
264 355
265 356 /**
266 357 * Register gateway settings.
267 358 */
268 - public function init_form_fields()
359 + public function init_form_fields(): void
269 360 {
270 - $oney_range = PayplugWoocommerceHelper::get_min_max_oney();
271 - $min_oney_price = (isset($oney_range['min'])) ? $oney_range['min'] : 100;
272 - $max_oney_price = (isset($oney_range['max'])) ? $oney_range['max'] : 3000;
273 -
361 + $anchor = esc_html_x(__('More informations', 'payplug'), 'modal', 'payplug');
362 + $domain = __('support.payplug.com/hc/fr/articles/4408142346002', 'payplug');
363 + $link = sprintf(' <a href="https://%s" target="_blank">%s</a>', $domain, $anchor);
364 +
365 + $anchor_bancontact = esc_html_x(__('payplug_bancontact_activation_request', 'payplug'), 'modal', 'payplug');
366 + $domain_bancontact = __('payplug_bancontact_activation_url', 'payplug');
367 + $bancontact_call_to_action = sprintf(' <a id="bancontact_call_to_action" href="https://%s" target="_blank">%s</a>', $domain_bancontact, $anchor_bancontact);
368 +
369 + $oney_cfg = $this->get_configuration()->get_option('payment_methods.configuration.oney');
370 + if (!empty($oney_cfg)) {
371 + $oney_amount = json_decode($oney_cfg['custom_amounts'], true);
372 + $oney_amount['min'] = (float) $oney_amount['min'] / 100;
373 + $oney_amount['max'] = (float) $oney_amount['max'] / 100;
374 + } else {
375 + $oney_amount = [
376 + 'min' => 100,
377 + 'max' => 3000,
378 + ];
379 + }
274 380 $fields = [
275 - 'enabled' => [
276 - 'title' => __('Enable/Disable', 'payplug'),
277 - 'type' => 'checkbox',
278 - 'label' => __('Enable PayPlug', 'payplug'),
381 + 'enabled' => [
382 + 'title' => __('Enable/Disable', 'payplug'),
383 + 'type' => 'checkbox',
384 + 'label' => __('Enable PayPlug', 'payplug'),
279 385 'description' => __('Only Euro payments can be processed with PayPlug.', 'payplug'),
280 - 'default' => 'no',
386 + 'default' => false,
281 387 ],
282 - 'title' => [
283 - 'title' => __('Title', 'payplug'),
284 - 'type' => 'text',
285 - 'description' => __('The payment solution title displayed during checkout.', 'payplug'),
286 - 'default' => _x('Credit card checkout', 'Default gateway title', 'payplug'),
287 - 'desc_tip' => true,
388 + 'title' => [
389 + 'title' => __('Title', 'payplug'),
390 + 'type' => 'text',
391 + 'description' => __('The payment solution title displayed to your customers during checkout', 'payplug'),
392 + 'default' => _x('Credit card checkout', 'Default gateway title', 'payplug'),
393 + 'desc_tip' => false,
288 394 ],
289 - 'description' => [
290 - 'title' => __('Description', 'payplug'),
291 - 'type' => 'text',
292 - 'description' => __('The payment solution description displayed during checkout.', 'payplug'),
293 - 'default' => '',
294 - 'desc_tip' => true,
395 + 'description' => [
396 + 'title' => __('Description', 'payplug'),
397 + 'type' => 'text',
398 + 'description' => __('The payment solution description displayed to your customers during checkout', 'payplug'),
399 + 'default' => '',
400 + 'desc_tip' => false,
295 401 ],
296 - 'title_connexion' => [
402 + 'title_connexion' => [
297 403 'title' => __('Connection', 'payplug'),
298 - 'type' => 'title',
404 + 'type' => 'title',
299 405 ],
300 - 'email' => [
301 - 'type' => 'hidden',
406 + 'email' => [
407 + 'type' => 'hidden',
302 408 'default' => '',
303 409 ],
304 - 'login' => [
305 - 'type' => 'login',
410 + 'login' => [
411 + 'type' => 'login',
306 412 'default' => '',
307 413 ],
308 - 'payplug_test_key' => [
309 - 'type' => 'hidden',
310 - 'default' => '',
311 - ],
312 - 'payplug_live_key' => [
313 - 'type' => 'hidden',
314 - 'default' => '',
315 - ],
316 - 'payplug_merchant_id' => [
317 - 'type' => 'hidden',
318 - 'default' => '',
319 - ],
320 - 'title_testmode' => [
414 + 'title_testmode' => [
321 415 'title' => __('Mode', 'payplug'),
322 - 'type' => 'title',
416 + 'type' => 'title',
323 417 ],
324 - 'mode' => [
325 - 'title' => '',
326 - 'label' => '',
327 - 'type' => 'yes_no',
328 - 'yes' => 'Live',
329 - 'no' => 'Test',
418 + 'mode' => [
419 + 'title' => '',
420 + 'label' => '',
421 + 'type' => 'yes_no',
422 + 'yes' => 'Live',
423 + 'no' => 'Test',
330 424 'description' => __('In TEST mode, all payments will be simulations and will not generate real transactions.', 'payplug'),
331 - 'default' => 'no',
332 - 'hide_label' => true,
425 + 'default' => false,
426 + 'hide_label' => true,
333 427 ],
334 - 'title_settings' => [
428 + 'title_settings' => [
335 429 'title' => __('Settings', 'payplug'),
336 - 'type' => 'title',
430 + 'type' => 'title',
337 431 ],
338 - 'payment_method' => [
339 - 'title' => __('Payment page', 'payplug'),
340 - 'type' => 'radio',
341 - 'description' => __('Customers will be redirected to a PayPlug payment page to finalize the transaction, or payments will be performed in an embeddable payment form on your website.', 'payplug'),
342 - 'default' => 'redirect',
343 - 'desc_tip' => true,
344 - 'options' => array(
432 + 'payment_method' => [
433 + 'title' => __('Payment page', 'payplug'),
434 + 'type' => 'radio',
435 + 'options' => [
345 436 'redirect' => __('Redirect', 'payplug'),
346 437 'embedded' => __('Integrated', 'payplug'),
347 - ),
438 + ],
439 + 'description' => __('Customers will be redirected to a PayPlug payment page to finalize the transaction, or payments will be performed in an embeddable payment form on your website.', 'payplug'),
440 + 'default' => 'redirect',
441 + 'desc_tip' => false,
348 442 ],
349 - 'debug' => [
350 - 'title' => __('Debug', 'payplug'),
351 - 'type' => 'checkbox',
443 + 'debug' => [
444 + 'title' => __('Debug', 'payplug'),
445 + 'type' => 'checkbox',
352 446 'description' => __('Debug mode saves additional information on your server for each operation done via the PayPlug plugin (Developer setting).', 'payplug'),
353 - 'label' => __('Activate debug mode', 'payplug'),
354 - 'default' => 'yes',
355 - 'desc_tip' => true,
447 + 'label' => __('Activate debug mode', 'payplug'),
448 + 'default' => true,
449 + 'desc_tip' => false,
356 450 ],
357 451 'title_advanced_settings' => [
358 - 'title' => __('Advanced Settings', 'payplug'),
452 + 'title' => __('payplug_advanced_settings', 'payplug'),
359 453 'description' => __(
360 454 'Your current offer does not allow this option. Try it on TEST mode. More information <a href="https://www.payplug.com/pricing" target="_blank">here.</a>',
361 455 'payplug'
362 456 ),
363 - 'type' => 'title',
457 + 'type' => 'title',
364 458 ],
365 - 'oneclick' => [
366 - 'title' => __('One Click Payment', 'payplug'),
367 - 'type' => 'checkbox',
368 - 'label' => __('Activate', 'payplug'),
459 + 'save_card' => [
460 + 'title' => __('One Click Payment', 'payplug'),
461 + 'type' => 'checkbox',
462 + 'label' => __('Activate', 'payplug'),
369 463 'description' => __('Allow your customers to save their credit card information for later purchases.', 'payplug'),
370 - 'default' => 'no',
371 - 'desc_tip' => true
464 + 'default' => false,
465 + 'desc_tip' => false,
372 466 ],
373 - 'oney' => [
374 - 'title' => __('Split Oney Payment', 'payplug'),
375 - 'type' => 'checkbox',
376 - 'label' => __('Activate', 'payplug'),
467 + 'bancontact' => [
468 + 'title' => __('payplug_bancontact_activate_title', 'payplug'),
469 + 'type' => 'checkbox',
470 + 'label' => __('Activate', 'payplug'),
471 + 'description' => '<p class="description" id="bancontact_test_mode_description"> ' . __('payplug_bancontact_testmode_description', 'payplug') . ' </p>' .
472 + '<p class="description" id="bancontact_live_mode_description_disabled"> ' . __('payplug_bancontact_livemode_description_disabled', 'payplug') . ' </p>' .
473 + $bancontact_call_to_action,
474 + 'default' => false,
475 + ],
476 + 'apple_pay' => [
477 + 'title' => __('payplug_apple_pay_activate_title', 'payplug'),
478 + 'type' => 'checkbox',
479 + 'label' => __('Activate', 'payplug'),
480 + 'description' => '<p class="description" id="apple_pay_test_mode_description"> ' . __('payplug_apple_pay_testmode_description', 'payplug') . ' </p>' .
481 + '<p class="description" id="apple_pay_live_mode_description"> ' . __('payplug_apple_pay_livemode_description', 'payplug') . ' </p>',
482 + 'default' => false,
483 + ],
484 + 'american_express' => [
485 + 'title' => __('payplug_amex_title', 'payplug'),
486 + 'type' => 'checkbox',
487 + 'label' => __('payplug_amex_activate', 'payplug'),
488 + 'description' => '<p class="description" id="amex_test_mode_description"> ' . __('payplug_amex_testmode_description', 'payplug') . ' </p>' .
489 + '<p class="description" id="amex_live_mode_description"> ' . __('payplug_amex_livemode_description', 'payplug') . ' </p>',
490 + 'default' => false,
491 + ],
492 + 'oney' => [
493 + 'title' => __('3x 4x Oney payments', 'payplug'),
494 + 'type' => 'checkbox',
495 + 'label' => __('Activate', 'payplug'),
377 496 // TRAD
378 - 'description' => sprintf(__('Allow customers to spread out payments over 3 or 4 installments from %s€ to %s€.', 'payplug'), $min_oney_price, $max_oney_price),
379 - 'default' => 'no',
380 - 'desc_tip' => true
381 - ]
497 + 'description' => sprintf(__('Allow your customers to split payments into 3 or 4 installments, for orders between %s€ and %s€', 'payplug'), $this->min_oney_price, $this->max_oney_price) . $link,
498 + 'default' => false,
499 + 'desc_tip' => false,
500 + ],
501 + 'oney_type' => [
502 + 'title' => '',
503 + 'type' => 'oney_type',
504 + 'options' => [
505 + 'with_fees' => __('Oney with fees', 'payplug'),
506 + 'without_fees' => __('Oney without fees', 'payplug'),
507 + ],
508 + 'descriptions' => [
509 + 'with_fees' => __('The fees are split between you and your customers', 'payplug'),
510 + 'without_fees' => __('You pay the fees', 'payplug'),
511 + ],
512 + 'description' => '',
513 + 'default' => 'with_fees',
514 + 'desc_tip' => false,
515 + ],
516 + 'oney_thresholds' => [
517 + 'title' => '',
518 + 'type' => 'oney_thresholds',
519 + 'description' => sprintf(
520 + __('I would like to offer guaranteed payment in installments for amounts between %s€ and %s€.', 'payplug'),
521 + '<b class="min">' . $oney_amount['min'] . '</b>',
522 + '<b class="max">' . $oney_amount['max'] . '</b>'
523 + ),
524 + 'desc_tip' => false,
525 + ],
526 + 'oney_product_animation' => [
527 + 'title' => __('oney_installments_pop_up', 'payplug'),
528 + 'description' => __('display_the_oney_installments_pop_up_on_the_product_page', 'payplug'),
529 + 'label' => __('Activate', 'payplug'),
530 + 'default' => false,
531 + 'desc_tip' => false,
532 + 'type' => 'oney_product_animation',
533 + ],
382 534 ];
383 -
535 +
384 536 if ($this->user_logged_in()) {
385 537 if ($this->permissions->has_permissions(PayplugPermissions::SAVE_CARD)) {
386 538 unset($fields['title_advanced_settings']);
387 - } else if ('live' === $this->get_current_mode()){
388 - $fields['oneclick']['disabled'] = true;
389 - }
539 + } elseif ('live' === $this->get_current_mode()) {
540 + $fields['save_card']['disabled'] = true;
541 + }
390 542 }
391 543
392 544 /**
393 545 * Filter PayPlug gateway settings.
@@ -393,9 +545,9 @@
393 545 * Filter PayPlug gateway settings.
394 546 *
395 547 * @param array $fields
396 548 */
397 - $fields = apply_filters('payplug_gateway_settings', $fields);
549 + $fields = apply_filters('payplug_gateway_settings', $fields);
398 550 $this->form_fields = $fields;
399 551 }
400 552
401 553 /**
@@ -400,65 +552,23 @@
400 552
401 553 /**
402 554 * Set global configuration for PayPlug instance.
403 555 */
404 - public function init_payplug()
556 + public function init_payplug(): void
405 557 {
406 - $this->api = new PayplugApi($this);
407 - $this->api->init();
558 + $this->payplug_api = new PayplugApi($this);
559 + $this->payplug_api->init();
408 560
409 - $this->permissions = new PayplugPermissions($this);
410 - $this->response = new PayplugResponse($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());
564 + $this->response = new PayplugResponse($this);
411 565
412 566 // Register IPN handler
413 567 new PayplugIpnResponse($this);
414 -
415 568 }
416 569
417 570 /**
418 - * Embedded payment form scripts.
419 - *
420 - * Register scripts and additionnal data needed for the
421 - * embedded payment form.
422 - */
423 - public function scripts()
424 - {
425 - if (!is_cart() && !is_checkout() && !isset($_GET['pay_for_order']) && !is_add_payment_method_page() && !isset($_GET['change_payment_method'])) {
426 - return;
427 - }
428 -
429 - // If PayPlug is not enabled bail.
430 - if ('no' === $this->enabled) {
431 - return;
432 - }
433 -
434 - // If keys are not set bail.
435 - if (empty($this->get_api_key($this->mode))) {
436 - PayplugGateway::log('Keys are not set correctly.');
437 -
438 - return;
439 - }
440 -
441 - // Register checkout styles.
442 - wp_register_style('payplug-checkout', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/css/payplug-checkout.css', [], PAYPLUG_GATEWAY_VERSION);
443 - wp_enqueue_style('payplug-checkout');
444 -
445 - wp_register_script('payplug', 'https://api.payplug.com/js/1/form.latest.js', [], null, true);
446 - wp_register_script('payplug-checkout', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/js/payplug-checkout.js', [
447 - 'jquery',
448 - 'payplug'
449 - ], PAYPLUG_GATEWAY_VERSION, true);
450 - wp_localize_script('payplug-checkout', 'payplug_checkout_params', [
451 - 'ajax_url' => \WC_AJAX::get_endpoint('payplug_create_order'),
452 - 'nonce' => [
453 - 'checkout' => wp_create_nonce('woocommerce-process_checkout'),
454 - ],
455 - 'is_embedded' => 'redirect' !== $this->payment_method
456 - ]);
457 - wp_enqueue_script('payplug-checkout');
458 - }
459 -
460 - /**
461 571 * Filter saved tokens for the gateway.
462 572 *
463 573 * A token will be removed if :
464 574 * - it doesn't match the current merchant logged in,
@@ -472,16 +582,27 @@
472 582 * @return array
473 583 */
474 584 public function filter_tokens($tokens, $user_id, $gateway_id)
475 585 {
586 + if (!is_user_logged_in() || !class_exists('WC_Payment_Gateway_CC')) {
587 + return $tokens;
588 + }
476 589
477 - if (!is_user_logged_in() || !class_exists('WC_Payment_Gateway_CC')) {
590 + $saved_card = $this->get_configuration()->get_option('payment_methods.configuration.payplug.save_card')
591 + && is_user_logged_in();
592 +
593 + if (!$saved_card) {
594 + foreach ($tokens as $token_id => $token) {
595 + if ('payplug' == (string) $token->get_gateway_id()) {
596 + unset($tokens[$token_id]);
597 + }
598 + }
599 +
478 600 return $tokens;
479 601 }
480 602
481 603 /* @var \WC_Payment_Token_CC $token */
482 604 foreach ($tokens as $k => $token) {
483 -
484 605 if ($this->id !== $token->get_gateway_id()) {
485 606 continue;
486 607 }
487 608
@@ -492,9 +613,9 @@
492 613 continue;
493 614 }
494 615
495 616 // check if token is available for the current gateway mode
496 - if ($this->mode !== $token->get_meta('mode', true)) {
617 + if ($this->mode != $token->get_meta('mode', true)) {
497 618 unset($tokens[$k]);
498 619 continue;
499 620 }
500 621
@@ -499,15 +620,15 @@
499 620 }
500 621
501 622 // check if token is not expired
502 623 $current_month = \absint(date('n'));
503 - $current_year = \absint(date('Y'));
624 + $current_year = \absint(date('Y'));
504 625 if ($current_year > (int) $token->get_expiry_year()) {
505 626 unset($tokens[$k]);
506 627 continue;
507 628 }
508 629
509 - if ($current_year === (int) $token->get_expiry_year() && $current_month >= (int) $token->get_expiry_month()) {
630 + if ($current_year === (int) $token->get_expiry_year() && $current_month > (int) $token->get_expiry_month()) {
510 631 unset($tokens[$k]);
511 632 continue;
512 633 }
513 634 }
@@ -514,16 +635,20 @@
514 635
515 636 return $tokens;
516 637 }
517 638
518 - public function payment_fields()
639 + /**
640 + * extra payment fields
641 + */
642 + public function payment_fields(): void
519 643 {
520 644 $description = $this->get_description();
645 +
521 646 if (!empty($description)) {
522 647 echo wpautop(wptexturize($description));
523 648 }
524 649
525 - if ($this->oneclick_available()) {
650 + if ($this->save_card_available()) {
526 651 $this->tokenization_script();
527 652 $this->saved_payment_methods();
528 653 }
529 654 }
@@ -530,293 +655,185 @@
530 655
531 656 /**
532 657 * Handle admin display.
533 658 */
534 - public function admin_options()
659 + public function admin_options(): void
535 660 {
536 - wp_enqueue_style(
537 - 'payplug-gateway-style',
538 - PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/css/app.css',
539 - [],
540 - PAYPLUG_GATEWAY_VERSION
541 - );
542 -
543 - wp_enqueue_script(
544 - 'payplug-gateway-admin',
545 - PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/js/payplug-admin.js',
546 - ['jquery-ui-dialog'],
547 - PAYPLUG_GATEWAY_VERSION
548 - );
661 + /************ VUE Code *************/
662 + wp_enqueue_script('chunk-vendors.js', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/dist/js/chunk-vendors-' . PAYPLUG_GATEWAY_VERSION . '.js', [], PAYPLUG_GATEWAY_VERSION);
663 + wp_enqueue_script('app.js', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/dist/js/app-' . PAYPLUG_GATEWAY_VERSION . '.js', [], PAYPLUG_GATEWAY_VERSION);
664 + wp_enqueue_style('app.css', PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/dist/css/app-' . PAYPLUG_GATEWAY_VERSION . '.css', [], PAYPLUG_GATEWAY_VERSION);
665 + wp_localize_script(
666 + 'app.js',
667 + 'payplug_admin_config',
668 + [
669 + 'img_path' => esc_url(PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/dist/'),
670 + 'ajax_url' => get_home_url(),
671 + 'rest_url' => get_home_url() . '/?rest_route=/payplug_api/',
672 + ]
673 + ); ?>
674 + <script>window.get_data_url = "<?php echo rest_url('payplug/data'); ?>"</script>
675 + <script>window.set_data_url = "<?php echo rest_url('payplug/save_data'); ?>"</script>
676 + <div id="payplug_admin"></div>
549 677
550 - wp_localize_script('payplug-gateway-admin', 'payplug_admin_config', array(
551 - 'ajax_url' => admin_url('admin-ajax.php'),
552 - 'has_live_key' => (false === $this->has_api_key('live')) ? false : true,
553 - 'btn_ok' => _x('Ok', 'modal', 'payplug'),
554 - 'btn_label' => _x('Cancel', 'modal', 'payplug'),
555 - 'general_error' => _x('Something went wrong. Please refresh the page and retry.', 'modal', 'payplug'),
556 - ));
678 + <?php
557 679
558 - wp_enqueue_script(
559 - 'payplug-gateway-admin-oney',
560 - PAYPLUG_GATEWAY_PLUGIN_URL . 'assets/js/payplug-admin-oney.js',
561 - ['jquery-ui-dialog'],
562 - PAYPLUG_GATEWAY_VERSION
563 - );
564 -
565 - wp_localize_script('payplug-gateway-admin-oney', 'payplug_admin_config', array(
566 - 'ajax_url' => admin_url('admin-ajax.php'),
567 - 'btn_ok' => _x('Ok', 'modal', 'payplug'),
568 - ));
569 - if ($this->user_logged_in() && false === $this->has_api_key('live')) {
570 - add_action('admin_footer', function () {
571 - $email = $this->get_option('email');
572 -?>
573 - <div id="payplug-refresh-keys-modal" title="<?php echo esc_attr_x('Mode LIVE', 'modal', 'payplug'); ?>">
574 - <form id="payplug-refresh-keys-modal__form">
575 - <p id="dialog-msg"></p>
576 - <p><?php echo esc_html_x('Please enter your PayPlug account password', 'modal', 'payplug'); ?></p>
577 - <input type="password" name="password" required title="<?php echo esc_attr_x('Enter your PayPlug account password', 'modal', 'payplug'); ?>" />
578 - <input type="hidden" name="email" value="<?php echo esc_attr($email); ?>">
579 - <input type="hidden" name="action" value="<?php echo esc_attr(Ajax::REFRESH_KEY_ACTION); ?>">
580 - <?php wp_nonce_field(sprintf('%s_%s', $email, Ajax::REFRESH_KEY_ACTION)); ?>
581 - <input class="ui-dialog-sronly" type="submit" tabindex="-1">
582 - </form>
583 - </div>
584 - <?php
585 - });
586 - }
587 -
588 - $payplug_requirements = new PayplugGatewayRequirements($this); ?>
589 -
590 - <h2 class="title--logo"><?php esc_html($this->get_method_title()) ?></h2>
591 - <p><?php _e(sprintf('Version %s', PAYPLUG_GATEWAY_VERSION)); ?></p>
592 - <div class="payplug-requirements">
593 - <?php echo $payplug_requirements->curl_requirement(); ?>
594 - <?php echo $payplug_requirements->php_requirement(); ?>
595 - <?php echo $payplug_requirements->openssl_requirement(); ?>
596 - <?php echo $payplug_requirements->account_requirement(); ?>
597 - <?php echo $payplug_requirements->currency_requirement(); ?>
598 - <?php echo $payplug_requirements->oney_requirement(); ?>
599 - </div>
600 - <?php echo wp_kses_post(wpautop($this->get_method_description())); ?>
601 -
602 - <?php if ($this->user_logged_in()) : ?>
603 - <table class="form-table">
604 - <?php $this->generate_settings_html($this->get_form_fields()); ?>
605 - </table>
606 - <?php else :
607 - $GLOBALS['hide_save_button'] = true; ?>
608 - <h3 class="wc-settings-sub-title"><?php _e('Connection', 'payplug'); ?></h3>
609 - <table class="form-table">
610 - <tbody>
611 - <tr valign="top">
612 - <th scope="row" class="titledesc">
613 - <label for="payplug_email"><?php _e('Email', 'payplug'); ?></label>
614 - </th>
615 - <td class="forminp">
616 - <fieldset>
617 - <legend class="screen-reader-text"><span><?php _e('Email', 'payplug'); ?></span></legend>
618 - <input class="input-text regular-input" type="text" name="payplug_email" id="payplug_email" value="" placeholder="<?php _e('[email protected]', 'payplug'); ?>" />
619 - </fieldset>
620 - </td>
621 - </tr>
622 - <tr valign="top">
623 - <th scope="row" class="titledesc">
624 - <label for="payplug_password"><?php _e('Password', 'payplug'); ?></label>
625 - </th>
626 - <td class="forminp">
627 - <fieldset>
628 - <legend class="screen-reader-text"><span><?php _e('Password', 'payplug'); ?></span>
629 - </legend>
630 - <input class="input-text regular-input" type="password" name="payplug_password" id="payplug_password" value="" />
631 - </fieldset>
632 - </td>
633 - </tr>
634 - <tr valign="top">
635 - <td class="forminp">
636 - <input id="payplug-login" class="button" type="submit" value="<?php _e('Login', 'payplug'); ?>">
637 - <input type="hidden" name="save" value="login">
638 - <?php wp_nonce_field('payplug_user_login', '_loginaction'); ?>
639 - </td>
640 - </tr>
641 - </tbody>
642 - </table>
643 - <?php
644 - endif;
645 - ?>
646 - <div id="payplug-oney-modal" title="<?php echo esc_attr_x('Mode LIVE', 'modal', 'payplug'); ?>">
647 - <p>
648 - <?php echo esc_html_x('Attention, pour utiliser la méthode de paiement Oney en mode LIVE merci de nous contacter à', 'modal', 'payplug'); ?>
649 - <br/>
650 - <a href="mailto:[email protected]">[email protected]</a>
651 - </p>
652 - </div>
653 - <?php
680 + /*********** End VUE Code ***********/
654 681 }
655 682
656 683 /**
657 - * Process admin options.
684 + * Process payment.
658 685 *
659 - * @return bool
686 + * @param int $order_id
687 + *
688 + * @throws \Exception
689 + *
690 + * @return array
660 691 */
661 - public function process_admin_options()
692 + public function process_payment($order_id)
662 693 {
663 - $data = $this->get_post_data();
664 - $settings = get_option( 'woocommerce_payplug_settings', [] );
665 - $oneclick_fieldkey = $this->get_field_key('oneclick');
666 -
667 - // Handle logout process
668 - if (
669 - isset($data['submit_logout'])
670 - && false !== check_admin_referer('payplug_user_logout', '_logoutaction')
671 - ) {
694 + self::log(sprintf('Processing payment for order #%s', $order_id));
672 695
673 - if ($this->permissions) {
674 - $this->permissions->clear_permissions();
675 - }
696 + $order = wc_get_order($order_id);
697 + if (!$order instanceof \WC_Order) {
698 + self::log(sprintf('Order #%s not found.', $order_id), 'error');
699 + throw new \Exception(__('Order not found.', 'payplug'));
700 + }
701 + $customer_id = PayplugWoocommerceHelper::is_pre_30() ? $order->customer_user : $order->get_customer_id();
702 + $amount = (int) PayplugWoocommerceHelper::get_payplug_amount($order->get_total());
703 + $amount = $this->validate_order_amount($amount);
676 704
677 - $data = get_option($this->get_option_key());
678 - $data['payplug_test_key'] = '';
679 - $data['payplug_live_key'] = '';
680 - $data['payplug_merchant_id'] = '';
681 - $data['enabled'] = 'no';
682 - $data['mode'] = 'no';
683 - $data['oneclick'] = 'no';
684 - update_option(
685 - $this->get_option_key(),
686 - apply_filters('woocommerce_settings_api_sanitized_fields_' . $this->id, $data)
687 - );
688 - if("payplug" === $this->id) {
689 - \WC_Admin_Settings::add_message(__('Successfully logged out.', 'payplug'));
690 - }
691 -
692 - return true;
705 + if (is_wp_error($amount)) {
706 + self::log(sprintf('Invalid amount %s for the order.', $order->get_total()), 'error');
707 + throw new \Exception($amount->get_error_message());
693 708 }
694 709
695 - // Handle login process
696 - if (
697 - isset($data['payplug_email'])
698 - && false !== check_admin_referer('payplug_user_login', '_loginaction')
699 - ) {
700 - $email = $data['payplug_email'];
701 - $password = wp_unslash($data['payplug_password']);
702 - $response = $this->retrieve_user_api_keys($email, $password);
703 - if (is_wp_error($response)) {
704 - \WC_Admin_Settings::add_error($response->get_error_message());
710 + $payment_token_id = (isset($_POST['wc-' . $this->id . '-payment-token']) && 'new' !== $_POST['wc-' . $this->id . '-payment-token'])
711 + ? wc_clean($_POST['wc-' . $this->id . '-payment-token'])
712 + : false;
705 713
706 - return false;
707 - }
714 + if ($payment_token_id && (int) $customer_id > 0) {
715 + self::log(sprintf('Payment token found.', $amount));
708 716
709 - // try to use the api keys to retrieve the merchant id
710 - $merchant_id = isset($response['test']) ? $this->retrieve_merchant_id($response['test']) : '';
717 + return $this->process_payment_with_token($order, $amount, $customer_id, $payment_token_id);
718 + }
711 719
712 - $this->init_form_fields();
713 - $fields = $this->get_form_fields();
714 - $data = [];
720 + return $this->process_standard_payment($order, $amount, $customer_id);
721 + }
715 722
716 - // Load existing values if the user is re-login.
717 - foreach ($fields as $key => $field) {
718 - if (in_array($field['type'], ['title', 'login'])) {
719 - continue;
720 - }
721 -
722 - switch ($key) {
723 - case 'enabled':
724 - $val = 'yes';
725 - break;
726 - case 'mode':
727 - $val = 'no';
728 - break;
729 - case 'payplug_test_key':
730 - $val = esc_attr($response['test']);
731 - break;
732 - case 'payplug_live_key':
733 - $val = esc_attr($response['live']);
734 - break;
735 - case 'payplug_merchant_id':
736 - $val = esc_attr($merchant_id);
737 - break;
738 - case 'email':
739 - $val = esc_html($email);
740 - break;
741 - default:
742 - $val = $this->get_option($key);
743 - }
744 -
745 - $data[$key] = $val;
746 - }
747 -
748 - $this->set_post_data($data);
749 - update_option(
750 - $this->get_option_key(),
751 - apply_filters('woocommerce_settings_api_sanitized_fields_' . $this->id, $data)
752 - );
753 - if("payplug" === $this->id) {
754 - \WC_Admin_Settings::add_message(__('Successfully logged in.', 'payplug'));
755 - }
756 -
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')) {
757 736 return true;
758 737 }
759 738
760 - // Don't let user without live key leave TEST mode.
761 - $mode_fieldkey = $this->get_field_key('mode');
762 - $live_key_fieldkey = $this->get_field_key('payplug_live_key');
763 - if (isset($data[$mode_fieldkey]) && '1' === $data[$mode_fieldkey] && empty($data[$live_key_fieldkey])) {
764 - $data[$mode_fieldkey] = null;
765 - $this->set_post_data($data);
766 - \WC_Admin_Settings::add_error(__('Your account does not support LIVE mode at the moment, it must be validated first. If your account has already been validated, please log out and log in again.', 'payplug'));
739 + $posted_key = $_POST['order_pay_key'] ?? $_POST['order_key'] ?? '';
740 + if (empty($posted_key)) {
741 + return false;
767 742 }
768 743
769 - // Check user permissions before activating one-click feature.
770 - $oneclick_fieldkey = $this->get_field_key('oneclick');
771 - if (
772 - isset($data[$oneclick_fieldkey])
773 - && '1' === $data[$oneclick_fieldkey]
774 - && '1' === $data[$mode_fieldkey]
775 - && (!$this->user_logged_in()
776 - || false === $this->permissions->has_permissions(PayplugPermissions::SAVE_CARD))
777 - ) {
778 - $data[$oneclick_fieldkey] = null;
779 - \WC_Admin_Settings::add_error(__('Only PREMIUM accounts can enable the One Click option in LIVE mode.', 'payplug'));
780 - }
781 -
782 - $this->data = $data;
783 - parent::process_admin_options();
744 + return $order instanceof \WC_Order && hash_equals($order->get_order_key(), wc_clean(wp_unslash($posted_key)));
784 745 }
785 746
786 747 /**
787 - * Process payment.
748 + * if payment was generated by an intend, we shouldn't generate another one and try to pay it, this would generate duplications
788 749 *
789 - * @param int $order_id
750 + * @param $order
790 751 *
791 - * @return array
792 752 * @throws \Exception
753 + *
754 + * @return array|null
793 755 */
794 - public function process_payment($order_id)
756 + private function process_standard_intent_payment($order)
795 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);
796 762
797 - PayplugGateway::log(sprintf('Processing payment for order #%s', $order_id));
763 + //no order-pay page, no ajax_on_order_review_page
764 + if (!$is_order_pay &&
765 + PayplugWoocommerceHelper::is_checkout_block() &&
766 + (
767 + ('payplug' == $this->id && in_array($this->embedded_mode, ['integrated', 'popup'])) ||
768 + ('american_express' == $this->id && 'popup' == $this->embedded_mode)
769 + ) &&
770 + ($_GET['wc-ajax'] ?? '') !== 'payplug_order_review_url' &&
771 + !empty($order->get_transaction_id())
772 + ) {
773 + $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
798 774
799 - $order = wc_get_order($order_id);
800 - $customer_id = PayplugWoocommerceHelper::is_pre_30() ? $order->customer_user : $order->get_customer_id();
801 - $amount = (int) PayplugWoocommerceHelper::get_payplug_amount($order->get_total());
802 - $amount = $this->validate_order_amount($amount);
803 - if (is_wp_error($amount)) {
804 - PayplugGateway::log(sprintf('Invalid amount %s for the order.', $order->get_total()), 'error');
805 - throw new \Exception($amount->get_error_message());
806 - }
775 + try {
776 + $payment = $this->payplug_api->payment_retrieve($order->get_transaction_id());
777 + if (ob_get_length() > 0) {
778 + ob_clean();
779 + }
807 780
808 - $payment_token_id = (isset($_POST['wc-' . $this->id . '-payment-token']) && 'new' !== $_POST['wc-' . $this->id . '-payment-token'])
809 - ? wc_clean($_POST['wc-' . $this->id . '-payment-token'])
810 - : false;
781 + // Save transaction id for the order
782 + PayplugWoocommerceHelper::is_pre_30()
783 + ? update_post_meta($order_id, '_transaction_id', $payment->id)
784 + : $order->set_transaction_id($payment->id);
811 785
812 - if ($payment_token_id && $this->oneclick_available() && (int) $customer_id > 0) {
813 - PayplugGateway::log(sprintf('Payment token found.', $amount));
786 + if ($payment->is_paid) {
787 + $finished_status = wc_get_is_paid_statuses();
788 + $order->set_status($finished_status[0]);
789 + }
814 790
815 - return $this->process_payment_with_token($order, $amount, $customer_id, $payment_token_id);
791 + if (is_callable([$order, 'save'])) {
792 + $order->save();
793 + }
794 +
795 + /**
796 + * Fires once a payment has been created.
797 + *
798 + * @param int $order_id Order ID
799 + * @param PaymentResource $payment Payment resource
800 + */
801 + \do_action('payplug_gateway_payment_created', $order_id, $payment);
802 +
803 + $metadata = PayplugWoocommerceHelper::extract_transaction_metadata($payment);
804 + PayplugWoocommerceHelper::save_transaction_metadata($order, $metadata);
805 +
806 + self::log(sprintf('Payment intent created for order #%s', $order_id));
807 +
808 + $return_url = esc_url_raw($order->get_checkout_order_received_url());
809 +
810 + $result = [
811 + 'payment_id' => $payment->id,
812 + 'result' => 'success',
813 + 'redirect' => !empty($payment->hosted_payment->payment_url) ? $payment->hosted_payment->payment_url : $return_url,
814 + 'cancel' => !empty($payment->hosted_payment->cancel_url) ? $payment->hosted_payment->cancel_url : null,
815 + ];
816 +
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;
826 + } catch (HttpException $e) {
827 + self::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
828 + throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
829 + } catch (\Exception $e) {
830 + self::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
831 + throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
832 + }
816 833 }
817 834
818 - return $this->process_standard_payment($order, $amount, $customer_id);
835 + return null;
819 836 }
820 837
821 838 /**
822 839 * @param \WC_Order $order
@@ -822,37 +839,70 @@
822 839 * @param \WC_Order $order
823 840 * @param int $amount
824 841 * @param int $customer_id
825 842 *
843 + * @throws \Exception
844 + *
826 845 * @return array
827 - * @throws \Exception
828 846 */
829 847 public function process_standard_payment($order, $amount, $customer_id)
830 848 {
849 + $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
831 850
832 - $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
851 + $intent = $this->process_standard_intent_payment($order);
852 + if (!empty($intent)) {
853 + return $intent;
854 + }
833 855
834 856 try {
835 857 $address_data = PayplugAddressData::from_order($order);
836 858
859 + $return_url = esc_url_raw($order->get_checkout_order_received_url());
860 +
861 + if (!(substr($return_url, 0, 4) === 'http')) {
862 + $return_url = get_site_url() . $return_url;
863 + }
864 +
837 865 $payment_data = [
838 - 'amount' => $amount,
839 - 'currency' => get_woocommerce_currency(),
840 - 'allow_save_card' => $this->oneclick_available() && (int) $customer_id > 0,
841 - 'billing' => $address_data->get_billing(),
842 - 'shipping' => $address_data->get_shipping(),
843 - 'hosted_payment' => [
844 - 'return_url' => esc_url_raw($order->get_checkout_order_received_url()),
866 + 'amount' => $amount,
867 + 'currency' => get_woocommerce_currency(),
868 + 'allow_save_card' => $this->save_card_available() && (int) $customer_id > 0,
869 + 'billing' => $address_data->get_billing(),
870 + 'shipping' => $address_data->get_shipping(),
871 + 'hosted_payment' => [
872 + 'return_url' => $return_url,
845 873 'cancel_url' => esc_url_raw($order->get_cancel_order_url_raw()),
846 874 ],
847 875 'notification_url' => esc_url_raw(WC()->api_request_url('PayplugGateway')),
848 - 'metadata' => [
849 - 'order_id' => $order_id,
876 + 'metadata' => [
877 + 'order_id' => $order_id,
850 878 'customer_id' => ((int) $customer_id > 0) ? $customer_id : 'guest',
851 - 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
879 + 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
852 880 ],
853 881 ];
854 882
883 + if (PayplugWoocommerceHelper::is_checkout_block() && is_checkout()) {
884 + $payment_data['metadata']['woocommerce_block'] = 'CHECKOUT';
885 + } elseif (PayplugWoocommerceHelper::is_cart_block() && is_cart()) {
886 + $payment_data['metadata']['woocommerce_block'] = 'CART';
887 + }
888 +
889 + //IP request required variables
890 + if ('integrated' == $this->embedded_mode) {
891 + $payment_data['initiator'] = 'PAYER';
892 + $payment_data['integration'] = 'INTEGRATED_PAYMENT';
893 + unset($payment_data['hosted_payment']['cancel_url']);
894 + }
895 +
896 + //for subscriptions the card needs to be saved
897 + $is_subscription = PayplugWoocommerceHelper::is_subscription();
898 + if (!empty($is_subscription) && $is_subscription === true) {
899 + $payment_data['allow_save_card'] = false;
900 + $payment_data['save_card'] = true;
901 + $payment_data['force_3ds'] = true;
902 + $payment_data['metadata']['subscription'] = 'subscription';
903 + }
904 +
855 905 /**
856 906 * Filter the payment data before it's used
857 907 *
858 908 * @param array $payment_data
@@ -860,9 +910,9 @@
860 910 * @param array $customer_details
861 911 * @param PayplugAddressData $address_data
862 912 */
863 913 $payment_data = apply_filters('payplug_gateway_payment_data', $payment_data, $order_id, [], $address_data);
864 - $payment = $this->api->payment_create($payment_data);
914 + $payment = $this->payplug_api->payment_create($payment_data);
865 915
866 916 // Save transaction id for the order
867 917 PayplugWoocommerceHelper::is_pre_30()
868 918 ? update_post_meta($order_id, '_transaction_id', $payment->id)
@@ -867,8 +917,11 @@
867 917 PayplugWoocommerceHelper::is_pre_30()
868 918 ? update_post_meta($order_id, '_transaction_id', $payment->id)
869 919 : $order->set_transaction_id($payment->id);
870 920
921 + $order->set_payment_method($this->id);
922 + $order->set_payment_method_title($this->method_title);
923 +
871 924 if (is_callable([$order, 'save'])) {
872 925 $order->save();
873 926 }
874 927
@@ -882,20 +935,25 @@
882 935
883 936 $metadata = PayplugWoocommerceHelper::extract_transaction_metadata($payment);
884 937 PayplugWoocommerceHelper::save_transaction_metadata($order, $metadata);
885 938
886 - PayplugGateway::log(sprintf('Payment creation complete for order #%s', $order_id));
939 + self::log(sprintf('Payment creation complete for order #%s', $order_id));
887 940
941 + if (ob_get_length() > 0) {
942 + ob_clean();
943 + }
944 +
888 945 return [
889 - 'result' => 'success',
890 - 'redirect' => $payment->hosted_payment->payment_url,
891 - 'cancel' => $payment->hosted_payment->cancel_url,
946 + 'payment_id' => $payment->id,
947 + 'result' => 'success',
948 + 'redirect' => !empty($payment->hosted_payment->payment_url) ? $payment->hosted_payment->payment_url : $return_url,
949 + 'cancel' => !empty($payment->hosted_payment->cancel_url) ? $payment->hosted_payment->cancel_url : null,
892 950 ];
893 951 } catch (HttpException $e) {
894 - PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
952 + self::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
895 953 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
896 954 } catch (\Exception $e) {
897 - PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
955 + self::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
898 956 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
899 957 }
900 958 }
901 959
@@ -904,18 +962,18 @@
904 962 * @param int $amount
905 963 * @param int $customer_id
906 964 * @param string $token_id
907 965 *
966 + * @throws \Exception
967 + *
908 968 * @return array
909 - * @throws \Exception
910 969 */
911 970 public function process_payment_with_token($order, $amount, $customer_id, $token_id)
912 971 {
913 -
914 - $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
972 + $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
915 973 $payment_token = WC_Payment_Tokens::get($token_id);
916 974 if (!$payment_token || (int) $customer_id !== (int) $payment_token->get_user_id()) {
917 - PayplugGateway::log('Could not find the payment token or the payment doesn\'t belong to the current user.', 'error');
975 + self::log('Could not find the payment token or the payment doesn\'t belong to the current user.', 'error');
918 976 throw new \Exception(__('Invalid payment method.', 'payplug'));
919 977 }
920 978
921 979 try {
@@ -920,49 +978,79 @@
920 978
921 979 try {
922 980 $address_data = PayplugAddressData::from_order($order);
923 981
982 + $return_url = esc_url_raw($order->get_checkout_order_received_url());
983 +
984 + if (!(substr($return_url, 0, 4) === 'http')) {
985 + $return_url = get_site_url() . $return_url;
986 + }
987 +
924 988 $payment_data = [
925 - 'amount' => $amount,
926 - 'currency' => get_woocommerce_currency(),
927 - 'payment_method' => $payment_token->get_token(),
928 - 'allow_save_card' => false,
929 - 'billing' => $address_data->get_billing(),
930 - 'shipping' => $address_data->get_shipping(),
931 - 'initiator' => 'PAYER',
932 - 'hosted_payment' => [
933 - 'return_url' => esc_url_raw($order->get_checkout_order_received_url()),
989 + 'amount' => $amount,
990 + 'currency' => get_woocommerce_currency(),
991 + 'payment_method' => $payment_token->get_token(),
992 + 'allow_save_card' => false,
993 + 'billing' => $address_data->get_billing(),
994 + 'shipping' => $address_data->get_shipping(),
995 + 'initiator' => 'PAYER',
996 + 'hosted_payment' => [
997 + 'return_url' => $return_url,
934 998 'cancel_url' => esc_url_raw($order->get_cancel_order_url_raw()),
935 999 ],
936 1000 'notification_url' => esc_url_raw(WC()->api_request_url('PayplugGateway')),
937 - 'metadata' => [
938 - 'order_id' => $order_id,
1001 + 'metadata' => [
1002 + 'order_id' => $order_id,
939 1003 'customer_id' => ((int) $customer_id > 0) ? $customer_id : 'guest',
940 - 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
1004 + 'domain' => $this->limit_length(esc_url_raw(home_url()), 500),
1005 + 'woocommerce_block' => \WC_Blocks_Utils::has_block_in_page(wc_get_page_id('checkout'), 'woocommerce/checkout'),
941 1006 ],
942 1007 ];
943 1008
1009 + $is_subscription = PayplugWoocommerceHelper::is_subscription();
1010 + if (!empty($is_subscription) && $is_subscription === true) {
1011 + $payment_data['metadata']['subscription'] = 'subscription';
1012 + }
1013 +
944 1014 /** This filter is documented in src/Gateway/PayplugGateway */
945 1015 $payment_data = apply_filters('payplug_gateway_payment_data', $payment_data, $order_id, [], $address_data);
946 - $payment = $this->api->payment_create($payment_data);
1016 + $payment = $this->payplug_api->payment_create($payment_data);
947 1017
1018 + // Save transaction id for the order
1019 + PayplugWoocommerceHelper::is_pre_30()
1020 + ? update_post_meta($order_id, '_transaction_id', $payment->id)
1021 + : $order->set_transaction_id($payment->id);
1022 +
1023 + if (is_callable([$order, 'save'])) {
1024 + $order->save();
1025 + }
1026 +
948 1027 /** This action is documented in src/Gateway/PayplugGateway */
949 1028 \do_action('payplug_gateway_payment_created', $order_id, $payment);
950 1029
1030 + $metadata = PayplugWoocommerceHelper::extract_transaction_metadata($payment);
1031 + PayplugWoocommerceHelper::save_transaction_metadata($order, $metadata);
1032 +
951 1033 $this->response->process_payment($payment, true);
1034 + if (($payment->__get('is_paid'))) {
1035 + $redirect = $order->get_checkout_order_received_url();
1036 + } elseif (isset($payment->__get('hosted_payment')->payment_url)) {
1037 + $redirect = $payment->__get('hosted_payment')->payment_url;
1038 + } else {
1039 + $redirect = $return_url;
1040 + }
952 1041
953 - PayplugGateway::log(sprintf('Payment process complete for order #%s', $order_id));
954 -
955 1042 return [
956 - 'result' => 'success',
957 - 'is_paid' => $payment->__get('is_paid'), // Use for path redirect before DSP2
958 - 'redirect' => ($payment->__get('is_paid')) ? $order->get_checkout_order_received_url() : $payment->__get('hosted_payment')->payment_url
1043 + 'payment_id' => $payment->id,
1044 + 'result' => 'success',
1045 + 'is_paid' => $payment->__get('is_paid'), // Use for path redirect before DSP2
1046 + 'redirect' => $redirect,
959 1047 ];
960 1048 } catch (HttpException $e) {
961 - PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
1049 + self::log(sprintf('Error while processing order #%s : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
962 1050 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
963 1051 } catch (\Exception $e) {
964 - PayplugGateway::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
1052 + self::log(sprintf('Error while processing order #%s : %s', $order_id, $e->getMessage()), 'error');
965 1053 throw new \Exception(__('Payment processing failed. Please retry.', 'payplug'));
966 1054 }
967 1055 }
968 1056
@@ -976,19 +1064,25 @@
976 1064 * @return bool|\WP_Error
977 1065 */
978 1066 public function process_refund($order_id, $amount = null, $reason = '')
979 1067 {
980 - PayplugGateway::log(sprintf('Processing refund for order #%s', $order_id));
1068 + self::log(sprintf('Processing refund for order #%s', $order_id));
981 1069
1070 + if (!$this->user_logged_in()) {
1071 + self::log(__('You must be logged in with your PayPlug account.', 'payplug'), 'error');
1072 +
1073 + return new \WP_Error('process_refund_error', __('You must be logged in with your PayPlug account.', 'payplug'));
1074 + }
1075 +
982 1076 $order = wc_get_order($order_id);
983 1077 if (!$order instanceof \WC_Order) {
984 - PayplugGateway::log(sprintf('The order #%s does not exist.', $order_id), 'error');
1078 + self::log(sprintf('The order #%s does not exist.', $order_id), 'error');
985 1079
986 1080 return new \WP_Error('process_refund_error', sprintf(__('The order %s does not exist.', 'payplug'), $order_id));
987 1081 }
988 1082
989 - if ($order->get_status() === "cancelled") {
990 - PayplugGateway::log(sprintf('The order #%s cannot be refund.', $order_id), 'error');
1083 + if ($order->get_status() === 'cancelled') {
1084 + self::log(sprintf('The order #%s cannot be refund.', $order_id), 'error');
991 1085
992 1086 return new \WP_Error('process_refund_error', sprintf(__('The order %s cannot be refund.', 'payplug'), $order_id));
993 1087 }
994 1088
@@ -993,9 +1087,9 @@
993 1087 }
994 1088
995 1089 $transaction_id = PayplugWoocommerceHelper::is_pre_30() ? get_post_meta($order_id, '_transaction_id', true) : $order->get_transaction_id();
996 1090 if (empty($transaction_id)) {
997 - PayplugGateway::log(sprintf('The order #%s does not have PayPlug transaction ID associated with it.', $order_id), 'error');
1091 + self::log(sprintf('The order #%s does not have PayPlug transaction ID associated with it.', $order_id), 'error');
998 1092
999 1093 return new \WP_Error('process_refund_error', __('No PayPlug transaction was found for this order. The refund could not be processed.', 'payplug'));
1000 1094 }
1001 1095
@@ -1002,12 +1096,12 @@
1002 1096 $customer_id = PayplugWoocommerceHelper::is_pre_30() ? $order->customer_user : $order->get_customer_id();
1003 1097
1004 1098 $data = [
1005 1099 'metadata' => [
1006 - 'order_id' => $order_id,
1100 + 'order_id' => $order_id,
1007 1101 'customer_id' => ((int) $customer_id > 0) ? $customer_id : 'guest',
1008 1102 'refund_from' => 'woocommerce',
1009 - ]
1103 + ],
1010 1104 ];
1011 1105
1012 1106 if (!is_null($amount)) {
1013 1107 $data['amount'] = PayplugWoocommerceHelper::get_payplug_amount($amount);
@@ -1026,9 +1120,9 @@
1026 1120 */
1027 1121 $data = apply_filters('payplug_gateway_refund_data', $data, $order_id, $transaction_id);
1028 1122
1029 1123 try {
1030 - $refund = $this->api->refund_create($transaction_id, $data);
1124 + $refund = $this->payplug_api->refund_create($transaction_id, $data);
1031 1125
1032 1126 /**
1033 1127 * Fires once a refund has been created.
1034 1128 *
@@ -1052,23 +1146,23 @@
1052 1146 }
1053 1147 $order->add_order_note($note);
1054 1148
1055 1149 try {
1056 - $payment = $this->api->payment_retrieve($transaction_id);
1150 + $payment = $this->payplug_api->payment_retrieve($transaction_id);
1057 1151 $metadata = PayplugWoocommerceHelper::extract_transaction_metadata($payment);
1058 1152 PayplugWoocommerceHelper::save_transaction_metadata($order, $metadata);
1059 1153 } catch (\Exception $e) {
1060 1154 }
1061 1155
1062 - PayplugGateway::log('Refund process complete for the order.');
1156 + self::log('Refund process complete for the order.');
1063 1157
1064 1158 return true;
1065 1159 } catch (HttpException $e) {
1066 - PayplugGateway::log(sprintf('Refund request error for the order %s from PayPlug API : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
1160 + self::log(sprintf('Refund request error for the order %s from PayPlug API : %s', $order_id, wc_print_r($e->getErrorObject(), true)), 'error');
1067 1161
1068 1162 return new \WP_Error('process_refund_error', __('The transaction could not be refunded. Please try again.', 'payplug'));
1069 1163 } catch (\Exception $e) {
1070 - PayplugGateway::log(sprintf('Refund request error for the order %s : %s', $order_id, wc_clean($e->getMessage())), 'error');
1164 + self::log(sprintf('Refund request error for the order %s : %s', $order_id, wc_clean($e->getMessage())), 'error');
1071 1165
1072 1166 return new \WP_Error('process_refund_error', __('The transaction could not be refunded. Please try again.', 'payplug'));
1073 1167 }
1074 1168 }
@@ -1123,15 +1217,15 @@
1123 1217 }
1124 1218
1125 1219 try {
1126 1220 $response = Authentication::getKeysByLogin($email, $password);
1127 - if (empty($response) || !isset($response['httpResponse']) && "payplug" === $this->id) {
1221 + if (empty($response) || !isset($response['httpResponse']) && 'payplug' === $this->id) {
1128 1222 return new \WP_Error('invalid_credentials', __('Invalid credentials.', 'payplug'));
1129 1223 }
1130 1224
1131 1225 return $response['httpResponse']['secret_keys'];
1132 1226 } catch (HttpException $e) {
1133 - if("payplug" === $this->id) {
1227 + if ('payplug' === $this->id) {
1134 1228 return new \WP_Error('invalid_credentials', __('Invalid credentials.', 'payplug'));
1135 1229 }
1136 1230 }
1137 1231 }
@@ -1147,23 +1241,20 @@
1147 1241 * @return string
1148 1242 */
1149 1243 public function retrieve_merchant_id($key = null)
1150 1244 {
1245 + $merchant_id = '';
1151 1246 try {
1152 - $response = !is_null($key) ? Authentication::getAccount(new Payplug($key)) : Authentication::getAccount();
1247 + $response = !is_null($key) && !empty($key) ? Authentication::getAccount(new Payplug($key)) : Authentication::getAccount();
1248 + PayplugWoocommerceHelper::set_transient_data($response);
1153 1249 $merchant_id = isset($response['httpResponse']['id']) ? $response['httpResponse']['id'] : '';
1154 1250 } catch (ConfigurationException $e) {
1155 - PayplugGateway::log(sprintf('Missing API key for PayPlug client : %s', wc_print_r($e->getMessage(), true)), 'error');
1156 -
1157 - $merchant_id = '';
1251 + self::log(sprintf('Missing API key for PayPlug client : %s', wc_print_r($e->getMessage(), true)), 'error');
1158 1252 } catch (HttpException $e) {
1159 - PayplugGateway::log(sprintf('Account request error from PayPlug API : %s', wc_print_r($e->getErrorObject(), true)), 'error');
1160 -
1161 - $merchant_id = '';
1253 + self::log(sprintf('Account request error from PayPlug API : %s', wc_print_r($e->getErrorObject(), true)), 'error');
1254 + PayplugWoocommerceHelper::exception_handler_400_logout($e->getCode(), '', sprintf('Account request error from PayPlug API : %s', wc_print_r($e->getMessage(), true)));
1162 1255 } catch (\Exception $e) {
1163 - PayplugGateway::log(sprintf('Account request error : %s', wc_clean($e->getMessage())), 'error');
1164 -
1165 - $merchant_id = '';
1256 + self::log(sprintf('Account request error : %s', wc_clean($e->getMessage())), 'error');
1166 1257 }
1167 1258
1168 1259 return $merchant_id;
1169 1260 }
@@ -1168,217 +1259,8 @@
1168 1259 return $merchant_id;
1169 1260 }
1170 1261
1171 1262 /**
1172 - * Generate Hidden HTML.
1173 - *
1174 - * @param string $key
1175 - * @param array $data
1176 - *
1177 - * @return string
1178 - */
1179 - public function generate_hidden_html($key, $data)
1180 - {
1181 - $field_key = $this->get_field_key($key);
1182 - $defaults = array(
1183 - 'title' => '',
1184 - 'disabled' => false,
1185 - 'class' => '',
1186 - 'css' => '',
1187 - 'placeholder' => '',
1188 - 'type' => 'text',
1189 - 'desc_tip' => false,
1190 - 'description' => '',
1191 - 'custom_attributes' => array(),
1192 - );
1193 -
1194 - $data = wp_parse_args($data, $defaults);
1195 -
1196 - ob_start();
1197 - ?>
1198 - <input type="<?php echo esc_attr($data['type']); ?>" name="<?php echo esc_attr($field_key); ?>" id="<?php echo esc_attr($field_key); ?>" value="<?php echo esc_attr($this->get_option($key)); ?>" />
1199 - <?php
1200 -
1201 - return ob_get_clean();
1202 - }
1203 -
1204 - /**
1205 - * Generate Yes/No Input HTML.
1206 - *
1207 - * @param string $key
1208 - * @param array $data
1209 - *
1210 - * @return string
1211 - */
1212 - public function generate_yes_no_html($key, $data)
1213 - {
1214 - $field_key = $this->get_field_key($key);
1215 - $defaults = array(
1216 - 'title' => '',
1217 - 'no' => 'No',
1218 - 'yes' => 'Yes',
1219 - 'disabled' => false,
1220 - 'class' => '',
1221 - 'css' => '',
1222 - 'placeholder' => '',
1223 - 'type' => 'text',
1224 - 'desc_tip' => false,
1225 - 'description' => '',
1226 - 'custom_attributes' => [],
1227 - 'hide_label' => false,
1228 - );
1229 -
1230 - $data = wp_parse_args($data, $defaults);
1231 - $checked = 'yes' === $this->get_option($key) ? '1' : '0';
1232 -
1233 - ob_start();
1234 - ?>
1235 - <tr valign="top">
1236 - <?php if (!$data['hide_label']) : ?>
1237 - <th scope="row" class="titledesc">
1238 - <label for="<?php echo esc_attr($field_key); ?>">
1239 - <?php echo wp_kses_post($data['title']); ?>
1240 - <?php echo $this->get_tooltip_html($data); ?>
1241 - </label>
1242 - </th>
1243 - <?php endif; ?>
1244 - <td class="forminp">
1245 - <fieldset>
1246 - <legend class="screen-reader-text"><span><?php echo wp_kses_post($data['title']); ?></span>
1247 - </legend>
1248 - <div class="radio--custom">
1249 - <input class="radio radio-yes <?php echo esc_attr($data['class']); ?>" type="radio" name="<?php echo esc_attr($field_key); ?>" id="<?php echo esc_attr($field_key); ?>-yes" value="1" <?php checked('1', $checked); ?> <?php disabled($data['disabled'], true); ?> <?php echo $this->get_custom_attribute_html($data); ?>>
1250 - <label for="<?php echo esc_attr($field_key); ?>-yes"><?php echo esc_html($data['yes']); ?></label>
1251 - </div>
1252 - <div class="radio--custom">
1253 - <input class="radio radio-no <?php echo esc_attr($data['class']); ?>" type="radio" name="<?php echo esc_attr($field_key); ?>" id="<?php echo esc_attr($field_key); ?>-no" value="0" <?php checked('0', $checked); ?> <?php disabled($data['disabled'], true); ?> <?php echo $this->get_custom_attribute_html($data); ?>>
1254 - <label for="<?php echo esc_attr($field_key); ?>-no"><?php echo esc_html($data['no']); ?></label>
1255 - </div>
1256 - <?php echo $this->get_description_html($data); ?>
1257 - </fieldset>
1258 - </td>
1259 - </tr>
1260 - <?php
1261 -
1262 - return ob_get_clean();
1263 - }
1264 -
1265 - /**
1266 - * Generate Radio Input HTML.
1267 - *
1268 - * @param string $key
1269 - * @param array $data
1270 - *
1271 - * @return string
1272 - */
1273 - public function generate_radio_html($key, $data)
1274 - {
1275 - $field_key = $this->get_field_key($key);
1276 - $defaults = array(
1277 - 'title' => '',
1278 - 'disabled' => false,
1279 - 'class' => '',
1280 - 'css' => '',
1281 - 'placeholder' => '',
1282 - 'type' => 'text',
1283 - 'desc_tip' => false,
1284 - 'description' => '',
1285 - 'custom_attributes' => [],
1286 - 'options' => [],
1287 - );
1288 -
1289 - $data = wp_parse_args($data, $defaults);
1290 -
1291 - ob_start();
1292 - ?>
1293 - <tr valign="top">
1294 - <th scope="row" class="titledesc">
1295 - <label for="<?php echo esc_attr($field_key); ?>">
1296 - <?php echo wp_kses_post($data['title']); ?>
1297 - <?php echo $this->get_tooltip_html($data); ?>
1298 - </label>
1299 - </th>
1300 - <td class="forminp">
1301 - <fieldset>
1302 - <legend class="screen-reader-text"><span><?php echo wp_kses_post($data['title']); ?></span>
1303 - </legend>
1304 - <?php foreach ($data['options'] as $option_key => $option_value) : ?>
1305 - <input class="radio <?php echo esc_attr($data['class']); ?>" type="radio" name="<?php echo esc_attr($field_key); ?>" id="<?php echo esc_attr($field_key); ?>-<?php echo esc_attr($option_key); ?>" value="<?php echo esc_attr($option_key); ?>" <?php checked($option_key, $this->get_option($key)); ?> <?php disabled($data['disabled'], true); ?> <?php echo $this->get_custom_attribute_html($data); ?>>
1306 - <label for="<?php echo esc_attr($field_key); ?>-<?php echo esc_attr($option_key); ?>"><?php echo esc_html($option_value); ?></label>
1307 - <?php endforeach; ?>
1308 - </fieldset>
1309 - </td>
1310 - </tr>
1311 - <?php
1312 -
1313 - return ob_get_clean();
1314 - }
1315 -
1316 - /**
1317 - * Generate Login HTML.
1318 - *
1319 - * @param string $key
1320 - * @param array $data
1321 - *
1322 - * @return string
1323 - */
1324 - public function generate_login_html($key, $data)
1325 - {
1326 - $field_key = $this->get_field_key($key);
1327 - $defaults = [];
1328 -
1329 - $data = wp_parse_args($data, $defaults);
1330 -
1331 - ob_start();
1332 - ?>
1333 - <tr valign="top">
1334 - <td class="forminp">
1335 - <p><?php echo $this->get_option('email'); ?></p>
1336 - <p>
1337 - <input id="payplug-logout" type="submit" name="submit_logout" value="<?php _e('Logout', 'payplug'); ?>">
1338 - <input type="hidden" name="save" value="logout">
1339 - <?php wp_nonce_field('payplug_user_logout', '_logoutaction'); ?>
1340 - |
1341 - <a href="https://portal.payplug.com" target="_blank"><?php _e('Go to your PayPlug Portal', 'payplug'); ?></a>
1342 - </p>
1343 - </td>
1344 - </tr>
1345 -<?php
1346 -
1347 - return ob_get_clean();
1348 - }
1349 -
1350 - /**
1351 - * Validate Radio Field.
1352 - *
1353 - * Make sure the data is escaped correctly, etc.
1354 - *
1355 - * @param string $key
1356 - * @param string|null $value Posted Value
1357 - *
1358 - * @return string
1359 - */
1360 - public function validate_radio_field($key, $value)
1361 - {
1362 - $value = is_null($value) ? '' : $value;
1363 -
1364 - return wc_clean(stripslashes($value));
1365 - }
1366 -
1367 - /**
1368 - * Validate Yes/No Field.
1369 - *
1370 - * @param string $key
1371 - * @param string $value Posted Value
1372 - *
1373 - * @return string
1374 - */
1375 - public function validate_yes_no_field($key, $value)
1376 - {
1377 - return ('1' === (string) $value) ? 'yes' : 'no';
1378 - }
1379 -
1380 - /**
1381 1263 * Get PayPlug gateway mode.
1382 1264 *
1383 1265 * @return string
1384 1266 */
@@ -1383,9 +1265,9 @@
1383 1265 * @return string
1384 1266 */
1385 1267 public function get_current_mode()
1386 1268 {
1387 - return ('yes' === $this->get_option('mode')) ? 'live' : 'test';
1269 + return $this->get_configuration()->get_option('mode');
1388 1270 }
1389 1271
1390 1272 /**
1391 1273 * Get user API key.
@@ -1395,40 +1277,12 @@
1395 1277 * @return string
1396 1278 */
1397 1279 public function get_api_key($mode = 'test')
1398 1280 {
1399 -
1400 - switch ($mode) {
1401 - case 'test':
1402 - $key = $this->get_option('payplug_test_key');
1403 - break;
1404 - case 'live':
1405 - $key = $this->get_option('payplug_live_key');
1406 - break;
1407 - default:
1408 - $key = '';
1409 - break;
1410 - }
1411 -
1412 - return $key;
1281 + return $this->get_api()->get_bearer_token($mode);
1413 1282 }
1414 1283
1415 1284 /**
1416 - * Check if an api key exist for a mode.
1417 - *
1418 - * @param string $mode
1419 - *
1420 - * @return bool
1421 - */
1422 - public function has_api_key($mode = 'test')
1423 - {
1424 - $key = $this->get_api_key($mode);
1425 - $key = trim($key);
1426 -
1427 - return !empty($key);
1428 - }
1429 -
1430 - /**
1431 1285 * Get current merchant id.
1432 1286 *
1433 1287 * @return string
1434 1288 */
@@ -1433,9 +1287,9 @@
1433 1287 * @return string
1434 1288 */
1435 1289 public function get_merchant_id()
1436 1290 {
1437 - return $this->get_option('payplug_merchant_id', '');
1291 + return $this->get_configuration()->get_option('company_id');
1438 1292 }
1439 1293
1440 1294 /**
1441 1295 * Check if user is logged in and we have an API key for TEST mode.
@@ -1443,9 +1297,21 @@
1443 1297 * @return bool
1444 1298 */
1445 1299 public function user_logged_in()
1446 1300 {
1447 - return !empty($this->get_option('payplug_test_key'));
1301 + $options = $this->get_configuration()->get_options();
1302 + if (empty($options) || !isset($options['api_key']) || !isset($options['jwt'])) {
1303 + return false;
1304 + }
1305 +
1306 + $jwt = json_decode($options['jwt'], true);
1307 + if (!empty($jwt) && isset($jwt['test']) && isset($jwt['test']['access_token'])) {
1308 + return true;
1309 + }
1310 +
1311 + $api_key = json_decode($options['api_key'], true);
1312 +
1313 + return !empty($api_key) && isset($api_key['test']) && !empty($api_key['test']);
1448 1314 }
1449 1315
1450 1316 /**
1451 1317 * Check if oneclick payment is activated and merchant can use it.
@@ -1451,12 +1317,12 @@
1451 1317 * Check if oneclick payment is activated and merchant can use it.
1452 1318 *
1453 1319 * @return bool
1454 1320 */
1455 - public function oneclick_available()
1321 + public function save_card_available()
1456 1322 {
1457 - return $this->user_logged_in()
1458 - && $this->oneclick
1323 + return 'payplug' == $this->id && $this->user_logged_in()
1324 + && $this->save_card
1459 1325 && $this->permissions->has_permissions(PayplugPermissions::SAVE_CARD);
1460 1326 }
1461 1327
1462 1328 /**
@@ -1462,18 +1328,31 @@
1462 1328 /**
1463 1329 * Check if the gatteway is allowed for the order amount
1464 1330 *
1465 1331 * @param array
1332 + *
1466 1333 * @return array
1467 1334 */
1468 1335 public function check_gateway($gateways)
1469 1336 {
1470 - if (isset($gateways[$this->id]) && $gateways[$this->id]->id == $this->id) {
1337 + if (!empty(WC()->cart) && isset($gateways[$this->id]) && $gateways[$this->id]->id == $this->id) {
1471 1338 $order_amount = $this->get_order_total();
1472 - if ($order_amount < self::MIN_AMOUNT || $order_amount > self::MAX_AMOUNT) {
1473 - unset($gateways[$this->id]);
1339 + foreach ($gateways[$this->id]->settings['payment_methods']['permissions'] as $key => &$permission) {
1340 + $method_amounts = json_decode($permission['amounts'], true);
1341 + if ($order_amount < $method_amounts['min']['EUR'] / 100 || $order_amount > $method_amounts['max']['EUR'] / 100) {
1342 + unset($gateways[$key]);
1343 + }
1474 1344 }
1475 1345 }
1346 +
1347 + if ((bool) $this->get_configuration()->get_option('payment_methods.configuration.oney.with_fees')) {
1348 + unset($gateways['oney_x3_without_fees']);
1349 + unset($gateways['oney_x4_without_fees']);
1350 + } else {
1351 + unset($gateways['oney_x3_with_fees']);
1352 + unset($gateways['oney_x4_with_fees']);
1353 + }
1354 +
1476 1355 return $gateways;
1477 1356 }
1478 1357
1479 1358 /**
@@ -1479,13 +1358,15 @@
1479 1358 /**
1480 1359 * Can the order be refunded via this gateway?
1481 1360 *
1482 1361 *
1483 - * @param WC_Order $order Order object.
1362 + * @param WC_Order $order Order object.
1363 + *
1484 1364 * @return bool If false, the automatic refund button is hidden in the UI.
1485 1365 */
1486 1366 public function can_refund_order($order)
1487 1367 {
1488 1368 $status = $order->get_status();
1489 - return $order && $this->supports('refunds') && $status !== "cancelled" && $status !== "failed";
1369 +
1370 + return $order && $this->supports('refunds') && $status !== 'cancelled' && $status !== 'failed';
1490 1371 }
1491 1372 }