Mollie Payments for WooCommerce - Version 3.0.0

Version Description

  • 17/04/2018 =

  • New - WooCommerce Subscriptions: add support for 'subscription_payment_method_change', shop-customers can change payment method if renewal payment fails (SEPA incasso, credit card)

  • New - WooCommerce Subscriptions: disable Mollie payment methods on shop-customer's my account page for "Payment method change", keep it enabled for "Pay now" link in emails

  • New - WooCommerce Subscriptions: improve handling and update messages and notices for Subscription switch to better explain what's happening

  • New - WooCommerce Subscriptions: set renewal orders and subscriptions to 'On-Hold' if renewal payment fails

  • Fix - Fallback for getUserMollieCustomerId, get Mollie Customer ID from recent subscription if it's empty in WordPress user meta

  • Fix - Improve support for Polylang option "Hide URL language information for default language" in webhook and return URLs,

  • Fix - Only check if customer ID is valid on current API key if there is a customer ID (not empty)(and improve log messages)

  • Fix - Make sure payment instructions (Bank Transfer) are styled the same as WooCommerce content (Order received, payment pending)

  • Fix - Don't update/process/expire Mollie payments on WooCommerce orders that have been paid with other payment gateways

  • Fix - Updated text strings for Bancontact/Mister Cash to just Bancontact

  • Fix - Use the exact same translation as WooCommerce for order statuses

  • Fix - Resolve error (fatal error get_payment_method()) that occurred when users made certain custom changes to the WooCommerce template files

  • Fix - Add order note and log message when customer returns to the site but payment is open/pending

  • Fix - Improved order note for charged back renewal payments

Download this release

Release Info

Developer davdebcom
Plugin Icon wp plugin Mollie Payments for WooCommerce
Version 3.0.0
Comparing to
See all releases

Code changes from version 2.9.0 to 3.0.0

includes/mollie/wc/gateway/abstract.php CHANGED
@@ -307,183 +307,184 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
307
  return false;
308
  }
309
 
310
- /**
311
- * @param int $order_id
312
- * @return array
313
- */
314
- public function process_payment ($order_id)
315
- {
316
- $order = Mollie_WC_Plugin::getDataHelper()->getWcOrder($order_id);
317
-
318
- if (!$order)
319
- {
320
- Mollie_WC_Plugin::debug($this->id . ': Could not process payment, order ' . $order_id . ' not found.');
321
 
322
- Mollie_WC_Plugin::addNotice(sprintf(__('Could not load order %s', 'mollie-payments-for-woocommerce'), $order_id), 'error');
 
323
 
324
- return array('result' => 'failure');
325
- }
326
 
327
- $initial_order_status = $this->getInitialOrderStatus();
 
328
 
329
- // Overwrite plugin-wide
330
- $initial_order_status = apply_filters(Mollie_WC_Plugin::PLUGIN_ID . '_initial_order_status', $initial_order_status);
331
 
332
- // Overwrite gateway-wide
333
- $initial_order_status = apply_filters(Mollie_WC_Plugin::PLUGIN_ID . '_initial_order_status_' . $this->id, $initial_order_status);
334
 
335
- $settings_helper = Mollie_WC_Plugin::getSettingsHelper();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
 
337
- // Is test mode enabled?
338
- $test_mode = $settings_helper->isTestModeEnabled();
339
- $customer_id = $this->getUserMollieCustomerId($order,$test_mode);
340
- $paymentRequestData = $this->getPaymentRequestData($order, $customer_id);
341
-
342
- $data = array_filter($paymentRequestData);
343
-
344
- $data = apply_filters('woocommerce_' . $this->id . '_args', $data, $order);
345
-
346
- // If this is a subscription switch and customer has a valid mandate, process the order internally
347
- try {
348
-
349
- if ( ( '0.00' === $order->get_total() ) && ( $this->is_subscription( $order_id ) == true ) &&
350
- 0 != $order->get_user_id() && ( wcs_order_contains_switch( $order ) )
351
- ) {
352
- try {
353
- Mollie_WC_Plugin::debug( $this->id . ': Subscription switch, fetch mandate ' . $order_id );
354
- $mandates = Mollie_WC_Plugin::getApiHelper()->getApiClient( $test_mode )->customers_mandates->withParentId( $customer_id )->all();
355
- $validMandate = false;
356
- foreach ( $mandates as $mandate ) {
357
- if ( $mandate->status == 'valid' ) {
358
- $validMandate = true;
359
- $data['method'] = $mandate->method;
360
- break;
361
- }
362
- }
363
- if ( $validMandate ) {
364
 
365
- $order->payment_complete();
 
366
 
367
- $order->add_order_note( sprintf(
368
- __( 'Order completed internally because of an existing valid mandate at Mollie.', 'mollie-payments-for-woocommerce' ) ) );
369
 
370
- Mollie_WC_Plugin::debug( $this->id . ': Subscription switch, valid mandate ' . $order_id );
 
 
 
371
 
372
- return array (
373
- 'result' => 'success',
374
- 'redirect' => $this->get_return_url( $order ),
375
- );
 
 
 
 
 
 
 
376
 
377
- } else {
378
- Mollie_WC_Plugin::debug( $this->id . ': Subscription switch, payment problem ' . $order_id );
379
- throw new Mollie_API_Exception( __( 'Subscription switch cannot be processed, no valid mandate.', 'mollie-payments-for-woocommerce-mandate-problem' ) );
380
- }
381
- }
382
- catch ( Mollie_API_Exception $e ) {
383
- if ( $e->getField() ) {
384
- throw $e;
385
- }
386
- }
387
 
388
- }
389
 
390
- if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
391
- Mollie_WC_Plugin::debug( $this->id . ': Create payment for order ' . $order->id, true );
392
- } else {
393
- Mollie_WC_Plugin::debug( $this->id . ': Create payment for order ' . $order->get_id(), true );
394
- }
 
 
 
 
395
 
396
- do_action(Mollie_WC_Plugin::PLUGIN_ID . '_create_payment', $data, $order);
397
 
398
- // Create Mollie payment with customer id.
399
- try
400
- {
401
- $payment = Mollie_WC_Plugin::getApiHelper()->getApiClient($test_mode)->payments->create($data);
402
- }
403
- catch (Mollie_API_Exception $e)
404
- {
405
- if ($e->getField() !== 'customerId')
406
- {
407
- throw $e;
408
- }
409
-
410
- // Retry without customer id.
411
- unset($data['customerId']);
412
- $payment = Mollie_WC_Plugin::getApiHelper()->getApiClient($test_mode)->payments->create($data);
413
- }
414
 
415
- $this->saveMollieInfo($order, $payment);
 
 
 
416
 
417
- do_action(Mollie_WC_Plugin::PLUGIN_ID . '_payment_created', $payment, $order);
418
 
419
- if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
420
- Mollie_WC_Plugin::debug( $this->id . ': Payment ' . $payment->id . ' (' . $payment->mode . ') created for order ' . $order->id );
421
- } else {
422
- Mollie_WC_Plugin::debug( $this->id . ': Payment ' . $payment->id . ' (' . $payment->mode . ') created for order ' . $order->get_id() );
423
- }
424
 
