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
Другие вопросы по тегам