Forum

Thread tagged as: Problem, Shop

Shop return_url not working on a view (MVC app)

I've been integrating perch with a site which has an MVC framework. The original site allows people to post classified adverts and the perch integration is intended to make use of the members and shop features so that users must log in before posting ads and can pay for upgrading their ads.

Everything has been going fine and everything seems to have integrated well but the only issue I seem to have is that, after the user submits their ad and comes to the payment page, the stripe payment goes through fine but the return_url is not working. After the stripe popup disappears with the green tick it just seems to reload the same page instead of going to the return_url that's been set.

I wonder if it has something to do with the fact the page where they enter their card details is not a physical page, it's a page I guess generated on the fly by the app and includes a token, in the form:

mywebsite.com/ads/0001/publish/ede46bf0f4b226ab33ef8c7bbf04ad23

The return_url works fine if I create a new, separate page away from the MVC app so I think that code itself is sound. Here are some of the files in question:

ad.publish.php view:

<?php 
// pass to stripe basics
$customer_firstname = perch_member_get('first_name');
$customer_surname = perch_member_get('last_name');
$customer_name = $customer_firstname . ' ' . $customer_surname;
$customer_email = perch_member_get('email');

// pass to stripe cart titles, skus
$cart = perch_shop_cart(['skip-template'=>true]);
$cart_items = $cart['items'];

foreach($cart_items as $item) {
$product_titles[] = $item['title'];
$product_skus[] = $item['sku'];
}

$product_title = implode(', ', $product_titles);
$product_sku = implode(', ', $product_skus);

