diff --git a/modules/payment_form/src/Entity/Payment/PaymentForm.php b/modules/payment_form/src/Entity/Payment/PaymentForm.php
index 48c9e48..fc78795 100644
--- a/modules/payment_form/src/Entity/Payment/PaymentForm.php
+++ b/modules/payment_form/src/Entity/Payment/PaymentForm.php
@@ -12,7 +12,7 @@ use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\payment\Plugin\Payment\MethodSelector\PaymentMethodSelectorManagerInterface;
-use Drupal\payment\ResponseInterface;
+use Drupal\payment\Response\ResponseInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
diff --git a/modules/payment_form/src/Plugin/Payment/Type/PaymentForm.php b/modules/payment_form/src/Plugin/Payment/Type/PaymentForm.php
index 9e3a47b..eb48381 100644
--- a/modules/payment_form/src/Plugin/Payment/Type/PaymentForm.php
+++ b/modules/payment_form/src/Plugin/Payment/Type/PaymentForm.php
@@ -12,7 +12,7 @@ use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\Url;
 use Drupal\payment\Plugin\Payment\Type\PaymentTypeBase;
-use Drupal\payment\Response;
+use Drupal\payment\Response\RedirectResponse;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -94,7 +94,7 @@ class PaymentForm extends PaymentTypeBase implements ContainerFactoryPluginInter
    * {@inheritdoc}
    */
   protected function doGetResumeContextResponse() {
-    return new Response(Url::fromUri($this->getDestinationUrl()));
+    return new RedirectResponse(Url::fromUri($this->getDestinationUrl()));
   }
 
   /**
diff --git a/modules/payment_form/tests/src/Unit/Entity/Payment/PaymentFormUnitTest.php b/modules/payment_form/tests/src/Unit/Entity/Payment/PaymentFormUnitTest.php
index 70f142a..e95ff14 100644
--- a/modules/payment_form/tests/src/Unit/Entity/Payment/PaymentFormUnitTest.php
+++ b/modules/payment_form/tests/src/Unit/Entity/Payment/PaymentFormUnitTest.php
@@ -9,7 +9,7 @@ namespace Drupal\Tests\payment_form\Unit\Entity\Payment;
 
 use Drupal\Core\Form\FormState;
 use Drupal\Core\Url;
-use Drupal\payment\Response;
+use Drupal\payment\Response\RedirectResponse;
 use Drupal\payment_form\Entity\Payment\PaymentForm;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -212,7 +212,7 @@ class PaymentFormUnitTest extends UnitTestCase {
    */
   public function testSubmitForm() {
     $redirect_url = new Url($this->randomMachineName());
-    $response = new Response($redirect_url);
+    $response = new RedirectResponse($redirect_url);
 
     $result = $this->getMock('\Drupal\payment\PaymentExecutionResultInterface');
     $result->expects($this->atLeastOnce())
diff --git a/modules/payment_reference/src/Plugin/Payment/Type/PaymentReference.php b/modules/payment_reference/src/Plugin/Payment/Type/PaymentReference.php
index 6d23d26..0b19633 100644
--- a/modules/payment_reference/src/Plugin/Payment/Type/PaymentReference.php
+++ b/modules/payment_reference/src/Plugin/Payment/Type/PaymentReference.php
@@ -13,7 +13,7 @@ use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\Url;
 use Drupal\payment\Plugin\Payment\Type\PaymentTypeBase;
-use Drupal\payment\Response;
+use Drupal\payment\Response\RedirectResponse;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -99,7 +99,7 @@ class PaymentReference extends PaymentTypeBase implements ContainerFactoryPlugin
    * {@inheritdoc}
    */
   protected function doGetResumeContextResponse() {
-    return new Response(new Url('payment_reference.resume_context', array(
+    return new RedirectResponse(new Url('payment_reference.resume_context', array(
       'payment' => $this->getPayment()->id(),
     ), array(
       'absolute' => TRUE,
diff --git a/modules/payment_test/src/Plugin/Payment/Method/PaymentTestResponse.php b/modules/payment_test/src/Plugin/Payment/Method/PaymentTestResponse.php
index c8dc25a..d430830 100644
--- a/modules/payment_test/src/Plugin/Payment/Method/PaymentTestResponse.php
+++ b/modules/payment_test/src/Plugin/Payment/Method/PaymentTestResponse.php
@@ -8,7 +8,7 @@ namespace Drupal\payment_test\Plugin\Payment\Method;
 
 use Drupal\Core\Url;
 use Drupal\payment\PaymentExecutionResult;
-use Drupal\payment\Response;
+use Drupal\payment\Response\RedirectResponse;
 
 /**
  * A testing payment method.
@@ -26,7 +26,7 @@ class PaymentTestResponse extends PaymentTestNoResponse {
    * {@inheritdoc}
    */
   public function getPaymentExecutionResult() {
-    return new PaymentExecutionResult(new Response(new Url('http://example.com')));
+    return new PaymentExecutionResult(new RedirectResponse(new Url('http://example.com')));
   }
 
 }
diff --git a/payment.routing.yml b/payment.routing.yml
index 411307b..11605be 100644
--- a/payment.routing.yml
+++ b/payment.routing.yml
@@ -195,3 +195,10 @@ payment.payment_type:
     _title_callback: '\Drupal\payment\Controller\PaymentType::configureTitle'
   requirements:
     _permission: 'payment.payment_type.administer'
+
+payment.form_post_redirect:
+  path: '/payment-form-post-redirect'
+  defaults:
+    _controller: '\Drupal\payment\Controller\FormPostRedirect::execute'
+  requirements:
+    _custom_access: '\Drupal\payment\Controller\FormPostRedirect::access'
diff --git a/src/Controller/FormPostRedirect.php b/src/Controller/FormPostRedirect.php
new file mode 100644
index 0000000..7fd8ca7
--- /dev/null
+++ b/src/Controller/FormPostRedirect.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Controller\FormPostRedirect.
+ */
+
+namespace Drupal\payment\Controller;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\payment\Response\FormPostRedirectBuilderInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Handles the "form POST redirect" route.
+ */
+class FormPostRedirect extends ControllerBase implements ContainerInjectionInterface {
+
+  /**
+   * The form POST redirect builder.
+   *
+   * @var \Drupal\payment\Response\FormPostRedirectBuilderInterface
+   */
+  protected $formPostRedirectBuilder;
+
+  /**
+   * The request stack.
+   *
+   * @var \Symfony\Component\HttpFoundation\RequestStack
+   */
+  protected $requestStack;
+
+  /**
+   * Constructs a new instance.
+   *
+   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
+   * @param \Drupal\payment\Response\FormPostRedirectBuilderInterface $form_post_redirect_builder
+   */
+  public function __construct(RequestStack $request_stack, FormPostRedirectBuilderInterface $form_post_redirect_builder) {
+    $this->formPostRedirectBuilder = $form_post_redirect_builder;
+    $this->requestStack = $request_stack;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static($container->get('request_stack'), $container->get('payment.form_post_redirect_builder'));
+  }
+
+  /**
+   * Executes the route.
+   *
+   * @return \Symfony\Component\HttpFoundation\Response
+   */
+  public function execute() {
+    $request = $this->requestStack->getCurrentRequest();
+    $query_values = $request->query->all();
+    $values = [];
+    foreach ($query_values as $name => $query_value) {
+      if (strpos($name, 'value-') !== FALSE) {
+        $values[substr($name, 6)] = $query_value;
+      }
+    }
+
+    return $this->formPostRedirectBuilder->buildResponse($request->query->get('destination'), $values)->getResponse();
+  }
+
+  /**
+   * Checks if the user has access to the route.
+   *
+   * @return \Drupal\Core\Access\AccessResultInterface
+   */
+  public function access() {
+    $request = $this->requestStack->getCurrentRequest();
+    $query_values = $request->query->all();
+    $has_value = FALSE;
+    foreach ($query_values as $name => $query_value) {
+      if (strpos($name, 'value-') !== FALSE) {
+        $has_value = TRUE;
+        break;
+      }
+    }
+
+    return AccessResult::allowedIf($request->query->has('destination') && $has_value);
+  }
+
+}
diff --git a/src/PaymentExecutionResult.php b/src/PaymentExecutionResult.php
index 4a458f0..2c8ae7d 100644
--- a/src/PaymentExecutionResult.php
+++ b/src/PaymentExecutionResult.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\payment;
+use Drupal\payment\Response\ResponseInterface;
 
 /**
  * Provides a payment execution result.
@@ -15,14 +16,14 @@ class PaymentExecutionResult implements PaymentExecutionResultInterface {
   /**
    * The response.
    *
-   * @var \Drupal\payment\ResponseInterface|null
+   * @var \Drupal\payment\Response\ResponseInterface|null
    */
   protected $response;
 
   /**
    * Creates a new instance.
    *
-   * @param \Drupal\payment\ResponseInterface|null $response
+   * @param \Drupal\payment\Response\ResponseInterface|null $response
    *   A response or NULL if execution has completed.
    */
   public function __construct(ResponseInterface $response = NULL) {
diff --git a/src/PaymentExecutionResultInterface.php b/src/PaymentExecutionResultInterface.php
index e91725a..f6e0c5a 100644
--- a/src/PaymentExecutionResultInterface.php
+++ b/src/PaymentExecutionResultInterface.php
@@ -28,7 +28,7 @@ interface PaymentExecutionResultInterface {
   /**
    * Gets the response to complete payment execution.
    *
-   * @return \Drupal\payment\ResponseInterface|null
+   * @return \Drupal\payment\Response\ResponseInterface|null
    *   A response (only if self::isInProgress() returns TRUE) or NULL if payment
    *   execution cannot be completed (anymore).
    */
diff --git a/src/Plugin/Payment/Type/PaymentTypeBase.php b/src/Plugin/Payment/Type/PaymentTypeBase.php
index f7cb9f3..a8725e7 100644
--- a/src/Plugin/Payment/Type/PaymentTypeBase.php
+++ b/src/Plugin/Payment/Type/PaymentTypeBase.php
@@ -117,7 +117,7 @@ abstract class PaymentTypeBase extends PluginBase implements ContainerFactoryPlu
   /**
    * Performs the actual context resumption.
    *
-   * @return \Drupal\payment\ResponseInterface
+   * @return \Drupal\payment\Response\ResponseInterface
    */
   abstract protected function doGetResumeContextResponse();
 
diff --git a/src/Plugin/Payment/Type/PaymentTypeInterface.php b/src/Plugin/Payment/Type/PaymentTypeInterface.php
index bf7b626..98c330e 100644
--- a/src/Plugin/Payment/Type/PaymentTypeInterface.php
+++ b/src/Plugin/Payment/Type/PaymentTypeInterface.php
@@ -56,7 +56,7 @@ interface PaymentTypeInterface extends PluginInspectionInterface, ConfigurablePl
   /**
    * Resumes the payer's original workflow.
    *
-   * @return \Drupal\payment\ResponseInterface
+   * @return \Drupal\payment\Response\ResponseInterface
    *
    * @see self::resumeContextAccess
    */
diff --git a/src/Response.php b/src/Response.php
deleted file mode 100644
index 6d96950..0000000
--- a/src/Response.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\payment\Response.
- */
-
-namespace Drupal\payment;
-
-use Drupal\Core\Url;
-use Symfony\Component\HttpFoundation\RedirectResponse;
-use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
-
-/**
- * Provides a payment response.
- */
-class Response implements ResponseInterface {
-
-  /**
-   * The redirect URL.
-   *
-   * @var \Drupal\Core\Url
-   */
-  protected $url;
-
-  /**
-   * The response.
-   *
-   * @var \Symfony\Component\HttpFoundation\Response|null
-   */
-  protected $response;
-
-  /**
-   * Creates a new instance.
-   *
-   * @param \Drupal\Core\Url $url
-   * @param \Symfony\Component\HttpFoundation\Response|null $response
-   */
-  public function __construct(Url $url, SymfonyResponse $response = NULL) {
-    $this->response = $response;
-    $this->url = $url;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getRedirectUrl() {
-    return $this->url;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getResponse() {
-    return $this->response ? $this->response : new RedirectResponse($this->getRedirectUrl()->toString());
-  }
-
-}
diff --git a/src/Response/FormPostRedirectBuilder.php b/src/Response/FormPostRedirectBuilder.php
new file mode 100644
index 0000000..7f8395d
--- /dev/null
+++ b/src/Response/FormPostRedirectBuilder.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Response\FormPostRedirectBuilder.
+ */
+
+namespace Drupal\payment\Response;
+
+use Drupal\Core\Render\RendererInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\Core\Url;
+use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
+
+/**
+ * Provides a form POST redirect builder.
+ */
+class FormPostRedirectBuilder implements FormPostRedirectBuilderInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * The renderer.
+   *
+   * @var \Drupal\Core\Render\RendererInterface
+   */
+  protected $renderer;
+
+  /**
+   * Constructs a new instance.
+   *
+   * @param \Drupal\Core\Render\RendererInterface $renderer
+   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
+   */
+  public function __construct(RendererInterface $renderer, TranslationInterface $string_translation) {
+    $this->renderer = $renderer;
+    $this->stringTranslation = $string_translation;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildResponse($destination, array $values) {
+    $form = [
+      '#action' => $destination,
+      '#id' => 'payment-form-post-redirect',
+    ];
+    foreach ($values as $name => $value) {
+      $form[$name] = [
+        '#type' => 'hidden',
+        '#value' => $value,
+      ];
+    }
+    // We need form submission as quickly as possible, so use light inline code.
+    $form['js'] = [
+      '#markup' => '<script type="text/javascript">document.getElementById(\'payment-form-post-redirect\').submit();</script>',
+    ];
+    $form['submit'] = [
+      '#attributes' => [
+        'class' => ['js-hide'],
+      ],
+      '#value' => $this->t('Go'),
+    ];
+
+    $query_values = [];
+    foreach ($values as $name => $value) {
+      $query_values['value-' . $name] = $value;
+    }
+    $url = new Url('payment.form_post_redirect', [], [
+      'query' => [
+          'destination' => $destination,
+        ] + $query_values,
+    ]);
+    $symfony_response = new SymfonyResponse($this->renderer->renderRoot($form));
+
+    return new Response($url, $symfony_response);
+  }
+
+}
diff --git a/src/Response/FormPostRedirectBuilderInterface.php b/src/Response/FormPostRedirectBuilderInterface.php
new file mode 100644
index 0000000..59ce822
--- /dev/null
+++ b/src/Response/FormPostRedirectBuilderInterface.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Response\FormPostRedirectBuilderInterface.
+ */
+
+namespace Drupal\payment\Response;
+
+/**
+ * Defines a form POST redirect builder.
+ */
+interface FormPostRedirectBuilderInterface {
+
+  /**
+   * Builds a redirect response.
+   *
+   * @param string $destination
+   * @param mixed[] $values
+   *   Values MUST be scalars.
+   *
+   * @return \Drupal\payment\Response\ResponseInterface
+   */
+  public function buildResponse($destination, array $values);
+
+}
diff --git a/src/Response/RedirectResponse.php b/src/Response/RedirectResponse.php
new file mode 100644
index 0000000..2f6e94f
--- /dev/null
+++ b/src/Response/RedirectResponse.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\RedirectResponse.
+ */
+
+namespace Drupal\payment\Response;
+
+use Drupal\Core\Url;
+use Symfony\Component\HttpFoundation\RedirectResponse as SymfonyRedirectResponse;
+
+/**
+ * Provides a redirect payment response.
+ */
+class RedirectResponse extends Response {
+
+  /**
+   * Creates a new instance.
+   *
+   * @param \Drupal\Core\Url $url
+   */
+  public function __construct(Url $url) {
+    $this->response = new SymfonyRedirectResponse($url->toString());
+    $this->url = $url;
+  }
+
+}
diff --git a/src/Response/Response.php b/src/Response/Response.php
new file mode 100644
index 0000000..685d634
--- /dev/null
+++ b/src/Response/Response.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Response.
+ */
+
+namespace Drupal\payment\Response;
+
+use Drupal\Core\Url;
+use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
+
+/**
+ * Provides a payment response.
+ */
+class Response implements ResponseInterface {
+
+  /**
+   * The redirect URL.
+   *
+   * @var \Drupal\Core\Url
+   */
+  protected $url;
+
+  /**
+   * The redirect values.
+   *
+   * @param mixed[] $values
+   *   Values MUST be scalars.
+   */
+  protected $values;
+
+  /**
+   * Creates a new instance.
+   *
+   * @param \Drupal\Core\Url $url
+   * @param \Symfony\Component\HttpFoundation\Response $response
+   */
+  public function __construct(Url $url, SymfonyResponse $response) {
+    $this->response = $response;
+    $this->url = $url;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRedirectUrl() {
+    return $this->url;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getResponse() {
+    return $this->response;
+  }
+
+}
diff --git a/src/Response/ResponseInterface.php b/src/Response/ResponseInterface.php
new file mode 100644
index 0000000..1a32f10
--- /dev/null
+++ b/src/Response/ResponseInterface.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\ResponseInterface.
+ */
+
+namespace Drupal\payment\Response;
+
+/**
+ * Defines a payment response.
+ */
+interface ResponseInterface {
+
+  /**
+   * Gets the URL the calling code must redirect to after payment execution.
+   *
+   * @return \Drupal\Core\Url
+   */
+  public function getRedirectUrl();
+
+  /**
+   * Gets the response the calling code must return after payment execution.
+   *
+   * @return \Symfony\Component\HttpFoundation\Response
+   */
+  public function getResponse();
+
+}
diff --git a/src/ResponseInterface.php b/src/ResponseInterface.php
deleted file mode 100644
index c9e9497..0000000
--- a/src/ResponseInterface.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\payment\ResponseInterface.
- */
-
-namespace Drupal\payment;
-
-/**
- * Defines a payment response.
- *
- * When returning a instance of a class that implements this interface,
- * self::getRedirectUrl() MUST return a value and calling code MUST be able to
- * perform a redirect using this value. All other functionality is optional.
- */
-interface ResponseInterface {
-
-  /**
-   * Gets the URL the calling code may redirect to after payment execution.
-   *
-   * @return \Drupal\Core\Url
-   */
-  public function getRedirectUrl();
-
-  /**
-   * Gets the response
-   *
-   * @return \Symfony\Component\HttpFoundation\Response
-   */
-  public function getResponse();
-
-}
diff --git a/tests/src/Unit/PaymentExecutionResultUnitTest.php b/tests/src/Unit/PaymentExecutionResultUnitTest.php
index 61cbf60..d2ff8c9 100644
--- a/tests/src/Unit/PaymentExecutionResultUnitTest.php
+++ b/tests/src/Unit/PaymentExecutionResultUnitTest.php
@@ -21,7 +21,7 @@ class PaymentExecutionResultUnitTest extends UnitTestCase {
   /**
    * The response.
    *
-   * @var \Drupal\payment\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\payment\Response\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
    */
   protected $response;
 
diff --git a/tests/src/Unit/ResponseUnitTest.php b/tests/src/Unit/ResponseUnitTest.php
index c6e4aae..cd72a4c 100644
--- a/tests/src/Unit/ResponseUnitTest.php
+++ b/tests/src/Unit/ResponseUnitTest.php
@@ -9,7 +9,7 @@ namespace Drupal\Tests\payment\Unit;
 
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Url;
-use Drupal\payment\Response;
+use Drupal\payment\Response\RedirectResponse;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -36,7 +36,7 @@ class ResponseUnitTest extends UnitTestCase {
   /**
    * The response under test.
    *
-   * @var \Drupal\payment\Response
+   * @var \Drupal\payment\Response\RedirectResponse
    */
   protected $response;
 
@@ -52,7 +52,7 @@ class ResponseUnitTest extends UnitTestCase {
       ->disableOriginalConstructor()
       ->getMock();
 
-    $this->response = new Response($this->redirectUrl, $this->symfonyResponse);
+    $this->response = new RedirectResponse($this->redirectUrl, $this->symfonyResponse);
   }
 
   /**
@@ -85,7 +85,7 @@ class ResponseUnitTest extends UnitTestCase {
 
     \Drupal::setContainer($container);
 
-    $this->response = new Response($this->redirectUrl);
+    $this->response = new RedirectResponse($this->redirectUrl);
 
     $this->assertInstanceOf('\Symfony\Component\HttpFoundation\RedirectResponse', $this->response->getResponse());
   }