425
- // Update initial order status for payment methods where the payment status will be delivered after a couple of days.
426
- // See: https://www.mollie.com/nl/docs/status#expiry-times-per-payment-method
427
- // Status is only updated if the new status is not the same as the default order status (pending)
428
- if ( ( $payment->method == 'banktransfer' ) || ( $payment->method == 'directdebit' ) ) {
 
429
 
430
- // Don't change the status of the order if it's Partially Paid
431
- // This adds support for WooCommerce Deposits (by Webtomizer)
432
- // See https://github.com/mollie/WooCommerce/issues/138
 
433
 
434
- $order_status = ( version_compare( WC_VERSION, '3.0', '<' ) ) ? $order->status : $order->get_status();
 
 
435
 
436
- if ( $order_status != 'wc-partially-paid ' ) {
437
 
438
- $this->updateOrderStatus(
439
- $order,
440
- $initial_order_status,
441
- __( 'Awaiting payment confirmation.', 'mollie-payments-for-woocommerce' ) . "\n"
442
- );
443
 
444
- }
445
- }
 
 
 
446
 
 
 
447
 
448
- $order->add_order_note(sprintf(
449
- /* translators: Placeholder 1: Payment method title, placeholder 2: payment ID */
450
- __('%s payment started (%s).', 'mollie-payments-for-woocommerce'),
451
- $this->method_title,
452
- $payment->id . ($payment->mode == 'test' ? (' - ' . __('test mode', 'mollie-payments-for-woocommerce')) : '')
453
- ));
454
 
455
- if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
456
- Mollie_WC_Plugin::debug( "For order " . $order->id . " redirect user to payment URL: {$payment->getPaymentUrl()}" );
457
- } else {
458
- Mollie_WC_Plugin::debug( "For order " . $order->get_id() . " redirect user to payment URL: {$payment->getPaymentUrl()}" );
459
- }
460
 
461
- return array(
462
- 'result' => 'success',
463
- 'redirect' => $this->getProcessPaymentRedirect($order, $payment),
464
- );
465
- }
466
- catch (Mollie_API_Exception $e)
467
- {
468
- if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
469
- Mollie_WC_Plugin::debug( $this->id . ': Failed to create payment for order ' . $order->id . ': ' . $e->getMessage() );
470
- } else {
471
- Mollie_WC_Plugin::debug( $this->id . ': Failed to create payment for order ' . $order->get_id() . ': ' . $e->getMessage() );
472
- }
473
 
474
- /* translators: Placeholder 1: Payment method title */
475
- $message = sprintf(__('Could not create %s payment.', 'mollie-payments-for-woocommerce'), $this->title);
476
 
477
- if (defined('WP_DEBUG') && WP_DEBUG)
478
- {
479
- $message .= ' ' . $e->getMessage();
480
- }
481
 
482
- Mollie_WC_Plugin::addNotice($message, 'error');
483
- }
484
 
485
- return array('result' => 'failure');
486
- }
487
 
488
  /**
489
  * @param $order
@@ -808,7 +809,7 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
808
  $order_id = $order->get_id();
809
  }
810
 
811
- Mollie_WC_Plugin::debug( $this->id . ": Order $order_id does not need a payment (payment webhook {$payment->id}).", true );
812
 
813
  }
814
 
@@ -983,54 +984,6 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
983
 
984
  }
985
 
986
- /**
987
- * @param WC_Order $order
988
- * @param Mollie_API_Object_Payment $payment
989
- */
990
- protected function onWebhookChargedback( WC_Order $order, Mollie_API_Object_Payment $payment ) {
991
-
992
- // Get order ID in the correct way depending on WooCommerce version
993
- if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
994
- $order_id = $order->id;
995
- } else {
996
- $order_id = $order->get_id();
997
- }
998
-
999
- // Add messages to log
1000
- Mollie_WC_Plugin::debug( __METHOD__ . ' called for order ' . $order_id );
1001
-
1002
- // New order status
1003
- $new_order_status = self::STATUS_ON_HOLD;
1004
-
1005
- // Overwrite plugin-wide
1006
- $new_order_status = apply_filters( Mollie_WC_Plugin::PLUGIN_ID . '_order_status_on_hold', $new_order_status );
1007
-
1008
- // Overwrite gateway-wide
1009
- $new_order_status = apply_filters( Mollie_WC_Plugin::PLUGIN_ID . '_order_status_on_hold_' . $this->id, $new_order_status );
1010
-
1011
- $paymentMethodTitle = $this->getPaymentMethodTitle( $payment );
1012
-
1013
- // Update order status for order with charged_back payment, don't restore stock
1014
- $this->updateOrderStatus(
1015
- $order,
1016
- $new_order_status,
1017
- sprintf(
1018
- /* translators: Placeholder 1: payment method title, placeholder 2: payment ID */
1019
- __( '%s payment charged back via Mollie (%s). You will need to manually review the payment and adjust product stocks if you use them.', 'mollie-payments-for-woocommerce' ),
1020
- $paymentMethodTitle,
1021
- $payment->id . ( $payment->mode == 'test' ? ( ' - ' . __( 'test mode', 'mollie-payments-for-woocommerce' ) ) : '' )
1022
- ),
1023
- $restore_stock = false
1024
- );
1025
-
1026
- // Send a "Failed order" email to notify the admin
1027
- $emails = WC()->mailer()->get_emails();
1028
- if ( ! empty( $emails ) && ! empty( $order_id ) ) {
1029
- $emails['WC_Email_Failed_Order']->trigger( $order_id );
1030
- }
1031
-
1032
- }
1033
-
1034
  /**
1035
  * @param WC_Order $order
1036
  *
@@ -1222,8 +1175,10 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
1222
  }
1223
  else
1224
  {
1225
- echo '<h2>' . __('Payment', 'mollie-payments-for-woocommerce') . '</h2>';
 
1226
  echo wpautop($instructions) . PHP_EOL;
 
1227
  }
1228
  }
1229
  }
@@ -1271,6 +1226,7 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
1271
  if ( is_order_received_page() && get_the_ID() === $id ) {
1272
  global $wp;
1273
 
 
1274
  $order_id = apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) );
1275
  $order_key = apply_filters( 'woocommerce_thankyou_order_key', empty( $_GET['key'] ) ? '' : wc_clean( $_GET['key'] ) );
1276
  if ( $order_id > 0 ) {
@@ -1287,6 +1243,10 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
1287
  }
1288
  }
1289
 
 
 
 
 
1290
  $order = Mollie_WC_Plugin::getDataHelper()->getWcOrder( $order );
1291
 
1292
  if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
@@ -1320,6 +1280,28 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
1320
  }
1321
 
1322
  if ( $payment->isOpen() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1323
  $title .= __( ', payment pending.', 'mollie-payments-for-woocommerce' );
1324
 
1325
  return $title;
@@ -1363,6 +1345,11 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
1363
  */
