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