How to "see" json response from POST request (webhook) - php

I created a chatbot in Dialogflow which informs the user about the members of my (extended) family and about where they are living. I have created a small database with MySQL which has these data stored and I fetch them with a PHP script (hosted on Heroku) whenever this is appropriate depending on the interaction of the user with the chatbot.
My PHP script which receives the POST request (webhook) from Dialogflow is the following:
<?php
$dbServername = '******************';
$dbUsername = '******************';
$dbPassword = '******************';
$dbName = '******************';
$conn = mysqli_connect($dbServername, $dbUsername, $dbPassword, $dbName);
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
if($method == 'POST'){
$requestBody = file_get_contents('php://input');
$json = json_decode($requestBody);
$action = $json->result->action;
$first_name = $json->result->contexts[0]->parameters->{'given-name'};
$last_name = $json->result->contexts[0]->parameters->{'last-name'};
$lifespan = $json->result->contexts[0]->lifespan;
$sql = "SELECT * FROM family WHERE name LIKE '%$first_name%$last_name%';";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck > 0) {
while ($row = mysqli_fetch_assoc($result)) {
$person = $row;
}
switch ($action) {
case 'Name':
$speech= "$first_name is my" . $person["name"] . ".";
break;
case 'Location':
$speech = "$first_name is living in {$person["location"]}.";
break;
default:
$speech = "Please ask me something more relevant to my family";
break;
}
}
else {
$speech = "Sorry, $first_name $last_name is not a member of my family.";
}
$response = new \stdClass();
$response->speech = $speech;
$response->displayText = $speech;
$response->source = "agent";
echo json_encode($response);
}
else
{
echo "Method not allowed";
}
?>
I can instantly see on Dialogflow the json response that I am receiving from it in my PHP script. However, Google Assistant does not provide this option. The problem also is that the json response when using Google Assistant is considerably different than the one when using only Dialogflow.
My question is: how can I "see" what JSON is being sent to my PHP script when using the Google Assistant? In other words, how can I "see" the whole of $requestBody variable at once?
For example, I tried to use https://webhook.site/ and I filled in the following information to create the new URL/endpoint:
Default status code -> 200
Content Type -> application/json
Timeout before response -> 0
Response body -> {
"speech": "WEBHOOK",
"displayText": "WEBHOOK",
"source": "agent"
}
The response body has the same structure as in my PHP script. However, for some reason, Google Assistant does not receive the json response from this custom endpoint (while Dialogflow does receive it perfectly). Therefore I cannot exactly move on and see what it is sent by Dialogflow & Google Assistant in the case of intents which are further triggered by context...