1364
  protected function orderNeedsPayment (WC_Order $order)
1365
  {
 
 
 
 
 
1366
  // Check whether the order is processed and paid via Mollie
1367
  if ( ! $this->isOrderPaidAndProcessed( $order ) ) {
1368
  return true;
@@ -1490,38 +1477,39 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
1490
  return $url;
1491
  }
1492
 
1493
- /**
1494
- * Check if any multi language plugins are enabled and return the correct site url.
1495
- *
1496
- * @return string
1497
- */
1498
- protected function getSiteUrlWithLanguage()
1499
- {
1500
- /**
1501
- * function is_plugin_active() is not available. Lets include it to use it.
1502
- */
1503
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
1504
 
1505
- $site_url = get_site_url();
1506
- $slug = ''; // default is NO slug/language
1507
 
1508
- if (is_plugin_active('polylang/polylang.php')
1509
- || is_plugin_active('polylang-pro/polylang-pro.php')
1510
- || is_plugin_active('mlang/mlang.php')
1511
- || is_plugin_active('mlanguage/mlanguage.php')
1512
- )
1513
- {
1514
- // we probably have a multilang site. Retrieve current language.
1515
- $slug = get_bloginfo('language');
1516
- $pos = strpos($slug, '-');
1517
- if ($pos !== false)
1518
- $slug = substr($slug, 0, $pos);
1519
-
1520
- $slug = '/' . $slug;
1521
- }
1522
 
1523
- return str_replace($site_url, $site_url . $slug, $site_url);
1524
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1525
 
1526
  /**
1527
  * @return string|NULL
@@ -1596,6 +1584,22 @@ abstract class Mollie_WC_Gateway_Abstract extends WC_Payment_Gateway
1596
 
1597
  }
1598
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1599
 
1600
  /**
1601
  * @return mixed
307
  return false;
308
  }
309
 
310
+ /**
311
+ * @param int $order_id
312
+ *
313
+ * @return array
314
+ */
315
+ public function process_payment( $order_id ) {
316
+ $order = Mollie_WC_Plugin::getDataHelper()->getWcOrder( $order_id );
 
 
 
 
317
 
318
+ if ( ! $order ) {
319
+ Mollie_WC_Plugin::debug( $this->id . ': Could not process payment, order ' . $order_id . ' not found.' );
320
 
321
+ Mollie_WC_Plugin::addNotice( sprintf( __( 'Could not load order %s', 'mollie-payments-for-woocommerce' ), $order_id ), 'error' );
 
322
 
323
+ return array ( 'result' => 'failure' );
324
+ }
325
 
326
+ $initial_order_status = $this->getInitialOrderStatus();
 
327
 
328
+ // Overwrite plugin-wide
329
+ $initial_order_status = apply_filters( Mollie_WC_Plugin::PLUGIN_ID . '_initial_order_status', $initial_order_status );
330
 
331
+ // Overwrite gateway-wide
332
+ $initial_order_status = apply_filters( Mollie_WC_Plugin::PLUGIN_ID . '_initial_order_status_' . $this->id, $initial_order_status );
333
+
334
+ $settings_helper = Mollie_WC_Plugin::getSettingsHelper();
335
+
336
+ // Is test mode enabled?
337
+ $test_mode = $settings_helper->isTestModeEnabled();
338
+ $customer_id = $this->getUserMollieCustomerId( $order, $test_mode );
339
+ $paymentRequestData = $this->getPaymentRequestData( $order, $customer_id );
340
+
341
+ $data = array_filter( $paymentRequestData );
342
+
343
+ $data = apply_filters( 'woocommerce_' . $this->id . '_args', $data, $order );
344
+
345
+ //
346
+ // PROCESS SUBSCRIPTION SWITCH - If this is a subscription switch and customer has a valid mandate, process the order internally
347
+ //
348
+ if ( ( '0.00' === $order->get_total() ) && ( $this->is_subscription( $order_id ) == true ) &&
349
+ 0 != $order->get_user_id() && ( wcs_order_contains_switch( $order ) )
350
+ ) {
351
+
352
+ try {
353
+ Mollie_WC_Plugin::debug( $this->id . ': Subscription switch started, fetching mandate(s) for order #' . $order_id );
354
+ $mandates = Mollie_WC_Plugin::getApiHelper()->getApiClient( $test_mode )->customers_mandates->withParentId( $customer_id )->all();
355
+ $validMandate = false;
356
+ foreach ( $mandates as $mandate ) {
357
+ if ( $mandate->status == 'valid' ) {
358
+ $validMandate = true;
359
+ $data['method'] = $mandate->method;
360
+ break;
361
+ }
362
+ }
363
+ if ( $validMandate ) {
364
 
365
+ $order->payment_complete();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
 
367
+ $order->add_order_note( sprintf(
368
+ __( 'Order completed internally because of an existing valid mandate at Mollie.', 'mollie-payments-for-woocommerce' ) ) );
369
 
370
+ Mollie_WC_Plugin::debug( $this->id . ': Subscription switch completed, valid mandate for order #' . $order_id );
 
371
 
372
+ return array (
373
+ 'result' => 'success',
374
+ 'redirect' => $this->get_return_url( $order ),
375
+ );
376
 
377
+ } else {
378
+ Mollie_WC_Plugin::debug( $this->id . ': Subscription switch failed, no valid mandate for order #' . $order_id );
379
+ Mollie_WC_Plugin::addNotice( __( 'Subscription switch failed, no valid mandate found. Place a completely new order to change your subscription.', 'mollie-payments-for-woocommerce' ), 'error' );
380
+ throw new Mollie_API_Exception( __( 'Subscription switch failed, no valid mandate.', 'mollie-payments-for-woocommerce' ) );
381
+ }
382
+ }
383
+ catch ( Mollie_API_Exception $e ) {
384
+ if ( $e->getField() ) {
385
+ throw $e;
386
+ }
387
+ }
388
 
389
+ return array ( 'result' => 'failure' );
 
 
 
 
 
 
 
 
 
390
 
391
+ }
392
 
393
+ //
394
+ // PROCESS REGULAR PAYMENT
395
+ //
396
+ try {
397
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
398
+ Mollie_WC_Plugin::debug( $this->id . ': Create payment for order ' . $order->id, true );
399
+ } else {
400
+ Mollie_WC_Plugin::debug( $this->id . ': Create payment for order ' . $order->get_id(), true );
401
+ }
402
 
403
+ do_action( Mollie_WC_Plugin::PLUGIN_ID . '_create_payment', $data, $order );
404
 
405
+ // Create Mollie payment with customer id.
406
+ try {
407
+ $payment = Mollie_WC_Plugin::getApiHelper()->getApiClient( $test_mode )->payments->create( $data );
408
+ }
409
+ catch ( Mollie_API_Exception $e ) {
410
+ if ( $e->getField() !== 'customerId' ) {
411
+ throw $e;
412
+ }
 
 
 
 
 
 
 
 
413
 
414
+ // Retry without customer id.
415
+ unset( $data['customerId'] );
416
+ $payment = Mollie_WC_Plugin::getApiHelper()->getApiClient( $test_mode )->payments->create( $data );
417
+ }
418
 
419
+ $this->saveMollieInfo( $order, $payment );
420
 
421
+ do_action( Mollie_WC_Plugin::PLUGIN_ID . '_payment_created', $payment, $order );
 
 
 
 
422
 
423
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
424
+ Mollie_WC_Plugin::debug( $this->id . ': Payment ' . $payment->id . ' (' . $payment->mode . ') created for order ' . $order->id );
425
+ } else {
426
+ Mollie_WC_Plugin::debug( $this->id . ': Payment ' . $payment->id . ' (' . $payment->mode . ') created for order ' . $order->get_id() );
427
+ }
428
 
429
+ // Update initial order status for payment methods where the payment status will be delivered after a couple of days.
430
+ // See: https://www.mollie.com/nl/docs/status#expiry-times-per-payment-method
431
+ // Status is only updated if the new status is not the same as the default order status (pending)
432
+ if ( ( $payment->method == 'banktransfer' ) || ( $payment->method == 'directdebit' ) ) {
433
 
434
+ // Don't change the status of the order if it's Partially Paid
435
+ // This adds support for WooCommerce Deposits (by Webtomizer)
436
+ // See https://github.com/mollie/WooCommerce/issues/138
437
 
438
+ $order_status = ( version_compare( WC_VERSION, '3.0', '<' ) ) ? $order->status : $order->get_status();
439
 
440
+ if ( $order_status != 'wc-partially-paid ' ) {
 
 
 
 
441
 
442
+ $this->updateOrderStatus(
443
+ $order,
444
+ $initial_order_status,
445
+ __( 'Awaiting payment confirmation.', 'mollie-payments-for-woocommerce' ) . "\n"
446
+ );
447
 
448
+ }
449
+ }
450
 
451
+ $order->add_order_note( sprintf(
452
+ /* translators: Placeholder 1: Payment method title, placeholder 2: payment ID */
453
+ __( '%s payment started (%s).', 'mollie-payments-for-woocommerce' ),
454
+ $this->method_title,
455
+ $payment->id . ( $payment->mode == 'test' ? ( ' - ' . __( 'test mode', 'mollie-payments-for-woocommerce' ) ) : '' )
456
+ ) );
457
 
458
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
459
+ Mollie_WC_Plugin::debug( "For order " . $order->id . " redirect user to payment URL: {$payment->getPaymentUrl()}" );
460
+ } else {
461
+ Mollie_WC_Plugin::debug( "For order " . $order->get_id() . " redirect user to payment URL: {$payment->getPaymentUrl()}" );
462
+ }
463
 
464
+ return array (
465
+ 'result' => 'success',
466
+ 'redirect' => $this->getProcessPaymentRedirect( $order, $payment ),
467
+ );
468
+ }
469
+ catch ( Mollie_API_Exception $e ) {
470
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
471
+ Mollie_WC_Plugin::debug( $this->id . ': Failed to create payment for order ' . $order->id . ': ' . $e->getMessage() );
472
+ } else {
473
+ Mollie_WC_Plugin::debug( $this->id . ': Failed to create payment for order ' . $order->get_id() . ': ' . $e->getMessage() );
474
+ }
 
