Telegram bot Referal with Php using the /start command - php

I am trying to get points allocated to ma user based on the number of referrals, using the telegram bot by passing a payload to the /start command from where i can track it and know who has been referring people to the bot
i have tried following the documentation process and was able to set the command but i didn't see a way of getting the payload
ini_set('error_reporting', E_ALL);
$token="870645666:AAHrjEF006uje1SpG0dFJRFnmfNIZHbGxdM";
$website ="https://api.telegram.org/bot".$token;
$update =file_get_contents("php://input");
$update =json_decode($update, TRUE);
$chatid =$update["message"]["chat"]["id"];
$message =$update["message"]["text"];
$refid=$update["message"]["text"]["payload"];
$ref=mysqli_fetch_assoc(mysqli_query($connect, "SELECT * FROM
bot where refid='$refid'"));
sendMessage($chatid, "You were referred by".$ref['name'];
function sendMessage($chatid, $message){
$url =$website."/sendMessage?
chat_id=".$chatid."&text=".urldecode($message);
file_get_contents($url);
}
There is no output for the payload when i try to access it
i have tried google but i can't find a way to fetch the payload using php. Any help would be appreciated

https://core.telegram.org/bots#deep-linking
You can receive the payload in a normal text message that starts with "/start"
$text = '/start PAYLOAD';
if(stripos($text, '/start ') === 0)
{
$payload = str_replace('/start ', '', $text);
}

Telegram sends Payload inside the message content to your bot
$message =$update["message"]["text"];
// extract payload from message text
$refid=substr($message, strlen('/start'));
// check is it really first message to start the bot
if($update["message"]["message_id"] != 1 || stripos($message, "/start ") != 0){
// $refid = "";
}

Related

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

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.)

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).

How to get LINE user mid using PHP SDK?

I use the LINE BOT API Trial SDK PHP (https://github.com/line/line-bot-sdk-php).
But, for this method:
$res = $bot->sendText(['TARGET_MID'], 'Message');
How to get the user's MID to send them a message?
Thanks for help.
1) A very quick way to get the mid of an interactive user (more of a fun hack, really) is to register a callback URL as per the API instructions, then capture the POST data to that URL like so:
// /callback/index.php
<?php
$postdata = file_get_contents("php://input");
#file_get_contents('https://'.$_SERVER['SERVER_NAME'].'/LINE/' . json_encode($postdata));
Next, scan the QR code in the channel console and add your trial bot to your LINE account. After that is done, send it a quick "Hello!" text.
You could then save the POST data to a text file if you wish, or you could check the server logs. For example, you might see something like this:
163.128.118.223 - - [03/Sep/2016:07:25:25 -0700] "POST /line/callback/ HTTP/1.1" 200 - "-" "ChannelEventDispatcher/1.0"
106.152.218.107 - - [03/Sep/2016:07:25:25 -0700] "GET /LINE/{\"result\":[{\"content\":{\"toType\":1,\"createdTime\":1472114754839,\"from\":\"ub7dbd4a12c322f6c0117773d739c55a4\",\"location\":null,\"id\":\"4357194057879\",\"to\":[\"u2b6a4ba287028dee7291122094dac827\"],\"text\":\"Hello!\",\"contentMetadata\":{\"AT_RECV_MODE\":\"2\",\"SKIP_BADGE_COUNT\":\"true\"},\"deliveredTime\":0,\"contentType\":1,\"seq\":null},\"createdTime\":1472912724868,\"eventType\":\"138311609000106301\",\"from\":\"u236d23c2e36bd87217655609a1c31cb8\",\"fromChannel\":1241102815,\"id\":\"WB1519-3102846635\",\"to\":[\"u2b6a4ba287028dee7291122094dac827\"],\"toChannel\":1462261375}]} HTTP/1.1" 404 15 "-" "-"
The \"from\":\"ub7dbd4a12c322f6c0117773d739c55a4\" is the pertinent part.
2) If you'd like to get started with receiving messages, you can start like this as your callback script. Simply send your BOT the message 'mid' and it should respond with your mid.
Here is a starting callback script I made with signature verification included for you.
// /callback/index.php
<?php
// Show all errors for testing
error_reporting(E_ALL);
// SDK is installed via composer
require_once __DIR__ . "/includes/vendor/autoload.php";
use LINE\LINEBot;
use LINE\LINEBot\HTTPClient\GuzzleHTTPClient;
// Set these
$config = [
'channelId' => LINE_CHANNEL_ID,
'channelSecret' => LINE_CHANNEL_SECRET,
'channelMid' => LINE_CHANNEL_MID,
];
$sdk = new LINEBot($config, new GuzzleHTTPClient($config));
$postdata = #file_get_contents("php://input");
$messages = $sdk->createReceivesFromJSON($postdata);
// Verify the signature
// REF: http://line.github.io/line-bot-api-doc/en/api/callback/post.html#signature-verification
$sigheader = 'X-LINE-ChannelSignature';
// REF: http://stackoverflow.com/a/541450
$signature = #$_SERVER[ 'HTTP_'.strtoupper(str_replace('-','_',$sigheader)) ];
if($signature && $sdk->validateSignature($postdata, $signature)) {
// Next, extract the messages
if(is_array($messages)) {
foreach ($messages as $message) {
if ($message instanceof LINEBot\Receive\Message\Text) {
$text = $message->getText();
if ($text == "mid") {
$fromMid = $message->getFromMid();
// Send the mid back to the sender and check if the message was delivered
$result = $sdk->sendText([$fromMid], 'mid: ' . $fromMid);
if(!$result instanceof LINE\LINEBot\Response\SucceededResponse) {
error_log('LINE error: ' . json_encode($result));
}
} else {
// Process normally, or do nothing
}
} else {
// Process other types of LINE messages like image, video, sticker, etc.
}
}
} // Else, error
} else {
error_log('LINE signatures didn\'t match');
}

