diff --git a/payment/src/Annotations/PaymentMethod.php b/payment/src/Annotations/PaymentMethod.php
index c61adc4..538e5fe 100644
--- a/payment/src/Annotations/PaymentMethod.php
+++ b/payment/src/Annotations/PaymentMethod.php
@@ -28,6 +28,17 @@ class PaymentMethod extends Plugin {
   public $active = TRUE;
 
   /**
+   * Whether executing a payment interferes with the payment type context.
+   *
+   * If payment execution interrupts the context's workflow, this must be TRUE.
+   * An example of an interruption is when the payer must be redirected
+   * off-site.
+   *
+   * @var bool
+   */
+  public $interrupts_payment_type_context = TRUE;
+
+  /**
    * The plugin ID.
    *
    * @var string
diff --git a/payment/src/Plugin/Payment/Method/BasicDeriver.php b/payment/src/Plugin/Payment/Method/BasicDeriver.php
index 85ff2ab..a1e9808 100644
--- a/payment/src/Plugin/Payment/Method/BasicDeriver.php
+++ b/payment/src/Plugin/Payment/Method/BasicDeriver.php
@@ -64,6 +64,7 @@ class BasicDeriver extends DeriverBase implements ContainerDeriverInterface {
         $configuration_plugin = $this->paymentMethodConfigurationManager->createInstance($payment_method->getPluginId(), $payment_method->getPluginConfiguration());
         $this->derivatives[$payment_method->id()] = array(
           'active' => $payment_method->status(),
+          'interrupts_payment_type_context' => FALSE,
           'label' => $configuration_plugin->getBrandLabel() ? $configuration_plugin->getBrandLabel() : $payment_method->label(),
           'message_text' => $configuration_plugin->getMessageText(),
           'message_text_format' => $configuration_plugin->getMessageTextFormat(),
diff --git a/payment/src/Plugin/Payment/MethodSelector/PaymentSelect.php b/payment/src/Plugin/Payment/MethodSelector/PaymentSelect.php
index f9fd2b5..90aaa69 100644
--- a/payment/src/Plugin/Payment/MethodSelector/PaymentSelect.php
+++ b/payment/src/Plugin/Payment/MethodSelector/PaymentSelect.php
@@ -10,6 +10,7 @@ use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface;
+use Drupal\payment\Entity\PaymentInterface;
 use Drupal\payment\Plugin\Payment\Method\PaymentMethodManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -24,6 +25,11 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 class PaymentSelect extends PaymentMethodSelectorBase {
 
   /**
+   * The number of seconds a payment should remain stored.
+   */
+  const KEY_VALUE_TTL = 3600;
+
+  /**
    * The previously selected payment methods.
    *
    * @var \Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface[]
@@ -260,6 +266,41 @@ class PaymentSelect extends PaymentMethodSelectorBase {
   /**
    * Retrieves the element's ID from the form's state.
    *
+   * @param array $element
+   * @param array $form_state
+   *
+   * @return string
+   */
+  protected function getKeyValueKey(array $element, array &$form_state) {
+    return $form_state[$this->getPluginId()][$element['#name']]['key_value_key'];
+  }
+
+  /**
+   * Stores the payment temporarily, so it can be retrieved using the key/value key.
+   *
+   * @param array $element
+   * @param array $form_state
+   * @param \Drupal\payment\Entity\PaymentInterface $payment
+   */
+  protected function setKeyValueData(array $element, array &$form_state, PaymentInterface $payment) {
+    \Drupal::keyValueExpirable('payment.payment_method_selector.payment_select')->setWithExpire($this->getKeyValueKey($element, $form_state), $payment, static::KEY_VALUE_TTL);
+  }
+
+  /**
+   * Retrieves the temporarily stored payment.
+   *
+   * @param array $element
+   * @param array $form_state
+   *
+   * @return \Drupal\payment\Entity\PaymentInterface
+   */
+  protected function getKeyValueData(array $element, array &$form_state) {
+    return \Drupal::keyValueExpirable('payment.payment_method_selector.payment_select')->get($this->getKeyValueKey($element, $form_state));
+  }
+
+  /**
+   * Check if the form's state has been initialized for an element.
+   *
    * @param array $form_state
    *
    * @return string
diff --git a/payment_form/tests/src/Plugin/Field/FieldFormatter/PaymentFormUnitTest.php b/payment_form/tests/src/Plugin/Field/FieldFormatter/PaymentFormUnitTest.php
index 5714c21..89684f7 100644
--- a/payment_form/tests/src/Plugin/Field/FieldFormatter/PaymentFormUnitTest.php
+++ b/payment_form/tests/src/Plugin/Field/FieldFormatter/PaymentFormUnitTest.php
@@ -264,9 +264,8 @@ class PaymentFormUnitTest extends UnitTestCase {
       'token' => $this->randomName(),
     );
 
-    $method = new \ReflectionMethod($this->fieldFormatter, 'viewElementsPostRenderCache');
-    $method->setAccessible(TRUE);
-    $this->assertSame($element, $method->invoke($this->fieldFormatter, $element, $context));
+    $field_formatter = $this->fieldFormatter;
+    $this->assertSame($element, $field_formatter::viewElementsPostRenderCache($element, $context));
   }
 
 }
diff --git a/payment_reference/payment_reference.module b/payment_reference/payment_reference.module
index ace9247..aa5361b 100644
--- a/payment_reference/payment_reference.module
+++ b/payment_reference/payment_reference.module
@@ -29,15 +29,18 @@ function payment_reference_element_info() {
     // The name of the field the element is used for.
     '#field_name' => NULL,
     '#input' => TRUE,
+    // An array with IDs of the payment methods the payer is allowed to pay the
+    // payment with, or NULL to allow all.
+    '#limit_allowed_payment_method_ids' => NULL,
+    // The ID of the payment method selector plugin to use.
     // The ID of the account that must own the payment.
     '#owner_id' => NULL,
-    // Values are arrays with two keys:
-    // - plugin_id: the ID of the line item plugin instance.
-    // - plugin_configuration: the configuration of the line item plugin
-    //   instance.
-    '#payment_line_items_data' => array(),
-    '#payment_currency_code' => '',
+    '#payment_method_selector_id' => NULL,
     '#process' => array(array('Drupal\payment_reference\Element\PaymentReference', 'process')),
+    // The ID of the queue category the element is used for.
+    // The payment that must be made if none are available in the queue yet. It
+    // must be an instance of \Drupal\payment\Entity\PaymentInterface.
+    '#prototype_payment' => NULL,
     '#theme_wrappers' => array('form_element'),
     '#value_callback' => 'payment_reference_element_payment_reference_value',
   );
diff --git a/payment_reference/payment_reference.services.yml b/payment_reference/payment_reference.services.yml
index 405de6c..95d0184 100644
--- a/payment_reference/payment_reference.services.yml
+++ b/payment_reference/payment_reference.services.yml
@@ -1,4 +1,7 @@
 services:
+  payment_reference.factory:
+    class: Drupal\payment_reference\Factory
+    arguments: ['@entity.manager', '@plugin.manager.payment.line_item']
   payment_reference.queue:
     arguments: ['payment_reference', '@database', '@module_handler', '@event_dispatcher', '@plugin.manager.payment.status']
     class: Drupal\payment\Queue
\ No newline at end of file
diff --git a/payment_reference/src/Element/PaymentReference.php b/payment_reference/src/Element/PaymentReference.php
index 261d646..1890081 100644
--- a/payment_reference/src/Element/PaymentReference.php
+++ b/payment_reference/src/Element/PaymentReference.php
@@ -8,6 +8,7 @@
 namespace Drupal\payment_reference\Element;
 
 use Drupal\payment\Entity\Payment;
+use Drupal\payment\Entity\PaymentInterface;
 use Drupal\payment\Payment as PaymentServiceWrapper;
 use Drupal\payment_reference\PaymentReference as PaymentReferenceServiceWrapper;
 
@@ -25,7 +26,7 @@ class PaymentReference {
       throw new \InvalidArgumentException('#bundle must be a string, but ' . gettype($element['#bundle']) . ' was given.');
     }
     if (!is_int($element['#default_value']) && !is_null($element['#default_value'])) {
-      throw new \InvalidArgumentException('The default value must be an integer or NULL, but ' . gettype($element['#default_value']) . ' was given.');
+      throw new \InvalidArgumentException('#default_value must be an integer or NULL, but ' . gettype($element['#default_value']) . ' was given.');
     }
     if (!is_string($element['#entity_type_id'])) {
       throw new \InvalidArgumentException('#entity_type_id must be a string, but ' . gettype($element['#entity_type_id']) . ' was given.');
@@ -33,11 +34,17 @@ class PaymentReference {
     if (!is_string($element['#field_name'])) {
       throw new \InvalidArgumentException('#field_name must be a string, but ' . gettype($element['#field_name']) . ' was given.');
     }
+    if (!is_null($element['#limit_allowed_payment_method_ids']) && !is_array($element['#limit_allowed_payment_method_ids'])) {
+      throw new \InvalidArgumentException('#limit_allowed_payment_method_ids must be an array or NULL, but ' . gettype($element['#limit_allowed_payment_method_ids']) . ' was given.');
+    }
     if (!is_int($element['#owner_id'])) {
       throw new \InvalidArgumentException('The owner ID must be an integer, but ' . gettype($element['#owner_id']) . ' was given.');
     }
-    if (!is_string($element['#payment_currency_code'])) {
-      throw new \InvalidArgumentException('The currency code must be a string, but ' . gettype($element['#payment_currency_code']) . ' was given.');
+    if (!is_string($element['#payment_method_selector_id'])) {
+      throw new \InvalidArgumentException('#payment_method_selector_id must be a string, but ' . gettype($element['#payment_method_selector_id']) . ' was given.');
+    }
+    if (!($element['#prototype_payment'] instanceof PaymentInterface)) {
+      throw new \InvalidArgumentException('#prototype_payment must implement \Drupal\payment\Entity\PaymentInterface.');
     }
 
     // Find the default payment to use.
@@ -65,28 +72,29 @@ class PaymentReference {
       ),
     );
 
-    // Payment information.
-    $element['payment'] = array(
-      '#empty' => \Drupal::translation()->translate('There are no line items.'),
-      '#header' => array(\Drupal::translation()->translate('Amount'), \Drupal::translation()->translate('Status'), \Drupal::translation()->translate('Last updated')),
-      '#type' => 'table',
-    );
+    // There are no queued payments, so display a payment method selection and
+    // configuration form.
     if (!$payment_id) {
-      $amount = 0;
-      foreach ($element['#payment_line_items_data'] as $line_item_data) {
-        $line_item = PaymentServiceWrapper::lineItemManager()->createInstance($line_item_data['plugin_id'], $line_item_data['plugin_configuration']);
-        $amount += $line_item->getTotalAmount();
-      }
-      /** @var \Drupal\currency\Entity\CurrencyInterface $currency */
-      $currency = entity_load('currency', $element['#payment_currency_code']);
-      $element['payment'][0]['amount'] = array(
-        '#markup' => $currency->formatAmount($amount),
+      /** @var \Drupal\payment\Entity\PaymentInterface $payment */
+      $payment = clone $element['#prototype_payment'];
+      $element['line_items'] = array(
+        '#payment' => $payment,
+        '#type' => 'payment_line_items_display',
       );
+      $payment_method_selector = PaymentServiceWrapper::methodSelectorManager()->createInstance($element['#payment_method_selector_id']);
+      $payment_method_selector->setPaymentMethod($payment);
+      if (!is_null($element['#limit_allowed_payment_method_ids'])) {
+        $payment_method_selector->setAllowedPaymentMethods($element['#limit_allowed_payment_method_ids']);
+      }
+      $element['payment_method'] = $payment_method_selector->buildConfigurationForm(array(), $form_state);
+
       $element['payment'][0]['add'] = array(
         '#attributes' => array(
           'colspan' => 2,
         ),
         '#markup' => \Drupal::translation()->translate('<a href="@url" target="_blank">Add a new payment</a> (opens in a new window)', array(
+          // @todo This form element pretends to be implementation-agnostic, but
+          //   it does depend on a Payment Reference route. Fix this.
           '@url' => \Drupal::urlGenerator()->generateFromRoute('payment_reference.pay', array(
               'bundle' => $element['#bundle'],
               'entity_type_id' => $element['#entity_type_id'],
@@ -95,13 +103,18 @@ class PaymentReference {
         )),
       );
     }
+    // There is a queued payment, so display its information.
     else {
       /** @var \Drupal\payment\Entity\PaymentInterface $payment */
       $payment = Payment::load($payment_id);
-      /** @var \Drupal\currency\Entity\CurrencyInterface $currency */
-      $currency = entity_load('currency', $payment->getCurrencyCode());
+      $currency = $payment->getCurrency();
       $status = $payment->getStatus();
       $status_definition = $status->getPluginDefinition();
+      $element['payment'] = array(
+        '#empty' => t('There are no line items.'),
+        '#header' => array(t('Amount'), t('Status'), t('Last updated')),
+        '#type' => 'table',
+      );
       $element['payment'][0]['amount'] = array(
         '#markup' => $currency->formatAmount($payment->getAmount()),
       );
diff --git a/payment_reference/src/Factory.php b/payment_reference/src/Factory.php
new file mode 100644
index 0000000..3b62760
--- /dev/null
+++ b/payment_reference/src/Factory.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment_reference\Factory.
+ */
+
+namespace Drupal\payment_reference;
+
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\field\FieldInstanceConfigInterface;
+use Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface;
+
+/**
+ * Provides a payment factory service.
+ */
+class Factory implements FactoryInterface {
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * The payment line item manager.
+   *
+   * @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface
+   */
+  protected $paymentLineItemManager;
+
+  /**
+   * Constructs a new class instance.
+   *
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   * @param \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface $payment_line_item_manager
+   *   The payment line item manager.
+   */
+  public function __construct(EntityManagerInterface $entity_manager, PaymentLineItemManagerInterface $payment_line_item_manager) {
+    $this->entityManager = $entity_manager;
+    $this->paymentLineItemManager = $payment_line_item_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createPayment(FieldInstanceConfigInterface $field_instance_config) {
+    /** @var \Drupal\payment\Entity\PaymentInterface $payment */
+    $payment = $this->entityManager
+      ->getStorage('payment')
+      ->create(array(
+        'bundle' => 'payment_reference',
+      ));
+    /** @var \Drupal\payment_reference\Plugin\Payment\Type\PaymentReference $payment_type */
+    $payment_type = $payment->getPaymentType();
+    $payment_type->setFieldInstanceConfigId($field_instance_config->id());
+    $payment->setCurrencyCode($field_instance_config->getSetting('currency_code'));
+    foreach ($field_instance_config->getSetting('line_items_data') as $line_item_data) {
+      $line_item = $this->paymentLineItemManager->createInstance($line_item_data['plugin_id'], $line_item_data['plugin_configuration']);
+      $payment->setLineItem($line_item);
+    }
+
+    return $payment;
+  }
+}
diff --git a/payment_reference/src/FactoryInterface.php b/payment_reference/src/FactoryInterface.php
new file mode 100644
index 0000000..e8f689d
--- /dev/null
+++ b/payment_reference/src/FactoryInterface.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment_reference\FactoryInterface.
+ */
+
+namespace Drupal\payment_reference;
+
+use Drupal\field\FieldInstanceConfigInterface;
+
+/**
+ * Defines a payment factory service.
+ */
+interface FactoryInterface {
+
+  /**
+   * Creates a payment for a field instance configuration entity.
+   *
+   * @param \Drupal\field\FieldInstanceConfigInterface
+   *
+   * @return \Drupal\payment\Entity\PaymentInterface
+   */
+  public function createPayment(FieldInstanceConfigInterface $field_instance_config);
+}
diff --git a/payment_reference/src/PaymentReference.php b/payment_reference/src/PaymentReference.php
index 97969d9..a5ef287 100644
--- a/payment_reference/src/PaymentReference.php
+++ b/payment_reference/src/PaymentReference.php
@@ -13,6 +13,15 @@ namespace Drupal\payment_reference;
 class PaymentReference {
 
   /**
+   * Returns the payment factory.
+   *
+   * @return \Drupal\payment_reference\FactoryInterface
+   */
+  public static function factory() {
+    return \Drupal::service('payment_reference.factory');
+  }
+
+  /**
    * Returns the payment reference queue.
    *
    * @return \Drupal\payment\QueueInterface
diff --git a/payment_reference/src/Plugin/Field/FieldWidget/PaymentReference.php b/payment_reference/src/Plugin/Field/FieldWidget/PaymentReference.php
index 31227b6..3ce978d 100644
--- a/payment_reference/src/Plugin/Field/FieldWidget/PaymentReference.php
+++ b/payment_reference/src/Plugin/Field/FieldWidget/PaymentReference.php
@@ -7,11 +7,13 @@
 
 namespace Drupal\payment_reference\Plugin\Field\FieldWidget;
 
+use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\WidgetBase;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\payment_reference\FactoryInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -30,6 +32,13 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 class PaymentReference extends WidgetBase implements ContainerFactoryPluginInterface {
 
   /**
+   * The config factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
    * The current user.
    *
    * @var \Drupal\Core\Session\AccountInterface
@@ -37,6 +46,13 @@ class PaymentReference extends WidgetBase implements ContainerFactoryPluginInter
   protected $currentUser;
 
   /**
+   * The payment reference factory.
+   *
+   * @var \Drupal\payment_reference\FactoryInterface
+   */
+  protected $paymentFactory;
+
+  /**
    * Constructs a new class instance.
    *
    * @param array $plugin_id
@@ -49,34 +65,43 @@ class PaymentReference extends WidgetBase implements ContainerFactoryPluginInter
    *   The widget settings.
    * @param array $third_party_settings
    *   Any third party settings.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory.
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
+   * @param \Drupal\payment_reference\FactoryInterface $payment_factory
+   *   The payment reference factory.
    */
-  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, AccountInterface $current_user) {
+  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ConfigFactoryInterface $config_factory, AccountInterface $current_user, FactoryInterface $payment_factory) {
     parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
+    $this->configFactory = $config_factory;
     $this->currentUser = $current_user;
+    $this->paymentFactory = $payment_factory;
   }
 
   /**
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container->get('current_user'));
+    return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container->get('config.factory'), $container->get('current_user'), $container->get('payment_reference.factory'));
   }
 
   /**
    * {@inheritdoc}
    */
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
+    $config = $this->configFactory->get('payment_reference.payment_type');
+    $payment = $this->paymentFactory->createPayment($this->fieldDefinition);
     $element['payment_id'] = array(
       '#bundle' => $items->getEntity()->bundle(),
       '#default_value' => isset($items[$delta]) ? $items[$delta]->target_id : NULL,
       '#entity_type_id' => $items->getEntity()->getEntityTypeId(),
       '#field_name' => $this->fieldDefinition->getName(),
+      '#limit_allowed_payment_method_ids' => $config->get('limit_allowed_payment_methods') ? $config->get('allowed_payment_method_ids') : NULL,
+      '#payment_method_selector_id' => $config->get('payment_method_selector_id'),
+      '#prototype_payment' => $payment,
       // The requested user account may contain a string numeric ID.
-      '#owner_id' => (int) $this->currentUser->id(),
-      '#payment_line_items_data' => $this->getFieldSetting('line_items_data'),
-      '#payment_currency_code' => $this->getFieldSetting('currency_code'),
+      '#queue_owner_id' => (int) $this->currentUser->id(),
       '#required' => $this->fieldDefinition->isRequired(),
       '#type' => 'payment_reference',
     );
diff --git a/payment_reference/src/Plugin/Payment/Type/PaymentReference.php b/payment_reference/src/Plugin/Payment/Type/PaymentReference.php
index bcd9392..24905e1 100644
--- a/payment_reference/src/Plugin/Payment/Type/PaymentReference.php
+++ b/payment_reference/src/Plugin/Payment/Type/PaymentReference.php
@@ -102,16 +102,22 @@ class PaymentReference extends PaymentTypeBase implements ContainerFactoryPlugin
    * {@inheritdoc}
    */
   protected function doResumeContext() {
-    $url = $this->urlGenerator->generateFromRoute('payment_reference.resume_context', array(
-      'payment' => $this->getPayment()->id(),
-    ), array(
-      'absolute' => TRUE,
-    ));
-    $response = new RedirectResponse($url);
-    $listener = function(FilterResponseEvent $event) use ($response) {
-      $event->setResponse($response);
-    };
-    $this->eventDispatcher->addListener(KernelEvents::RESPONSE, $listener, 999);
+    // If the payment method does not interrupt the payment type context, the
+    // payer is still in the original context and we do not need to redirect
+    // them back.
+    $payment_method_definition = $this->getPayment()->getPaymentMethod()->getPluginDefinition();
+    if ($payment_method_definition['interrupts_payment_type_context']) {
+      $url = $this->urlGenerator->generateFromRoute('payment_reference.resume_context', array(
+        'payment' => $this->getPayment()->id(),
+      ), array(
+        'absolute' => TRUE,
+      ));
+      $response = new RedirectResponse($url);
+      $listener = function(FilterResponseEvent $event) use ($response) {
+        $event->setResponse($response);
+      };
+      $this->eventDispatcher->addListener(KernelEvents::RESPONSE, $listener, 999);
+    }
   }
 
   /**
diff --git a/payment_reference/src/Tests/FactoryUnitTest.php b/payment_reference/src/Tests/FactoryUnitTest.php
new file mode 100644
index 0000000..442baba
--- /dev/null
+++ b/payment_reference/src/Tests/FactoryUnitTest.php
@@ -0,0 +1,141 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment_reference\Tests\FactoryUnitTest.
+ */
+
+namespace Drupal\payment_reference\Tests;
+
+use Drupal\payment_reference\Factory;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\payment_reference\Factory
+ */
+class FactoryUnitTest extends UnitTestCase {
+
+  /**
+   * The entity manager used for testing.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $entityManager;
+
+  /**
+   * The payment line item manager used for testing.
+   *
+   * @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $paymentLineItemManager;
+
+  /**
+   * The factory under test.
+   *
+   * @var \Drupal\payment_reference\Factory
+   */
+  protected $factory;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'description' => '',
+      'name' => '\Drupal\payment_reference\Factory unit test',
+      'group' => 'Payment Reference Field',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+
+    $this->paymentLineItemManager = $this->getMock('\Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface');
+
+    $this->factory = new Factory($this->entityManager, $this->paymentLineItemManager);
+  }
+
+  /**
+   * @covers ::createPayment
+   */
+  public function testCreatePayment() {
+    $currency_code = $this->randomName();
+    $field_instance_config_id = $this->randomName();
+
+    $payment_type = $this->getMockBuilder('\Drupal\payment_reference\Plugin\Payment\Type\PaymentReference')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $payment_type->expects($this->once())
+      ->method('setFieldInstanceConfigId')
+      ->with($field_instance_config_id);
+
+    $payment = $this->getMockBuilder('\Drupal\payment\Entity\Payment')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $payment->expects($this->once())
+      ->method('setCurrencyCode')
+      ->with($currency_code);
+    $payment->expects($this->once())
+      ->method('getPaymentType')
+      ->will($this->returnValue($payment_type));
+
+    $payment_storage = $this->getMock('\Drupal\Core\Entity\EntityStorageInterface');
+    $payment_storage->expects($this->once())
+      ->method('create')
+      ->with(array(
+        'bundle' => 'payment_reference',
+      ))
+      ->will($this->returnValue($payment));
+
+    $this->entityManager->expects($this->once())
+      ->method('getStorage')
+      ->with('payment')
+      ->will($this->returnValue($payment_storage));
+
+    $line_item_a = $this->getMock('\Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface');
+    $line_item_plugin_id_a = $this->randomName();
+    $line_item_plugin_configuration_a = array(
+      'foo' => $this->randomName(),
+    );
+    $line_item_b = $this->getMock('\Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface');
+    $line_item_plugin_id_b = $this->randomName();
+    $line_item_plugin_configuration_b = array(
+      'bar' => $this->randomName(),
+    );
+
+    $field_instance_config = $this->getMock('\Drupal\field\FieldInstanceConfigInterface');
+    $field_instance_config->expects($this->once())
+      ->method('id')
+      ->will($this->returnValue($field_instance_config_id));
+    $map = array(
+      array('currency_code', $currency_code),
+      array('line_items_data', array(
+        array(
+          'plugin_configuration' => $line_item_plugin_configuration_a,
+          'plugin_id' => $line_item_plugin_id_a,
+        ),
+        array(
+          'plugin_configuration' => $line_item_plugin_configuration_b,
+          'plugin_id' => $line_item_plugin_id_b,
+        ),
+      )),
+    );
+    $field_instance_config->expects($this->exactly(2))
+      ->method('getSetting')
+      ->will($this->returnValueMap($map));
+
+    $this->paymentLineItemManager->expects($this->at(0))
+      ->method('createInstance')
+      ->with($line_item_plugin_id_a, $line_item_plugin_configuration_a)
+      ->will($this->returnValue($line_item_a));
+    $this->paymentLineItemManager->expects($this->at(1))
+      ->method('createInstance')
+      ->with($line_item_plugin_id_b, $line_item_plugin_configuration_b)
+      ->will($this->returnValue($line_item_b));
+
+    $this->assertSame(spl_object_hash($payment), spl_object_hash($this->factory->createPayment($field_instance_config)));
+  }
+}
diff --git a/payment_reference/tests/src/PaymentReferenceUnitTest.php b/payment_reference/tests/src/PaymentReferenceUnitTest.php
index 6bd2129..8ae5f52 100644
--- a/payment_reference/tests/src/PaymentReferenceUnitTest.php
+++ b/payment_reference/tests/src/PaymentReferenceUnitTest.php
@@ -29,4 +29,15 @@ class PaymentReferenceUnitTest extends UnitTestCase {
     $this->assertSame($queue, PaymentReference::queue());
   }
 
+  /**
+   * @covers ::factory
+   */
+  public function testFactory() {
+    $container = new Container();
+    $factory = $this->getMock('\Drupal\payment\FactoryInterface');
+    $container->set('payment_reference.factory', $factory);
+    \Drupal::setContainer($container);
+    $this->assertSame($factory, PaymentReference::factory());
+  }
+
 }
diff --git a/payment_reference/tests/src/Plugin/Field/FieldWidget/PaymentReferenceUnitTest.php b/payment_reference/tests/src/Plugin/Field/FieldWidget/PaymentReferenceUnitTest.php
index 7f0ff1b..1014d79 100644
--- a/payment_reference/tests/src/Plugin/Field/FieldWidget/PaymentReferenceUnitTest.php
+++ b/payment_reference/tests/src/Plugin/Field/FieldWidget/PaymentReferenceUnitTest.php
@@ -20,6 +20,13 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 class PaymentReferenceUnitTest extends UnitTestCase {
 
   /**
+   * The config factory used for testing.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $configFactory;
+
+  /**
    * A user account used for testing.
    *
    * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -34,6 +41,13 @@ class PaymentReferenceUnitTest extends UnitTestCase {
   protected $fieldDefinition;
 
   /**
+   * The payment reference factory used for testing.
+   *
+   * @var \Drupal\payment_reference\FactoryInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $paymentFactory;
+
+  /**
    * The field widget plugin under test.
    *
    * @var \Drupal\payment_reference\Plugin\Field\FieldWidget\PaymentReference|\PHPUnit_Framework_MockObject_MockObject
@@ -50,7 +64,7 @@ class PaymentReferenceUnitTest extends UnitTestCase {
 
     $this->currentUser = $this->getMock('\Drupal\Core\Session\AccountInterface');
 
-    $this->widget = new PaymentReference($this->randomName(), array(), $this->fieldDefinition, array(), array(), $this->currentUser);
+    $this->widget = new PaymentReference($this->randomName(), array(), $this->fieldDefinition, array(), array(), $this->configFactory, $this->currentUser, $this->paymentFactory);
   }
 
   /**
@@ -59,7 +73,9 @@ class PaymentReferenceUnitTest extends UnitTestCase {
   function testCreate() {
     $container = $this->getMock('\Symfony\Component\DependencyInjection\ContainerInterface');
     $map = array(
+      array('config.factory', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->configFactory),
       array('current_user', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->currentUser),
+      array('payment_reference.factory', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->paymentFactory),
     );
     $container->expects($this->any())
       ->method('get')
@@ -73,7 +89,7 @@ class PaymentReferenceUnitTest extends UnitTestCase {
     $plugin_definition = array();
     $plugin_id = $this->randomName();
     $plugin = PaymentReference::create($container, $configuration, $plugin_id, $plugin_definition);
-    $this->assertInstanceOf('\Drupal\payment_reference\Plugin\Field\FIeldWidget\PaymentReference', $plugin);
+    $this->assertInstanceOf('\Drupal\payment_reference\Plugin\Field\FieldWidget\PaymentReference', $plugin);
   }
 
   /**
@@ -108,8 +124,9 @@ class PaymentReferenceUnitTest extends UnitTestCase {
       ),
     );
     $map = array(
-      array('currency_code', $currency_code),
-      array('line_items_data', $line_items_data),
+      array('limit_allowed_payment_methods', TRUE),
+      array('allowed_payment_method_ids', $allowed_payment_method_ids),
+      array('payment_method_selector_id', $payment_method_selector_id),
     );
     $this->fieldDefinition->expects($this->exactly(2))
       ->method('getSetting')
diff --git a/payment_reference_test/src/PaymentReferenceElement.php b/payment_reference_test/src/PaymentReferenceElement.php
index 49abede..7aff290 100644
--- a/payment_reference_test/src/PaymentReferenceElement.php
+++ b/payment_reference_test/src/PaymentReferenceElement.php
@@ -33,6 +33,8 @@ class PaymentReferenceElement implements FormInterface {
       '#owner_id' => 2,
       '#payment_line_items' => Generate::createPaymentLineItems(),
       '#payment_currency_code' => 'EUR',
+      '#payment_method_selector_id' => 'payment_select',
+      '#prototype_payment' => Generate::createPayment(2),
       '#required' => TRUE,
       '#title' => 'FooBarBaz',
       '#type' => 'payment_reference',
