I'm on Laravel 5.1, stripe api 2015-10-16
I'm trying to handle: customer.subscription.deleted so I'm overriding handleCustomerSubscriptionDeleted
but the method is never called.. (even if I return a 200 response without other lines of code the stripe log a 500 error response)
I'm routing as described in docs:
Route::post('/stripe/webhook', 'WebhookController#handleWebhook');
a custom controller:
namespace App\Http\Controllers;
use App\Abbonamento;
use Symfony\Component\HttpFoundation\Response;
use Laravel\Cashier\WebhookController as BaseController;
class WebhookController extends BaseController
{
/**
* Handle a stripe webhook.
*
* #param array $payload
* #return Response
*/
public function handleInvoicePaymentSucceeded($payload)
{
$subscription = $payload['data']['object']['subscription'];
$abbo = Abbonamento::bySubscription($subscription)->first();
if ($abbo)
{
$abbo->makeStripePayment($payload);
}
}
public function handleCustomerSubscriptionDeleted($payload)
{
$subscription = $payload['data']['object']['id'];
$abbo = Abbonamento::bySubscription($subscription)->first();
if ($abbo and $abbo->subscribed())
{
$abbo->subscription()->cancel();
}
return new Response('Webhook Handled', 200);
}
}
Someone can tel me why "handleInvoicePaymentSucceeded" works but "handleCustomerSubscriptionDeleted" was never called?
The question is not about my custom entity "Abbonamento", is just about why I see always error 500 as return response in the test env on stripe for customer.subscription.deleted, and an ok response on
invoice.payment_succeeded
the problem was the method declaration,
looking at the laravel.log I swiched it to:
public function handleCustomerSubscriptionDeleted(array $payload)
so the missed part was "array"
Related
I am using laravel 5.8 version, i have one api which is responsible for registering ,i create one Request file which contains rules() and messages() function to display error messages but it's not throwing any error messages if any validation fails ,why this is happening can somebody explain ?
UserController.php
<?php
namespace App\Http\Controllers;
use App\Http\Requests\userRequest;
use App\UserSection;
class UserController extends Controller
{
public function userRegister(userRequest $request){
//logic of my code
return response()->json($success);
}
}
userRequest.php
<?php
namespace App\Http\Requests;
use App\Rules\CustomRule;
use Illuminate\Foundation\Http\FormRequest;
class userRequest extends FormRequest
{
public function messages()
{
return [
'first_name.required' => 'A title is required',
];
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'first_name' => 'string|required|max:25',
'phone_number' => 'required|integer'
];
}
}
The error i am facing when i hit the route without first_name key it's showing 404 not found error
you might have missed headers part for taking the form-data
Accept = application/json
As laravel docs
If validation fails, a redirect response will be generated to send the
user back to their previous location. The errors will also be flashed
to the session so they are available for display. If the request was
an AJAX request, a HTTP response with a 422 status code will be
returned to the user including a JSON representation of the validation
errors.
So you need to specify the response type you expect, if you use postman for testing your api end point you have to add in request header Accept:application/json
<?php
namespace App\Http\Controllers;
use App\Http\Requests\userRequest;
use App\UserSection;
class UserController extends Controller
{
public function userRegister(userRequest $request){
//logic of my code
return response()->json($success);
}
}
In my Laravel project I want to authorize user via a Request like this:
<?php
namespace Domain\Contents\Http\Requests\Blog;
use Domain\Contents\Models\Blog\Post;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
class ReadPostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
if (request('id') === null) {
abort(403);
}
$post = Post::whereId(request('id'))->first();
return Gate::allows('view-post', $this->user(), $post);
}
// ...
}
But I think here this part of my code is little bit messy:
if (request('id') === null) {
abort(403);
}
$post = Post::whereId(request('id'))->first();
Is there any simpler solution for accessing current Post model in the Request class?
The documentation for FormRequests suggests that the authorize() method supports type hinting.
If you are using route model binding you could therefore just type hint the post:
public function authorize(Post $post)
{
return Gate::allows('view-post', $this->user(), $post);
}
Alternative solution is that you can directly access your Models that are used with Model Binding.
return Gate::allows('view-post', $this->user(), $this->post);
For ease of use you can typehint it in the comments.
/**
* #property \App\Models\Post $post
*/
I'm using Laravel 8 to build an API, I have a route which for the purposes of the question is... /api/fact which GETs a random fact. I have a FactsController.php file and two traits, one for constructing a JSON response, the other for getting a fact. For some reason when calling the trait's function from within my controller (which made the request) I'm not getting any returned JSON back in Postman...
Traits/GetFact.php
<?php
namespace App\Traits;
use App\Traits\ApiResponse;
trait GetFact {
use ApiResponse;
/**
* Get random fact
*
* get random fact
*/
public function getRandomFact () {
$this->getFact();
$this->apiResponse([
'msg' => "Fact..."
], 200, true);
}
}
Traits/ApiResponse.php
<?php
namespace App\Traits;
trait ApiResponse {
/**
* API Response
*
* Return a JSON response for our API with params
*/
public function apiResponse ($data, $code, $success = false) {
return response()->json(array_merge(['success' => $success], $data), $code);
}
}
Controllers/FactController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Traits\GetFact;
class FactsController extends Controller
{
use GetFact;
/**
* Fact
*
* #param Request $request
*/
public function fact()
{
$this->getRandomFact()
}
}
When I make my request to /api/fact I should be getting the returned JSON listed where I'm calling $this->apiResponse() with the msg, but I'm not? It's like the return doesn't seem to return JSON because it's scoped to the trait and not the controller and that there isn't a return in there? How can I achieve the listed.
You are not "returning" anything from your Controller method. You have to return something for their to be a response with content. Also, fact and getRandomFact do not return anything so calling those isn't doing anything for you. You are also calling a getFact method and not assigning the return to anything (if it even returns anything).
In Laravel fortify on customization authentication process, i can not able to redirect to login page with error message which we were able to do in Auth.
Here is the customization documentation link: https://jetstream.laravel.com/1.x/features/authentication.html#customizing-the-authentication-process
if ($user && Hash::check($request->password, $user->password) && $user->status == 'active') {
return $user;
} elseif ($user->status == 'inactive') {
//redirect with some error message to login blade
} elseif ($user->status == 'blocked') {
//redirect with some error message to login blade
}
Please help me out on this.
For those coming from google search who use Laravel Jetstream (which uses Fortify):
Snapey of Laracasts answered this question and made a tutorial which uses your own LoginResponse to override the default login behavior.
I made mine like this but of course you should create your own according to your needs.
// app/Http/Responses/LoginResponse.php
namespace App\Http\Responses;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
class LoginResponse implements LoginResponseContract
{
/**
* #param $request
* #return mixed
*/
public function toResponse($request)
{
// replace this with your own code
// the user can be located with Auth facade
$home = Auth::user()->is_admin ? config('fortify.dashboard') : config('fortify.home');
return $request->wantsJson()
? response()->json(['two_factor' => false])
: redirect($home);
}
}
The next step it to modify JetstreamServiceProvider to use your LoginReponse
public function boot()
{
$this->configurePermissions();
Jetstream::deleteUsersUsing(DeleteUser::class);
// register new LoginResponse
$this->app->singleton(
\Laravel\Fortify\Contracts\LoginResponse::class,
\App\Http\Responses\LoginResponse::class
);
}
Hope it saves you time.
I understand your frustration with the documentation (or lack thereof). I had a similar problem and this is how I managed to do it:
if ($user && in_array($user->status_id, [1,2,3])) {
if (Hash::check($request->password, $user->password)) {
return $user;
}
}
else {
throw ValidationException::withMessages([
Fortify::username() => "Username not found or account is inactive. Please check your username.",
]);
}
https://github.com/laravel/fortify/issues/94#issuecomment-700777994
For SPA applications that only want a custom JSON response rather than the default {two_factor: false}.
Create a custom response that implements LoginResponse contract of Fortify (in this case I'm returning the user object):
<?php
declare(strict_types=1);
namespace App\Http\Responses;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
use Symfony\Component\HttpFoundation\Response;
class LoginResponse implements LoginResponseContract
{
public function toResponse($request): Response
{
return response()->json(auth()->user());
}
}
Add this line to the boot method of FortifyServiceProvider:
$this->app->singleton(LoginResponseContract::class, LoginResponse::class);
Making sure you've imported the namespaces correctly:
use App\Http\Responses\LoginResponse;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
If you are still not getting a JSON from the server, make sure your request has the right headers. It should be an XHR request that accepts application/json.
Inspired by this article from Laravel News.
for example - custom redirect after login/logout/register. By request parameter - alias
In FortifyServiceProvider class
Add.
use Laravel\Fortify\Contracts\LoginResponse;
use Laravel\Fortify\Contracts\LogoutResponse;
use Laravel\Fortify\Contracts\RegisterResponse;
And then in register method.
$this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
public function toResponse($request)
{
return redirect('/'.$request->alias);
}
});
$this->app->instance(LoginResponse::class, new class implements LoginResponse {
public function toResponse($request)
{
return redirect()->intended('/'.$request->alias.'/admin/dashboard');
}
});
$this->app->instance(RegisterResponse::class, new class implements RegisterResponse {
public function toResponse($request)
{
return redirect('/'.$request->alias.'/admin/dashboard');
}
});
goto \config\fortify.php at line 66, change home value to any path you want
'home' => '/dashboard',
Currently, Fortify doesn't have a way to customize redirects.
There is an open issue requesting this bahavior here: https://github.com/laravel/fortify/issues/77
There is a good chance this will be added soon!
I'm having difficulty how do I get the user id based on the token generated by laravel? I'm not very familiar with framewrok can anyone help me?
class ForgotPasswordController extends Controller
{
use SendsPasswordResetEmails;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
}
ResetPasswordController
class ResetPasswordController extends Controller
{
use ResetsPasswords;
protected $redirectTo = '/login';
public function __construct()
{
$this->middleware('guest');
}
protected function guard()
{
return Auth::guard('user');
}
public function broker()
{
return Password::broker('users');
}
public function showResetForm(Request $request, $token = null)
{
var_dump($request->email);
var_dump( $request->token);
return view('auth.passwords.reset')->with(
['token' => $token, 'email' => $request->email]
);
}
}
how to update password? I only have the token received by email?
Check this steps so you can understand better how laravel auth works.
Generate the auth scaffolding with: php artisan make:auth
Run the created migrations:php artisan migrate
Check your route list with php artisan route:list, you can see that routes were created too when you ran make:auth command.
Take note of the controllers and methods the Auth routes are calling.
Go to the routes web.php file. See the Auth::routes();, this generate the default Laravel Auth routes, if you don't need em all, comment or delete this line and add the required Lines.
If you took note of the controllers and methods, you can see what's been called on each route. In this particular case, i think you'd be looking for ResetPasswordController which uses ResetsPasswords from vendor/laravel/framework/src/Illuminate/Foundation/Auth/ResetsPasswords.php there you can see the resets method this is what you'll have to override on your ResetPasswordController.