Getting a Parse error while executing a Twilio file to perform an action when a user calls the number [duplicate]

So I am trying to take an incoming SMS and based on what the SMS says make a call with a specific recording.
For example:
I have a door sensor with a modem that can send a text to my twilio # when the door is open or when the door is closed.
If Twilio receives "door open" text then twilio will call my cell phone and plays recording that says "door is open"
If Twilio receives "door closed" text then twilio will call my cell phone and plays recording that says "door is closed"
<?php
require_once('/home/protranx/public_html/twilio-php- latest/Services/Twilio.php');
$sid = "SID";
$token = "Token";
$client = new Services_Twilio($sid, $token);
$alert = $_REQUEST['body'];
$TwilioNumber = "+twilio #";
$to = "+my cell #";
$url1 = "http://protran.x10.mx/Oak1_armed_door_open.php";
$url2 = "http://protran.x10.mx/Oak1_disarmed_door_closed.php";
$string1 = "door open";
$string2 = "door closed";
if ($alert == $string1){
$call = $client->account->calls->create($TwilioNumber, $to, $url1);}
elseif ($alert == $string2){
$call = $client->account->calls->create($TwilioNumber, $to, $url2);}
echo $call->sid;
header('content-type: text/xml');
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?>
<Response>
</Response>
I keep getting this error:
Error: 12100 - Document parse failure
Any help would be greatly appreciated.
Thank you
Twilio evangelist here.
Hard to tell from your code, as it generally looks right.
One thing that occasionally trips me up is spaces being rendered before the start of the xml or between the xml declaration and the root element, so you might check for either of those that since those can be hard to catch.
For example, I'm not sure you need the newline that you have at the end of your xml declaration.
Hope that helps.

How do I take an SMS and make a call to alert someone based on what SMS says?

So I am trying to take an incoming SMS and based on what the SMS says make a call with a specific recording.
For example:
I have a door sensor with a modem that can send a text to my twilio # when the door is open or when the door is closed.
If Twilio receives "door open" text then twilio will call my cell phone and plays recording that says "door is open"
If Twilio receives "door closed" text then twilio will call my cell phone and plays recording that says "door is closed"
<?php
require_once('/home/protranx/public_html/twilio-php- latest/Services/Twilio.php');
$sid = "SID";
$token = "Token";
$client = new Services_Twilio($sid, $token);
$alert = $_REQUEST['body'];
$TwilioNumber = "+twilio #";
$to = "+my cell #";
$url1 = "http://protran.x10.mx/Oak1_armed_door_open.php";
$url2 = "http://protran.x10.mx/Oak1_disarmed_door_closed.php";
$string1 = "door open";
$string2 = "door closed";
if ($alert == $string1){
$call = $client->account->calls->create($TwilioNumber, $to, $url1);}
elseif ($alert == $string2){
$call = $client->account->calls->create($TwilioNumber, $to, $url2);}
echo $call->sid;
header('content-type: text/xml');
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?>
<Response>
</Response>
I keep getting this error:
Error: 12100 - Document parse failure
Any help would be greatly appreciated.
Thank you
Twilio evangelist here.
Hard to tell from your code, as it generally looks right.
One thing that occasionally trips me up is spaces being rendered before the start of the xml or between the xml declaration and the root element, so you might check for either of those that since those can be hard to catch.
For example, I'm not sure you need the newline that you have at the end of your xml declaration.
Hope that helps.

Categories