475
 
476
+ /* translators: Placeholder 1: Payment method title */
477
+ $message = sprintf( __( 'Could not create %s payment.', 'mollie-payments-for-woocommerce' ), $this->title );
478
 
479
+ if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
480
+ $message .= ' ' . $e->getMessage();
481
+ }
 
482
 
483
+ Mollie_WC_Plugin::addNotice( $message, 'error' );
484
+ }
485
 
486
+ return array ( 'result' => 'failure' );
487
+ }
488
 
489
  /**
490
  * @param $order
809
  $order_id = $order->get_id();
810
  }
811
 
812
+ Mollie_WC_Plugin::debug( __METHOD__ . ' - ' . $this->id . ": Order $order_id does not need a payment by Mollie (payment {$payment->id}).", true );
813
 
814
  }
815
 
984
 
985
  }
986
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
987
  /**
988
  * @param WC_Order $order
989
  *
1175
  }
1176
  else
1177
  {
1178
+ echo '<section class="woocommerce-order-details mollie-instructions abc">';
1179
+ echo '<h2 class="woocommerce-order-details__title">' . __('Payment', 'mollie-payments-for-woocommerce') . '</h2>';
1180
  echo wpautop($instructions) . PHP_EOL;
1181
+ echo '</section>';
1182
  }
1183
  }
1184
  }
1226
  if ( is_order_received_page() && get_the_ID() === $id ) {
1227
  global $wp;
1228
 
1229
+ $order = false;
1230
  $order_id = apply_filters( 'woocommerce_thankyou_order_id', absint( $wp->query_vars['order-received'] ) );
1231
  $order_key = apply_filters( 'woocommerce_thankyou_order_key', empty( $_GET['key'] ) ? '' : wc_clean( $_GET['key'] ) );
1232
  if ( $order_id > 0 ) {
1243
  }
1244
  }
1245
 
1246
+ if ( $order == false){
1247
+ return $title;
1248
+ }
1249
+
1250
  $order = Mollie_WC_Plugin::getDataHelper()->getWcOrder( $order );
1251
 
1252
  if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
1280
  }
1281
 
1282
  if ( $payment->isOpen() ) {
1283
+
1284
+ // Add a message to log and order explaining a payment with status "open", only if it hasn't been added already
1285
+ if ( get_post_meta( $order_id, '_mollie_open_status_note', true ) !== '1' ) {
1286
+
1287
+ // Get payment method title
1288
+ $paymentMethodTitle = $this->getPaymentMethodTitle( $payment );
1289
+
1290
+ // Add message to log
1291
+ Mollie_WC_Plugin::debug( $this->id . ': Customer returned to store, but payment still pending for order #' . $order_id . '. Status should be updated automatically in the future, if it doesn\'t this might indicate a communication issue between the site and Mollie.' );
1292
+
1293
+ // Add message to order as order note
1294
+ $order->add_order_note( sprintf(
1295
+ /* translators: Placeholder 1: payment method title, placeholder 2: payment ID */
1296
+ __( '%s payment still pending (%s) but customer already returned to the store. Status should be updated automatically in the future, if it doesn\'t this might indicate a communication issue between the site and Mollie.', 'mollie-payments-for-woocommerce' ),
1297
+ $paymentMethodTitle,
1298
+ $payment->id . ( $payment->mode == 'test' ? ( ' - ' . __( 'test mode', 'mollie-payments-for-woocommerce' ) ) : '' )
1299
+ ) );
1300
+
1301
+ update_post_meta( $order_id, '_mollie_open_status_note', '1' );
1302
+ }
1303
+
1304
+ // Update the title on the Order received page to better communicate that the payment is pending.
1305
  $title .= __( ', payment pending.', 'mollie-payments-for-woocommerce' );
