Publication initiale de RelaisSMS : documentation et sources nettoyees
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Sms;
|
||||
|
||||
use App\Models\CalendarReminder;
|
||||
use App\Models\SmsCampaign;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SmsCampaignReconciler
|
||||
{
|
||||
public function __construct(private readonly OvhSmsProvider $provider) {}
|
||||
|
||||
public function reconcile(SmsCampaign $campaign): SmsCampaign
|
||||
{
|
||||
try {
|
||||
$messages = $this->provider->outgoing($campaign);
|
||||
} catch (SmsProviderException $exception) {
|
||||
Log::warning('SMS campaign verification unavailable.', [
|
||||
'sms_campaign_id' => $campaign->id,
|
||||
'reason' => $exception->getMessage(),
|
||||
]);
|
||||
|
||||
return $campaign;
|
||||
}
|
||||
|
||||
return $this->applyOutgoing($campaign, $messages);
|
||||
}
|
||||
|
||||
/** @param array<int, array<string, mixed>> $messages */
|
||||
public function applyOutgoing(SmsCampaign $campaign, array $messages): SmsCampaign
|
||||
{
|
||||
return DB::transaction(function () use ($campaign, $messages): SmsCampaign {
|
||||
$campaign = SmsCampaign::query()->lockForUpdate()->findOrFail($campaign->id);
|
||||
|
||||
if (! in_array($campaign->status, ['uncertain', 'sending'], true)) {
|
||||
return $campaign;
|
||||
}
|
||||
|
||||
$byNumber = [];
|
||||
foreach ($messages as $message) {
|
||||
if (($message['tag'] ?? null) !== $campaign->provider_tag
|
||||
|| ($message['message'] ?? null) !== $campaign->message
|
||||
|| empty($message['id']) || empty($message['receiver'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$byNumber[(string) $message['receiver']] = $message;
|
||||
}
|
||||
|
||||
foreach ($campaign->deliveries()->whereIn('status', ['uncertain', 'queued'])->get() as $delivery) {
|
||||
$message = $byNumber[$delivery->number] ?? null;
|
||||
if ($message === null) {
|
||||
$delivery->update(['status' => 'uncertain']);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// "sent" records acceptance by OVH, not delivery to the handset.
|
||||
$delivery->update([
|
||||
'status' => 'sent',
|
||||
'provider_message_id' => (string) $message['id'],
|
||||
'provider_response' => $message,
|
||||
'error_message' => null,
|
||||
'sent_at' => $message['sentAt'] ?? $message['creationDatetime'] ?? now(),
|
||||
]);
|
||||
}
|
||||
|
||||
$sentCount = $campaign->deliveries()->where('status', 'sent')->count();
|
||||
$failedCount = $campaign->deliveries()->where('status', 'failed')->count();
|
||||
$unconfirmed = $campaign->deliveries()->whereIn('status', ['uncertain', 'queued'])->exists();
|
||||
$status = $unconfirmed ? 'uncertain' : ($failedCount > 0 ? ($sentCount > 0 ? 'partial' : 'failed') : 'sent');
|
||||
$campaign->update([
|
||||
'status' => $status,
|
||||
'sent_count' => $sentCount,
|
||||
'failed_count' => $failedCount,
|
||||
'sent_at' => $campaign->deliveries()->where('status', 'sent')->min('sent_at'),
|
||||
'response_payload' => ['verification' => 'OVH outgoing history', 'confirmed_recipients' => $sentCount],
|
||||
'error_message' => $unconfirmed
|
||||
? 'Certains envois restent a verifier chez OVH. Aucun renvoi automatique ; ne pas renvoyer cette campagne.'
|
||||
: null,
|
||||
]);
|
||||
|
||||
CalendarReminder::query()->where('sms_campaign_id', $campaign->id)->where('status', 'uncertain')->update([
|
||||
'status' => $status === 'uncertain' ? 'uncertain' : ($sentCount > 0 ? 'sent' : 'failed'),
|
||||
'last_error' => $campaign->error_message,
|
||||
'sent_at' => $campaign->sent_at,
|
||||
]);
|
||||
|
||||
Log::info('SMS campaign verified against OVH history.', [
|
||||
'sms_campaign_id' => $campaign->id,
|
||||
'sent_count' => $sentCount,
|
||||
'status' => $status,
|
||||
]);
|
||||
|
||||
return $campaign->fresh(['deliveries', 'user']);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user