I have a problem on an API call with the Guzzle 7.4.3 library to PATCH severals produced on Akeneo 5.0.50
By following the documentation below:
https://api.akeneo.com/api-reference.html#patch_products
I first tested the api via Postman here is the result:
Res Postman
However with the guzzle code this one doesn't work and returns a null body with a 200 code.
Here is the code:
public function patchProductGlobalAkeneo(string $token_akeneo, string $data_products): object
{
try {
$request = $this->client->request('PATCH', $_ENV["AKENEO_API_URL"] . $_ENV["AKENEO_API_URL_PRODUCTS"], [
'headers' => [
'Authorization' => 'Bearer ' . $token_akeneo,
'Content-Type' => 'application/vnd.akeneo.collection+json'
],
'json' => json_decode('{"identifier":"01750003001400","values":{"stock":[{"data":"10","locale":null,"scope":null}]}}
{"identifier":"01750003001400","values":{"stock":[{"data":"10","locale":null,"scope":null}]}}')
]);
} catch (RequestException $e) {
$res = new stdClass();
$res->content = json_decode($e->getResponse()->getBody()->getContents());
$res->status_res = $e->getResponse()->getStatusCode();
var_dump($res->status_res);
var_dump("ERROR");
return $res;
}
$res = new stdClass();
$res->content = json_decode($request->getBody()->getContents());
$res->status_res = $request->getStatusCode();
var_dump($res->content);
var_dump($res->status_res);
var_dump("GOOD");
return $res;
}
The result of the var_dump : Res Var_dump
as far as I understand, there is no way in selenium to get the response code of the website. How can I work it around to know if a website has sent me an error or exception without having to expect an element in the site and wait for it until it times out?
use strict;
use warnings;
use Selenium::Chrome;
use Selenium::Waiter qw/wait_until/;
my $chrome_driver_path = "./../../tools/drivers/chromedriver.exe";
my $driver;
my %settings = (
'binary' => $chrome_driver_path,
);
$driver = Selenium::Chrome->new(%settings);
print("Getting stackoverflow\n");
wait_until{$driver->get("https://www.stackoverflow.com")};
validate_site($driver);
print("Getting unexistent url of stackoverflow\n");
wait_until{$driver->get("https://www.stackoverflow.com/this-does-not-exists-and-returns-404")};
validate_site($driver);
sleep(20);
$driver->shutdown_binary;
sub validate_site{
my ($driver) = #_;
#if ($driver->something) {
# print("Looks good)\n");
#}else{
# warn("Error\n");
# }
}
Expected result:
Getting stackoverflow:
Looks good
Getting unexistent url of stackoverflow:
Error
PD: I want to use selenium because I´m working in websites with javascript and storing cookies through different views, this is just an example to illustrate the problem that could be solved with a curl, but is not the case in my project.
Based on solution from your previous comment here's another solution.
Here extra_capabilities are used to enable more logging (please note I added additional package). This will work in version 1.38 of Selenium::Remote::Driver that was released just recently, so you will need to update you packages if you haven't done so yet. This solution does not require falling back to WD2.
use strict;
use warnings;
use Selenium::Chrome;
use Selenium::Waiter qw/wait_until/;
use JSON;
my $chrome_driver_path = "./../../tools/drivers/chromedriver.exe";
my $driver;
my %settings = (
'binary' => $chrome_driver_path,
'extra_capabilities' =>{
'goog:loggingPrefs' => {
'performance' => 'ALL',
},
'goog:chromeOptions' => {
'perfLoggingPrefs' => {
'traceCategories' => 'performance',
},
},
}
);
$driver = Selenium::Chrome->new(%settings);
print("Getting stackoverflow\n");
wait_until{$driver->get("https://www.stackoverflow.com")};
validate_site($driver);
print("Getting unexistent url of stackoverflow\n");
wait_until{$driver->get("https://www.stackoverflow.com/this-does-not-exists-and-returns-404")};
validate_site($driver);
#sleep(20);
$driver->shutdown_binary;
sub validate_site{
my ($driver) = #_;
my $logs = $driver->get_log('performance');
my #responses = grep {$_->{'message'} =~ /"Network\.responseReceived"/ } #$logs;
my #stat = grep {$_->{'message'} =~ $driver->get_current_url() } #responses;
my $json= decode_json $stat[0]->{'message'};
my $status = $json->{'message'}->{'params'}->{'response'}->{'status'};
if ($status==200) {
print("Looks good)\n");
}else{
warn("Error\n");
}
}
In version 1.37 you would have to fallback to WD2 as goog:loggingPrefs capability was not supoprted:
use strict;
use warnings;
use Selenium::Chrome;
use Selenium::Waiter qw/wait_until/;
use JSON;
my $chrome_driver_path = "./../../tools/drivers/chromedriver.exe";
my $driver;
my %settings = (
'binary' => $chrome_driver_path,
'extra_capabilities' =>{
'loggingPrefs' => {
#'browser' => 'ALL',
#'driver' => 'ALL',
'performance' => 'ALL'
},
'perfLoggingPrefs' => {
'traceCategories' => 'performance'
},
}
);
$Selenium::Remote::Driver::FORCE_WD2=1;
$driver = Selenium::Chrome->new(%settings);
print("Getting stackoverflow\n");
wait_until{$driver->get("https://www.stackoverflow.com")};
validate_site($driver);
print("Getting unexistent url of stackoverflow\n");
wait_until{$driver->get("https://www.stackoverflow.com/this-does-not-exists-and-returns-404")};
validate_site($driver);
#sleep(20);
$driver->shutdown_binary;
sub validate_site{
my ($driver) = #_;
my $logs = $driver->get_log('performance');
my #responses = grep {$_->{'message'} =~ /"Network\.responseReceived"/ } #$logs;
my #stat = grep {$_->{'message'} =~ $driver->get_current_url() } #responses;
my $json= decode_json $stat[0]->{'message'};
my $status = $json->{'message'}->{'params'}->{'response'}->{'status'};
if ($status==200) {
print("Looks good)\n");
}else{
warn("Error\n");
}
}
As you mentioned, WebDriver does not expose http response codes and it is suggested to use proxy if you really need it .
If you do not want to wait for the element too long, you could reduce implicit timeouts in validate_site and look for reliable element eg:
sub validate_site{
my ($driver) = #_;
my $implicit=$driver->get_timeouts()->{implicit};# get current value
$driver->set_implicit_wait_timeout(0);# set it to 0
my #elem = $driver->find_elements(".py128","css");#this 'reliable element' it's present on https://www.stackoverflow.com but not on 404 page
if (#elem) {
print("Looks good)\n");
}else{
warn("Error\n");
}
$driver->set_implicit_wait_timeout($implicit);# restore original value
}
or if you really want to workaround it and don't mind duplicating requests you could try https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
sub validate_site{
my ($driver) = #_;
my $script = q{
let page_url=window.document.URL;
let resp = await fetch(page_url);
return resp.status;
};
my $status = $driver->execute_script($script);
if ($status==200) {
print("Looks good)\n");
}else{
warn("Error\n");
}
}
if you don't need the body (saves you response size) then you can request only headers by adding HEAD method (instead of default GET)
let resp = await fetch(page_url,{method:"HEAD"});
I should like to insert the return token from api into the .env in when after i want pass it header in
<!-- language: php -->
class GuzzleController extends Controller
{
public function getToken()
{
$client = new Client();
$request = $client->request('POST', 'http://192.168.53.27:1996/api/login/',
[
'form_params' => [
'user_name' => 'userName',
'password' => 'Passs',
]
]);
return json_decode((string)$request->getBody(), true);
}
}
As same question has been answere here;
This method should save new value to your .env file
private function setEnvironmentValue($envKey, $envValue)
{
$envFile = app()->environmentFilePath();
$str = file_get_contents($envFile);
$str .= "\n"; // In case the searched variable is in the last line without \n
$keyPosition = strpos($str, "{$envKey}=");
$endOfLinePosition = strpos($str, PHP_EOL, $keyPosition);
$oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);
$str = str_replace($oldLine, "{$envKey}={$envValue}", $str);
$str = substr($str, 0, -1);
$fp = fopen($envFile, 'w');
fwrite($fp, $str);
fclose($fp);
}
usage
$this->setEnvironmentValue('DEPLOY_SERVER', 'forge#122.11.244.10');
Why is my webhook not working? I do not get any data from telegram bot API. Here is the detailed explanation of my problem:
I got SSL cert from StartSSL, it works fine on my website (according to GeoCerts SSL checker), but still seems like my webhook to Telegram Bot API doesn't work (despite it says that webhook was set I do not get any data).
I am making a webhook to my script on my website in this form:
https://api.telegram.org/bot<token>/setWebhook?url=https://mywebsite.com/path/to/giveawaysbot.php
I get this text in response:
{"ok":true,"result":true,"description":"Webhook was set"}
So it must be working, but it actually doesn't.
Here is my script code:
<?php
ini_set('error_reporting', E_ALL);
$botToken = "<token>";
$website = "https://api.telegram.org/bot".$botToken;
$update = file_get_contents('php://input');
$update = json_decode($update);
print_r($update); // this is made to check if i get any data or not
$chatId = $update["message"]["chat"]["id"];
$message = $update["message"]["text"];
switch ($message) {
case "/test":
sendMessage($chatId,"test complete");
break;
case "/hi":
sendMessage($chatId,"hey there");
break;
default:
sendMessage($chatId,"nono i dont understand you");
}
function sendMessage ($chatId, $message) {
$url = $GLOBALS[website]."/sendMessage?chat_id=".$chatId."&text=".urlencode($message);
file_get_contents($url);
}
?>
I don't actually receive any data to $update. So webhook is not working. Why?
Just another one moment, why your webhooks not work.
In my case the reason was in allowed_updates webhook parameter.
By calling :
https://api.telegram.org/bot<your_bot_token>/getWebhookInfo
You can see
{
"ok": true,
"result": {
"url": "<your webhook url should be here>",
"has_custom_certificate": false,
"pending_update_count": 0,
"max_connections": 40,
"allowed_updates": [
"callback_query"
]
}
}
It means, that your bot can't react to your text messages, and you will not receive any webhooks!
You can note, that "allowed_updates" contains array. So, currently it will react only to inline button events (passed as keyboard layout!). According to the setWebhook documentation, allowed_updates is an "optional" parameter.
To start receieve text messages, you need to add "message" to your "allowed_updates" prop. To do it, just again set your webhooks and add it to query. Like here :
https://api.telegram.org/bot<your_token>/setWebHook?url=<your_url>&allowed_updates=["callback_query","message"]
You will receive something like "url already added", but don't worry, allowed_updates will be updated even in this case. Just try type your message to bot and test your webhooks.
That's all, now, telegram will send webhooks to each direct message from you to your bot. Hope, it helps someone.
I was with this problem. I was trying to look everywhere and couldn't find the solution for my problem, because people were all the time saying that the problem was the SSL certificate. But I found the problem, and that were a lot of things missing on the code to interact with the telegram API webhook envolving curl and this kind of stuff. After I looked in an example at the telegram bot documentation, I solved my problem. Look this example https://core.telegram.org/bots/samples/hellobot
<?php
//telegram example
define('BOT_TOKEN', '12345678:replace-me-with-real-token');
define('API_URL', 'https://api.telegram.org/bot'.BOT_TOKEN.'/');
function apiRequestWebhook($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
$parameters["method"] = $method;
header("Content-Type: application/json");
echo json_encode($parameters);
return true;
}
function exec_curl_request($handle) {
$response = curl_exec($handle);
if ($response === false) {
$errno = curl_errno($handle);
$error = curl_error($handle);
error_log("Curl returned error $errno: $error\n");
curl_close($handle);
return false;
}
$http_code = intval(curl_getinfo($handle, CURLINFO_HTTP_CODE));
curl_close($handle);
if ($http_code >= 500) {
// do not wat to DDOS server if something goes wrong
sleep(10);
return false;
} else if ($http_code != 200) {
$response = json_decode($response, true);
error_log("Request has failed with error {$response['error_code']}: {$response['description']}\n");
if ($http_code == 401) {
throw new Exception('Invalid access token provided');
}
return false;
} else {
$response = json_decode($response, true);
if (isset($response['description'])) {
error_log("Request was successfull: {$response['description']}\n");
}
$response = $response['result'];
}
return $response;
}
function apiRequest($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
foreach ($parameters as $key => &$val) {
// encoding to JSON array parameters, for example reply_markup
if (!is_numeric($val) && !is_string($val)) {
$val = json_encode($val);
}
}
$url = API_URL.$method.'?'.http_build_query($parameters);
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
return exec_curl_request($handle);
}
function apiRequestJson($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
$parameters["method"] = $method;
$handle = curl_init(API_URL);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($parameters));
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
return exec_curl_request($handle);
}
function processMessage($message) {
// process incoming message
$message_id = $message['message_id'];
$chat_id = $message['chat']['id'];
if (isset($message['text'])) {
// incoming text message
$text = $message['text'];
if (strpos($text, "/start") === 0) {
apiRequestJson("sendMessage", array('chat_id' => $chat_id, "text" => 'Hello', 'reply_markup' => array(
'keyboard' => array(array('Hello', 'Hi')),
'one_time_keyboard' => true,
'resize_keyboard' => true)));
} else if ($text === "Hello" || $text === "Hi") {
apiRequest("sendMessage", array('chat_id' => $chat_id, "text" => 'Nice to meet you'));
} else if (strpos($text, "/stop") === 0) {
// stop now
} else {
apiRequestWebhook("sendMessage", array('chat_id' => $chat_id, "reply_to_message_id" => $message_id, "text" => 'Cool'));
}
} else {
apiRequest("sendMessage", array('chat_id' => $chat_id, "text" => 'I understand only text messages'));
}
}
define('WEBHOOK_URL', 'https://my-site.example.com/secret-path-for-webhooks/');
if (php_sapi_name() == 'cli') {
// if run from console, set or delete webhook
apiRequest('setWebhook', array('url' => isset($argv[1]) && $argv[1] == 'delete' ? '' : WEBHOOK_URL));
exit;
}
$content = file_get_contents("php://input");
$update = json_decode($content, true);
if (!$update) {
// receive wrong update, must not happen
exit;
}
if (isset($update["message"])) {
processMessage($update["message"]);
}
?>
I had similar problem. Now solved.
The problem is possibly in a wrong public certificate. Please follow with attention instructions I propose in my project:
https://github.com/solyaris/BOTServer/blob/master/wiki/usage.md#step-4-create-self-signed-certificate
openssl req -newkey rsa:2048 -sha256 -nodes -keyout /your_home/BOTServer/ssl/PRIVATE.key -x509 -days 365 -out /your_home/BOTServer/ssl/PUBLIC.pem -subj "/C=IT/ST=state/L=location/O=description/CN=your_domain.com"
Telegram setWebhooks API do not check data inside your self-signed digital certificate, returning "ok" even if by example you do not specify a valid /CN! So be carefull to generate a public .pem certificate containing /CN=your_domain corresponding to your REAL HOST domain name!
It may be the SSL cert. I had the same problem: Webhook confirmed but actually SSL cert borked.
This reddit thread was helpful: https://www.reddit.com/r/Telegram/comments/3b4z1k/bot_api_recieving_nothing_on_a_correctly/
This may help who works with Laravel Telegram SDK.
I had a problem with self-signed webhook in Laravel 5.3.
After setup and getting OK result from Telegram with "Webhook was set" message, it didn't work.
The problem was related to CSRF verification. So I added the webhook url to CSRF exceptions and now everything works like a charm.
I had this problem too, after somehow the telegram didn't run my bot, so I tried to renew the certificate and set web hooks again, but again it didn't work, so I updated my VPS(yum update) and then renew my certificate and set web hooks again. after these it started working again.
This is because you are not setting the certificate like this
curl -F "url=https://bot.sapamatech.com/tg" -F "certificate=#/etc/apache2/ssl/bot.pem" https://api.telegram.org/bot265033849:AAHAs6vKVlY7UyqWFUHoE7Toe2TsGvu0sf4/setWebhook
Check this link on how to set Telegram Self Signed Certificate
Try this code. If you have a valid SSL on your web host and you have properly run the setWebhook, it should work (does for me). Make sure you create a file called "log.txt" and give write permission to it:
<?php
define('BOT_TOKEN', '????');
define('API_URL', 'https://api.telegram.org/bot'.BOT_TOKEN.'/');
// read incoming info and grab the chatID
$content = file_get_contents("php://input");
$update = json_decode($content, true);
$chatID = $update["message"]["chat"]["id"];
$message = $update["message"]["text"];
// compose reply
$reply ="";
switch ($message) {
case "/start":
$reply = "Welcome to Siamaks's bot. Type /help to see commands";
break;
case "/test":
$reply = "test complete";
break;
case "/hi":
$reply = "hey there";
break;
case "/help":
$reply = "commands: /start , /test , /hi , /help ";
break;
default:
$reply = "NoNo, I don't understand you";
}
// send reply
$sendto =API_URL."sendmessage?chat_id=".$chatID."&text=".$reply;
file_get_contents($sendto);
// Create a debug log.txt to check the response/repy from Telegram in JSON format.
// You can disable it by commenting checkJSON.
checkJSON($chatID,$update);
function checkJSON($chatID,$update){
$myFile = "log.txt";
$updateArray = print_r($update,TRUE);
$fh = fopen($myFile, 'a') or die("can't open file");
fwrite($fh, $chatID ."nn");
fwrite($fh, $updateArray."nn");
fclose($fh);
}
I had this problem too. In my case was mistake in declaring my API method. I created GET method instead of POST at first.
#api.route('/my-webhook-url')
class TelegramWebhook(Resource):
def post(self): # POST, Carl!
# ...
return response
In my case the error was due to the PHP configuration ( using cPanel )
[26-Jan-2021 09:38:17 UTC] PHP Warning: file_get_contents(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0 in /home/myUsername/public_html/mydomain.com/my_bot_file.php on line 40
and
[26-Jan-2021 09:38:17 UTC] PHP Warning: file_get_contents(https://api.telegram.org/bot<my-bot-id>/sendmessage?chat_id=647778451&text=hello charlie ! k99 ): failed to open stream: no suitable wrapper could be found in /home/myUsername/public_html/myDomain.com/my_bot_file.php on line 40
so - it is pretty self explanatory.
The allow_url_fopen=0 var in the php configuration actually disables the requiered action.
But anyhow your best bet is to look at the error log on your server and see if there are any other errors in the script or server config.
In the Joomla source, I found a method caled onUserAuthenticate, which could not be found in the API (through google), but its functionality is the similar to onLoginUser... So, after login/password check I need to run some more code via this function. As a result, I have true/false - depending on it I need to set users' authorization completely. Even if the user's login/password is correct, but my code returns false -> authorization fail...
I am trying something like:
functionon UserAuthenticate($credentials,$options,&$response){
jimport('joomla.user.helper');
$username=mysql_real_escape_string($credentials['username']);
$password=mysql_real_escape_string(md5($credentials['password']));
//my code returns $result
if($result!=NULL){
$response->status=JAUTHENTICATE_STATUS_SUCCESS;
$response->error_message='';
}
else{
$response->status=JAUTHENTICATE_STATUS_FAILURE;
$response->error_message=JText::_('JGLOBAL_AUTH_INVALID_PASS');
}
}
onUserAuthenticate is an event not a method. You use plugins to listen for Joomla events, in this case usually a user plugin would listen for this. When the event happens your code will run.
http://docs.joomla.org/Plugin
You can try this for custom login form-
$app = JFactory::getApplication();
$data = array();
$data['return'] = '';
$data['username'] = JRequest::getVar('username', '', 'method', 'username');
$data['password'] = JRequest::getString('password', '', 'post', JREQUEST_ALLOWRAW);
// Get the log in options.
$options = array();
// Get the log in credentials.
$credentials = array();
$credentials['username'] = $data['username'];
$credentials['password'] = $data['password'];
// Perform the log in.
$error = $app->login($credentials, $options);
if (!JError::isError($error)) {
$response->status=JAUTHENTICATE_STATUS_SUCCESS;
$response->error_message='';
}else{
$response->status=JAUTHENTICATE_STATUS_FAILURE;
$response->error_message=JText::_('JGLOBAL_AUTH_INVALID_PASS');
}
If you want authenticate solution on function "onUserAuthenticate" you should check it yourself if user credential is valid or not And you do it with this code :
function onUserAuthenticate($credentials, $options, &$response)
{
$response->type = 'Joomla';
// Joomla does not like blank passwords
if (empty($credentials['password'])) {
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message = JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
return false;
}
// Initialise variables.
$conditions = '';
// Get a database object
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('id, password');
$query->from('#__users');
$query->where('username=' . $db->Quote($credentials['username']));
$db->setQuery($query);
$result = $db->loadObject();
if ($result) {
$parts = explode(':', $result->password);
$crypt = $parts[0];
$salt = #$parts[1];
$testcrypt = JUserHelper::getCryptedPassword($credentials['password'], $salt);
if ($crypt == $testcrypt) {
$user = JUser::getInstance($result->id); // Bring this in line with the rest of the system
$response->email = $user->email;
$response->fullname = $user->name;
$response->status = JAuthentication::STATUS_SUCCESS;
$response->error_message = '';
print_r("You login correct Sir");
die();
} else {
print_r("you enter wrong credential");
die();
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message = JText::_('JGLOBAL_AUTH_INVALID_PASS');
}
} else {
print_r("you enter blank credential");
die();
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message = JText::_('JGLOBAL_AUTH_NO_USER');
}
return true;
}