AJAX subscribe receiving 403 error with Expression Engine

Tim Clarke

New Member
I'm trying to implement the AJAX subscribe based on the code from the '/vendor/ems-api/php-client/example' folder. However, I just get a 403 error in the browser console when I click the "submit" button, and on the website nothing appears to happen.

I have MailWhizz installed on a different domain to the website. With no PHP or JS code, the form on the website works, adding the subscriber and redirecting to the MailWhizz domain. The website is running expression engine. I have enabled PHP in that, and I have included and edited the PHP above the <head>. I had to alter the "require_once" code slightly because of the way Expression Engine generates paths with PHP, but it is calling the 'setup.php' from the plugins folder. And, of course edited the 'List ID' and input ID's to reflect the form.

<?php

// require the setup which has registered the autoloader
include_once PATH_THIRD . '/email_api/setup.php';

// see if the request is made via ajax.
$isAjaxRequest = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';

// and if it is and we have post values, then we can proceed in sending the subscriber.
if ($isAjaxRequest && !empty($_POST)) {
$listUid = 'de808b3mrj4b4'; // you'll take this from your customers area, in list overview from the address bar.
$endpoint = new EmsApi\Endpoint\ListSubscribers();
$response = $endpoint->create($listUid, [
'NAME' => isset($_POST['NAME']) ? $_POST['NAME'] : null,
'EMAIL' => isset($_POST['EMAIL']) ? $_POST['EMAIL'] : null,
]);
$response = $response->body;

// if the returned status is success, we are done.
if ($response->itemAt('status') == 'success') {
exit(json_encode([
'status' => 'success',
'message' => 'Thank you for joining our email list. Please confirm your email address now!'
]));
}

// otherwise, the status is error
exit(json_encode([
'status' => 'error',
'message' => $response->itemAt('error')
]));
}
?>

I have also edited the the 'setup.php' so that the path would work in Expression Engine. Using "require_once __DIR__ . '/path/vendor/autoload.php';" caused it to point to Mailwhizz installation, takes it into a Expression Engine system folder before trying to resolve the rest of the path. So I changed it to "require_once('/path/vendor/autoload.php');" which takes it to the correct place.

I created an API key in the customer area, and included that in the config section of the "setup.php".

I've included the JS in the foot of the HTML below JQuery. I've tried moving them to the head, but the same problem persists. As nothing happens when the button is clicked, the "preventDefault" is working, However, I get no javascript errors, and the js does not add a success or error tag, indicating that the problem is before that. Also, if I remove the PHP, the same result is present, in that nothing happens when the button is clicked and the browser throws a 403 error.

This all leads me to believe the problem is connecting with the Mailwhizz API with the PHP.

I've been trying to work this out through a process of elimination, but I have run out of things to try and could do with some assistance.

-Some additional info-

I'm using bootstrap, and bootstrap.js v4.
There are no whitelisted or blacklisted IPs in both the customer and backend API settings.
I'm not getting any server errors (checked in CPANAL).
Using PHP 7.4.
 
Last edited:
If you get a 403, my hunch is that you're touching some EE url which you are not allowed to do so, most likely you try to hit a file in a folder that has a htaccess in it to prevent access and to give that 403 error, so check that as well.
If I where you, I would try this outside of EE until it works, then when it does, implement it in EE, that way you know who's the culprit in case it fails to work.
 
If you get a 403, my hunch is that you're touching some EE url which you are not allowed to do so, most likely you try to hit a file in a folder that has a htaccess in it to prevent access and to give that 403 error, so check that as well.
If I where you, I would try this outside of EE until it works, then when it does, implement it in EE, that way you know who's the culprit in case it fails to work.
Thank you for the response and suggestions. I moved everything out into a static PHP file on a different domain, and everything worked with some minor tweaking. It was determined then that the issue was with Expression Engine, however I could not see anything in the .htaccess to prevent it working.

I decided to turn the script into a plugin, instead of putting the php within templates, and upon doing so learnt that Expression Engine has built in protection against Cross-site Request Forgery (CSRF).

For anyone looking at this who may have this same problem, the solution is as simple as including the code "<input type="hidden" name="csrf_token" value="{csrf_token}">" within the form.

More information can be read in the Expression Engine documentation under Add-On Development > Guidelines > Security Guidlines
 
Back
Top