Easy solution: add logging
Add some error logging into your code that prints out the formatted JSON. Something like this right after you create $json would log it to your normal HTTP log file:
error_log( json_encode( $json, JSON_PRETTY_PRINT ) );
You can then examine your HTTP error log after each request to see what was sent. (As you've noted in the comments, you can do this with heroku logs on heroku in the terminal in your project directory.)
If you want it sent to a different location, you can examine the documentation for error_log() for details about how to send it to an email address (if your configuration supports that) or to another file. For example, this would log things to a file named /tmp/json.txt:
error_log( json_encode( $json, JSON_PRETTY_PRINT ), 3, "/tmp/json.txt" );
More complicated solution: use a proxy
You could also use a proxy such as ngrok that allows request inspection. This will give you a public hostname that you will set to forward to the hostname where your service is running. You can then use this public hostname for the fulfillment URL in Dialogflow with the path for the webhook. When Dialogflow sends a request, it will go to this proxy which will forward it to your service. Your service replies to the proxy which forwards it back to Dialogflow. You can inspect both the request and the response. (ngrok runs on the same machine as the service and allows inspection by having another URL you can use that views the request and response. Other proxies may work differently. webhook.site looks like it does something similar, but I haven't tested how its proxying works.)

Related

EWS CreateAttachment API call not working

I'm currently facing some problems with the CreateAttachment API call in EWS 2010. We are using PHP 5.5 with curl 7.49.1.
We are currently using the following little script to test this issue:
$ewswrapper = new EWSWrapper($host, $user, $pass);
try {
// See examples:
//
// http://jamesarmes.com/php-ews/doc/0.1/examples/contact-set-update-photo.html
// https://github.com/jamesiarmes/php-ews/blob/master/examples/contact/set-photo.php
$picture = base64_decode(" ... some valid base64 image ... ");
$attachment = new EWSType_FileAttachmentType();
$attachment->IsContactPhoto = true;
$attachment->Content = $picture;
$attachment->Name = "ContactPicture.jpg";
$attachment->ContentType = "image/png";
// Create the attachment request
$attRequest = new EWSType_CreateAttachmentType();
$attRequest->ParentItemId = new EWSType_ItemIdType();
$attRequest->ParentItemId->Id = " ... some ItemId of a contact ... ";
$attRequest->ParentItemId->ChangeKey = " ... some ChangeKey of the contact ... ";
$attRequest->Attachments = new EWSType_NonEmptyArrayOfAttachmentsType();
$attRequest->Attachments->FileAttachment = [];
$attRequest->Attachments->FileAttachment[] = $attachment;
$ewswrapper->service->CreateAttachment($attRequest);
} catch (Exception $e) {
var_dump($e->getMessage());
}
The returned status code of the response is 100. As far as we can tell, the response is empty. Dumping the request before sending it shows us a valid xml output that should theoretically work. We have checked both the official Microsoft documentation at https://msdn.microsoft.com/en-us/library/office/aa565931(v=exchg.140).aspx and the API examples at http://jamesarmes.com/php-ews/doc/0.1/examples/contact-set-update-photo.html.
Other requests to the API work perfectly. We can create, update, query and delete just fine, it seems to be this request specifically which fails.
We would highly appreciate any pointers into the right direction! Thanks in advance! If more information is needed regarding the code, infrastructure, etc, please ask!

Why my PHP script does not "see" the webhook from Dialogflow?

I am using DIalogflow (api.ai) to create chat interfaces. I created a webhook from Dialogflow to a simple app containing a php script deployed on Heroku.
Therefore, I placed in the webhook form of Dialogflow the url of my Heroku app which resembles to this: https://my_heroku_app_name.herokuapp.com.
My ultimate goal is to fetch some data from a database (through the php script) and then feed Dialogflow with them. For now, I am only trying to connect the Heroku app (php script) with Dialogflow through a webhook.
The php script of the Heroku app is the following:
<?php
$method = $_SERVER['REQUEST_METHOD'];
if($method == 'GET'){
$requestBody = file_get_contents('php://input');
$json = json_decode($requestBody);
$text = $json->metadata->intentName->text;
switch ($text) {
case 'Name':
$speech = "This question is too personal";
break;
default:
$speech = "Sorry, I didnt get that.";
break;
}
$response = new \stdClass();
$response->speech = $speech;
$response->displayText = $speech;
$response->source = "webhook";
echo json_encode($response);
}
else
{
echo "Method not allowed";
}
?>
Keep in mind the following:
$method is GET for some reason instead of POST as it is supposed to be from Dialogflow.
if you try to echo any of the variables $requestBody, $json or $text then nothing is printed.
I have tested that the if branch is executed and that the default branch is executed at switch.
Why my PHP script cannot "see" the webhook from DIaloflow and fetch the data from it so as to respond appropriately?
P.S. My question is not a duplicate of Valid JSON output but still getting error. The former is about the input of the php script whereas the latter is about the output of the php script. These two things do not necessarily constitute identical problems.
try to do something like this with some modification in your code.
First, I suggest you to use action instead of using intent name for switch case.
index.php
<?php
require 'get_wardinfo.php';
function processMessage($input) {
$action = $input["result"]["action"];
switch($action){
case 'wardinfo':
$param = $input["result"]["parameters"]["number"];
getWardInfo($param);
break;
default :
sendMessage(array(
"source" => "RMC",
"speech" => "I am not able to understand. what do you want ?",
"displayText" => "I am not able to understand. what do you want ?",
"contextOut" => array()
));
}
}
function sendMessage($parameters) {
header('Content-Type: application/json');
$data = str_replace('\/','/',json_encode($parameters));
echo $data;
}
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input["result"]["action"])) {
processMessage($input);
}
?>
get_wardinfo.php
<?php
require 'config.php';
function getWardInfo($param){
$wardinfo="";
$Query="SELECT * FROM public.wardinfo WHERE wardno=$param";
$Result=pg_query($con,$Query);
if(isset($Result) && !empty($Result) && pg_num_rows($Result) > 0){
$row=pg_fetch_assoc($Result);
$wardinfo= "Here is details that you require: Name: " . $row["name"]. " --- Address: " . $row["address"]. " --- MobileNo: " . $row["contact"];
$arr=array(
"source" => "RMC",
"speech" => $wardinfo,
"displayText" => $wardinfo,
);
sendMessage($arr);
}else{
$arr=array(
"source" => "RMC",
"speech" => "Have some problem .",
"displayText" => "Have some problem .",
);
sendMessage($arr);
}
}
?>
It seems you know each parameter and all about dialogflow and how it works with PHP arrays and all still if you have confusion in above code or method kindly put a comment.
And I will suggest you don't go for Heroku directly first try it with ngrok it will make your local server live and put the URL as webhook in dialogflow and you can easily debug the errors and all.
I managed to connect Dialogflow to my php script on Heroku.
I made the following changes on my php script (on Heroku) and on Dialogflow which led to this result:
I replaced the condition if($method == 'GET') with the condition if($method == 'POST') so as to anticipate the POST request of Dialogflow.
Keep in mind that until I solved the whole problem I was not receiving any POST request but I GET request so I thought that the POST request from Dialogflow leads to GET request because of a webpage redirection which I could not really see at that moment.
I replaced $text = $json->metadata->intentName->text; with $text = $json->results->metadata->intentName; which was the right json parsing for retrieving the value of intentName. (I have published here the json request from Dialogflow but nobody noticed my mistake)
I published my bot on Dialogflow through its built-in web demo and on Slack. This may sound quite irrelevant but also one person on the Dialogflow forum stated that: "Maybe it should rementioned somewhere. that api.ai98 is not parsing any parameters/values/data to you service untill you bot is published!!" (See the second post here: https://discuss.api.ai/t/webhook-in-php-example/229).

PHP script receives GET instead of POST REQUEST

I am using PHP with XAMPP and Dialogflow to create a chat interface. In a simple intent(question) in Dialogflow, I have created a webhook to XAMPP regarding the question 'Who is X' (e.g. Paul, George). Therefore , I place a POST REQUEST in order to have access to the json form of this question in DIalogflow so that I can answer it as I want to. Specifically, the ultimate goal of this is to retrieve some data from a MySQL database in phpMyAdmin about this question and respond for example that 'X is a developer' or 'X is a financial analyst'. This is why wrote a php script which is the following:
<?php
$method = $_SERVER['REQUEST_METHOD'];
// Process when it is POST method
if ($method == 'POST') {
$requestBody = file_get_contents('php://input');
$json = json_decode($requestBody);
$text = $json->result->parameters;
switch($text) {
case 'given-name':
$name = $text->given-name;
$speech = $name . 'is a developer';
break;
default:
$speech = 'Sorry I did not get this. Can you repeat please?';
}
$response = new \stdClass();
$response->speech = "";
$response->displayText = "";
$respone->source = "webhook";
echo json_encode($response);
}
else
{
echo "Method not allowed";
}
?>
However, the output of this program is: Method not allowed.
Paradoxically enough $method has the value 'GET' so it identifies a GET REQUEST while Dialogflow explicitly states at the webhook page that
Your web service will receive a POST request from Dialogflow in the
form of the response to a user query matched by intents with webhook
enabled.
Hence I am wondering: why my php script cannot see and process the POST REQUEST from Dialogflow?
P.S. Questions close to mine are the following: Form sends GET instead of POST, Why is $_SERVER['REQUEST_METHOD'] always GET?.
It doesn't work because $_SERVER['REQUEST_METHOD'] == "GET" by default.
So you program execute the 'else' condition.
You need to submit a request with the POST method to change this value.
You can use
<form method="POST">
[...]
</form>
in your HTML, or
$.ajax({
url : "ajax_url.php",
type : 'POST',
data : 'data='+data,
[...]
});
in your AJAX JS code for example
Here i am doing same like you from below code your Query will be resolved,
index.php
<?php
require 'get_enews.php';
function processMessage($input) {
$action = $input["result"]["action"];
switch($action){
case 'getNews':
$param = $input["result"]["parameters"]["number"];
getNews($param);
break;
default :
sendMessage(array(
"source" => "RMC",
"speech" => "I am not able to understand. what do you want ?",
"displayText" => "I am not able to understand. what do you want ?",
"contextOut" => array()
));
}
}
function sendMessage($parameters) {
header('Content-Type: application/json');
$data = str_replace('\/','/',json_encode($parameters));
echo $data;
}
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input["result"]["action"])) {
processMessage($input);
}
?>
get_enews.php
<?php
function getNews($param){
require 'config.php';
$getNews="";
$Query="SELECT link FROM public.news WHERE year='$param'";
$Result=pg_query($con,$Query);
if(isset($Result) && !empty($Result) && pg_num_rows($Result) > 0){
$row=pg_fetch_assoc($Result);
$getNews= "Here is details that you require - Link: " . $row["link"];
$arr=array(
"source" => "RMC",
"speech" => $getNews,
"displayText" => $getNews,
);
sendMessage($arr);
}else{
$arr=array(
"source" => "RMC",
"speech" => "No year matched in database.",
"displayText" => "No year matched in database.",
);
sendMessage($arr);
}
}
?>
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input

