Implement Gocardless webhook in Laravel - php

I was trying to implement a webhook in laravel.
I have created access token and created webhook endpoint also.
my webhook end point is like,https://www.example.com/gocardless.php
and my route is like,
Route::get('/gocardless.php',
'\App\Http\Controllers\gocardlessController#remote')->name('remote');
Controller code like,
class gocardlessController extends Controller
{
public function remote(Request $request)
{
$token ="token";
$raw_payload = file_get_contents('php://input');
$headers = getallheaders();
$provided_signature = $headers["Webhook-Signature"];
$calculated_signature = hash_hmac("sha256",$raw_payload,$token);
if ($provided_signature == $calculated_signature) {
$payload = json_decode($raw_payload, true);
}
}
}
But when i clik on send test webhook in gocardless account,they are given "405 no method found" as responce.
How i can solve this?

The HTTP 405 error you're seeing indicates that your Laravel application doesn't know how to handle the method of the incoming request.
GoCardless webhooks use the POST method to send you a request with a JSON body, but the route you've written is for handling a GET request (Route::get). To resolve this, you should define a route for POST requests to the endpoint which will receive webhooks.

A few remarks and fixes
Remark
Why do you include the "ugly" .php extension in your route, there is no need for that
Fix
Change your route (in web.php) to
Route::get('gocardless', 'gocardlessController#remote');
Remark
I also see you start your controller name with lowercase, this is not common practise
Fix
Don't forget to add these lines in your controller at the top
namespace App\Http\Controllers; // declare right namespace
use Illuminate\Http\Request; // Hint which Request class to use below
For the body: that you really have to write yourself and return the data as json for example

Related

Laravel Http request to route sends forever

I want to have a link in an email that send to the user, the link is the url of the site and has an api token for the user to authenticate with.
however I am trying to send an api request to get the user details so I can authenticate the user and redirect them to the relavent page, however doing this I end up with a request the spins endlessly.
what could be the issue and if there are any other solutions please let me know.
the link/request looks like this
http://localhost:8005/api/token?_token=<API TOKEN>
The controller that handles the request
<?php
namespace App\Http\Controllers;
use Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Http;
class PassportController extends Controller
{
function getToken(Request $request)
{
// return $request->_token;
return $user = Http::withToken($request->_token)->get('http://localhost:8005/api/user');
Auth::login($user);
return redirect('/dashboard');
}
}
Also when I send the request it gets stuck and I have to restart my php artisan serve again to make more requests, and every time i do so, It opens up on a new port, 8001,8002,8003 etc
You can make a call back to the app itself like this:
$tokenRequest = Request::create('/api/user', 'GET', ['name' => 'value']);
$tokenResult = app()->handle($tokenRequest);
Update the variables to match your implementations.

Injecting Request object into controller's constructor, on an API route

Problem
It seems like my API-handling controller cannot process an injected Request object. Details below.
I have a route in my api.php routes file:
Route::namespace('Mailing')->prefix('mailing/webhook')->group(function () {
Route::post('open', 'WebhookController#getOpened');
});
In the WebhookController.php, there's a constructor with the injected Request object:
use Illuminate\Http\Request;
public function __construct(Request $request) {
// Log it in the database
Logger::info('constructor called...');
// Filter the input in the injected Request
$this->input = $this->getFilteredInput($request);
}
Now, when I deploy this code to the server and make the API call against my endpoint, the log message at the beginning of the __construct() method is not even fired. I also get no data stored in the database (which should happen if the webhook is correctly processed).
What I tested
However, when I create a dummy route in web.php routes file:
Route::post('open', 'WebhookController#getOpened');
and then create a form and make a POST call to the getOpened() method - all works as expected: I have the Request injected and can manipulate it.
I checked that:
The API endpoint is correct and available
There are no obsolete use statements at the top of the
WebhookController
Questions
Why does the api.php route fail on me? Doesn't Laravel's dependency injection work for API-handling controllers?

REST - Laravel redirect POST with body to other route

