Laravel Nexmo invalid signature - php

I have SMS notification sending method via Nexmo client:
try {
$client = new Client(new SignatureSecret($nexmoKey, $signatureSecret, 'md5hash'));
$message = $client->message()->send(
[
'to' => $this->userNumber,
'from' => $from,
'text' => $this->notificationMessage,
'callback' => $webhookReceiveURL,
]
);
$response = $message->getResponseData();
$this->notificationId = $response['messages'][0]['message-id'];
return true;
} catch (\Exception $e) {
$this->exceptions[] = $e->getMessage();
return false;
}
If I put this piece of code in a service class where handle() method is called in Laravel's commands via crontab I get: Invalid Signature error but if I call this method from any controller method notification sends successfully. Can anyone explain why I get error if I try to send notification via crontab?

If the same code works in a controller, it sounds like configuration settings aren't getting passed into the job correctly. I would make sure that $nexmoKey and $signatureSecret look correct in the job.
On a side note, we do also offer a Laravel plugin through nexmo/laravel (https://github.com/Nexmo/nexmo-laravel/), which provides access to a Nexmo object via the Service Container and Facade layer. That may help cut down on the boilerplate for making the Nexmo object.

Related

Send Laravel verification email with a custom template using aws ses

What I am trying to do.
My goal is to send a custom blade template for the built-in Laravel email verification functionality. Right now in my AuthServiceProvider inside the boot function I call VerifyEmail::toMailUsing function and attempt to create an email based on the send_email function I already have. it takes a template name, email and params, finds the blade file, and inserts the params and sends the email with aws ses.
VerifyEmail::toMailUsing(function ($notifiable, $url) {
$params = [
'first_name' => $notifiable->first_name,
'verify_url' => $url
];
$generate_email = new SendEmailController();
$generate_email->send_email('verify', $notifiable->email, $params);
});
The issue:
The email gets sent successfully but throws an error:
I understand it must have to do with the toMailUsing, but just cant point my finger to it.
Expected outcome should be: no error :)

Laravel handle Telegram webhooks

I'm fairly new to Laravel, and recently I tried to create a Telegram bot that can manage incoming messages and reply accordingly. Initially I plan to ask a user's name and use his name the next time the bot replies.
So how can I manage my bot's webhook which I already managed to set up.
Route::any('/setWebhook', function () {
$response = Telegram::setWebhook([
'url' => 'https://57f7-2806-104e-c-5c3b-3dc7-3284-7383-e130.ngrok.io/NdqvlJstHyIUhmNyTZhCYTnoYxdGzoPcLCzDiMiH/webhook'
]);
dd($response);
});
How can I manage the bot's incoming updates? I'm currently using irazasyed sdk.
You need to use a DB, which requires Model & migration
Telegram Bot API will send POST requests to your webhook
You should add ->middleware('api'), because you'll receive data
Use file_get_contents('php://input') to get the update, Or use a library.
To me, I use SimpleBotAPI library
Simple code in SimpleBotAPI:
// Handle updates here
class BotHandler extends UpdatesHandler
{
public function MessageHandler($message) : bool
{
// Do whatever:
$this->Bot->SendMessage(['chat_id' => $message->chat->id, 'text' => 'new Message!']);
return true;
}
}
Route::post('/bot_webhook', function () {
$Bot = new TelegramBot(env('BOT_TOKEN'), new BotHandler());
$Bot->OnWebhookUpdate();
})->middleware('api');

Notification endpoint validation not working with Laravel Endpoint

