dpl/app/Services/MailFlow/ExpiredSubscriptionNotifier.php

47 lines
2.5 KiB
PHP

<?php
namespace App\Services\MailFlow;
use App\Jobs\SendMailMessageJob;
use App\Models\MailMessage;
use App\Models\User;
class ExpiredSubscriptionNotifier
{
public function queueDue(): int
{
$state = AutomaticMailPolicy::state();
if (!$state || $state['level'] !== 2 || !$state['since'] || !admin_setting('remind_mail_enable', false)) { return 0; }
$queued = 0;
User::where('remind_expire', true)->where('banned', false)->whereNotNull('plan_id')
->where('expired_at', '>', $state['since'])->where('expired_at', '<=', now()->timestamp)
->chunkById(500, function ($users) use (&$queued) {
foreach ($users as $user) {
if (!filter_var($user->email, FILTER_VALIDATE_EMAIL)) { continue; }
$key = 'subscription-expired:' . $user->id . ':' . $user->expired_at;
$params = ['message_key' => $key, 'email' => $user->email, 'user_id' => $user->id,
'purpose' => 'service_expired', 'subscription_expired_at' => (int) $user->expired_at,
'template_name' => 'serviceExpired', 'subject' => admin_setting('app_name', 'XBoard') . ' - 套餐已到期',
'template_value' => ['name' => admin_setting('app_name', 'XBoard'), 'url' => admin_setting('app_url')]];
if (AutomaticMailPolicy::decision('service_expired', $params)) { continue; }
// Persist before dispatch. The same user can renew and receive a later distinct expiry event.
$message = MailMessage::firstOrCreate(['message_key' => $key], [
'purpose' => 'service_expired', 'user_id' => $user->id, 'email' => $user->email,
'subject' => $params['subject'], 'template_name' => 'serviceExpired',
'expires_at' => now()->addDay(), 'payload' => ['email_params' => $params],
]);
if (!$message->wasRecentlyCreated && ($message->status !== 'pending' || !$message->payload
|| $message->updated_at->gt(now()->subMinutes(2)))) { continue; }
if ($message->attempts >= 6) {
$message->update(['status' => 'failed', 'error_code' => 'mail_retry_exhausted', 'payload' => null]);
continue;
}
$message->touch();
SendMailMessageJob::dispatch($message->id);
$queued++;
}
});
return $queued;
}
}