1306
 
1307
  return $title;
1345
  */
1346
  protected function orderNeedsPayment (WC_Order $order)
1347
  {
1348
+ // Check whether the order is processed and paid via another gateway
1349
+ if ( $this->isOrderPaidByOtherGateway( $order ) ) {
1350
+ return false;
1351
+ }
1352
+
1353
  // Check whether the order is processed and paid via Mollie
1354
  if ( ! $this->isOrderPaidAndProcessed( $order ) ) {
1355
  return true;
1477
  return $url;
1478
  }
1479
 
1480
+ /**
1481
+ * Check if any multi language plugins are enabled and return the correct site url.
1482
+ *
1483
+ * @return string
1484
+ */
1485
+ protected function getSiteUrlWithLanguage() {
1486
+ /**
1487
+ * function is_plugin_active() is not available. Lets include it to use it.
1488
+ */
1489
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
 
1490
 
1491
+ $site_url = get_site_url();
 
1492
 
1493
+ if ( is_plugin_active( 'polylang/polylang.php' ) || is_plugin_active( 'polylang-pro/polylang-pro.php' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
1494
 
1495
+ $lang = PLL()->model->get_language( pll_current_language() );
1496
+ $polylang_url = $lang->search_url;
1497
+ $site_url = str_replace( $site_url, $polylang_url, $site_url );
1498
+
1499
+ } else if ( is_plugin_active( 'mlang/mlang.php' ) || is_plugin_active( 'mlanguage/mlanguage.php' ) ) {
1500
+
1501
+ $slug = get_bloginfo( 'language' );
1502
+ $pos = strpos( $slug, '-' );
1503
+ if ( $pos !== false ) {
1504
+ $slug = substr( $slug, 0, $pos );
1505
+ }
1506
+ $slug = '/' . $slug;
1507
+ $site_url = str_replace( $site_url, $site_url . $slug, $site_url );
1508
+
1509
+ }
1510
+
1511
+ return $site_url;
1512
+ }
1513
 
1514
  /**
1515
  * @return string|NULL
1584
 
1585
  }
1586
 
1587
+ /**
1588
+ * @return bool
1589
+ */
1590
+ protected function isOrderPaidByOtherGateway( WC_Order $order ) {
1591
+
1592
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
1593
+ $order_id = $order->id;
1594
+ $paid_by_other_gateway = get_post_meta( $order_id, '_mollie_paid_by_other_gateway', $single = true );
1595
+ } else {
1596
+ $paid_by_other_gateway = $order->get_meta( '_mollie_paid_by_other_gateway', true );
1597
+ }
1598
+
1599
+ return $paid_by_other_gateway;
1600
+
1601
+ }
1602
+
1603
 
1604
  /**
1605
  * @return mixed
includes/mollie/wc/gateway/abstractsubscription.php CHANGED
@@ -37,6 +37,8 @@ abstract class Mollie_WC_Gateway_AbstractSubscription extends Mollie_WC_Gateway_
37
  'subscription_amount_changes',
38
  'subscription_date_changes',
39
  'multiple_subscriptions',
 
 
40
  );
41
 
42
  $this->supports = array_merge($this->supports,$supportSubscriptions);
@@ -649,6 +651,7 @@ abstract class Mollie_WC_Gateway_AbstractSubscription extends Mollie_WC_Gateway_
649
  {
650
  if ( $this->id === $payment_method_id ) {
651
 
 
652
  if ( ! isset( $payment_meta['post_meta']['_mollie_customer_id']['value'] ) || empty( $payment_meta['post_meta']['_mollie_customer_id']['value'] ) ) {
653
  throw new Exception( 'A "_mollie_customer_id" value is required.' );
654
  }
@@ -689,6 +692,107 @@ abstract class Mollie_WC_Gateway_AbstractSubscription extends Mollie_WC_Gateway_
689
 
690
  }
691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
692
  /**
693
  * @param $order_id
694
  * @return bool
37
  'subscription_amount_changes',
38
  'subscription_date_changes',
39
  'multiple_subscriptions',
40
+ 'subscription_payment_method_change',
41
+ 'subscription_payment_method_change_customer',
42
  );
43
 
44
  $this->supports = array_merge($this->supports,$supportSubscriptions);
651
  {
652
  if ( $this->id === $payment_method_id ) {
653
 
654
+ // Check that a Mollie Customer ID is entered
655
  if ( ! isset( $payment_meta['post_meta']['_mollie_customer_id']['value'] ) || empty( $payment_meta['post_meta']['_mollie_customer_id']['value'] ) ) {
656
  throw new Exception( 'A "_mollie_customer_id" value is required.' );
657
  }
692
 
693
  }
694
 
695
+ /**
696
+ * @param WC_Order $order
697
+ * @param Mollie_API_Object_Payment $payment
698
+ */
699
+ protected function onWebhookFailed( WC_Order $order, Mollie_API_Object_Payment $payment ) {
700
+
701
+ // Get order ID in the correct way depending on WooCommerce version
702
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
703
+ $order_id = $order->id;
704
+ } else {
705
+ $order_id = $order->get_id();
706
+ }
707
+
708
+ // Add messages to log
709
+ Mollie_WC_Plugin::debug( __METHOD__ . ' called for order ' . $order_id );
710
+
711
+ if ( wcs_order_contains_renewal( $order_id ) ) {
712
+
713
+ // New order status
714
+ $new_order_status = self::STATUS_ON_HOLD;
715
+
716
+ // Overwrite plugin-wide
717
+ $new_order_status = apply_filters( Mollie_WC_Plugin::PLUGIN_ID . '_order_status_on_hold', $new_order_status );
718
+
719
+ // Overwrite gateway-wide
720
+ $new_order_status = apply_filters( Mollie_WC_Plugin::PLUGIN_ID . '_order_status_on_hold_' . $this->id, $new_order_status );
721
+
722
+ $paymentMethodTitle = $this->getPaymentMethodTitle( $payment );
723
+
724
+ // Update order status for order with failed payment, don't restore stock
725
+ $this->updateOrderStatus(
726
+ $order,
727
+ $new_order_status,
728
+ sprintf(
729
+ /* translators: Placeholder 1: payment method title, placeholder 2: payment ID */
730
+ __( '%s renewal payment failed via Mollie (%s). You will need to manually review the payment and adjust product stocks if you use them.', 'mollie-payments-for-woocommerce' ),
731
+ $paymentMethodTitle,
732
+ $payment->id . ( $payment->mode == 'test' ? ( ' - ' . __( 'test mode', 'mollie-payments-for-woocommerce' ) ) : '' )
733
+ ),
734
+ $restore_stock = false
735
+ );
736
+
737
+ Mollie_WC_Plugin::debug( __METHOD__ . ' called for order ' . $order_id . ' and payment ' . $payment->id . ', renewal order payment failed, order set to On-Hold for shop-owner review. ' . $mollie_payment_id );
738
+
739
+
740
+ // Send a "Failed order" email to notify the admin
741
+ $emails = WC()->mailer()->get_emails();
742
+ if ( ! empty( $emails ) && ! empty( $order_id ) ) {
743
+ $emails['WC_Email_Failed_Order']->trigger( $order_id );
744
+ }
745
+ }
746
+ }
747
+
748
+ /**
749
+ * @param WC_Order $order
750
+ * @param Mollie_API_Object_Payment $payment
751
+ */
752
+ protected function onWebhookChargedback( WC_Order $order, Mollie_API_Object_Payment $payment ) {
753
+
754
+ // Get order ID in the correct way depending on WooCommerce version
755
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
756
+ $order_id = $order->id;
757
+ } else {
758
+ $order_id = $order->get_id();
759
+ }
760
+
761
+ // Add messages to log
762
+ Mollie_WC_Plugin::debug( __METHOD__ . ' called for order ' . $order_id );
763
+
764
+ // New order status
765
+ $new_order_status = self::STATUS_ON_HOLD;
766
+
767
+ // Overwrite plugin-wide
768
+ $new_order_status = apply_filters( Mollie_WC_Plugin::PLUGIN_ID . '_order_status_on_hold', $new_order_status );
769
+
770
+ // Overwrite gateway-wide
771
+ $new_order_status = apply_filters( Mollie_WC_Plugin::PLUGIN_ID . '_order_status_on_hold_' . $this->id, $new_order_status );
772
+
773
+ $paymentMethodTitle = $this->getPaymentMethodTitle( $payment );
774
+
775
+ // Update order status for order with charged_back payment, don't restore stock
776
+ $this->updateOrderStatus(
777
+ $order,
778
+ $new_order_status,
779
+ sprintf(
780
+ /* translators: Placeholder 1: payment method title, placeholder 2: payment ID */
781
+ __( '%s renewal payment charged back via Mollie (%s). You will need to manually review the payment and adjust product stocks if you use them.', 'mollie-payments-for-woocommerce' ),
782
+ $paymentMethodTitle,
783
+ $payment->id . ( $payment->mode == 'test' ? ( ' - ' . __( 'test mode', 'mollie-payments-for-woocommerce' ) ) : '' )
784
+ ),
785
+ $restore_stock = false
786
+ );
787
+
788
+ // Send a "Failed order" email to notify the admin
789
+ $emails = WC()->mailer()->get_emails();
790
+ if ( ! empty( $emails ) && ! empty( $order_id ) ) {
791
+ $emails['WC_Email_Failed_Order']->trigger( $order_id );
792
+ }
793
+
794
+ }
795
+
796
  /**
797
  * @param $order_id
798
  * @return bool
includes/mollie/wc/gateway/creditcard.php CHANGED
@@ -8,9 +8,11 @@ class Mollie_WC_Gateway_Creditcard extends Mollie_WC_Gateway_AbstractSubscriptio
8
  {
9
  $this->supports = array(
10
  'products',
11
- 'refunds',
12
  );
 
13
  $this->initSubscriptionSupport();
 
14
  parent::__construct();
15
  }
16
 
8
  {
9
  $this->supports = array(
10
  'products',
11
+ 'refunds'
12
  );
13
+
14
  $this->initSubscriptionSupport();
15
+
16
  parent::__construct();
17
  }
18
 
includes/mollie/wc/gateway/directdebit.php CHANGED
@@ -1,6 +1,14 @@
1
  <?php
2
 
3
  class Mollie_WC_Gateway_DirectDebit extends Mollie_WC_Gateway_Abstract {
 
 
 
 
 
 
 
 
4
  /**
5
  * @return string
6
  */
