$raw Decoded provider response, for the log. */ private function __construct( public bool $ok, public string $messageId = '', public float $cost = 0.0, public string $errorCode = '', public string $error = '', public bool $retryable = false, public array $raw = [] ) {} /** * The provider accepted the message. * * @param string $messageId Provider identifier. * @param float $cost Reported cost. * @param array $raw Decoded response. */ public static function success( string $messageId = '', float $cost = 0.0, array $raw = [] ): self { return new self( true, $messageId, $cost, '', '', false, $raw ); } /** * The attempt failed, but trying again might work. * * Network timeouts, HTTP 5xx, provider rate limits. * * @param string $code Machine-readable code. * @param string $message Human-readable message. * @param array $raw Decoded response. */ public static function retryable( string $code, string $message, array $raw = [] ): self { return new self( false, '', 0.0, $code, $message, true, $raw ); } /** * The attempt failed and will keep failing. * * Bad credentials, unknown pattern code, malformed recipient, empty credit. * Retrying these burns the queue and delays real work. * * @param string $code Machine-readable code. * @param string $message Human-readable message. * @param array $raw Decoded response. */ public static function permanent( string $code, string $message, array $raw = [] ): self { return new self( false, '', 0.0, $code, $message, false, $raw ); } /** * Loggable summary. Never includes credentials. * * @return array */ public function toLog(): array { return array_filter( [ 'ok' => $this->ok, 'message_id' => $this->messageId, 'cost' => $this->cost, 'error_code' => $this->errorCode, 'error' => $this->error, 'retryable' => $this->retryable, ], static fn( $value ): bool => '' !== $value && 0.0 !== $value ); } }