0

I have a controller that calls the Stripe API using stripe-php to create a checkout session.

  /**
   * Checkout using Stripe.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   The response.
   */
  public function checkout(Request $request): Response {
    $stripe_settings = $this->config('stripe.settings');
    Stripe::setApiKey($stripe_settings->get('apikey.' . $stripe_settings->get('environment') . '.secret'));

    // Create a Stripe checkout session.
    // https://stripe.com/docs/checkout/quickstart
    $checkout_session = Session::create([
      'line_items' => [
        [
          'price_data' => [
            'currency' => 'usd',
            'unit_amount' => 100,
            'product_data' => [
              'name' => 'Product $1',
              'description' => 'Description',
            ],
          ],
          'quantity' => 1,
        ],
      ],
      'mode' => 'payment',
      'success_url' => 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}',
      'cancel_url' => 'https://example.com/cancel',
    ]);
    $checkout_url = $checkout_session->baseUrl() . $checkout_session->instanceUrl();

    // In order to avoid errors like this:
    // - LogicException: The controller result claims to be providing relevant
    //   cache metadata, but leaked metadata was detected. Please ensure you are
    //   not rendering content too early. ... TrustedRedirectResponse.
    // Every Url::toString needs to have "->toString(TRUE)->getGeneratedUrl();".
    // See https://www.drupal.org/node/2638686
    $url = Url::fromUri($checkout_url, ['absolute' => TRUE, 'https' => TRUE])->toString(TRUE);
    $headers = [
      'Authorization' => 'Bearer ' . Stripe::getApiKey(),
    ];
    $response = new TrustedRedirectResponse($url->getGeneratedUrl(), Response::HTTP_SEE_OTHER, $headers);
    $response->addCacheableDependency((new CacheableMetadata())->setCacheMaxAge(0));

    // Redirect to Stripe checkout URL.
    return $response;
  }

So I call Stripe::setApiKey, I have my keys correctly set up (the checkout session is created), and the redirect to the external Stripe.com checkout session URL works. But it says the API key is missing from the headers.

I checked using Fiddler, and the header I added is sent correct in the controller's redirect response.

When looking at Stripe's checkout documentation, it doesn't use a controller, and it doesn't seem to need a separate header with the API key. So I'm not really sure what I'm missing. Do I have to do something different to ensure the header stays there after the redirect occurs in the browser or something?

3
  • As far as I know, it's not possible to send headers when redirecting.
    – Jaypan
    Mar 2 at 0:22
  • 1
    You could send headers and, as the OP is telling, this was successful. But it's a futile attempt because the browser won't recognize them. See stackoverflow.com/questions/7583461/…. If you want to preserve data you set them in a session before redirecting and according to the class name of the PHP library this is what the code is trying to do.
    – 4uk4
    Mar 2 at 7:41
  • So what you're saying is that, looking at the code at stripe.com/docs/checkout/quickstart, it should work without such a header (which isn't possible to send), because the checkout session is a session that has been authenticated already.
    – mbomb007
    Mar 2 at 14:25

1 Answer 1

0

The problem was that I used

$checkout_url = $checkout_session->baseUrl() . $checkout_session->instanceUrl();

Because that is https://api.stripe.com/v1/checkout/sessions/cs_test_...

I needed to use

$checkout_url = $checkout_session->url;

Which is https://checkout.stripe.com/c/pay/cs_test_...

So now I just have

$response = new TrustedRedirectResponse($checkout_session->url, Response::HTTP_SEE_OTHER);
$response->addCacheableDependency((new CacheableMetadata())->setCacheMaxAge(0));

return $response;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.