Forum

Thread tagged as: Question, Error, Shop

PHP Error Redirect to return_url success page

Hi, I'm using stripe checkout. The following log error prevents redirects to the return_url success page

[08-Jul-2016 18:58:14 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/shop/cart/checkout.php:7) in /Applications/MAMP/htdocs/perch/core/lib/PerchUtil.class.php on line 194

Diagnostic Report

Perch: 2.8.30, PHP: 5.6.10, MySQL: mysqlnd 5.0.11-dev - 20120503 - $Id: 3c688b6bbc30d36af3ac34fdd4b7b5b787fe5555 $, with PDO
Server OS: Darwin, apache2handler
Installed apps: content (2.8.30), assets (2.8.30), categories (2.8.30), perch_shop_orders (1.0.6), perch_shop_products (1.0.6), perch_shop (1.0.6), perch_members (1.5)
App runtimes: <?php $apps_list = array( 'content', 'categories', 'perch_members', 'perch_shop', ); ?>
PERCH_LOGINPATH: /perch
PERCH_PATH: /Applications/MAMP/htdocs/perch
PERCH_CORE: /Applications/MAMP/htdocs/perch/core
PERCH_RESFILEPATH: /Applications/MAMP/htdocs/perch/resources
Image manipulation: GD
PHP limits: Max upload 32M, Max POST 32M, Memory: 128M, Total max file upload: 32M
F1: 2edba60ed1f613d6dd804feb202456a2
Resource folder writeable: Yes
HTTP_HOST: localhost:8888
DOCUMENT_ROOT: /Applications/MAMP/htdocs
REQUEST_URI: /perch/core/settings/diagnostics/
SCRIPT_NAME: /perch/core/settings/diagnostics/index.php
Fred Stidston

Fred Stidston 0 points

  • 5 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

What's on checkout.php line 7 (as per the error message)?

Line 7 makes no difference when removed

    <?php perch_get_css(); ?>

The error moves to Line 11. Thats a line containing the perch content tag for the heading. This is the full page

<?php include($_SERVER['DOCUMENT_ROOT'].'/perch/runtime.php'); ?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Perch Example Page</title>
  <script src="https://checkout.stripe.com/checkout.js"></script>
</head>
<body>
  <header>
    <h1><a href="../../"><?php perch_content('Main heading'); ?></a></h1>
    <span><?php perch_content('Introduction'); ?></span>
  </header>
  <main>
    <h2>Checkout </h2>
    <?php
    if (!perch_member_logged_in()) {
      // Returning customer login form
      perch_shop_login_form();
      // New customer sign up form
      perch_shop_registration_form();
    } else {
      perch_shop_payment_form('stripe');
    }
    if (perch_member_logged_in() && perch_post('stripeToken')) {
      perch_shop_checkout('stripe', [
        'return_url' => 'success.php',
        'cancel_url' => 'failure.php',
        'token'      => perch_post('stripeToken')
      ]);
    }
    ?>
    <?php PerchUtil::output_debug(); ?>
  </main>
    <?php perch_get_javascript(); ?>
</body>
</html>
Drew McLellan

Drew McLellan 2638 points
Perch Support

If you want Perch to be able to issue a redirect, the call has to occur before you send any HTML to the browser.

Okay, please may you explain how the perch return_url variable is intended to be used to issue the redirect?

Drew McLellan

Drew McLellan 2638 points
Perch Support

If you wish to make an apple pie from scratch, you must first invent the universe. :)

It's down to the basics of HTTP. An HTTP response includes headers and a body. In those headers, you can set things like a Location header (a redirect), cookies, all sorts.

The body is typically the content of the file you're sending - so in our case an HTML document.

The trick is, once you stop sending the headers and start sending the body, you can't go back and set new headers. Therefore if you want to do anything that involves setting a header, you need to do it before the page content is output.

A redirect is a Location header, so it needs to be sent before any part of the page. If you put perch_shop_checkout() down in the middle of your page, the top chunk of HTML will have already been sent to the browser by the time it's processed, and so the redirect is going to fail - it's a header that can't be sent.

So, move this:

if (perch_member_logged_in() && perch_post('stripeToken')) {
      perch_shop_checkout('stripe', [
        'return_url' => 'success.php',
        'cancel_url' => 'failure.php',
        'token'      => perch_post('stripeToken')
      ]);
    }

to right after this:

<?php include($_SERVER['DOCUMENT_ROOT'].'/perch/runtime.php'); ?>

Like this:

<?php include($_SERVER['DOCUMENT_ROOT'].'/perch/runtime.php'); 

if (perch_member_logged_in() && perch_post('stripeToken')) {
      perch_shop_checkout('stripe', [
        'return_url' => 'success.php',
        'cancel_url' => 'failure.php',
        'token'      => perch_post('stripeToken')
      ]);
    }
?>

Now the redirect will happen before any of the HTML is sent, so the server will be able to set the correct HTTP header and everyone's happy.

Wow thank you very much, Drew.

A 301 redirect is a permanent redirect from one URL to another. 301 redirects send site visitors and search engines to a different URL than the one they originally typed into their browser or selected from a search engine results page. These redirects also link various URLs under one umbrella so search engines rank all of the addresses based on the domain authority from inbound links. More about....Redirect a Web Page

Brian