diff --git a/payment/lib/Drupal/payment/Annotations/PaymentContext.php b/payment/lib/Drupal/payment/Annotations/PaymentContext.php
new file mode 100644
index 0000000..5458681
--- /dev/null
+++ b/payment/lib/Drupal/payment/Annotations/PaymentContext.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Annotations\PaymentContext.
+ */
+
+namespace Drupal\payment\Annotations;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Defines a payment context plugin annotation.
+ *
+ * @Annotation
+ */
+class PaymentContext extends Plugin {
+
+  /**
+   * The plugin ID.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The translated human-readable plugin name.
+   *
+   * @var string
+   */
+  public $label;
+}
diff --git a/payment/lib/Drupal/payment/Plugin/Core/entity/Payment.php b/payment/lib/Drupal/payment/Plugin/Core/entity/Payment.php
index e3bc216..6061dc5 100644
--- a/payment/lib/Drupal/payment/Plugin/Core/entity/Payment.php
+++ b/payment/lib/Drupal/payment/Plugin/Core/entity/Payment.php
@@ -12,9 +12,9 @@ use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Entity\EntityNG;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\payment\Plugin\Core\entity\PaymentInterface;
+use Drupal\payment\Plugin\payment\context\PaymentContextInterface;
 use Drupal\payment\Plugin\payment\line_item\LineItemInterface;
 use Drupal\payment\Plugin\payment\status\PaymentStatusInterface;
-use Symfony\Component\Validator\ConstraintViolation;
 
 /**
  * Defines a payment entity.
@@ -38,6 +38,13 @@ use Symfony\Component\Validator\ConstraintViolation;
 class Payment extends EntityNG implements PaymentInterface {
 
   /**
+   * The payment context.
+   *
+   * @var \Drupal\payment\Plugin\payment\context\PaymentContextInterface
+   */
+  protected $context;
+
+  /**
    * Line items.
    *
    * @var array
@@ -69,8 +76,8 @@ class Payment extends EntityNG implements PaymentInterface {
   /**
    * {@inheritdoc}
    */