Always getting response as Invalid Session Token in soap client php

I have php version 7.1 in my localhost. I have made changes in my php.ini file to run SOAP from my localhost.
I need to generate primary and secondary session token by passing login id and password to SOAP client API.
Once session token is authenticated it will return some rate chart. My code is generating session tokens. But when I am passing that token key to the next method in SOAP Client api its always giving me an error like "Invalid Session Token" or "Invalid Authentication". However the same tokens are working well in SOAP UI exe. I mean I have installed SOAP UI exe and by using wsdl "http://cnx.test.dat.com:9280/wsdl/TfmiFreightMatching.wsdl" and using method "Login" and "LookupRate" its working everything fine. The way i need that.
But whenever i am using that tokens in php localhost its always giving me an authentication error by SOAP Client.
I am sharing my code below.
$wsdl = "http://cnx.test.dat.com:9280/wsdl/TfmiFreightMatching.wsdl";
$client = new SoapClient($wsdl, array('trace' => true));
$params = array('loginOperation'=>array('loginId'=>'ryder_cnx1','password'=>'ryder1','thirdPartyId'=>'dl'));
$client->Login($params);
$data = $client->__getLastResponse();
$p = xml_parser_create();
xml_parse_into_struct($p, $data, $vals, $index);
xml_parser_free($p);
$token = [];
foreach ($vals as $key => $value) {
foreach ($value as $key1 => $value1) {
if($key1 == "value")
$token[] = $value1;
}
}
echo "Primary Token = ".$token[0];
echo "<br> Secondary Token = ".$token[1];
//echo "<br> Expiry Date = ".$token[2];
$params_session = array("sessionToken"=> array("primary"=>$token[0], "secondary"=>$token[1]));
$namespace = 'http://www.tcore.com/TcoreTypes.xsd'; // I am not sure about this namespace. Whether its correct or not.
$header = new SoapHeader($namespace,'sessionHeader',$params_session,true);
$client->__setSoapHeaders($header);
$params_data = array('lookupRateOperations'=> array(
'equipment'=>'Vans',
'origin'=>array('postalCode'=>array('country'=>'US','code'=>'30004')),
'destination'=>array('postalCode'=>array('country'=>'US','code'=>'10001'))
));
try{
$result = $client->LookupRate($params_data);
print_r($result);
}catch (SoapFault $exception){
//or any other handling you like
print_r(get_class($exception));
enter code hereprint_r($exception);
}
if anybody have any idea, please share it with me.
Awaiting any response.
Thanks a lot in advance :)
I know this is very old, and most likely the OP figured it out. But in case anyone else comes along, I was able to get it working with two slight changes.
First,
$namespace = 'http://www.tcore.com/TcoreTypes.xsd';
Should be
$namespace = 'http://www.tcore.com/TcoreHeaders.xsd';
Second,
$params_session = array("sessionToken"=> array("primary"=>$token[0], "secondary"=>$token[1]));
should be
$params_session = array(
"sessionToken"=> array(
"primary"=>base64_decode($token[0]),
"secondary"=>base64_decode($token[1])
)
);
The rest of my code is similar enough that if the above changes are made, it should work. I would also refrain from posting real usernames and passwords, btw.