// stripe urls
if (perch_member_logged_in() && perch_post('stripeToken')) {

$return_url = '/dashboard';
$cancel_url = '/cancel';

// stripe data
perch_shop_checkout('stripe', [
'return_url' => $return_url,
'cancel_url' => $cancel_url,
'token' => perch_post('stripeToken'),
'receipt_email' => $customer_email,
'metadata' => [
    'email' => $customer_email,
    'name' => $customer_name,
    'product(s)' => $product_title,
    'sku(s)' => $product_sku,
    ],
]);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>

<div>
<div>

<h1>Pay here</h1>

<?php 
    perch_shop_empty_cart();
    perch_shop_add_to_cart(1);
    // Show the cart with a non-interactive template
    perch_shop_cart([
        'template'=>'cart/cart_static.html'
    ]);
    // Show the order addresses
    perch_shop_order_addresses();
    // Show the payment form
    perch_shop_payment_form('stripe');

?>

</div>
</div>

</body>
</html>

the controller for the page:

// get publish ad details 
    $app->get('/:id/publish/:token', 'isAdPostAllowed', 'isBanned', function ($id, $token) use ($app) {

        global $lang;

        $j = new Ads($id);
        $ad = $j->getAdFromToken($token);

        $city = $j->getAdCity($ad->city);
        $category = $j->getAdCategory($ad->category);

        $amount = 0;
        if (!$ad->status) {
            $amount += AMOUNT_JOB;
        }
        if ($ad->is_featured < 0) {
            $amount += AMOUNT_FEATURED;
        }

        if (isset($ad) && $ad->id) {

            $seo_title = clean($ad->title) .' - '. APP_NAME;
            $seo_desc = excerpt($ad->description);
            $seo_url = BASE_URL ."ads/{$id}";

            $app->render(THEME_PATH . 'ad.publish.php', 
                        array('lang' => $lang,
                            'seo_url'=>$seo_url, 
                            'seo_title'=>$seo_title, 
                            'seo_desc'=>$seo_desc, 
                            'ad'=>$ad,
                            'slug'=>$j->getSlugTitle(), 
                            'city'=>$city, 
                            'category'=>$category,
                            'amount'=>$amount));
        } else {
            $app->flash('danger', $lang->t('alert|error_encountered'));
            $app->redirect(BASE_URL . "ads/{$id}");
        }        
    });

The perch runtime is being called in the main index.php file of the app, like so:

<?php

/*
 * Load the configuration file
 */
require 'config.php';
include('members/runtime.php'); // include perch

/*
 * Load category and city values
 */
$categories = Categories::findCategories();
$cities = Cities::findCities();

$perch_email = (perch_member_logged_in())? perch_member_get('email'):'';

/*
 * Load all existing controllers
 */
foreach (glob(CONTROLLER_PATH . "*.php") as $controller) {
    require_once $controller;
}

/*
 * Homepage
 * Front page controller
 */
$app->get('/(:page)', function ($page=null) use ($app) {

    global $categories;
    global $lang;

    if (isset($page) && $page != '') {
        $content = R::findOne('pages', ' url=:url ', array(':url'=>$page));
        if ($content && $content->id) {

            // show page information
            $seo_title = $content->name .' | '. APP_NAME;
            $seo_desc = excerpt($content->description);
            $seo_url = BASE_URL . $page;

            $app->render(THEME_PATH . 'page.php', 
                    array('lang' => $lang,
                        'seo_url'=>$seo_url, 
                        'seo_title'=>$seo_title, 
                        'seo_desc'=>$seo_desc, 
                        'content'=>$content));
        } else {
            $app->redirect(BASE_URL, 404);
        }
    } else {

        // show list of ad
        $seo_title = APP_NAME;
        $seo_desc = APP_DESC;
        $seo_url = BASE_URL;

        $j = new Ads();

        $ads = $j->getAdsAllCategories(ACTIVE, 0, HOME_LIMIT);

        $app->render(THEME_PATH . 'home.php', 
                    array('lang' => $lang,
                        'seo_url'=>$seo_url, 
                        'seo_title'=>$seo_title, 
                        'seo_desc'=>$seo_desc, 
                        'ads'=>$ads));
    }
});

// Run app
$app->run();

Any ideas how I can get that return_url to fire as expected within this environment?

Thanks!

Stephen Turvey

Stephen Turvey 0 points

  • 3 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

Have you turned on debug to see what's happening?

This is the debug. Once you put the card details in and confirm, the page reloads and the debug is exactly the same (other than the cartID number increasing)

Debug Message - Perch 3.0.12
[1] SELECT * FROM perch3_members_sessions WHERE sessionID='6c9bee5f647d1a62bed89ad99fd0c7c311fe2b70' AND sessionHttpFootprint='07a7cac1fdbe66fee0ec105f710f9e047cd55858' AND sessionExpires>'2018-01-04 19:24:39' LIMIT 1
User is logged in
[1] SELECT * FROM perch3_pages WHERE pagePath='/index.php' LIMIT 1
[1] SELECT * FROM perch3_shop_cart WHERE cartID=80
[1] SELECT * FROM perch3_shop_cart WHERE cartID=80
Using cart from cache.
DELETE FROM perch3_shop_cart WHERE cartID='80'
------------------------------ Calculating cart ------------------------------
[1] SELECT * FROM perch3_shop_cart WHERE cartID=0
[1] SELECT * FROM perch3_shop_cart WHERE cartID=0
[1] SELECT * FROM perch3_shop_tax_locations WHERE locationID=0 AND locationDeleted IS NULL LIMIT 1
[1] SELECT locationID FROM perch3_shop_tax_locations WHERE locationIsHome=1 LIMIT 1
[1] SELECT * FROM perch3_shop_tax_locations WHERE locationID=1 AND locationDeleted IS NULL LIMIT 1
[1] SELECT * FROM perch3_shop_currencies WHERE currencyID=0 LIMIT 1
[30] SELECT DISTINCT settingID, settingValue FROM perch3_settings WHERE userID=0
[1] SELECT * FROM perch3_shop_currencies WHERE currencyActive=1 AND currencyID=142
[1] SELECT COUNT(productID) AS product_count, SUM(itemQty) AS item_count FROM perch3_shop_cart_items WHERE cartID=0
Tax mode: exc
[nil] SELECT * FROM perch3_shop_cart_items WHERE cartID=0 ORDER BY itemID ASC
[1] SELECT locationID FROM perch3_shop_tax_locations WHERE locationIsHome=1 LIMIT 1
INSERT INTO perch3_shop_cart(memberID,locationID,currencyID,cartPricing,cartProperties) VALUES('1','1',142,'standard','[]')
[1] SELECT * FROM perch3_shop_cart WHERE cartID=81
[1] SELECT itemID, itemQty FROM perch3_shop_cart_items WHERE cartID=81 AND productID=1
[1] SELECT * FROM perch3_shop_products WHERE productID=1 AND productDeleted IS NULL LIMIT 1
INSERT INTO perch3_shop_cart_items(productID,itemQty,cartID) VALUES(1,1,'81')
------------------------------ Calculating cart ------------------------------
[1] SELECT * FROM perch3_shop_cart WHERE cartID=81
[1] SELECT * FROM perch3_shop_cart WHERE cartID=81
[1] SELECT * FROM perch3_shop_tax_locations WHERE locationID=1 AND locationDeleted IS NULL LIMIT 1
[1] SELECT locationID FROM perch3_shop_tax_locations WHERE locationIsHome=1 LIMIT 1
[1] SELECT * FROM perch3_shop_tax_locations WHERE locationID=1 AND locationDeleted IS NULL LIMIT 1
[1] SELECT * FROM perch3_shop_customers WHERE memberID=1
[1] SELECT * FROM perch3_shop_currencies WHERE currencyID=142 LIMIT 1
[1] SELECT COUNT(productID) AS product_count, SUM(itemQty) AS item_count FROM perch3_shop_cart_items WHERE cartID=81
Tax mode: exc
[1] SELECT * FROM perch3_shop_cart_items WHERE cartID=81 ORDER BY itemID ASC
[1] SELECT * FROM perch3_shop_products WHERE productID=1 AND productDeleted IS NULL LIMIT 1
[1] SELECT * FROM perch3_shop_tax_groups WHERE groupID=1 AND groupDeleted IS NULL LIMIT 1
[0] SELECT r.rateValue FROM perch3_shop_tax_group_rates gr, perch3_shop_tax_rates r WHERE gr.rateID=r.rateID AND gr.groupID=1 AND gr.locationID=1
[1] SELECT * FROM perch3_shop_tax_groups WHERE groupID=1 AND groupDeleted IS NULL LIMIT 1
[0] SELECT r.rateValue FROM perch3_shop_tax_group_rates gr, perch3_shop_tax_rates r WHERE gr.rateID=r.rateID AND gr.groupID=1 AND gr.locationID=1
[nil] SELECT * FROM perch3_shop_promotions WHERE promoFrom<='2018-01-04 19:24:00' AND promoTo>'2018-01-04 19:24:00' AND promoActive=1 AND promoDeleted IS NULL ORDER BY promoOrder ASC
UPDATE perch3_shop_cart SET cartTotalItems='1', cartTotalProducts='1', cartTotalWithTax='5.00', cartTotalWithoutTax='5.00' WHERE cartID='81'
[1] Using template: /addons/apps/perch_shop/templates/shop/cart/cart_static.html
[1] SELECT billingAddress, shippingAddress FROM perch3_shop_cart WHERE billingAddress IS NOT NULL AND cartID=81
Using template: /addons/apps/perch_shop/templates/shop/gateways/stripe_payment_form.html
Drew McLellan

Drew McLellan 2638 points
Perch Support

So you're getting a new cart?

Yes. Page reloads, get new cart, doesn't go to return_url. The stripe payment goes through fine though.

Also, I tried to see if it would help to set the page as outlined here:

https://docs.grabaperch.com/perch/building/working-with-front-controllers/

...but made no difference.

Drew McLellan

Drew McLellan 2638 points
Perch Support

What's going on with this?

perch_shop_empty_cart(); 
perch_shop_add_to_cart(1);

The nature of the page means you can go back to it and pay for your advert upgrade whenever you want (rather than a typical checkout process) therefore because I'm adding the product programatically I needed to empty the cart before adding the product on each page load, otherwise it just keeps multiplying the product each time you visit the page in the same session.

If I comment out the empty cart bit it still doesn't help with the redirect.

Drew McLellan

Drew McLellan 2638 points
Perch Support

Ok. Have you isolated the issue on a test page without all the rest of the unrelated code?

If I detach the perch code from the other app and put the cart on a standard 'my-cart.php' page then everything works fine.

As soon as I put the cart in a "view" within the app I get this return_url problem. All other perch functions are working fine within this same app.

Drew McLellan

Drew McLellan 2638 points
Perch Support

I think you need to look to what the rest of your code is doing, as this doesn't sound like a Perch issue.

Ok thanks. One thing that may or may not help me is that, if I put a perch form on the cart page, that submits and redirects to the redirect URL set for it in the admin with no problem at all. So I'm wondering what the difference is between the way the standard perch forms redirect and the way the redirect from a stripe transaction works, in the hope that narrows down what I should be looking for?

Drew McLellan

Drew McLellan 2638 points
Perch Support

I guess one difference would be the point at which the redirect occurs. For redirects should happen at the point the runtime is included. Shop redirects happen when you call the associated function.

So you might want to check your HTTP state.

How does one check their HTTP state?

Drew McLellan

Drew McLellan 2638 points
Perch Support

That depends on the rest of your application. Just check that you know what headers have already been sent, and if any body output has begun etc before you issue the checkout redirect.

For anyone in future, I solved my redirect issue by moving the perch shop related php from the view in to the controller for the page where the cart appears :)