I'm currently re-writing an API with multiple endpoints. However, for legacy purposes it's required that there is a single endpoint which can be used to access all other endpoints. Which endpoint we should redirect to is based upon a custom action header send along with the request.
Example:
Input: Header -> Action A
Output: Redirect to route '/some/url' 'ControllerA#someAction'
Input: Header -> Action B
Output: Redirect to route '/some/other/url' 'ControllerB#someOtherAction'
Normally, I could use the redirect() method but then I lose the body of the POST method. All the endpoints I declared are POST methods.
Basically, the question is how can I properly redirect a POST to another route?
Also note I can't use:
App::call('App\Http\Controllers\PlanningController#addOrUpdate', ['request' => $request]);
Since my method uses a custom Request class to handle the validation. I get an exception telling the argument should be the type of my custom class and Illuminate\Http\Request is given.
I've actually found the answer to my problem. I've created a middleware which will re-create the request based upon the value found in the header.
Here's the handle function of the middleware (only tested on Laravel 5.2):
use Request;
use Route;
use Illuminate\Http\Response;
...
public function handle($request, Closure $next, $guard = null)
{
// Get the header value
$action = $request->header('action');
// Find the route by the action name
$route = Actions::getRouteByName(action); // This returns some route, i.e.: 'api/v1/some/url'
// Perform the action
$request = Request::create(route, 'POST', ['body' => $request->getContent()]);
$response = Route::dispatch($request);
return new Response($response->getContent(), $response->status(), ['Content-Type' => 'text/xml']); // the last param can be any headers you like
}
Please note that this might conflict on your project with other middleware. I've disabled other middleware and created a special routegroup for this. Since we're redirecting the call manually to another route the middleware on that route is called anyway. However, you can also implement this code inside a controller function then there are no conflicting middleware problems!

Redirect a route in Laravel 5.3

Im building an API in Laravel 5.3. In my routes/api.php file I have 3 endpoints:
Route::post('/notify/v1/notifications', 'Api\Notify\v1\NotifyApiController#notificationsPost');
Route::post('/notify/v1/alerts', 'Api\Notify\v1\NotifyApiController#alertsPost');
Route::post('/notify/v1/incidents', 'Api\Notify\v1\NotifyApiController#incidentsPost');
Several services will call these routes directly, however, when a request comes in from some services, the input data needs to be processed before it can hit these endpoints.
For example, if a request comes in from JIRA, I need to process the input before it hits these endpoints.
Im thinking that the simplest way to do this would be to have a 4th endpoint like the below:
Route::post('/notify/v1/jira', 'Api\Notify\v1\JiraFormatter#formatJiraPost');
The idea being to hit the /notify/v1/jira endpoint, have the formatJiraPost method process the input and then forward the request to /notify/v1/notifications (/alerts, /incidents) as required.
How can I have the /notify/v1/jira endpoint forward the request to the /notify/v1/notifications endpoint?
Do you see a better way to do this?
Depending how your app will work, you could always have your services pointing to /notify/v1/jira and then do the processing like you suggested.
Another alternative is have the JIRA service pointing at the same routes as all the other services but to use a Before middleware group to pre-process your data. Something like
Route::group(['middleware' => ['verifyService']], function () {
Route::post('/notify/v1/notifications', 'Api\Notify\v1\NotifyApiController#notificationsPost');
Route::post('/notify/v1/alerts', 'Api\Notify\v1\NotifyApiController#alertsPost');
Route::post('/notify/v1/incidents', 'Api\Notify\v1\NotifyApiController#incidentsPost');
});
You could check in your middleware your service.
<?php
namespace App\Http\Middleware;
use Closure;
class verifyService
{
public function handle($request, Closure $next)
{
//You could use switch/break case structure
if (isJIRA($request)) {
//Do some processing, it could be outsourced to another class
//$JiraPost = new formatJiraPost($request);
//Keep the requesting going to the routes with processed data
return $next($request);
}
//You could add extra logic to check for more services.
return $next($request);
}
protected function isJIRA(Request $request){
//Logic to check if it is JIRA.
}
}

How can I send an API Request directly from Controller in Laravel 5.2?

I am currently working on a project that implement API integration on several sites.
Now as I go along, I noticed that I was using too much AJAX Request using JQuery on my project (of which codes viewable on page source) and I wanted to limit that as much as possible.
Is there a way to send an API Request directly from any controller in Laravel 5.2 just like the code below?
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HttpRequestController extends Controller
{
public function PostRequest($uri, $data) {
//functional code that will post the given data to the specified uri
}
public function GetRequest($uri) {
//functional code that will retrieve the given data via the specified uri
}
}
You can use Guzzle https://github.com/guzzle/guzzle library to make HTTP requests.

Categories