-  public function setPaymentContext($context) {
-    $this->set('paymentContext', $context);
+  public function setPaymentContext(PaymentContextInterface $context) {
+    $this->context = $context;
 
     return $this;
   }
@@ -79,7 +86,7 @@ class Payment extends EntityNG implements PaymentInterface {
    * {@inheritdoc}
    */
   public function getPaymentContext() {
-    return $this->get('paymentContext')->value;
+    return $this->context;
   }
 
   /**
@@ -101,22 +108,6 @@ class Payment extends EntityNG implements PaymentInterface {
   /**
    * {@inheritdoc}
    */
-  public function setFinishCallback($callback) {
-    $this->finishCallback[0]->setValue($callback);
-
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFinishCallback() {
-    return $this->finishCallback[0]->value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function setLineItems(array $line_items) {
     foreach ($line_items as $line_item) {
       $this->setLineItem($line_item);
@@ -295,19 +286,6 @@ class Payment extends EntityNG implements PaymentInterface {
   /**
    * {@inheritdoc}
    */
-  public function finish() {
-    $this->save();
-    $handler = \Drupal::moduleHandler();
-    $handler->invokeAll('payment_pre_finish', $this);
-    if ($handler->moduleExists('rules')) {
-      rules_invoke_event('payment_pre_finish', $this);
-    }
-    call_user_func($this->finish_callback, $this);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function execute() {
     $handler = \Drupal::moduleHandler();
     $manager = \Drupal::service('plugin.manager.payment.status');
diff --git a/payment/lib/Drupal/payment/Plugin/Core/entity/PaymentInterface.php b/payment/lib/Drupal/payment/Plugin/Core/entity/PaymentInterface.php
index 6d7122f..fb3b35f 100644
--- a/payment/lib/Drupal/payment/Plugin/Core/entity/PaymentInterface.php
+++ b/payment/lib/Drupal/payment/Plugin/Core/entity/PaymentInterface.php
@@ -10,6 +10,7 @@ namespace Drupal\payment\Plugin\Core\entity;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Executable\ExecutableInterface;
 use Drupal\payment\Plugin\Core\entity\PaymentMethodInterface;
+use Drupal\payment\Plugin\payment\context\PaymentContextInterface;
 use Drupal\payment\Plugin\payment\line_item\LineItemInterface;
 use Drupal\payment\Plugin\payment\status\PaymentStatusInterface;
 
@@ -22,11 +23,11 @@ interface PaymentInterface extends EntityInterface, ExecutableInterface {
    * Sets the machine name of the context that created this Payment, such as a
    * payment form, or a module.
    *
-   * @param string $context
+   * @param \Drupal\payment\Plugin\payment\context\PaymentContextInterface $context
    *
    * @return \Drupal\payment\Plugin\Core\entity\PaymentInterface
    */
-  public function setPaymentContext($context);
+  public function setPaymentContext(PaymentContextInterface $context);
 
   /**
    * Gets the machine name of the context that created this Payment, such as a
@@ -53,34 +54,6 @@ interface PaymentInterface extends EntityInterface, ExecutableInterface {
   public function getCurrencyCode();
 
   /**
-   * Sets the name of the function to call when payment execution is completed,
-   * regardless of the payment status. It receives one argument:
-   * - $payment Payment
-   *   The Payment object.
-   * The callback does not need to return anything and is free to redirect the
-   * user or display something.
-   * Use Payment::context_data to pass on arbitrary data to the finish callback.
-   *
-   * @param string $callback
-   *
-   * @return \Drupal\payment\Plugin\Core\entity\PaymentInterface
-   */
-  public function setFinishCallback($callback);
-
-  /**
-   * Gets the name of the function to call when payment execution is completed,
-   * regardless of the payment status. It receives one argument:
-   * - $payment Payment
-   *   The Payment object.
-   * The callback does not need to return anything and is free to redirect the
-   * user or display something.
-   * Use Payment::context_data to pass on arbitrary data to the finish callback.
-   *
-   * @return string|null
-   */
-  public function getFinishCallback();
-
-  /**
    * Sets line items.
    *
    * @param array $line_items
@@ -229,9 +202,4 @@ interface PaymentInterface extends EntityInterface, ExecutableInterface {
    *   objects.
    */
   public function getAvailablePaymentMethods(array $paymentMethods = array());
-
-  /**
-   * Finishes the payment and resumes context workflow.
-   */
-  public function finish();
 }
diff --git a/payment/lib/Drupal/payment/Plugin/Core/entity/PaymentStorageController.php b/payment/lib/Drupal/payment/Plugin/Core/entity/PaymentStorageController.php
index 6e8b967..1fa38f4 100644
--- a/payment/lib/Drupal/payment/Plugin/Core/entity/PaymentStorageController.php
+++ b/payment/lib/Drupal/payment/Plugin/Core/entity/PaymentStorageController.php
@@ -29,16 +29,16 @@ class PaymentStorageController extends DatabaseStorageControllerNG implements Pa
    * {@inheritdoc}
    */
   function attachLoad(&$queried_entities, $load_revision = FALSE) {
+    $manager = \Drupal::service('plugin.manager.payment.context');
     $line_items = $this->loadLineItems(array_keys($queried_entities));
     $statuses = $this->loadPaymentStatuses(array_keys($queried_entities));
     foreach ($queried_entities as $id => $queried_entity) {
       $queried_entities[$id] = (object) array(
-        'context' => $queried_entity->context,
+        'context' => $queried_entity->context_plugin_id ? $manager->createInstance($queried_entity->context_plugin_id) : NULL,
         'currencyCode' => $queried_entity->currency_code,
-        'finishCallback' => $queried_entity->finish_callback,
         'id' => (int) $queried_entity->id,
         'lineItems' => $line_items[$id],
-        'ownerId' => (int) $queried_entity->context,
+        'ownerId' => (int) $queried_entity->owner_id,
         'paymentMethodId' => $queried_entity->payment_method_id,
         'statuses' => $statuses[$id],
         'uuid' => $queried_entity->uuid,
@@ -52,10 +52,6 @@ class PaymentStorageController extends DatabaseStorageControllerNG implements Pa
    */
   public function baseFieldDefinitions() {
     $fields = parent::baseFieldDefinitions();
-    $fields['paymentContext'] = array(
-      'label' => t('Context'),
-      'type' => 'string_field',
-    );
     $fields['currencyCode'] = array(
       'label' => t('Currency code'),
       'settings' => array(
@@ -63,10 +59,6 @@ class PaymentStorageController extends DatabaseStorageControllerNG implements Pa
       ),
       'type' => 'string_field',
     );
-    $fields['finishCallback'] = array(
-      'label' => t('Finish callback'),
-      'type' => 'string_field',
-    );
     $fields['id'] = array(
       'label' => t('Payment ID'),
       'type' => 'integer_field',
@@ -98,9 +90,8 @@ class PaymentStorageController extends DatabaseStorageControllerNG implements Pa
    */
   protected function mapToStorageRecord(EntityInterface $entity) {
     $record = new \stdClass();
-    $record->context = $entity->getPaymentContext();
+    $record->context_plugin_id = $entity->getPaymentContext() ? $entity->getPaymentContext()->getPluginId() : NULL;
     $record->currency_code = $entity->getCurrencyCode();
-    $record->finish_callback = $entity->getFinishCallback();
     $record->id = $entity->id();
     $record->payment_method_id = $entity->getPaymentMethodId();
     $record->first_payment_status_id = current($entity->getStatuses())->getId();
diff --git a/payment/lib/Drupal/payment/Plugin/payment/context/Base.php b/payment/lib/Drupal/payment/Plugin/payment/context/Base.php
new file mode 100644
index 0000000..609a59e
--- /dev/null
+++ b/payment/lib/Drupal/payment/Plugin/payment/context/Base.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * Contains \Drupal\payment\Plugin\payment\context\Base.
+ */
+
+namespace Drupal\payment\Plugin\payment\context;
+
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\payment\Plugin\payment\context\ContextInterface;
+
+/**
+ * A base context.
+ */
+abstract class Base extends PluginBase implements PaymentContextInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
+    $configuration += array(
+      'paymentId' => 0,
+    );
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPaymentId() {
+    return $this->configuration['paymentId'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setPaymentId($id) {
+    $this->configuration['paymentId'] = $id;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * Child classes are required to overrided this method and explicitly resume
+   * the context workflow.
+   */
+  function resume() {
+    $handler = \Drupal::moduleHandler();
+    $handler->invokeAll('payment_pre_resume', entity_load('payment', $this->getPaymentId()));
+    // @todo Invoke Rules event.
+  }
+}
diff --git a/payment/lib/Drupal/payment/Plugin/payment/context/Manager.php b/payment/lib/Drupal/payment/Plugin/payment/context/Manager.php
new file mode 100644
index 0000000..c6f1904
--- /dev/null
+++ b/payment/lib/Drupal/payment/Plugin/payment/context/Manager.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * Contains \Drupal\payment\Plugin\payment\context\Manager.
+ */
+
+namespace Drupal\payment\Plugin\payment\context;
+
+use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Language\LanguageManager;
+use Drupal\Core\Plugin\DefaultPluginManager;
+
+/**
+ * Manages discovery and instantiation of payment context plugins.
+ *
+ * @see \Drupal\payment\Plugin\payment\context\ContextInterface
+ */
+class Manager extends DefaultPluginManager {
+
+  /**
+   * Constructor.
+   *
+   * @param \Traversable $namespaces
+   *   An object that implements \Traversable which contains the root paths
+   *   keyed by the corresponding namespace to look for plugin implementations.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
+   *   Cache backend instance to use.
+   * @param \Drupal\Core\Language\LanguageManager $language_manager
+   *   The language manager.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler to invoke the alter hook with.
+   */
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, LanguageManager $language_manager, ModuleHandlerInterface $module_handler) {
+    $annotation_namespaces = array(
+      'Drupal\payment\Annotations' => drupal_get_path('module', 'payment') . '/lib',
+    );
+    parent::__construct('payment/context', $namespaces, $annotation_namespaces, 'Drupal\payment\Annotations\PaymentContext');
+    $this->alterInfo($module_handler, 'payment_context');
+    $this->setCacheBackend($cache_backend, $language_manager, 'payment_context');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createInstance($plugin_id, array $configuration = array()) {
+    // If a plugin is missing, use the default.
+    try {
+      return parent::createInstance($plugin_id, $configuration);
+    }
+    catch (PluginException $e) {
+      return parent::createInstance('payment_unavailable', $configuration);
+    }
+  }
+}
diff --git a/payment/lib/Drupal/payment/Plugin/payment/context/PaymentContextInterface.php b/payment/lib/Drupal/payment/Plugin/payment/context/PaymentContextInterface.php
new file mode 100644
index 0000000..137d7a5
--- /dev/null
+++ b/payment/lib/Drupal/payment/Plugin/payment/context/PaymentContextInterface.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * Contains \Drupal\payment\Plugin\payment\context\PaymentContextInterface .
+ */
+
+namespace Drupal\payment\Plugin\payment\context;
+
+use Drupal\Component\Plugin\PluginInspectionInterface;
+
+/**
+ * A payment context plugin.
+ */
+interface PaymentContextInterface extends PluginInspectionInterface {
+
+  /**
+   * Sets the ID of the payment this context is of.
+   *
+   * @param int $id
+   * *
+   * * @return \Drupal\payment\Plugin\payment\context\ContextInterface
+   */
+  public function setPaymentId($id);
+
+  /**
+   * Gets the ID of the payment this context is of.
+   *
+   * @param int
+   */
+  public function getPaymentId();
+
+  /**
+   * Returns the description of the payment this context is of.
+   *
+   * @param string
+   */
+  public function paymentDescription();
+
+  /**
+   * Resumes the payer's context workflow.
+   */
+  public function resume();
+}
diff --git a/payment/lib/Drupal/payment/Plugin/payment/context/Unavailable.php b/payment/lib/Drupal/payment/Plugin/payment/context/Unavailable.php
new file mode 100644
index 0000000..8c89c64
--- /dev/null
+++ b/payment/lib/Drupal/payment/Plugin/payment/context/Unavailable.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * Contains \Drupal\payment\Plugin\payment\context\Unavailable.
+ */
+
+namespace Drupal\payment\Plugin\payment\context;
+
+
+use Drupal\Core\Annotation\Translation;
+use Drupal\payment\Annotations\PaymentContext;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+
+/**
+ * An unavailable context.
+ *
+ * @PaymentContext(
+ *   id = "payment_unavailable",
+ *   label = @Translation("Unavailable")
+ * )
+ */
+class Unavailable extends Base {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function resume() {
+    parent::resume();
+    throw new NotFoundHttpException();
+
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function paymentDescription() {
+    return t('Unavailable');
+  }
+}
diff --git a/payment/lib/Drupal/payment/Tests/Plugin/Core/entity/PaymentStorageControllerTest.php b/payment/lib/Drupal/payment/Tests/Plugin/Core/entity/PaymentStorageControllerTest.php
index e3821b0..6af38b5 100644
--- a/payment/lib/Drupal/payment/Tests/Plugin/Core/entity/PaymentStorageControllerTest.php
+++ b/payment/lib/Drupal/payment/Tests/Plugin/Core/entity/PaymentStorageControllerTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\payment\Tests\Plugin\Core\entity;
 
 use Drupal\payment\Plugin\Core\entity\PaymentInterface;
+use Drupal\payment\Plugin\payment\context\PaymentContextInterface;
 use Drupal\payment\Tests\Utility;
 use Drupal\simpletest\WebTestBase;
 
@@ -53,6 +54,7 @@ class PaymentStorageControllerTest extends WebTestBase {
     $payment_loaded = entity_load_unchanged('payment', $payment->id());
     $this->assertEqual(count($payment_loaded->getLineItems()), count($payment->getLineItems()));
     $this->assertEqual(count($payment_loaded->getStatuses()), count($payment->getStatuses()));
+    $this->assertTrue($payment_loaded->getPaymentContext() instanceof PaymentContextInterface);
   }
 
   /**
diff --git a/payment/lib/Drupal/payment/Tests/Plugin/Core/entity/PaymentTest.php b/payment/lib/Drupal/payment/Tests/Plugin/Core/entity/PaymentTest.php
index 9108613..f8a478b 100644
--- a/payment/lib/Drupal/payment/Tests/Plugin/Core/entity/PaymentTest.php
+++ b/payment/lib/Drupal/payment/Tests/Plugin/Core/entity/PaymentTest.php
@@ -48,7 +48,7 @@ class PaymentTest extends DrupalUnitTestBase {
    * Tests setPaymentContext() and getPaymentContext().
    */
   function testGetPaymentContext() {
-    $context = $this->randomName();
+    $context = \Drupal::service('plugin.manager.payment.context')->createInstance('payment_unavailable');
     $this->assertTrue($this->payment->setPaymentContext($context) instanceof PaymentInterface);
     $this->assertIdentical($this->payment->getPaymentContext(), $context);
   }
@@ -63,15 +63,6 @@ class PaymentTest extends DrupalUnitTestBase {
   }
 
   /**
-   * Tests setFinishCallback() and getFinishCallback().
-   */
-  function testGetFinishCallback() {
-    $callback = $this->randomName();
-    $this->assertTrue($this->payment->setFinishCallback($callback) instanceof PaymentInterface);
-    $this->assertIdentical($this->payment->getFinishCallback(), $callback);
-  }
-
-  /**
    * Tests setLineItem() and getLineItem().
    */
   function testGetLineItem() {
diff --git a/payment/lib/Drupal/payment/Tests/Plugin/payment/context/ManagerTest.php b/payment/lib/Drupal/payment/Tests/Plugin/payment/context/ManagerTest.php
new file mode 100644
index 0000000..f933de3
--- /dev/null
+++ b/payment/lib/Drupal/payment/Tests/Plugin/payment/context/ManagerTest.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Contains class \Drupal\payment\Tests\Plugin\payment\context\ManagerTest.
+ */
+
+namespace Drupal\payment\Tests\Plugin\payment\context;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+
+/**
+ * Tests \Drupal\payment\Plugin\payment\context\Manager.
+ */
+class ManagerTest extends DrupalUnitTestBase {
+
+  public static $modules = array('payment');
+
+  /**
+   * {@inheritdoc}
+   */
+  static function getInfo() {
+    return array(
+      'name' => '\Drupal\payment\Plugin\payment\context\Manager',
+      'group' => 'Payment',
+    );
+  }
+
+  /**
+   * {@inheritdoc
+   */
+  function setUp() {
+    parent::setUp();
+    $this->manager = \Drupal::service('plugin.manager.payment.context');
+  }
+
+  /**
+   * Tests getDefinitions().
+   */
+  function testGetDefinitions() {
+    // Test the default line item plugins.
+    $definitions = $this->manager->getDefinitions();
+    $this->assertEqual(count($definitions), 1);
+    foreach ($definitions as $definition) {
+      $this->assertIdentical(strpos($definition['id'], 'payment_'), 0);
+      $this->assertTrue(is_subclass_of($definition['class'], '\Drupal\payment\Plugin\payment\context\PaymentContextInterface'));
+    }
+  }
+
+  /**
+   * Tests createInstance().
+   */
+  function testCreateInstance() {
+    $id = 'payment_unavailable';
+    $this->assertEqual($this->manager->createInstance($id)->getPluginId(), $id);
+    $this->assertEqual($this->manager->createInstance('ThisIdDoesNotExist')->getPluginId(), $id);
+  }
+}
diff --git a/payment/lib/Drupal/payment/Tests/Plugin/payment/context/UnavailableTest.php b/payment/lib/Drupal/payment/Tests/Plugin/payment/context/UnavailableTest.php
new file mode 100644
index 0000000..91985cd
--- /dev/null
+++ b/payment/lib/Drupal/payment/Tests/Plugin/payment/context/UnavailableTest.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains class \Drupal\payment\Tests\Plugin\payment\context\UnavailableTest.
+ */
+
+namespace Drupal\payment\Tests\Plugin\payment\context;
+
+use Drupal\payment\Plugin\payment\context\PaymentContextInterface ;
+use Drupal\simpletest\WebTestBase;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+
+/**
+ * Tests \Drupal\payment\Plugin\payment\status\Base.
+ *
+ * @todo Convert this to a unit test once contexts accept payments instead of
+ * payment IDs.
+ */
+class UnavailableTest extends WebTestBase {
+
+  public static $modules = array('payment');
+
+  /**
+   * {@inheritdoc}
+   */
+  static function getInfo() {
+    return array(
+      'name' => '\Drupal\payment\Plugin\payment\context\Unavailable',
+      'group' => 'Payment',
+    );
+  }
+
+  /**
+   * {@inheritdoc
+   */
+  function setUp() {
+    parent::setUp();
+    $this->context = \Drupal::service('plugin.manager.payment.context')->createInstance('payment_unavailable', array());
+  }
+
+  /**
+   * Tests resume().
+   */
+  function testResume() {
+    try {
+      $this->context->resume();
+      $this->assertTrue(FALSE);
+    }
+    catch (NotFoundHttpException $exception) {
+      $this->assertTrue(TRUE);
+    }
+  }
+
+  /**
+   * Tests paymentDescription().
+   */
+  function testPaymentDescription() {
+    $this->assertTrue(strlen($this->context->paymentDescription()));
+
+  }
+
+  /**
+   * Tests setPaymentId() and getPaymentId().
+   */
+  function testGetPaymentId() {
+    $id = 7;
+    $this->assertTrue($this->context->setPaymentId($id) instanceof PaymentContextInterface );
+    $this->assertIdentical($this->context->getPaymentId(), $id);
+  }
+}
diff --git a/payment/lib/Drupal/payment/Tests/Utility.php b/payment/lib/Drupal/payment/Tests/Utility.php
index 5a77c81..60ef501 100644
--- a/payment/lib/Drupal/payment/Tests/Utility.php
+++ b/payment/lib/Drupal/payment/Tests/Utility.php
@@ -27,15 +27,16 @@ class Utility {
    * @return \Drupal\payment\Plugin\Core\entity\Payment
    */
   static function createPayment($uid, PaymentMethod $payment_method = NULL) {
-    $lineItemManager = \Drupal::service('plugin.manager.payment.line_item');
-    $payment = entity_create('payment', array());
-    $payment->setFinishCallback('payment_test_finish_callback');
-    $payment->setPaymentMethodId('payment_unavailable');
-    $payment->setOwnerId($uid);
-    $payment->setLineItem($lineItemManager->createInstance('payment_basic', array(
-      'name' => 'foo',
-      'amount' => 1.0,
-    )));
+    $line_item_manager = \Drupal::service('plugin.manager.payment.line_item');
+    $context_manager = \Drupal::service('plugin.manager.payment.context');
+    $payment = entity_create('payment', array())
+      ->setPaymentMethodId('payment_unavailable')
+      ->setOwnerId($uid)
+      ->setPaymentContext($context_manager->createInstance('payment_unavailable'))
+      ->setLineItem($line_item_manager->createInstance('payment_basic', array(
+        'name' => 'foo',
+        'amount' => 1.0,
+      )));
 
     return $payment;
   }
diff --git a/payment/payment.api.php b/payment/payment.api.php
index 00c0780..2dd5852 100644
--- a/payment/payment.api.php
+++ b/payment/payment.api.php
@@ -77,15 +77,13 @@ function hook_payment_pre_execute(PaymentInterface $payment) {
 }
 
 /**
- * Executes right before payment execution is finished.
+ * Executes right before the payment context is resumed.
  *
- * @see Payment::finish()
+ * @see \Drupal\payment\Plugin\payment\method\Base::resume()
  *
  * @param \Drupal\payment\Plugin\Core\Entity\PaymentInterface $payment
- *
- * @return NULL
  */
-function hook_payment_pre_finish(PaymentInterface $payment) {
+function hook_payment_pre_resume(PaymentInterface $payment) {
   if ($payment->getStatus()->isOrHasAncestor('payment_success')) {
     drupal_set_message(t('Your payment was successfully completed.'));
   }
diff --git a/payment/payment.classes.inc b/payment/payment.classes.inc
index de5eb84..3fe404d 100644
--- a/payment/payment.classes.inc
+++ b/payment/payment.classes.inc
@@ -68,12 +68,6 @@ class PaymentValidationMissingCurrencyException extends PaymentValidationExcepti
 class PaymentValidationUnsupportedCurrencyException extends PaymentValidationException {}
 
 /**
- * Exception thrown if a payment's finish callback is not set or the function
- * does not exist.
- */
-class PaymentValidationMissingFinishCallback extends PaymentValidationException {}
-
-/**
  * Exception thrown if a payment's description is missing.
  */
 class PaymentValidationDescriptionMissing extends PaymentValidationException {}
diff --git a/payment/payment.generate.inc b/payment/payment.generate.inc
index 113b8bc..2ab1c04 100644
--- a/payment/payment.generate.inc
+++ b/payment/payment.generate.inc
@@ -46,7 +46,6 @@ class PaymentGenerate {
     $payment = new Payment(array(
       'currency_code' => 'XXX',
       'description' => 'This is the payment description',
-      'finish_callback' => 'payment_generate_finish_callback',
       'method' => $payment_method,
       'uid' => $uid,
     ));
@@ -66,10 +65,3 @@ class PaymentGenerate {
     return $payment;
   }
 }
-
-/**
- * Implements Payment::finish_callback for generated payments.
- *
- * @see payment_generate_payment()
- */
-function payment_generate_finish_callback() {}
\ No newline at end of file
diff --git a/payment/payment.install b/payment/payment.install
index 02495b5..caa3e18 100644
--- a/payment/payment.install
+++ b/payment/payment.install
@@ -66,7 +66,7 @@ function payment_schema() {
   );
   $schema['payment'] = array(
     'fields' => array(
-      'context' => array(
+      'context_plugin_id' => array(
         'type' => 'varchar',
         'length' => 255,
       ),
@@ -76,11 +76,6 @@ function payment_schema() {
         'default' => 'XXX',
         'not null' => TRUE,
       ),
-      'finish_callback' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-      ),
       'id' => array(
         'type' => 'serial',
       ),
@@ -393,6 +388,12 @@ function payment_update_8200(array &$sandbox) {
       ->execute();
   }
 
+  // Rename context to context_plugin_id.
+  db_change_field('payment', 'context', 'context_plugin_id', array(
+    'type' => 'varchar',
+    'length' => 255,
+  ));
+
   // Rename psiid_first to first_payment_status_id.
   db_change_field('payment', 'psiid_first', 'first_payment_status_id', array(
     'description' => "The {payment_status_item}.id of this payment's first status item.",
@@ -429,9 +430,10 @@ function payment_update_8200(array &$sandbox) {
   db_add_index('payment', 'uuid', array('uuid'));
 
   // Drop unnecessary fields.
-  db_drop_field('payment_line_item', 'context_configuration');
-  db_drop_field('payment_line_item', 'description');
-  db_drop_field('payment_line_item', 'description_arguments');
+  db_drop_field('payment', 'context_configuration');
+  db_drop_field('payment', 'description');
+  db_drop_field('payment', 'description_arguments');
+  db_drop_field('payment', 'finish_callback');
 }
 
 /**
diff --git a/payment/payment.module b/payment/payment.module
index c36178f..307e1d5 100644
--- a/payment/payment.module
+++ b/payment/payment.module
@@ -338,7 +338,7 @@ function payment_hook_info() {
   $hooks['payment_pre_execute'] = array(
     'group' => 'payment',
   );
-  $hooks['payment_pre_finish'] = array(
+  $hooks['payment_pre_resume'] = array(
     'group' => 'payment',
   );
   $hooks['payment_validate'] = array(
diff --git a/payment/payment.rules.inc b/payment/payment.rules.inc
index 02aed22..46e1ef9 100644
--- a/payment/payment.rules.inc
+++ b/payment/payment.rules.inc
@@ -35,7 +35,7 @@ function payment_rules_event_info() {
       ),
     ),
   );
-  $event['payment_pre_finish'] = array(
+  $event['payment_pre_resume'] = array(
     'label' => t("When resuming the user's work after finishing payment execution"),
     'group' => t('Payment'),
     'access callback' => 'payment_rules_access',
diff --git a/payment/payment.services.yml b/payment/payment.services.yml
index 3ac4fc2..86c02ab 100644
--- a/payment/payment.services.yml
+++ b/payment/payment.services.yml
@@ -1,4 +1,7 @@
 services:
+  plugin.manager.payment.context:
+    class: Drupal\payment\Plugin\payment\context\Manager
+    arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
   plugin.manager.payment.line_item:
     class: Drupal\payment\Plugin\payment\line_item\Manager
     arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
diff --git a/payment/tests/payment_test/payment_test.module b/payment/tests/payment_test/payment_test.module
index d44e1e3..2cb3a88 100644
--- a/payment/tests/payment_test/payment_test.module
+++ b/payment/tests/payment_test/payment_test.module
@@ -66,17 +66,10 @@ function payment_test_payment_pre_execute(Payment $payment) {
 }
 
 /**
- * Implements hook_payment_pre_finish().
+ * Implements hook_payment_pre_resume().
  */
-function payment_test_payment_pre_finish(Payment $payment) {
-  $payment->payment_test_payment_pre_finish = TRUE;
-}
-
-/**
- * Implements Payment finish callback.
- */
-function payment_test_finish_callback(Payment $payment) {
-  $payment->payment_test_finish_callback = TRUE;
+function payment_test_payment_pre_resume(Payment $payment) {
+  $payment->payment_test_payment_pre_resume = TRUE;
 }
 
 /**
