Laravel Cashier Webhook: Получить текущего пользователя
Я использую следующее, чтобы переопределить значение по умолчанию handleCustomerSubscriptionDeleted
метод путем размещения следующего в app/Http/Controllers/WebHookController.php
:
<?php namespace App\Http\Controllers;
use Laravel\Cashier\WebhookController;
use Symfony\Component\HttpFoundation\Response;
class StripeWebhooks extends WebhookController {
/**
* Handle stripe subscription webhook
*
* @param array $payload
* @return Response
*/
public function handleCustomerSubscriptionDeleted($payload)
{
$billable = $this->getBillable($payload['data']['object']['customer']);
if ($billable && $billable->subscribed()) {
$billable->subscription()->cancel();
}
return new Response('Webhook Handled', 200);
}
}
Для того, чтобы это фактически переопределило стандартное значение по умолчанию, я должен обновить свой маршрут до моего расширенного контроллера, или все еще ссылаться на стандартное значение? Я не думаю, что оставив его по умолчанию, Laravel даже узнает, что мой контроллер существует, но также хотел подтвердить.
Текущий:
Route::post('stripe/webhook', '\Laravel\Cashier\WebhookController@handleWebhook');
Другая часть этого находится в пределах handleCustomerSubscriptionDeleted
Я также хотел бы иметь возможность получить текущий пользователь, на который он ссылается, и выполнить другие действия; в этом случае автоматическая установка записей на неопубликованные. Каков наилучший способ поиска пользователя? Это выглядит как $payload['data']['object']['customer']
потенциально может содержать и относиться к stripe_id
столбец в таблице пользователей, но хотел бы подтвердить. Спасибо за любую помощь!
Обновить
Я полагаю (основанный на документах), это должно быть больше как это:
<?php namespace App\Http\Controllers;
use App\Models\Dashboard\Listing;
use App\User;
use Symfony\Component\HttpFoundation\Response;
use Laravel\Cashier\WebhookController as BaseController;
class WebhookController extends BaseController
{
/**
* Handle stripe subscription webhook
*
* @param array $payload
* @return Response
*/
public function handleCustomerSubscriptionDeleted($payload)
{
$billable = $this->getBillable($payload['data']['object']['customer']);
if ($billable && $billable->subscribed()) {
$billable->subscription()->cancel();
// Get current user
$user = User::find($billable);
// Set each listing to draft
foreach ($user->listings as $listing) {
$current_listing = Listing::find($listing->id);
if ($current_listing->status == 'published') {
$current_listing->status = 'draft';
$current_listing->save();
}
}
}
return new Response('Webhook Handled', 200);
}
}
Затем я обновил свой маршрут до следующего:
Route::post('stripe/webhook', 'WebhookController@handleWebhook');
Но это все еще не стрельба. НО, что мне также интересно, если handleCustomerSubscriptionDeleted
называется "когда они отменяют" или после истечения льготного периода, и фактическая подписка отменяется. Есть ли для меня более надежный способ проверить это, чем играть в игру ожидания локально?
Обновление № 2
Я обновил свой класс переопределения следующим образом:
<?php namespace App\Http\Controllers;
use App\Models\Dashboard\Listing;
use App\User;
use Symfony\Component\HttpFoundation\Response;
use Laravel\Cashier\WebhookController as BaseController;
class WebhookController extends BaseController
{
/**
* Handle stripe subscription webhook
*
* @param array $payload
* @return Response
*/
public function handleCustomerSubscriptionDeleted(array $payload)
{
$billable = $this->getBillable($payload['data']['object']['customer']);
if ($billable && $billable->subscribed()) {
$billable->subscription()->cancel();
// Get current user
$user = User::where('stripe_id', $billable)->firstOrFail();
// Set each listing to draft
foreach ($user->listings as $listing) {
$current_listing = Listing::find($listing->id);
if ($current_listing->status == 'published') {
$current_listing->status = 'draft';
$current_listing->save();
}
}
}
return new Response('Webhook Handled', 200);
}
}
Часть, которую я изменил, менялась $billable
искать пользователя, поскольку именно это возвращает ответ, а не идентификатор пользователя, как я когда-то думал. В конце концов я попытался использовать localtunnel.me, как упомянул @Shaz, что позволило мне отправить ему запрос, НО без возможности передать идентификатор клиента. Я хотел бы повлиять, я не уверен, как я могу проверить все на самом деле работает. Я могу попытаться выяснить, могу ли я запустить событие вручную через Кассу, но все равно это выглядит немного странно.
Обновление № 3
Попытка сделать что-то немного проще, насколько слушать customer.subscription.created
(так как это срабатывает сразу):
<?php namespace App\Http\Controllers;
use App\Models\Dashboard\Listing;
use App\User;
use Symfony\Component\HttpFoundation\Response;
use Laravel\Cashier\WebhookController as BaseController;
class WebhookController extends BaseController
{
/**
* @param array $payload
*/
public function handleCustomerSubscriptionCreated(array $payload) {
$billable = $this->getBillable($payload['data']['object']['customer']);
if ($billable) {
// Get current user
$user = User::where('stripe_id', $billable)->firstOrFail();
$user->first_name = 'Helloooooo';
$user->save();
}
}
/**
* Handle stripe subscription webhook
*
* @param array $payload
* @return Response
*/
public function handleCustomerSubscriptionDeleted(array $payload)
{
$billable = $this->getBillable($payload['data']['object']['customer']);
if ($billable && $billable->subscribed()) {
$billable->subscription()->cancel();
// Get current user
$user = User::where('stripe_id', $billable)->firstOrFail();
// Set each listing to draft
foreach ($user->listings as $listing) {
$current_listing = Listing::find($listing->id);
if ($current_listing->status == 'published') {
$current_listing->status = 'draft';
$current_listing->save();
}
}
}
return new Response('Webhook Handled', 200);
}
}
Я использовал localtunnel.me для настройки webhook, но не похоже, что он правильно реагирует на webhook, так как я вижу 500 ошибок в журналах ответов Stripe, даже несмотря на то, что мое событие "Test Webhooks" сработало с информационной панели Stripe (с идентификатор клиента не установлен, очевидно) в порядке. Ответ, который я получаю об ошибке 500, к сожалению, потерян / обрезан в беспорядочном беспорядке исходного кода, который выкладывает Laravel:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="robots" content="noindex,nofollow" />
<style>
/* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
html { backgr...
3 ответа
Чтение ответа на этот вопрос - событие запускается в день / время, когда подписка фактически заканчивается, а не когда клиент инициирует отмену.
Исходя из документов Кассы Laravels - ваш маршрут должен быть:
Route::post('stripe/webhook', 'Laravel\Cashier\WebhookController@handleWebhook');
Убедитесь, что настройки вашего веб-крючка в полосе на самом деле указывают на yourapp.com/stripe/webhook
На основе handleWebhook
метод в Laravel\Cashier
код - да, любой метод с соответствующим именем (начинается с дескриптора, верблюжий для события полосы) переопределяет существующий.
Если вы хотите использовать свой расширенный контроллер в маршрутах; не забудьте добавить конструктор в начале класса:
public function __construct(){
parent::__construct();
}
Итак handleWebhook
метод доступен, когда вы делаете
Route::post('stripe/webhook', 'WebhookController@handleWebhook');
вместо вызова Laravel\Cashier\WebhookController
в пути.
У меня это работает, и я указываю маршрут к моему контроллеру.
Route::post(
'stripe/webhook',
'WebhookController@handleWebhook'
);
Поскольку мы расширяем базовый контроллер, любые методы базового контроллера уже доступны. Смысл этого контроллера в том, чтобы иметь доступ ко всем основным методам контроллера. Таким образом, вы можете расширить любые новые методы или перезаписать существующие.
У меня также была проблема с получением кода для отлова событий webhook. Стоит отметить, что если вы находитесь в тестовой среде чередования и запуска событий webhook, убедитесь, что вы добавили переменную env.
CASHIER_ENV=testing
В базовом контроллере webhook сначала проверяется, чтобы убедиться, что события существуют и событие не будет существовать, если webhook генерируется в тестовой среде.
public function handleWebhook(Request $request)
{
$payload = json_decode($request->getContent(), true);
if (! $this->isInTestingEnvironment() && ! $this->eventExistsOnStripe($payload['id'])) {
return;
}
$method = 'handle'.studly_case(str_replace('.', '_', $payload['type']));
if (method_exists($this, $method)) {
return $this->{$method}($payload);
} else {
return $this->missingMethod();
}
}
$billable = $this->getBillable($payload['data']['object']['customer']);
$user = $billable; // billable is User object