diff --git a/payment/uc_payment/lib/Drupal/uc_payment/Plugin/Ubercart/CheckoutPane/PaymentMethodPane.php b/payment/uc_payment/lib/Drupal/uc_payment/Plugin/Ubercart/CheckoutPane/PaymentMethodPane.php
index d4b83cf..87ecf3a 100644
--- a/payment/uc_payment/lib/Drupal/uc_payment/Plugin/Ubercart/CheckoutPane/PaymentMethodPane.php
+++ b/payment/uc_payment/lib/Drupal/uc_payment/Plugin/Ubercart/CheckoutPane/PaymentMethodPane.php
@@ -65,7 +65,7 @@ class PaymentMethodPane extends CheckoutPanePluginBase implements ContainerFacto
   public function view(UcOrderInterface $order, array $form, array &$form_state) {
     $contents['#attached']['css'][] = drupal_get_path('module', 'uc_payment') . '/css/uc_payment.css';
 
-    if (variable_get('uc_payment_show_order_total_preview', TRUE)) {
+    if ($this->configuration['show_preview']) {
       $contents['line_items'] = array(
         '#theme' => 'uc_payment_totals',
         '#order' => $order,
@@ -175,15 +175,24 @@ class PaymentMethodPane extends CheckoutPanePluginBase implements ContainerFacto
    * {@inheritdoc}
    */
   public function settingsForm() {
-    $form['uc_payment_show_order_total_preview'] = array(
+    $form['show_preview'] = array(
       '#type' => 'checkbox',
       '#title' => t('Show the order total preview on the payment pane.'),
-      '#default_value' => variable_get('uc_payment_show_order_total_preview', TRUE),
+      '#default_value' => $this->configuration['show_preview'],
     );
     return $form;
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return array(
+      'show_preview' => TRUE,
+    );
+  }
+
+  /**
    * Ajax callback to re-render the payment method pane.
    */
   function ajaxRender($form, &$form_state) {
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 f2a0274..133d9f0 100644
--- a/payment/uc_payment/lib/Drupal/uc_payment/Tests/PaymentPaneTest.php
+++ b/payment/uc_payment/lib/Drupal/uc_payment/Tests/PaymentPaneTest.php
@@ -62,11 +62,17 @@ class PaymentPaneTest extends UbercartTestBase {
    * Tests operation of uc_payment_show_order_total_preview variable.
    */
   public function testOrderTotalPreview() {
-    variable_set('uc_payment_show_order_total_preview', TRUE);
+    $edit = array(
+      'panes[payment][settings][show_preview]' => TRUE,
+    );
+    $this->drupalPostForm('admin/store/settings/checkout', $edit, 'Save configuration');
     $this->drupalGet('cart/checkout');
     $this->assertText('Order total:');
 
-    variable_set('uc_payment_show_order_total_preview', FALSE);
+    $edit = array(
+      'panes[payment][settings][show_preview]' => FALSE,
+    );
+    $this->drupalPostForm('admin/store/settings/checkout', $edit, 'Save configuration');
     $this->drupalGet('cart/checkout');
     $this->assertNoText('Order total:');
   }
diff --git a/uc_cart/config/uc_cart.settings.yml b/uc_cart/config/uc_cart.settings.yml
index a52e704..ca6492d 100644
--- a/uc_cart/config/uc_cart.settings.yml
+++ b/uc_cart/config/uc_cart.settings.yml
@@ -35,4 +35,3 @@ checkout_complete_page: ''
 checkout_enabled: true
 
 delivery_not_shippable: true
-new_account_details: '<b>Optional.</b> New customers may supply custom account details.<br />We will create these for you if no values are entered.'
diff --git a/uc_cart/lib/Drupal/uc_cart/CheckoutPanePluginBase.php b/uc_cart/lib/Drupal/uc_cart/CheckoutPanePluginBase.php
index c617918..1e3deee 100644
--- a/uc_cart/lib/Drupal/uc_cart/CheckoutPanePluginBase.php
+++ b/uc_cart/lib/Drupal/uc_cart/CheckoutPanePluginBase.php
@@ -16,6 +16,76 @@ use Drupal\uc_order\UcOrderInterface;
 abstract class CheckoutPanePluginBase extends PluginBase implements CheckoutPanePluginInterface {
 
   /**
+   * Whether the pane is enabled or not.
+   *
+   * @var bool
+   */
+  protected $status = TRUE;
+
+  /**
+   * The weight of the checkout pane.
+   *
+   * @var int|string
+   */
+  protected $weight = '';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isEnabled() {
+    return $this->status;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getWeight() {
+    return $this->weight;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->setConfiguration($configuration);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfiguration() {
+    return array(
+      'status' => $this->isEnabled(),
+      'weight' => $this->getWeight(),
+      'settings' => $this->configuration,
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setConfiguration(array $configuration) {
+    $configuration += array(
+      'status' => $this->pluginDefinition['status'],
+      'weight' => $this->pluginDefinition['weight'],
+      'settings' => array(),
+    );
+    $this->status = $configuration['status'];
+    $this->weight = $configuration['weight'];
+    $this->configuration = $configuration['settings'] + $this->defaultConfiguration();
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return array();
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function prepare(UcOrderInterface $order, array $form, array &$form_state) {
diff --git a/uc_cart/lib/Drupal/uc_cart/CheckoutPanePluginInterface.php b/uc_cart/lib/Drupal/uc_cart/CheckoutPanePluginInterface.php
index 743ebbf..4f01d8e 100644
--- a/uc_cart/lib/Drupal/uc_cart/CheckoutPanePluginInterface.php
+++ b/uc_cart/lib/Drupal/uc_cart/CheckoutPanePluginInterface.php
@@ -7,13 +7,14 @@
 
 namespace Drupal\uc_cart;
 
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
 use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\uc_order\UcOrderInterface;
 
 /**
  * Defines an interface for checkout pane plugins.
  */
-interface CheckoutPanePluginInterface extends PluginInspectionInterface {
+interface CheckoutPanePluginInterface extends PluginInspectionInterface, ConfigurablePluginInterface {
 
   /**
    * Prepares a pane for display.
@@ -84,4 +85,19 @@ interface CheckoutPanePluginInterface extends PluginInspectionInterface {
    */
   public function getTitle();
 
+  /**
+   * Returns whether the checkout pane is enabled.
+   *
+   * @return bool
+   *   TRUE if the pane is enabled, FALSE otherwise.
+   */
+  public function isEnabled();
+
+  /**
+   * Returns the weight of the checkout pane.
+   *
+   * @return int
+   *   The integer weight of the checkout pane.
+   */
+  public function getWeight();
 }
diff --git a/uc_cart/lib/Drupal/uc_cart/Controller/CheckoutController.php b/uc_cart/lib/Drupal/uc_cart/Controller/CheckoutController.php
index babbfff..cc5870c 100644
--- a/uc_cart/lib/Drupal/uc_cart/Controller/CheckoutController.php
+++ b/uc_cart/lib/Drupal/uc_cart/Controller/CheckoutController.php
@@ -175,7 +175,7 @@ class CheckoutController extends ControllerBase implements ContainerInjectionInt
       $filter['shippable'] = TRUE;
     }
 
-    $panes = $this->checkoutPaneManager->createInstances($filter);
+    $panes = $this->checkoutPaneManager->getPanes($filter);
     foreach ($panes as $pane) {
       $return = $pane->review($order);
       if (!is_null($return)) {
diff --git a/uc_cart/lib/Drupal/uc_cart/Form/CheckoutForm.php b/uc_cart/lib/Drupal/uc_cart/Form/CheckoutForm.php
index aecad37..b6ae2f1 100644
--- a/uc_cart/lib/Drupal/uc_cart/Form/CheckoutForm.php
+++ b/uc_cart/lib/Drupal/uc_cart/Form/CheckoutForm.php
@@ -71,7 +71,7 @@ class CheckoutForm extends FormBase {
       $filter['shippable'] = TRUE;
     }
 
-    $panes = $this->checkoutPaneManager->createInstances($filter);
+    $panes = $this->checkoutPaneManager->getPanes($filter);
 
     // Invoke the 'prepare' op of enabled panes, but only if their 'process' ops
     // have not been invoked on this request (i.e. when rebuilding after AJAX).
diff --git a/uc_cart/lib/Drupal/uc_cart/Form/CheckoutSettingsForm.php b/uc_cart/lib/Drupal/uc_cart/Form/CheckoutSettingsForm.php
index c1a16fd..ab30eb1 100644
--- a/uc_cart/lib/Drupal/uc_cart/Form/CheckoutSettingsForm.php
+++ b/uc_cart/lib/Drupal/uc_cart/Form/CheckoutSettingsForm.php
@@ -75,6 +75,7 @@ class CheckoutSettingsForm extends ConfigFormBase {
       '#type' => 'details',
       '#title' => t('Basic settings'),
       '#group' => 'checkout-settings',
+      '#weight' => -10,
     );
     $form['checkout']['uc_checkout_enabled'] = array(
       '#type' => 'checkbox',
@@ -100,6 +101,7 @@ class CheckoutSettingsForm extends ConfigFormBase {
       '#type' => 'details',
       '#title' => t('Anonymous checkout'),
       '#group' => 'checkout-settings',
+      '#weight' => -5,
     );
     $form['anonymous']['uc_checkout_anonymous'] = array(
       '#type' => 'checkbox',
@@ -153,7 +155,7 @@ class CheckoutSettingsForm extends ConfigFormBase {
       '#states' => $anon_state,
     );
 
-    $panes = $this->checkoutPaneManager->getDefinitions();
+    $panes = $this->checkoutPaneManager->getPanes();
     $form['checkout']['panes'] = array(
       '#type' => 'table',
       '#header' => array(t('Pane'), t('List position')),
@@ -165,30 +167,33 @@ class CheckoutSettingsForm extends ConfigFormBase {
         ),
       ),
     );
+    $form['checkout']['pane_settings']['#tree'] = TRUE;
     foreach ($panes as $id => $pane) {
       $form['checkout']['panes'][$id]['#attributes']['class'][] = 'draggable';
       $form['checkout']['panes'][$id]['status'] = array(
         '#type' => 'checkbox',
-        '#title' => check_plain($pane['title']),
-        '#default_value' => $pane['enabled'],
+        '#title' => check_plain($pane->getTitle()),
+        '#default_value' => $pane->isEnabled(),
       );
       $form['checkout']['panes'][$id]['weight'] = array(
         '#type' => 'weight',
-        '#title' => t('Weight for @title', array('@title' => $pane['title'])),
+        '#title' => t('Weight for @title', array('@title' => $pane->getTitle())),
         '#title_display' => 'invisible',
-        '#default_value' => $pane['weight'],
+        '#default_value' => $pane->getWeight(),
         '#attributes' => array(
           'class' => array('uc-checkout-pane-weight'),
         ),
       );
-      $form['checkout']['panes'][$id]['#weight'] = $pane['weight'];
+      $form['checkout']['panes'][$id]['#weight'] = $pane->getWeight();
 
-      $pane_settings = $this->checkoutPaneManager->createInstance($id)->settingsForm();
+      // @todo Move settingsForm to an interface.
+      $pane_settings = $pane->settingsForm();
       if (!empty($pane_settings)) {
-        $form['pane_' . $id] = $pane_settings + array(
+        $form['checkout']['pane_settings'][$id] = $pane_settings + array(
           '#type' => 'details',
-          '#title' => t('@pane pane', array('@pane' => $pane['title'])),
+          '#title' => t('@pane pane', array('@pane' => $pane->getTitle())),
           '#group' => 'checkout-settings',
+          '#parents' => array('panes', $id, 'settings'),
         );
       }
     }
@@ -284,11 +289,8 @@ class CheckoutSettingsForm extends ConfigFormBase {
       ->set('default_same_address', $form_state['values']['uc_cart_default_same_address'])
       ->set('delivery_not_shippable', $form_state['values']['uc_cart_delivery_not_shippable'])
       ->set('checkout_complete_page', $form_state['values']['uc_cart_checkout_complete_page'])
-      ->set('panes', $form_state['values']['panes']);
-
-    // @todo Handle (or remove) per-pane settings.
-
-    $cart_config->save();
+      ->set('panes', $form_state['values']['panes'])
+      ->save();
 
     \Drupal::config('uc_cart.messages')
       ->set('logged_in', $form_state['values']['uc_msg_order_logged_in'])
@@ -297,8 +299,6 @@ class CheckoutSettingsForm extends ConfigFormBase {
       ->set('new_user_logged_in', $form_state['values']['uc_msg_order_new_user_logged_in'])
       ->save();
 
-    $this->checkoutPaneManager->clearCachedDefinitions();
-
     parent::submitForm($form, $form_state);
   }
 
diff --git a/uc_cart/lib/Drupal/uc_cart/Plugin/CheckoutPaneManager.php b/uc_cart/lib/Drupal/uc_cart/Plugin/CheckoutPaneManager.php
index 96af4a0..df78ae0 100644
--- a/uc_cart/lib/Drupal/uc_cart/Plugin/CheckoutPaneManager.php
+++ b/uc_cart/lib/Drupal/uc_cart/Plugin/CheckoutPaneManager.php
@@ -29,7 +29,7 @@ class CheckoutPaneManager extends DefaultPluginManager {
    * {@inheritdoc}
    */
   protected $defaults = array(
-    'enabled' => TRUE,
+    'status' => TRUE,
     'weight' => 0,
   );
 
@@ -66,12 +66,16 @@ class CheckoutPaneManager extends DefaultPluginManager {
    * @return array
    *   An array of checkout pane plugin instances.
    */
-  public function createInstances($filter = array()) {
+  public function getPanes($filter = array()) {
     $definitions = $this->getDefinitions($filter);
 
     $instances = array();
     foreach (array_keys($definitions) as $id) {
-      $instances[$id] = $this->createInstance($id);
+      $configuration = $this->paneConfig[$id] ?: array();
+      $instance = $this->createInstance($id, $configuration);
+      if (!isset($filter['enabled']) || $filter['enabled'] != $instance->isEnabled()) {
+        $instances[$id] = $instance;
+      }
     }
     return $instances;
   }
@@ -101,18 +105,4 @@ class CheckoutPaneManager extends DefaultPluginManager {
     return $panes;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function processDefinition(&$definition, $plugin_id) {
-    parent::processDefinition($definition, $plugin_id);
-
-    if (isset($this->paneConfig[$plugin_id]['status'])) {
-      $definition['enabled'] = $this->paneConfig[$plugin_id]['status'];
-    }
-    if (isset($this->paneConfig[$plugin_id]['weight'])) {
-      $definition['weight'] = $this->paneConfig[$plugin_id]['weight'];
-    }
-  }
-
 }
diff --git a/uc_cart/lib/Drupal/uc_cart/Plugin/Ubercart/CheckoutPane/CustomerInfoPane.php b/uc_cart/lib/Drupal/uc_cart/Plugin/Ubercart/CheckoutPane/CustomerInfoPane.php
index c5f4e48..42e8870 100644
--- a/uc_cart/lib/Drupal/uc_cart/Plugin/Ubercart/CheckoutPane/CustomerInfoPane.php
+++ b/uc_cart/lib/Drupal/uc_cart/Plugin/Ubercart/CheckoutPane/CustomerInfoPane.php
@@ -88,7 +88,7 @@ class CustomerInfoPane extends CheckoutPanePluginBase {
         $array = array(
           '#type' => 'details',
           '#title' => t('New account details'),
-          '#description' => $cart_config->get('new_account_details', t('<b>Optional.</b> New customers may supply custom account details.<br />We will create these for you if no values are entered.')),
+          '#description' => $this->configuration['new_account_details'],
           '#collapsible' => FALSE,
         );
         $contents['new_account'] = array_merge($array, $contents['new_account']);
@@ -174,14 +174,23 @@ class CustomerInfoPane extends CheckoutPanePluginBase {
   public function settingsForm() {
     $cart_config = \Drupal::config('uc_cart.settings');
 
-    $form['uc_cart_new_account_details'] = array(
+    $form['new_account_details'] = array(
       '#type' => 'textarea',
       '#title' => t('New account details help message'),
       '#description' => t('Enter the help message displayed in the new account details fieldset when shown.'),
-      '#default_value' => $cart_config->get('new_account_details', t('<b>Optional.</b> New customers may supply custom account details.<br />We will create these for you if no values are entered.')),
+      '#default_value' => $this->configuration['new_account_details'],
     );
 
     return $form;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return array(
+      'new_account_details' => t('<b>Optional.</b> New customers may supply custom account details.<br />We will create these for you if no values are entered.'),
+    );
+  }
+
 }