1
  <?php
2
 
3
  class Mollie_WC_Gateway_DirectDebit extends Mollie_WC_Gateway_Abstract {
4
+ /**
5
+ *
6
+ */
7
+ public function __construct ()
8
+ {
9
+ parent::__construct();
10
+ }
11
+
12
  /**
13
  * @return string
14
  */
includes/mollie/wc/gateway/mistercash.php CHANGED
@@ -27,7 +27,7 @@ class Mollie_WC_Gateway_MisterCash extends Mollie_WC_Gateway_AbstractSepaRecurri
27
  */
28
  public function getDefaultTitle ()
29
  {
30
- return __('Bancontact / Mister Cash', 'mollie-payments-for-woocommerce');
31
  }
32
 
33
  /**
27
  */
28
  public function getDefaultTitle ()
29
  {
30
+ return __('Bancontact', 'mollie-payments-for-woocommerce');
31
  }
32
 
33
  /**
includes/mollie/wc/helper/data.php CHANGED
@@ -570,16 +570,37 @@ class Mollie_WC_Helper_Data
570
  } else {
571
  $customer = new WC_Customer( $user_id );
572
  $customer_id = $customer->get_meta( 'mollie_customer_id' );
573
- }
574
 
575
- // Check that customer ID is valid for this API key
576
- try {
577
- $this->api_helper->getApiClient( $test_mode )->customers->get( $customer_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  }
579
- catch ( Exception $e ) {
580
- Mollie_WC_Plugin::debug( __FUNCTION__ . ": Mollie Customer ID " . $customer_id . " not valid for this API key, try to create a new one (" . ( $test_mode ? 'test' : 'live' ) . ")." );
581
- $customer_id = '';
582
 
 
 
 
 
 
 
 
 
 
 
583
  }
584
 
585
  // If there is no Mollie Customer ID set, try to create a new Mollie Customer
@@ -608,7 +629,9 @@ class Mollie_WC_Helper_Data
608
 
609
  $customer_id = $customer->id;
610
 
611
- Mollie_WC_Plugin::debug( __FUNCTION__ . ": Created a Mollie Customer for WordPress user with ID $user_id (" . ( $test_mode ? 'test' : 'live' ) . ")." );
 
 
612
 
613
  }
614
  catch (Exception $e)
@@ -617,6 +640,8 @@ class Mollie_WC_Helper_Data
617
  }
618
  }
619
 
 
 
620
  return $customer_id;
621
  }
622
 
570
  } else {
571
  $customer = new WC_Customer( $user_id );
572
  $customer_id = $customer->get_meta( 'mollie_customer_id' );
 
573
 
574
+ // If there is no Mollie Customer ID set, check the most recent active subscription
575
+ if ( empty( $customer_id ) ) {
576
+
577
+ $customer_latest_subscription = wc_get_orders( array (
578
+ 'limit' => 1,
579
+ 'customer' => $user_id,
580
+ 'type' => 'shop_subscription',
581
+ 'status' => 'wc-active',
582
+ ) );
583
+
584
+ if ( ! empty( $customer_latest_subscription ) ) {
585
+ $customer_id = get_post_meta( $customer_latest_subscription[0]->get_id(), '_mollie_customer_id', $single = true );
586
+
587
+ // Store this customer ID as user meta too
588
+ $this->setUserMollieCustomerId( $user_id, $customer_id );
589
+ }
590
+
591
+ }
592
  }
 
 
 
593
 
594
+ // If there is a Mollie Customer ID set, check that customer ID is valid for this API key
595
+ if ( ! empty( $customer_id ) ) {
596
+
597
+ try {
598
+ $this->api_helper->getApiClient( $test_mode )->customers->get( $customer_id );
599
+ }
600
+ catch ( Exception $e ) {
601
+ Mollie_WC_Plugin::debug( __FUNCTION__ . ": Mollie Customer ID ($customer_id) not valid for user $user_id on this API key, try to create a new one (" . ( $test_mode ? 'test' : 'live' ) . ")." );
602
+ $customer_id = '';
603
+ }
604
  }
605
 
606
  // If there is no Mollie Customer ID set, try to create a new Mollie Customer
629
 
630
  $customer_id = $customer->id;
631
 
632
+ Mollie_WC_Plugin::debug( __FUNCTION__ . ": Created a Mollie Customer ($customer_id) for WordPress user with ID $user_id (" . ( $test_mode ? 'test' : 'live' ) . ")." );
633
+
634
+ return $customer_id;
635
 
636
  }
637
  catch (Exception $e)
640
  }
641
  }
642
 
643
+ Mollie_WC_Plugin::debug( __FUNCTION__ . ": Mollie Customer ID ($customer_id) found and valid for user $user_id on this API key. (" . ( $test_mode ? 'test' : 'live' ) . ")." );
644
+
645
  return $customer_id;
646
  }
647
 
includes/mollie/wc/helper/settings.php CHANGED
@@ -376,8 +376,8 @@ class Mollie_WC_Helper_Settings
376
  'title' => __('Order status after cancelled payment', 'mollie-payments-for-woocommerce'),
377
  'type' => 'select',
378
  'options' => array(
379
- 'pending' => __('Pending', 'mollie-payments-for-woocommerce'),
380
- 'cancelled' => __('Cancelled', 'mollie-payments-for-woocommerce'),
381
  ),
382
  'desc' => __('Status for orders when a payment is cancelled. Default: pending. Orders with status Pending can be paid with another payment method, customers can try again. Cancelled orders are final. Set this to Cancelled if you only have one payment method or don\'t want customers to re-try paying with a different payment method.', 'mollie-payments-for-woocommerce'),
383
  'default' => 'pending',
376
  'title' => __('Order status after cancelled payment', 'mollie-payments-for-woocommerce'),
377
  'type' => 'select',
378
  'options' => array(
379
+ 'pending' => __('Pending', 'woocommerce'),
380
+ 'cancelled' => __('Cancelled', 'woocommerce'),
381
  ),
382
  'desc' => __('Status for orders when a payment is cancelled. Default: pending. Orders with status Pending can be paid with another payment method, customers can try again. Cancelled orders are final. Set this to Cancelled if you only have one payment method or don\'t want customers to re-try paying with a different payment method.', 'mollie-payments-for-woocommerce'),
383
  'default' => 'pending',
includes/mollie/wc/plugin.php CHANGED
@@ -7,7 +7,7 @@ class Mollie_WC_Plugin
7
  {
8
  const PLUGIN_ID = 'mollie-payments-for-woocommerce';
9
  const PLUGIN_TITLE = 'Mollie Payments for WooCommerce';
10
- const PLUGIN_VERSION = '2.9.0';
11
 
12
  const DB_VERSION = '1.0';
13
  const DB_VERSION_PARAM_NAME = 'mollie-db-version';
@@ -188,12 +188,18 @@ class Mollie_WC_Plugin
188
  // Listen to return URL call
189
  add_action( 'woocommerce_api_mollie_return', array ( __CLASS__, 'onMollieReturn' ) );
190
 
191
- // On order details
192
  add_action( 'woocommerce_order_details_after_order_table', array ( __CLASS__, 'onOrderDetails' ), 10, 1 );
193
 
194
-
195
  add_filter( 'woocommerce_available_payment_gateways', array ( __CLASS__, 'disableSEPAInCheckout' ), 10, 1 );
196
 
 
 
 
 
 
 
197
  self::initDb();
198
  self::schedulePendingPaymentOrdersExpirationCheck();
199
  // Mark plugin initiated
@@ -509,5 +515,60 @@ class Mollie_WC_Plugin
509
  return $available_gateways;
510
  }
511
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
  }
513
 
7
  {
8
  const PLUGIN_ID = 'mollie-payments-for-woocommerce';
9
  const PLUGIN_TITLE = 'Mollie Payments for WooCommerce';
10
+ const PLUGIN_VERSION = '3.0.0';
11
 
12
  const DB_VERSION = '1.0';
13
  const DB_VERSION_PARAM_NAME = 'mollie-db-version';
188
  // Listen to return URL call
189
  add_action( 'woocommerce_api_mollie_return', array ( __CLASS__, 'onMollieReturn' ) );
190
 
191
+ // Show Mollie instructions on order details page
192
  add_action( 'woocommerce_order_details_after_order_table', array ( __CLASS__, 'onOrderDetails' ), 10, 1 );
193
 
194
+ // Disable SEPA as payment option in WooCommerce checkout
195
  add_filter( 'woocommerce_available_payment_gateways', array ( __CLASS__, 'disableSEPAInCheckout' ), 10, 1 );
196
 
197
+ // Disable Mollie methods on some pages
198
+ add_filter( 'woocommerce_available_payment_gateways', array ( __CLASS__, 'disableMollieOnPaymentMethodChange' ), 10, 1 );
199
+
200
+ // Set order to paid and processed when eventually completed without Mollie
201
+ add_action( 'woocommerce_payment_complete', array ( __CLASS__, 'setOrderPaidByOtherGateway' ), 10, 1 );
202
+
203
  self::initDb();
204
  self::schedulePendingPaymentOrdersExpirationCheck();
205
  // Mark plugin initiated
515
  return $available_gateways;
516
  }
517
 
518
+ /**
519
+ * Don't show Mollie Payment Methods in WooCommerce Account > Subscriptions
520
+ */
521
+ public static function disableMollieOnPaymentMethodChange( $available_gateways ) {
522
+
523
+ // Can't use $wp->request or is_wc_endpoint_url() to check if this code only runs on /subscriptions and /view-subscriptions,
524
+ // because slugs/endpoints can be translated (with WPML) and other plugins.
525
+ // So disabling on is_account_page and $_GET['change_payment_method'] for now.
526
+
527
+ if ( is_account_page() || ! empty( $_GET['change_payment_method'] ) ) {
528
+ foreach ( $available_gateways as $key => $value ) {
529
+ if ( strpos( $key, 'mollie_' ) !== false ) {
530
+ unset( $available_gateways[ $key ] );
531
+ }
532
+ }
533
+
534
+ }
535
+
536
+ return $available_gateways;
537
+ }
538
+
539
+ /**
540
+ * If an order is paid with another payment method (gateway) after a first payment was
541
+ * placed with Mollie, set a flag, so status updates (like expired) aren't processed by
542
+ * Mollie Payments for WooCommerce.
543
+ */
544
+ public static function setOrderPaidByOtherGateway( $order_id ) {
545
+
546
+ $order = wc_get_order( $order_id );
547
+
548
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
549
+
550
+ $mollie_payment_id = get_post_meta( $order_id, '_mollie_payment_id', $single = true );
551
+ $order_payment_method = get_post_meta( $order_id, '_payment_method', $single = true );
552
+
553
+ if ( $mollie_payment_id !== '' && ( strpos( $order_payment_method, 'mollie' ) === false ) ) {
554
+ update_post_meta( $order->id, '_mollie_paid_by_other_gateway', '1' );
555
+ }
556
+
557
+ } else {
558
+
559
+ $mollie_payment_id = $order->get_meta( '_mollie_payment_id', $single = true );
560
+ $order_payment_method = $order->get_payment_method();
561
+
562
+ if ( $mollie_payment_id !== '' && ( strpos( $order_payment_method, 'mollie' ) === false ) ) {
563
+
564
+ $order->update_meta_data( '_mollie_paid_by_other_gateway', '1' );
565
+ $order->save();
566
+ }
567
+ }
568
+
569
+ return true;
570
+
571
+ }
572
+
573
  }
