diff --git a/payment/lib/Drupal/payment/Tests/Plugin/Payment/MethodSelector/PaymentSelectWebTest.php b/payment/lib/Drupal/payment/Tests/Plugin/Payment/MethodSelector/PaymentSelectWebTest.php
index 12a4749..538c6f1 100644
--- a/payment/lib/Drupal/payment/Tests/Plugin/Payment/MethodSelector/PaymentSelectWebTest.php
+++ b/payment/lib/Drupal/payment/Tests/Plugin/Payment/MethodSelector/PaymentSelectWebTest.php
@@ -52,12 +52,13 @@ class PaymentSelectWebTest extends WebTestBase {
    * Tests the element.
    */
   protected function testElement() {
+    $path = 'payment_test-payment_method_selector-payment_select';
     $state = \Drupal::state();
     /** @var \Drupal\payment\Plugin\Payment\Method\PaymentMethodManagerInterface|\Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface $payment_method_manager */
     $payment_method_manager = Payment::methodManager();
 
     // Test the presence of default elements without available payment methods.
-    $this->drupalGet('payment_test-payment_method_selector-payment_select');
+    $this->drupalGet($path);
     $this->assertNoFieldByName('payment_method[select][payment_method_plugin_id]');
     $this->assertNoFieldByName('payment_method[select][change]', t('Choose payment method'));
     $this->assertText(t('There are no available payment methods.'));
@@ -65,7 +66,7 @@ class PaymentSelectWebTest extends WebTestBase {
     // Test the presence of default elements with one available payment method.
     $payment_method_1 = $this->createPaymentMethod();
     $payment_method_manager->clearCachedDefinitions();
-    $this->drupalGet('payment_test-payment_method_selector-payment_select');
+    $this->drupalGet($path);
     $this->assertNoFieldByName('payment_method[select][payment_method_plugin_id]');
     $this->assertNoFieldByName('payment_method[select][change]', t('Choose payment method'));
     $this->assertNoText(t('There are no available payment methods.'));
@@ -74,7 +75,7 @@ class PaymentSelectWebTest extends WebTestBase {
     // methods.
     $payment_method_2 = $this->createPaymentMethod();
     $payment_method_manager->clearCachedDefinitions();
-    $this->drupalGet('payment_test-payment_method_selector-payment_select');
+    $this->drupalGet($path);
     $this->assertFieldByName('payment_method[select][payment_method_plugin_id]');
     $this->assertFieldByName('payment_method[select][change]', t('Choose payment method'));
     $this->assertNoText(t('There are no available payment methods.'));
diff --git a/payment_form/lib/Drupal/payment_form/Plugin/Field/FieldFormatter/PaymentForm.php b/payment_form/lib/Drupal/payment_form/Plugin/Field/FieldFormatter/PaymentForm.php
index 973b80e..1dd9b84 100644
--- a/payment_form/lib/Drupal/payment_form/Plugin/Field/FieldFormatter/PaymentForm.php
+++ b/payment_form/lib/Drupal/payment_form/Plugin/Field/FieldFormatter/PaymentForm.php
@@ -95,6 +95,7 @@ class PaymentForm extends FormatterBase implements ContainerFactoryPluginInterfa
     /** @var \Drupal\payment_form\Plugin\Payment\Type\PaymentForm $payment_type */
     $payment_type = $payment->getPaymentType();
     $payment_type->setDestinationUrl($this->request->getUri());
+    $payment_type->setFieldInstanceConfigId($this->fieldDefinition->getName());
     foreach ($items as $item) {
       /** @var \Drupal\payment_form\Plugin\Field\FieldType\PaymentForm $item */
       $plugin_id = $item->get('plugin_id')->getValue();
@@ -102,7 +103,6 @@ class PaymentForm extends FormatterBase implements ContainerFactoryPluginInterfa
         $payment->setLineItem($this->paymentLineItemManager->createInstance($plugin_id, $item->get('plugin_configuration')->getValue()));
       }
     }
-    $payment_type->setFieldInstanceConfigId($this->fieldDefinition->getName());
 
     return $this->formBuilder->getForm($this->entityManager->getFormController('payment', 'payment_form')->setEntity($payment));
   }
diff --git a/payment_form/lib/Drupal/payment_form/Tests/Plugin/Field/FieldFormatter/PaymentFormUnitTest.php b/payment_form/lib/Drupal/payment_form/Tests/Plugin/Field/FieldFormatter/PaymentFormUnitTest.php
index cf06b0c..fc6dfce 100644
--- a/payment_form/lib/Drupal/payment_form/Tests/Plugin/Field/FieldFormatter/PaymentFormUnitTest.php
+++ b/payment_form/lib/Drupal/payment_form/Tests/Plugin/Field/FieldFormatter/PaymentFormUnitTest.php
@@ -100,11 +100,22 @@ class PaymentFormUnitTest extends UnitTestCase {
    * Tests viewElements().
    */
   public function testViewElements() {
+    $request_uri = $this->randomName();
+    $field_id = $this->randomName();
+
+    $this->request->expects($this->once())
+      ->method('getUri')
+      ->will($this->returnValue($request_uri));
+
     $payment_type = $this->getMockBuilder('\Drupal\payment_form\Plugin\Payment\Type\PaymentForm')
       ->disableOriginalConstructor()
       ->getMock();
     $payment_type->expects($this->once())
-      ->method('setFieldInstanceConfigId');
+      ->method('setFieldInstanceConfigId')
+      ->with($field_id);
+    $payment_type->expects($this->once())
+      ->method('setDestinationUrl')
+      ->with($request_uri);
 
     $payment = $this->getMockBuilder('\Drupal\payment\Entity\Payment')
       ->disableOriginalConstructor()
@@ -178,7 +189,6 @@ class PaymentFormUnitTest extends UnitTestCase {
       ->method('getIterator')
       ->will($this->returnValue($iterator));
 
-    $field_id = $this->randomName();
     $this->fieldDefinition->expects($this->once())
       ->method('getName')
       ->will($this->returnValue($field_id));
diff --git a/payment_reference/lib/Drupal/payment_reference/Element/PaymentReference.php b/payment_reference/lib/Drupal/payment_reference/Element/PaymentReference.php
index 5e1810b..4913e72 100644
--- a/payment_reference/lib/Drupal/payment_reference/Element/PaymentReference.php
+++ b/payment_reference/lib/Drupal/payment_reference/Element/PaymentReference.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\payment_reference\Element;
 
+use Drupal\payment\Entity\PaymentInterface;
 use Drupal\payment\Payment;
 use Drupal\payment_reference\PaymentReference as PaymentReferenceServiceWrapper;
 
@@ -22,26 +23,32 @@ class PaymentReference {
   public static function process(array $element, array &$form_state, array $form) {
     // Validate the element's configuration.
     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_int($element['#owner_id'])) {
-      throw new \InvalidArgumentException('The owner ID must be an integer, but ' . gettype($element['#owner_id']) . ' 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_string($element['#payment_currency_code'])) {
-      throw new \InvalidArgumentException('The currency code must be a string, but ' . gettype($element['#payment_currency_code']) . ' was given.');
+    if (!($element['#prototype_payment'] instanceof PaymentInterface)) {
+      throw new \InvalidArgumentException('#prototype_payment must implement \Drupal\payment\Entity\PaymentInterface.');
     }
-    if (!is_string($element['#field_instance_config_id'])) {
-      throw new \InvalidArgumentException('The field instance config ID must be a string, but ' . gettype($element['#field_instance_config_id']) . ' 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 (!is_string($element['#queue_category_id'])) {
+      throw new \InvalidArgumentException('#queue_category_id must be a string, but ' . gettype($element['#queue_category_id']) . ' was given.');
+    }
+    if (!is_int($element['#queue_owner_id'])) {
+      throw new \InvalidArgumentException('#queue_owner_id must be an integer, but ' . gettype($element['#queue_owner_id']) . ' was given.');
     }
 
     // Find the default payment to use.
-    $pid = $element['#default_value'];
-    if (!$pid) {
-      $pids = PaymentReferenceServiceWrapper::queue()->loadPaymentIds($element['#field_instance_config_id'], $element['#owner_id']);
-      $pid = reset($pids);
+    $payment_id = $element['#default_value'];
+    if (!$payment_id) {
+      $payment_ids = PaymentReferenceServiceWrapper::queue()->loadPaymentIds($element['#queue_category_id'], $element['#queue_owner_id']);
+      $payment_id = reset($payment_ids);
     }
     // Form API considers an empty string to be an empty value, but not NULL.
-    $element['#value'] = $pid ? $pid : '';
+    $element['#value'] = $payment_id ? $payment_id : '';
 
     // AJAX.
     $ajax_wrapper_id = drupal_html_id('payment_reference-' . $element['#name']);
@@ -53,26 +60,32 @@ class PaymentReference {
       'type' => 'setting',
         'data' => array(
           'PaymentReferencePaymentAvailable' => array(
-            $ajax_wrapper_id => !empty($pid),
+            $ajax_wrapper_id => !empty($payment_id),
           ),
         ),
       ),
     );
 
-    // Payment information.
-    $element['payment'] = array(
-      '#empty' => t('There are no line items.'),
-      '#header' => array(t('Amount'), t('Status'), t('Last updated')),
-      '#type' => 'table',
-    );
-    if (!$pid) {
+    // There are no queued payments, so display a payment method selection and
+    // configuration form.
+    if (!$payment_id) {
+      /** @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 = Payment::methodSelectorManager()->createInstance($element['#payment_method_selector_id']);
+      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->formElements(array(), $form_state, $payment);
+
       $amount = 0;
-      foreach ($element['#payment_line_items_data'] as $line_item_data) {
-        $line_item = Payment::lineItemManager()->createInstance($line_item_data['plugin_id'], $line_item_data['plugin_configuration']);
+      foreach ($payment->getLineItems() as $line_item) {
         $amount += $line_item->getTotalAmount();
       }
-      /** @var \Drupal\currency\Entity\CurrencyInterface $currency */
-      $currency = entity_load('currency', $element['#payment_currency_code']);
+      $currency = $payment->getCurrency();
       $element['payment'][0]['amount'] = array(
         '#markup' => $currency->formatAmount($amount),
       );
@@ -81,19 +94,22 @@ class PaymentReference {
           'colspan' => 2,
         ),
         '#markup' => t('<a href="@url" target="_blank">Add a new payment</a> (opens in a new window)', array(
-          '@url' => \Drupal::urlGenerator()->generateFromRoute('payment_reference.pay', array(
-            'field_instance_config' => $element['#field_instance_config_id'],
-          )),
+          '@url' => \Drupal::urlGenerator()->generateFromRoute('payment_reference.pay'),
         )),
       );
     }
+    // There is a queued payment, so display its information.
     else {
       /** @var \Drupal\payment\Entity\PaymentInterface $payment */
-      $payment = entity_load('payment', $pid);
-      /** @var \Drupal\currency\Entity\CurrencyInterface $currency */
-      $currency = entity_load('currency', $payment->getCurrencyCode());
+      $payment = entity_load('payment', $payment_id);
+      $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/lib/Drupal/payment_reference/Factory.php b/payment_reference/lib/Drupal/payment_reference/Factory.php
new file mode 100644
index 0000000..3b62760
--- /dev/null
+++ b/payment_reference/lib/Drupal/payment_reference/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/lib/Drupal/payment_reference/FactoryInterface.php b/payment_reference/lib/Drupal/payment_reference/FactoryInterface.php
new file mode 100644
index 0000000..e8f689d
--- /dev/null
+++ b/payment_reference/lib/Drupal/payment_reference/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/lib/Drupal/payment_reference/PaymentReference.php b/payment_reference/lib/Drupal/payment_reference/PaymentReference.php
index 97969d9..a5ef287 100644
--- a/payment_reference/lib/Drupal/payment_reference/PaymentReference.php
+++ b/payment_reference/lib/Drupal/payment_reference/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/lib/Drupal/payment_reference/Plugin/Field/FieldWidget/PaymentReference.php b/payment_reference/lib/Drupal/payment_reference/Plugin/Field/FieldWidget/PaymentReference.php
index 04ffef2..636806f 100644
--- a/payment_reference/lib/Drupal/payment_reference/Plugin/Field/FieldWidget/PaymentReference.php
+++ b/payment_reference/lib/Drupal/payment_reference/Plugin/Field/FieldWidget/PaymentReference.php
@@ -7,12 +7,14 @@
 
 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\field\FieldInstanceConfigInterface;
+use Drupal\payment_reference\FactoryInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -31,6 +33,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
@@ -38,6 +47,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
@@ -48,19 +64,25 @@ class PaymentReference extends WidgetBase implements ContainerFactoryPluginInter
    *   The definition of the field to which the widget is associated.
    * @param array $settings
    *   The widget 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, AccountInterface $current_user) {
+  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, ConfigFactoryInterface $config_factory, AccountInterface $current_user, FactoryInterface $payment_factory) {
     parent::__construct($plugin_id, $plugin_definition, $field_definition, $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'], $container->get('current_user'));
+    return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $container->get('config.factory'), $container->get('current_user'), $container->get('payment_reference.factory'));
   }
 
   /**
@@ -71,13 +93,16 @@ class PaymentReference extends WidgetBase implements ContainerFactoryPluginInter
       throw new \RuntimeException('This widget can only be used on configurable fields.');
     }
 
+    $config = $this->configFactory->get('payment_reference.payment_type');
+    $payment = $this->paymentFactory->createPayment($this->fieldDefinition);
     $element['payment_id'] = array(
       '#default_value' => isset($items[$delta]) ? $items[$delta]->target_id : NULL,
-      '#field_instance_config_id' => $this->fieldDefinition->id(),
+      '#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,
+      '#queue_category_id' => $this->fieldDefinition->id(),
       // 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/lib/Drupal/payment_reference/Plugin/Payment/Type/PaymentReference.php b/payment_reference/lib/Drupal/payment_reference/Plugin/Payment/Type/PaymentReference.php
index 41c0924..25950eb 100644
--- a/payment_reference/lib/Drupal/payment_reference/Plugin/Payment/Type/PaymentReference.php
+++ b/payment_reference/lib/Drupal/payment_reference/Plugin/Payment/Type/PaymentReference.php
@@ -11,6 +11,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\HttpKernel;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
+use Drupal\field\FieldInstanceConfigInterface;
 use Drupal\payment\Plugin\Payment\Type\PaymentTypeBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
diff --git a/payment_reference/lib/Drupal/payment_reference/Tests/FactoryUnitTest.php b/payment_reference/lib/Drupal/payment_reference/Tests/FactoryUnitTest.php
new file mode 100644
index 0000000..442baba
--- /dev/null
+++ b/payment_reference/lib/Drupal/payment_reference/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/lib/Drupal/payment_reference/Tests/PaymentReferenceUnitTest.php b/payment_reference/lib/Drupal/payment_reference/Tests/PaymentReferenceUnitTest.php
index 9d33f1d..5610a7e 100644
--- a/payment_reference/lib/Drupal/payment_reference/Tests/PaymentReferenceUnitTest.php
+++ b/payment_reference/lib/Drupal/payment_reference/Tests/PaymentReferenceUnitTest.php
@@ -12,7 +12,7 @@ use Drupal\Tests\UnitTestCase;
 use Symfony\Component\DependencyInjection\Container;
 
 /**
- * Tests \Drupal\payment_reference\PaymentReference.
+ * @coversDefaultClass \Drupal\payment_reference\PaymentReference.
  */
 class PaymentReferenceUnitTest extends UnitTestCase {
 
@@ -28,9 +28,9 @@ class PaymentReferenceUnitTest extends UnitTestCase {
   }
 
   /**
-   * Tests lineItemManager().
+   * @covers ::queue()
    */
-  public function testLineItemManager() {
+  public function testQueue() {
     $container = new Container();
     $queue = $this->getMock('\Drupal\payment\QueueInterface');
     $container->set('payment_reference.queue', $queue);
@@ -38,4 +38,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/lib/Drupal/payment_reference/Tests/Plugin/Field/FieldWidget/PaymentReferenceUnitTest.php b/payment_reference/lib/Drupal/payment_reference/Tests/Plugin/Field/FieldWidget/PaymentReferenceUnitTest.php
index 1f46a43..b9c3bdb 100644
--- a/payment_reference/lib/Drupal/payment_reference/Tests/Plugin/Field/FieldWidget/PaymentReferenceUnitTest.php
+++ b/payment_reference/lib/Drupal/payment_reference/Tests/Plugin/Field/FieldWidget/PaymentReferenceUnitTest.php
@@ -8,6 +8,7 @@
 
 namespace Drupal\payment_reference\Tests\Plugin\Field\FieldWidget;
 
+use Drupal\payment_reference\Plugin\Field\FieldWidget\PaymentReference;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -16,6 +17,13 @@ use Drupal\Tests\UnitTestCase;
 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
@@ -30,6 +38,13 @@ class PaymentReferenceUnitTest extends UnitTestCase {
   protected $fieldInstanceConfig;
 
   /**
+   * 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
@@ -51,44 +66,68 @@ class PaymentReferenceUnitTest extends UnitTestCase {
    * {@inheritdoc}
    */
   protected function setUp() {
+    $this->configFactory = $this->getMock('\Drupal\Core\Config\ConfigFactoryInterface');
+
     $this->fieldInstanceConfig = $this->getMock('\Drupal\field\FieldInstanceConfigInterface');
 
     $this->currentUser = $this->getMock('\Drupal\Core\Session\AccountInterface');
 
-    $this->widget = $this->getMockBuilder('\Drupal\payment_reference\Plugin\Field\FieldWidget\PaymentReference')
-      ->setConstructorArgs(array($this->randomName(), array(), $this->fieldInstanceConfig, array(), $this->currentUser))
-      ->setMethods(array('getFieldSetting'))
-      ->getMock();
+    $this->paymentFactory = $this->getMock('\Drupal\payment_reference\FactoryInterface');
+
+    $plugin_id = $this->randomName();
+    $plugin_definition = array();
+    $settings = array();
+    $this->widget = new PaymentReference($plugin_id, $plugin_definition, $this->fieldInstanceConfig, $settings, $this->configFactory, $this->currentUser, $this->paymentFactory);
   }
 
   /**
    * Tests formElement().
    */
   public function testFormElement() {
+    $field_instance_config_id = $this->randomName();
+    $required = TRUE;
+
+    $this->fieldInstanceConfig->expects($this->once())
+      ->method('id')
+      ->will($this->returnValue($field_instance_config_id));
     $this->fieldInstanceConfig->expects($this->once())
       ->method('isRequired')
-      ->will($this->returnValue(TRUE));
+      ->will($this->returnValue($required));
 
     $user_id = 2;
     $this->currentUser->expects($this->exactly(1))
       ->method('id')
       ->will($this->returnValue($user_id));
 
-    $currency_code = 'EUR';
-    $line_items_data = array(
-      array(
-        'plugin_configuration' => array(),
-        'plugin_id' => $this->randomName(),
-      ),
-    );
+    $allowed_payment_method_ids = array($this->randomName());
+    $payment_method_selector_id = $this->randomName();
+
+    $config = $this->getMockBuilder('\Drupal\Core\Config\Config')
+      ->disableOriginalConstructor()
+      ->getMock();
     $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->widget->expects($this->exactly(2))
-      ->method('getFieldSetting')
+    $config->expects($this->exactly(3))
+      ->method('get')
       ->will($this->returnValueMap($map));
 
+    $this->configFactory->expects($this->any())
+      ->method('get')
+      ->with('payment_reference.payment_type')
+      ->will($this->returnValue($config));
+
+    $payment = $this->getMockBuilder('\Drupal\payment\Entity\Payment')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $this->paymentFactory->expects($this->once())
+      ->method('createPayment')
+      ->with($this->fieldInstanceConfig)
+      ->will($this->returnValue($payment));
+
     $items = $this->getMockBuilder('\Drupal\Core\Field\FieldItemList')
       ->disableOriginalConstructor()
       ->getMock();
@@ -96,9 +135,13 @@ class PaymentReferenceUnitTest extends UnitTestCase {
     $form = array();
     $form_state = array();
     $element = $this->widget->formElement($items, 3, array(), $form, $form_state);
-    $this->assertSame($element['payment_id']['#owner_id'], $user_id);
-    $this->assertSame($element['payment_id']['#payment_currency_code'], $currency_code);
-    $this->assertSame($element['payment_id']['#payment_line_items_data'], $line_items_data);
+    $this->assertSame($allowed_payment_method_ids, $element['payment_id']['#limit_allowed_payment_method_ids']);
+    $this->assertSame($payment, $element['payment_id']['#prototype_payment']);
+    $this->assertSame($payment_method_selector_id, $element['payment_id']['#payment_method_selector_id']);
+    $this->assertSame($field_instance_config_id, $element['payment_id']['#queue_category_id']);
+    $this->assertSame($user_id, $element['payment_id']['#queue_owner_id']);
+    $this->assertSame($required, $element['payment_id']['#required']);
+    $this->assertSame('payment_reference', $element['payment_id']['#type']);
   }
 
 }
diff --git a/payment_reference/payment_reference.module b/payment_reference/payment_reference.module
index f1e92fe..2da5f42 100644
--- a/payment_reference/payment_reference.module
+++ b/payment_reference/payment_reference.module
@@ -23,18 +23,20 @@ function payment_reference_element_info() {
   $elements['payment_reference'] = array(
     // The ID of a payment as the default value.
     '#default_value' => NULL,
-    // The ID of the field instance config the element is used for.
-    '#field_instance_config_id' => NULL,
     '#input' => TRUE,
-    // 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' => '',
+    // 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.
+    '#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,
+    '#queue_category_id' => NULL,
+    // The ID of the account that must own the payment.
+    '#queue_owner_id' => NULL,
     '#theme_wrappers' => array('form_element'),
     '#value_callback' => 'payment_reference_element_payment_reference_value',
   );
@@ -113,7 +115,7 @@ function payment_reference_entity_field_access($operation, FieldDefinitionInterf
  * https://drupal.org/node/2040559 has been fixed.
  */
 function payment_reference_element_payment_reference_value(array $element, $input, array &$form_state) {
-  $payment_ids = PaymentReference::queue()->loadPaymentIds($element['#field_instance_config_id'], $element['#owner_id']);
+  $payment_ids = PaymentReference::queue()->loadPaymentIds($element['#queue_category_id'], $element['#queue_owner_id']);
   if ($payment_ids) {
     return reset($payment_ids);
   }
diff --git a/payment_reference/payment_reference.routing.yml b/payment_reference/payment_reference.routing.yml
index 391f0b2..5f7015b 100644
--- a/payment_reference/payment_reference.routing.yml
+++ b/payment_reference/payment_reference.routing.yml
@@ -1,5 +1,5 @@
 payment_reference.pay:
-  path: '/payment_reference/pay/{field_instance_config}'
+  path: '/payment_reference/pay'
   defaults:
     _content: '\Drupal\payment_reference\Controller\PaymentReference::pay'
     _title_callback: '\Drupal\payment_reference\Controller\PaymentReference::payLabel'
diff --git a/payment_reference/payment_reference.services.yml b/payment_reference/payment_reference.services.yml
index 09a4613..856ab6b 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', '@plugin.manager.payment.status']
     class: Drupal\payment\Queue
\ No newline at end of file
diff --git a/payment_reference_test/lib/Drupal/payment_reference_test/PaymentReferenceElement.php b/payment_reference_test/lib/Drupal/payment_reference_test/PaymentReferenceElement.php
index cef0454..45616d0 100644
--- a/payment_reference_test/lib/Drupal/payment_reference_test/PaymentReferenceElement.php
+++ b/payment_reference_test/lib/Drupal/payment_reference_test/PaymentReferenceElement.php
@@ -27,15 +27,10 @@ class PaymentReferenceElement implements FormInterface {
    */
   public function buildForm(array $form, array &$form_state) {
     $form['payment_reference'] = array(
-      // The ID of the field instance the element is used for.
-      '#field_instance_config_id' => 'payment_reference_test_payment_reference_element',
-      // The ID of the account that must own the payment.
-      '#owner_id' => 2,
-      // An array of
-      // \Drupal\payment\Plugin\payment\line_item\PaymentLineItemInterface
-      // instances.
-      '#payment_line_items' => Generate::createPaymentLineItems(),
-      '#payment_currency_code' => 'EUR',
+      '#prototype_payment' => Generate::createPayment(2),
+      '#payment_method_selector_id' => 'payment_select',
+      '#queue_category_id' => 'payment_reference_test_payment_reference_element',
+      '#queue_owner_id' => 2,
       '#required' => TRUE,
       '#title' => 'Foo',
       '#type' => 'payment_reference',
