130 lines
4.4 KiB
PHP
130 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Webhook;
|
|
|
|
use App\Notifications\Subscription\FailedPaymentNotification;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\App;
|
|
use Laravel\Cashier\Http\Controllers\WebhookController;
|
|
use Stripe\Subscription as StripeSubscription;
|
|
|
|
class StripeController extends WebhookController
|
|
{
|
|
public function handleCustomerSubscriptionCreated(array $payload)
|
|
{
|
|
return parent::handleCustomerSubscriptionCreated($payload);
|
|
}
|
|
|
|
/**
|
|
* Override to add a sleep, and to detect plan upgrades
|
|
*
|
|
* @return \Symfony\Component\HttpFoundation\Response|void
|
|
*/
|
|
protected function handleCustomerSubscriptionUpdated(array $payload)
|
|
{
|
|
sleep(1);
|
|
|
|
if ($user = $this->getUserByStripeId($payload['data']['object']['customer'])) {
|
|
$data = $payload['data']['object'];
|
|
|
|
$subscription = $user->subscriptions()->firstOrNew(['stripe_id' => $data['id']]);
|
|
|
|
if (
|
|
isset($data['status']) &&
|
|
$data['status'] === StripeSubscription::STATUS_INCOMPLETE_EXPIRED
|
|
) {
|
|
$subscription->items()->delete();
|
|
$subscription->delete();
|
|
|
|
return;
|
|
}
|
|
|
|
$subscription->name = $subscription->name ?? $data['metadata']['name'] ?? $this->newSubscriptionName($payload);
|
|
|
|
$firstItem = $data['items']['data'][0];
|
|
$isSinglePrice = count($data['items']['data']) === 1;
|
|
|
|
// Price...
|
|
$subscription->stripe_price = $isSinglePrice ? $firstItem['price']['id'] : null;
|
|
|
|
// Name...
|
|
$subscription->name = $this->getSubscriptionName($data['plan']['product']);
|
|
|
|
// Quantity...
|
|
$subscription->quantity = $isSinglePrice && isset($firstItem['quantity']) ? $firstItem['quantity'] : null;
|
|
|
|
// Trial ending date...
|
|
if (isset($data['trial_end'])) {
|
|
$trialEnd = Carbon::createFromTimestamp($data['trial_end']);
|
|
|
|
if (! $subscription->trial_ends_at || $subscription->trial_ends_at->ne($trialEnd)) {
|
|
$subscription->trial_ends_at = $trialEnd;
|
|
}
|
|
}
|
|
|
|
// Cancellation date...
|
|
if (isset($data['cancel_at_period_end'])) {
|
|
if ($data['cancel_at_period_end']) {
|
|
$subscription->ends_at = $subscription->onTrial()
|
|
? $subscription->trial_ends_at
|
|
: Carbon::createFromTimestamp($data['current_period_end']);
|
|
} elseif (isset($data['cancel_at'])) {
|
|
$subscription->ends_at = Carbon::createFromTimestamp($data['cancel_at']);
|
|
} else {
|
|
$subscription->ends_at = null;
|
|
}
|
|
}
|
|
|
|
// Status...
|
|
if (isset($data['status'])) {
|
|
$subscription->stripe_status = $data['status'];
|
|
}
|
|
|
|
$subscription->save();
|
|
|
|
// Update subscription items...
|
|
if (isset($data['items'])) {
|
|
$prices = [];
|
|
|
|
foreach ($data['items']['data'] as $item) {
|
|
$prices[] = $item['price']['id'];
|
|
|
|
$subscription->items()->updateOrCreate([
|
|
'stripe_id' => $item['id'],
|
|
], [
|
|
'stripe_product' => $item['price']['product'],
|
|
'stripe_price' => $item['price']['id'],
|
|
'quantity' => $item['quantity'] ?? null,
|
|
]);
|
|
}
|
|
|
|
// Delete items that aren't attached to the subscription anymore...
|
|
$subscription->items()->whereNotIn('stripe_price', $prices)->delete();
|
|
}
|
|
}
|
|
|
|
return $this->successMethod();
|
|
}
|
|
|
|
protected function handleChargeFailed(array $payload)
|
|
{
|
|
if ($user = $this->getUserByStripeId($payload['data']['object']['customer'])) {
|
|
$user->notify(new FailedPaymentNotification());
|
|
}
|
|
|
|
return $this->successMethod();
|
|
}
|
|
|
|
private function getSubscriptionName(string $stripeProductId)
|
|
{
|
|
$config = App::environment() == 'production' ? config('pricing.production') : config('pricing.test');
|
|
foreach ($config as $plan => $data) {
|
|
if ($stripeProductId == $config[$plan]['product_id']) {
|
|
return $plan;
|
|
}
|
|
}
|
|
|
|
return 'default';
|
|
}
|
|
}
|