findOrFail($this->messageId); $msg->update(['status' => 'processing']); foreach ($msg->recipients as $r) { if (in_array($r->status, ['sent', 'failed'])) continue; try { $phone = $r->phone; $message = $msg->content; $params = array( 'to' => '+39' . $phone, 'from' => env('SMS_FROM', 'Leezard'), 'message' => $message, 'format' => 'json', ); $this->sms_send($params); $r->update(['status' => 'sent', 'sent_at' => now(), 'error_message' => null]); } catch (\Throwable $e) { $r->update(['status' => 'failed', 'error_message' => $e->getMessage()]); } } $total = $msg->recipients()->count(); $sent = $msg->recipients()->where('status', 'sent')->count(); $failed = $msg->recipients()->where('status', 'failed')->count(); $newStatus = 'draft'; if ($total === 0) { $newStatus = 'draft'; } elseif ($sent === $total) { $newStatus = 'sent'; } elseif ($sent > 0 && $failed > 0) { $newStatus = 'partial'; } else { $newStatus = 'failed'; } $msg->update([ 'status' => $newStatus, 'sent_at' => $sent > 0 ? now() : $msg->sent_at, ]); } public function sms_send(array $params, bool $backup = false) { if (!isset($params['format'])) { $params['format'] = 'json'; } $url = $backup ? 'https://api2.smsapi.com/sms.do' : 'https://api.smsapi.com/sms.do'; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $params, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . env('SMS_TOKEN'), ], CURLOPT_TIMEOUT => 15, CURLOPT_CONNECTTIMEOUT => 5, ]); $content = curl_exec($ch); $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); if ($content === false) { if (!$backup) { return $this->sms_send($params, true); } throw new RuntimeException('SMS API cURL error: ' . $curlError); } if ($httpStatus !== 200) { if (!$backup && $httpStatus >= 500 && $httpStatus < 600) { return $this->sms_send($params, true); } throw new RuntimeException("SMS API HTTP {$httpStatus}: {$content}"); } $data = json_decode($content, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new RuntimeException('SMS API invalid JSON response: ' . $content); } if (isset($data['error'])) { $msg = is_array($data['error']) ? ($data['error']['message'] ?? json_encode($data['error'])) : $data['error']; throw new RuntimeException('SMS API error: ' . $msg); } if (isset($data['list'][0]['status'])) { $status = strtoupper($data['list'][0]['status']); if (in_array($status, ['ERROR', 'FAILED', 'REJECTED'], true)) { $errMsg = $data['list'][0]['error_message'] ?? 'Unknown SMS API error'; throw new RuntimeException("SMS API message error ({$status}): {$errMsg}"); } } return $data; } }