574
 
mollie-payments-for-woocommerce.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
  /**
3
  * Plugin Name: Mollie Payments for WooCommerce
4
- * Plugin URI: https://github.com/mollie/WooCommerce
5
  * Description: Accept payments in WooCommerce with the official Mollie plugin
6
- * Version: 2.9.0
7
  * Author: Mollie
8
  * Author URI: https://www.mollie.com
9
  * Requires at least: 3.8
1
  <?php
2
  /**
3
  * Plugin Name: Mollie Payments for WooCommerce
4
+ * Plugin URI: https://www.mollie.com
5
  * Description: Accept payments in WooCommerce with the official Mollie plugin
6
+ * Version: 3.0.0
7
  * Author: Mollie
8
  * Author URI: https://www.mollie.com
9
  * Requires at least: 3.8
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: mollie, payments, woocommerce, payment gateway, e-commerce, credit card, i
4
  Requires at least: 3.8
5
  Tested up to: 4.9
6
  Requires PHP: 5.3
7
- Stable tag: 2.9.0
8
  Requires PHP: 5.3
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -164,6 +164,24 @@ Automatic updates should work like a charm; as always though, ensure you backup
164
 
165
  == Changelog ==
166
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  = 2.9.0 - 13/02/2018 =
168
 
169
  * New - Added support for new payment method: [ING Home'Pay](https://www.mollie.com/en/payments/ing-homepay)
@@ -307,7 +325,7 @@ WooCommerce -> Settings -> Checkout -> Mollie - Bank Transfer.
307
 
308
  = 2.0.1 - 02/10/2015 =
309
  * Add support for SEPA Direct Debit.
310
- * Add message for Belfius, Bitcoin, Bancontact/Mister Cash and paysafecard when the payment is paid successfully.
311
 
312
  = 2.0.0 - 17/08/2015 =
313
  * Complete rewrite of our WooCommerce plugin to better follow WordPress and WooCommerce standards and add better support for other plugins.
4
  Requires at least: 3.8
5
  Tested up to: 4.9
6
  Requires PHP: 5.3
7
+ Stable tag: 3.0.0
8
  Requires PHP: 5.3
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
164
 
165
  == Changelog ==
166
 
167
+ = 3.0.0 - 17/04/2018 =
168
+
169
+ * New - WooCommerce Subscriptions: add support for 'subscription_payment_method_change', shop-customers can change payment method if renewal payment fails (SEPA incasso, credit card)
170
+ * New - WooCommerce Subscriptions: disable Mollie payment methods on shop-customer's my account page for "Payment method change", keep it enabled for "Pay now" link in emails
171
+ * New - WooCommerce Subscriptions: improve handling and update messages and notices for Subscription switch to better explain what's happening
172
+ * New - WooCommerce Subscriptions: set renewal orders and subscriptions to 'On-Hold' if renewal payment fails
173
+
174
+ * Fix - Fallback for getUserMollieCustomerId, get Mollie Customer ID from recent subscription if it's empty in WordPress user meta
175
+ * Fix - Improve support for Polylang option "Hide URL language information for default language" in webhook and return URLs,
176
+ * Fix - Only check if customer ID is valid on current API key if there is a customer ID (not empty)(and improve log messages)
177
+ * Fix - Make sure payment instructions (Bank Transfer) are styled the same as WooCommerce content (Order received, payment pending)
178
+ * Fix - Don't update/process/expire Mollie payments on WooCommerce orders that have been paid with other payment gateways
179
+ * Fix - Updated text strings for Bancontact/Mister Cash to just Bancontact
180
+ * Fix - Use the exact same translation as WooCommerce for order statuses
181
+ * Fix - Resolve error (fatal error get_payment_method()) that occurred when users made certain custom changes to the WooCommerce template files
182
+ * Fix - Add order note and log message when customer returns to the site but payment is open/pending
183
+ * Fix - Improved order note for charged back renewal payments
184
+
185
  = 2.9.0 - 13/02/2018 =
186
 
187
  * New - Added support for new payment method: [ING Home'Pay](https://www.mollie.com/en/payments/ing-homepay)
325
 
326
  = 2.0.1 - 02/10/2015 =
327
  * Add support for SEPA Direct Debit.
328
+ * Add message for Belfius, Bitcoin, Bancontact and paysafecard when the payment is paid successfully.
329
 
330
  = 2.0.0 - 17/08/2015 =
331
  * Complete rewrite of our WooCommerce plugin to better follow WordPress and WooCommerce standards and add better support for other plugins.