Alamofire JSON could not be serialized

I'm trying to make a PHP Post request with Alamofire in my swift app, which has to send SMS with OVH api, but I got an issue :
FAILURE: Error Domain=com.alamofire.error Code=-6006 "JSON could not be serialized. Input data was nil or zero length." UserInfo={NSLocalizedFailureReason=JSON could not be serialized. Input data was nil or zero length.}
I'm not finding how to see echos from the PHP script to solve it. I think that it isn't an Alamofire problem because I make an other request to send emails and it works well. Here is my request where there is the error :
func sendSmsAutoRequest(completionHandler: (responseObject: NSDictionary?, error: NSError?) -> ()) {
let prefs = NSUserDefaults.standardUserDefaults()
let username = prefs.stringForKey(StorageManager.USER_NAME)!
let messageText = prefs.stringForKey(StorageManager.MESSAGE_TEXT)!
let parameters = ["contactsSms": contactsSms, "username": username, "messageText": messageText]
request(.POST, "http://XXX/dontworry/sendAutoSms.php", parameters: (parameters as! [String : AnyObject])).responseJSON { response in
print(response)
}
}
and here is my script :
<?php
require __DIR__ . '/vendor/autoload.php';
use \Ovh\Api;
$applicationKey = "XXX";
$applicationSecret = "XXX";
$consumer_key = "XXX";
$endpoint = "ovh-eu";
$contactsSms = $_POST['contactsSms'];
$userName = $_POST['username'];
$messageText = $_POST['messageText'];
$conn = new Api($applicationKey,
$applicationSecret,
$endpoint,
$consumer_key);
$smsServices = $conn->get('/sms/');
$content = (object) array(
"charset"=> "UTF-8",
"class"=> "phoneDisplay",
"coding"=> "7bit",
"message"=> $messageText,
"noStopClause"=> true,
"priority"=> "high",
"receivers"=> $contactsSms,
"senderForResponse"=> true,
"validityPeriod"=> 2880
);
$resultPostJob = $conn->post('/sms/'. $smsServices[0] . '/jobs/', $content);
$smsJobs = $conn->get('/sms/'. $smsServices[0] . '/jobs/');
echo '{"contacts": $contactsSms,"username": $username, "messageText": $messageText, "result": $resultPostJob, "sms": $smsJobs}'; ?>
EDIT : It seems to work, I don't have the error anymore ! But the SMS is not sent...
From a first reading, your PHP script most probably prints invalid JSON. The following statement will print JSON that contains unquoted strings (assuming one or more of the parameters like $_POST['messsageText'] contain string values):
echo '{"contacts": $contactsSms,"username": $username, "messageText": $messageText, "result": $resultPostJob, "sms": $smsJobs}';
Example output (pretty-printed for readability):
{
"contacts": foobar, # <-- This is invalid! It's a string and needs to be quoted!
"username": johndoe,
"messageText": Hello World, # <-- This is even more invalid!
...
}
I'd suggest to rely on PHP's json_encode function to generate valid JSON output:
echo json_encode([
"contacts" => $contactsSms,
"username" => $username,
"messageText" => $messageText,
// etc.
]);
This was kind of a bug in alamoFire, that was fixed in release 3.1.1, see pull #889, the fixed version works only if your REST like service returns response 204 (NO_RESPONSE) which is in theory the right way to do it.
Serialisation is the process of convert an object to a JSON string. So the problem is not the handling of your response, but that of your request.
Log the contents of your parameters dictionary, and check for nil values.

Categories