diff --git a/payment/uc_payment/lib/Drupal/uc_payment/Form/PaymentMethodsForm.php b/payment/uc_payment/lib/Drupal/uc_payment/Form/PaymentMethodsForm.php
index b41ae65..e208cae 100644
--- a/payment/uc_payment/lib/Drupal/uc_payment/Form/PaymentMethodsForm.php
+++ b/payment/uc_payment/lib/Drupal/uc_payment/Form/PaymentMethodsForm.php
@@ -106,9 +106,18 @@ class PaymentMethodsForm extends ConfigFormBase {
       }
 
       $links = array();
-      $null = NULL;
-      $method_settings = $method['callback']('settings', $null, array(), $form_state);
-      if (is_array($method_settings)) {
+
+      if (!isset($method['configurable'])) {
+        // Determine whether a legacy plugin has a valid settings form.
+        $method_settings = $this->paymentMethodManager->createInstance($id)->settingsForm(array(), $form_state);
+        if (is_array($method_settings)) {
+          $links['settings'] = array(
+            'title' => t('Settings'),
+            'href' => 'admin/store/settings/payment/method/' . $id,
+          );
+        }
+      }
+      elseif ($method['configurable']) {
         $links['settings'] = array(
           'title' => t('Settings'),
           'href' => 'admin/store/settings/payment/method/' . $id,
diff --git a/payment/uc_payment/lib/Drupal/uc_payment/PaymentMethodPluginBase.php b/payment/uc_payment/lib/Drupal/uc_payment/PaymentMethodPluginBase.php
index 5edfdab..2cb21e3 100644
--- a/payment/uc_payment/lib/Drupal/uc_payment/PaymentMethodPluginBase.php
+++ b/payment/uc_payment/lib/Drupal/uc_payment/PaymentMethodPluginBase.php
@@ -8,17 +8,98 @@
 namespace Drupal\uc_payment;
 
 use Drupal\Core\Plugin\PluginBase;
+use Drupal\uc_order\UcOrderInterface;
 
 /**
  * Defines a base payment method plugin implementation.
  */
 abstract class PaymentMethodPluginBase extends PluginBase implements PaymentMethodPluginInterface {
 
- /**
+  /**
    * {@inheritdoc}
    */
-  function cartReviewTitle() {
+  public function cartDetails(UcOrderInterface $order, array $form, array &$form_state) {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function cartProcess(UcOrderInterface $order, array $form, array &$form_state) {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function cartReviewTitle() {
     return !empty($this->pluginDefinition['review']) ? $this->pluginDefinition['review'] : $this->pluginDefinition['name'];
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function cartReview(UcOrderInterface $order) {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderDelete(UcOrderInterface $order) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderEditDetails(UcOrderInterface $order) {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderEditProcess(UcOrderInterface $order, array $form, array $form_state) {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderLoad(UcOrderInterface $order) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderSave(UcOrderInterface $order) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderSubmit(UcOrderInterface $order) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderView(UcOrderInterface $order) {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function customerView(UcOrderInterface $order) {
+    return $this->orderView($order);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    return array();
+  }
+
 }
diff --git a/payment/uc_payment/lib/Drupal/uc_payment/Plugin/Ubercart/PaymentMethod/FreeOrder.php b/payment/uc_payment/lib/Drupal/uc_payment/Plugin/Ubercart/PaymentMethod/FreeOrder.php
new file mode 100644
index 0000000..c179416
--- /dev/null
+++ b/payment/uc_payment/lib/Drupal/uc_payment/Plugin/Ubercart/PaymentMethod/FreeOrder.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\uc_payment\Plugin\Ubercart\PaymentMethod\FreeOrder.
+ */
+
+namespace Drupal\uc_payment\Plugin\Ubercart\PaymentMethod;
+
+use Drupal\uc_order\UcOrderInterface;
+use Drupal\uc_payment\PaymentMethodPluginBase;
+
+/**
+ * Defines a free order payment method.
+ *
+ * @Plugin(
+ *   id = "free_order",
+ *   name = @Translation("Free order"),
+ *   title = @Translation("No payment required"),
+ *   description = @Translation("Allow customers with free orders to check out without paying."),
+ *   checkout = TRUE,
+ *   no_gateway = TRUE,
+ *   configurable = FALSE,
+ *   weight = 0,
+ * )
+ */
+class FreeOrder extends PaymentMethodPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function cartDetails(UcOrderInterface $order, array $form, array &$form_state) {
+    return array(
+      '#markup' => t('Continue with checkout to complete your order.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function orderSubmit(UcOrderInterface $order) {
+    if ($order->getTotal() >= 0.01) {
+      return array(array(
+        'pass' => FALSE,
+        'message' => t('We cannot process your order without payment.'),
+      ));
+    }
+
+    uc_payment_enter($order->id(), 'free_order', 0, 0, NULL, t('Checkout completed for a free order.'));
+  }
+
+}
diff --git a/payment/uc_payment/lib/Drupal/uc_payment/Tests/PaymentPaneTest.php b/payment/uc_payment/lib/Drupal/uc_payment/Tests/PaymentPaneTest.php
index 060ec52..f2a0274 100644
--- a/payment/uc_payment/lib/Drupal/uc_payment/Tests/PaymentPaneTest.php
+++ b/payment/uc_payment/lib/Drupal/uc_payment/Tests/PaymentPaneTest.php
@@ -99,6 +99,7 @@ class PaymentPaneTest extends UbercartTestBase {
     $this->drupalGet('cart/checkout');
     $this->assertNoText('Check or money order');
     $this->assertText('No payment required');
+    $this->assertText('Continue with checkout to complete your order.');
     $this->assertText('Subtotal: $0.00');
 
     // Check that this is the only available payment method.
diff --git a/payment/uc_payment/uc_payment.module b/payment/uc_payment/uc_payment.module
index 3b0d8c3..5ac4241 100644
--- a/payment/uc_payment/uc_payment.module
+++ b/payment/uc_payment/uc_payment.module
@@ -175,23 +175,6 @@ function uc_payment_uc_order_state() {
 }
 
 /**
- * Implements hook_uc_payment_method().
- */
-function uc_payment_uc_payment_method() {
-  $methods['free_order'] = array(
-    'name' => t('Free order'),
-    'title' => t('No payment required'),
-    'desc' => t('Allow customers with !zero order totals to checkout without paying.', array('!zero' => uc_currency_format(0))),
-    'callback' => 'uc_payment_method_free_order',
-    'checkout' => TRUE,
-    'no_gateway' => TRUE,
-    'weight' => 0,
-  );
-
-  return $methods;
-}
-
-/**
  * Implements hook_uc_payment_method_checkout_alter().
  */
 function uc_payment_uc_payment_method_checkout_alter(&$methods, $order) {
@@ -212,30 +195,6 @@ function uc_payment_uc_payment_method_checkout_alter(&$methods, $order) {
 }
 
 /**
- * Payment method callback for free orders.
- *
- * @see uc_payment_uc_payment_method()
- */
-function uc_payment_method_free_order($op, &$order) {
-  switch ($op) {
-    case 'cart-details':
-      return array(
-        '#markup' => t('Continue with checkout to complete your order.'),
-      );
-
-    case 'order-submit':
-      if ($order->getTotal() >= 0.01) {
-        return array(array(
-          'pass' => FALSE,
-          'message' => t('We cannot process your order without payment.'),
-        ));
-      }
-
-      uc_payment_enter($order->id(), 'free_order', 0, 0, NULL, t('Checkout completed for a free order.'));
-  }
-}
-
-/**
  * Processes a payment through an enabled payment gateway.
  *
  * @param $method
