2

Cheers,

The problem: (1) I am failing to obtain a valid JSON payload from Zoho Forms. (2) I may be too ignorant to realize obvious problems.

In principle zoho forms is configured according to parameters. The content type is application/json

This is the payload I am expecting according to Zoho Forms:

{
"DateTime" : "<DateTime>",
"Email" : "<Email>",
"Name.First" : "<Name.First>",
"Name.Last" : "<Name.Last>",
"PhoneNumber" : "<PhoneNumber>"
}

It is being sent using the POST method.

The multiple tests always come identical:

Test Result: Webhook test executed successfully Status Code: 200 Response: No payload received.

In case it matters: Permissions for my file are 0644 Permissions for the folder are 0755

I am using Apache, there is no .htaccess file in my setup.

My code ->

<?php
require_once 'connectme.php';

// Create log file
$logFile = "webhook_log.txt";

// Check connection
if ($conn->connect_error) {
    $error_message = "Connection failed: " . $conn->connect_error . "\n";
    file_put_contents($logFile, $error_message, FILE_APPEND);
    die("Connection failed: " . $conn->connect_error);
} else {
    $success_message = "Connected successfully to the database.\n";
    file_put_contents($logFile, $success_message, FILE_APPEND);
}

// Get request body as JSON raw txt
if (!empty($_POST)) {
    $request_body = json_encode($_POST);
} else {
    $request_body = file_get_contents('php://input');
}


// // $request_data = $_POST;
// $request_data = array_merge($_POST, $_FILES);
// $request_body = file_get_contents('php://input');

// Log the received payload 
if (empty($request_body)) {
    $error_message = "Dude, there is othing to see here.\n";
    file_put_contents($logFile, $error_message, FILE_APPEND);
} else {
    $success_message = "Payload received: " . $request_body . "\n"; 
    file_put_contents($logFile, $success_message, FILE_APPEND);
}

// Check if payload is received
if (empty($request_body)) {
    $error_message = "No payload received from Zoho Forms.\n";
    file_put_contents($logFile, $error_message, FILE_APPEND);
    die("No payload received.");
} else {
    $success_message = "Payload received: " . $request_body . "\n";
    file_put_contents($logFile, $success_message, FILE_APPEND);
}

// Decode JSON payload
$json_data = json_decode($request_body, true);

// Check if payload is valid JSON
if (json_last_error() !== JSON_ERROR_NONE) {
    $error_message = "Received payload is not valid JSON format.\n";
    file_put_contents($logFile, $error_message, FILE_APPEND);
    die("Received payload is not valid JSON format.");
}

// Extract data from JSON payload
$NameFirst = isset($json_data['Name.First']) ? $json_data['Name.First'] : null;
$NameLast = isset($json_data['Name.Last']) ? $json_data['Name.Last'] : null;
$DateTime = isset($json_data['DateTime']) ? $json_data['DateTime'] : null;
$Email = isset($json_data['Email']) ? $json_data['Email'] : null;
$PhoneNumber = isset($json_data['PhoneNumber']) ? $json_data['PhoneNumber'] : null;

// Validate extracted data
if ($NameFirst === null || $NameLast === null || $DateTime === null || $Email === null || $PhoneNumber === null) {
    $error_message = "Invalid or missing parameter names in request: " . json_encode($json_data) . "\nRaw request body: " . $request_body . "\n";
    file_put_contents($logFile, $error_message, FILE_APPEND);
    die("Invalid or missing parameter names in request.");
} elseif (empty($NameFirst) || empty($NameLast) || empty($DateTime) || empty($Email) || empty($PhoneNumber)) {
    $error_message = "Parameters have empty values in request: " . json_encode($json_data) . "\nRaw request body: " . $request_body . "\n";
    file_put_contents($logFile, $error_message, FILE_APPEND);
    die("Parameters have empty values in request.");
}

// Insert data into the clients table
$stmt = $conn->prepare("INSERT INTO clients (NameFirst, NameLast, DateTime, Email, PhoneNumber) VALUES (?, ?, ?, ?, ?)");
$stmt->bind_param("sssss", $NameFirst, $NameLast, $DateTime, $Email, $PhoneNumber);

if ($stmt->execute()) {
    $success_message = "New record created successfully.\n";
    file_put_contents($logFile, $success_message, FILE_APPEND);
} else {
    $error_message = "Error: " . $stmt->error . "\n";
    file_put_contents($logFile, $error_message, FILE_APPEND);
}

// Close database connection and statement
$stmt->close();
$conn->close();
?>

What I have tried:

1- Checked and rechecked the configuration on Zoho Forms 2- Used Postman to test the webhook 3- Executed multiple tests 4- Asked chat GPT (which after several messages recommended contact zoho forms support) 5- Wrote to Zoho Forms support and got the following answer: "we have checked on our end and the data has been sent from our end as intended", which further cements my impression that I am im just to inexperience or stupid to be able to make this work.

I appreciate any and all help.