I am using the Microsoft Graph and I need to set up a webhook to receive changes to email and calendar events. I was able to get it working with my PHP Laravel application, but now that I am trying to subscribe to notifications, I am running into issues with validating the notificationUrl, which is pointing to a public server of mine.
The script for creating the webhook is returning the following error:
Client error: POST https://graph.microsoft.com/v1.0/subscriptions resulted in a 400 Bad Request response:
{
"error": {
"code": "InvalidRequest",
"message": "Subscription validation request failed. Response must ex (truncated...)
The truncated part I believe is
Subscription validation request failed. Must respond with 200 OK to this request.
Here is my code for creating the subscription:
$data = [
"changeType" => "created",
"notificationUrl" => "https://anatbanielmethod.successengine.net/office365/webhooks/events",
"resource" => "me/events",
"expirationDateTime" => "2018-12-20T18:23:45.9356913Z",
"clientState" => "secret",
];
$result = $graph->createRequest('POST', '/subscriptions')
->attachBody($data)
->execute();
and here is my method for my notificationUrl:
public function events()
{
//if validationToken exists return that to validate notificationUrl
if(isset($_REQUEST['validationToken'])){
return response($_REQUEST['validationToken'], 200)
->header('Content-Type', 'text/plain');
}
//process event normally for those that have already been validated
}
Once again this URL is public and live and I have tested it by using Postman to send it test posts and it is working fine. Also, I added this route to my VerifyCsrfToken middleware to allow a third party post to hit this URL.
Originally I set up a simple single page PHP script to test validating the notificationUrl and that simple script worked fine. It successfully validates Webhooks created that point to it. Here is that one page script code:
<?php
if(isset($_REQUEST['validationToken'])){
echo $_REQUEST['validationToken']; // needed only once when subscribing
} else {
//process like normal not a validation Token request...
}
}
So I would expect that the Laravel endpoint would work like the simple one page PHP script, and it is when I test both URLs in Postman, but the Laravel endpoint is not validating when Office365 attempts to validate it when creating a new webhook.
I have searched all over for help on this and read through all of the Microsoft developer documentation I can find on webhooks and these are some of the more helpful parts of the documentation but I am still not finding an answer to this issue:
https://learn.microsoft.com/en-us/graph/api/subscription-post-subscriptions?view=graph-rest-1.0
https://learn.microsoft.com/en-us/graph/webhooks#notification-endpoint-validation
Any ideas of this?
Thanks Marc! You were correct about the linefeed being the issue, I am still not sure where the line feed is coming from, some how Laravel appears to be adding it. Needless to say I found a solution by adding an "ob_clean();" right before returning the response. Below is my updated notificationUrl method:
public function events()
{
//if validationToken exists return that to validate notificationUrl
if(isset($_REQUEST['validationToken'])){
ob_clean();//this line is cleaning out that previously added linefeed
return response($_REQUEST['validationToken'], 200)
->header('Content-Type', 'text/plain');
}
//process event normally for those that have already been validated
}
It's odd that JakeD's answer requires the use of ob_clean(). here is my webhook controller method in my Laravel 5.7.x app:
use Illuminate\Http\Request;
public function webhook (Request $request) {
if (filled($request->input('validationToken'))) {
return response($request->input('validationToken'))
->header('Content-Type', 'text/plain');
}
// code to process the webhook after validation is complete
}
I don't see an extra linefeed character and the Microsoft Graph API subscription is validated and created.

Log data for Symfony Profiler

I created a Bundle that calls an third party api.
Now i want to show the received data in the Symfony Profiler.
I created a CustomDataCollector (http://symfony.com/doc/current/profiler/data_collector.html). That all works fine. But how can i get or "save" the received response for the api?
I created a service that calls the api with curl like that:
$raw_response = curl_exec($ch);
$response = json_decode($raw_response);
if (property_exists($response, 'error') && $response->errors) {
return ['status'=>false, 'msg'=> (string)$response->errors[0]->description ] ;
} else {
return ['status'=>true, 'msg' =>'Send Successfully' ];
}
I'd advise you to use the logger service for simple use-cases that don't require a specific collector. You can provide additional context to the logging:
/** LoggerInterface */
$container->get('logger')->error('There was an error on the API call.', array(
'description' => $response->errors[0]->description
);
The logger data is saved to a profile by default. For more advanced use cases you might be looking for the processors: http://symfony.com/doc/current/logging/processors.html

LinkedIn returns 401: unknown authentication scheme when trying to share

I am trying to implement sharing to LinkedIn in our project. It works for me like a charm, however, for all of my colleagues, it does not. It returns 401: Unknown authentication scheme just for sharing request (profile requests work fine).
The LinkedIn app that we use is owned by me. For testing purposes another developer tried to create an app in his account, but the problem stayed: I was the only one who could share.
We are using linkedinapi/linkedin for back-end. Here's the code:
protected function openConnection()
{
$credentials = \Config::get('services.linkedin');
try
{
$this->connection = new \LinkedIn\LinkedIn([
'api_key' => $credentials['client_id'],
'api_secret' => $credentials['client_secret'],
'callback_url' => $credentials['redirect'],
]);
$this->connection->setAccessToken(\Auth::user()->linkedin->token['access_token']);
}
catch (\Exception $e)
{
\Log::error('Failed LinkedIn auth, exception is attached', [$e]);
throw new CouldNotPostException('Please, re-link your LinkedIn account, failed to send your post to LinkedIn.');
}
}
protected function send()
{
$object = [
'content' => [
'title' => $this->post->title,
'description' => \Str::limit($this->post->description, 253),
'submitted-url' => $this->post->shortlink,
'submitted_image_url' => \URL::to($this->post->image),
],
'comment' => $this->content,
'visibility' => [
'code' => 'connections-only'
]
];
try
{
$result = $this->connection->post('/people/~/shares?format=json', $object);
$this->posted($result['updateKey']);
}
catch (\Exception $e)
{
\Log::error('Failed LinkedIn posting, exception is attached', [$e]);
throw new CouldNotPostException('Failed to send your post to LinkedIn, our developers have been notified of this error.');
}
}
UPD: turns out it can post only on my machine, so there is something wrong with the configuration on their machines. Looking for it.
Investigation
I asked my colleague to login to LinkedIn on my machine, to see if posting fails for his account or for his computer. It posted, which showed that something is up with my configuration, that is why it works.
My next step was to re-install all of the vendor packages, including the mentioned above linkedinapi/linkedin. After that posting stopped working for me as well. After inspecting the way that library signs requests, I found that it does not match the way LinkedIn requires it. The library was including a oauth2_access_token parameter in the URL, but LinkedIn expects an Authorization HTTP header as it is stated in their documentation:
Once you've obtained an Access Token, you can start making authenticated API requests on behalf of the user. This is accomplished by including an "Authorization" header in your HTTP call to LinkedIn's API.
Solution
So for now I changed the way I make the request. Instead of
$result = $this->connection->post('/people/~/shares?format=json', $object);
I use a different function that allows me to include the header manually:
$result = $this->connection->fetch(
'/people/~/shares?format=json',
$object,
\LinkedIn\LinkedIn::HTTP_METHOD_POST,
[ 'Authorization: Bearer ' . $this->connection->getAccessToken() ]
);
Also, I created a pull request to the repository.

Categories