Please let me know if there's any other information I should provide or any improvements I can make to my current setup too resolve this issue.

THE QUESTIONS: Do you see any obvious problem with this code that could prevent the payload to be be parsed and sent to the database? Am I missing anything with the configuration of zoho forms other than url, content type?

Thanks in advance.

edit0: typo edit1: log edit2: hosting service name (Dreamhost Sharing Hosting)

+++++ This is the feedback from the server:

Time: 2023-04-20 17:12:08
Request method: GET
Request headers: Array
(
    [Content-Length] => 0
    [Connection] => close
    [Host] => www.webhook.rsvphub.me
    [Content-Type] => application/x-www-form-urlencoded
    [User-Agent] => Zoho.com
    [Accept] => application/json
    [Req-Mi-Chain] => -1407411460:8080
)


_POST: Array
(
)


_SERVER: Array
(
    [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    [CONTENT_LENGTH] => 0
    [SCRIPT_NAME] => /tired.php
    [REQUEST_URI] => /tired.php
    [QUERY_STRING] => 
    [REQUEST_METHOD] => GET
    [SERVER_PROTOCOL] => HTTP/1.1
    [GATEWAY_INTERFACE] => CGI/1.1
    [REMOTE_PORT] => 60816
    [SCRIPT_FILENAME] => /home/captain_hook/webhook.rsvphub.me/tired.php
    [SERVER_ADMIN] => webmaster@webhook.rsvphub.me
    [CONTEXT_DOCUMENT_ROOT] => /home/captain_hook/webhook.rsvphub.me
    [CONTEXT_PREFIX] => 
    [REQUEST_SCHEME] => https
    [DOCUMENT_ROOT] => /home/captain_hook/webhook.rsvphub.me
    [REMOTE_ADDR] => 136.143.176.64
    [SERVER_PORT] => 443
    [SERVER_ADDR] => 173.236.170.13
    [SERVER_NAME] => www.webhook.rsvphub.me
    [SERVER_SOFTWARE] => Apache
    [SERVER_SIGNATURE] => 
    [HTTP_CONNECTION] => close
    [HTTP_HOST] => www.webhook.rsvphub.me
    [CONTENT_TYPE] => application/x-www-form-urlencoded
    [HTTP_USER_AGENT] => Zoho.com
    [HTTP_ACCEPT] => application/json
    [HTTP_REQ_MI_CHAIN] => -1407411460:8080
    [SSL_TLS_SNI] => www.webhook.rsvphub.me
    [HTTPS] => on
    [DH_USER] => captain_hook
    [ds_id_47565102] => 
    [dsid] => 47565102
    [SCRIPT_URI] => https://www.webhook.rsvphub.me/tired.php
    [SCRIPT_URL] => /tired.php
    [QS_ConnectionId] => 168202872854339796491526
    [QS_AllConn] => 7
    [QS_SrvConn] => 7
    [UNIQUE_ID] => ZEG4uKq--W0VG86HWLzo1AAAAGA
    [FCGI_ROLE] => RESPONDER
    [PHP_SELF] => /tired.php
    [REQUEST_TIME_FLOAT] => 1682028728.6623
    [REQUEST_TIME] => 1682028728
)


Missing required POST variables.

The service is Dreamhost Shared Hosting, I have no root access

  • `if (!empty($_POST)) { $request_body = json_encode($_POST); } else { $request_body = file_get_contents('php://input'); }` reads the body. First thing I would do is add some logging so you know which of those blocks it entered, and also make it log the output of `print_r($_POST, true);` and directly the of `print_r(file_get_contents('php://input'), true);`. Make it log those last two in all cases. – ADyson Apr 20 '23 at 15:12
  • You could also consider trying to get Apache to log the POST data as well, to ensure it's not getting stripped out there (something maybe along the lines described at https://stackoverflow.com/questions/989967/best-way-to-log-post-data-in-apache - there maybe other ways you can research too...it's not an area I know anything much about). Also, check the Apache logs to make sure the POST isn't being redirected to your PHP script as a GET or anything silly like that. – ADyson Apr 20 '23 at 15:38

1 Answers1

2

For those of you using Dreamhost, the solution is to modify yours .htaccess.

This is what I did:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteCond %{HTTP_REFERER} ^https?://(www\.)?zoho\.com(/.*)?$ [NC,OR]
    RewriteCond %{HTTP_REFERER} ^https?://.*\.zoho\.com(/.*)?$ [NC]
    RewriteRule .* - [R=200,L]
</IfModule>

Okay, so this code basically tells a web server that, if it uses the Apache mod_rewrite module, it should allow specific requests (called OPTIONS requests) only if they come from the main zoho.com website or any of its subdomains (like forms.zoho.com). If the request matches these conditions, the server will respond with a "200 OK" status, meaning everything is green, and then it won't do anything else. This is useful when you want to control where certain requests come from and make sure they're from a trusted source.

¯_(o o)_/¯