BraspressCliente::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 3
dl 0
loc 6
rs 10
1
<?php
2
3
namespace PedroQuezado\Code\Braspress;
4
5
/**
6
 * Classe responsável por integrar com a API da Braspress para realizar cotações de frete.
7
 */
8
class BraspressCliente
9
{
10
    /**
11
     * @var string Usuário da API da Braspress.
12
     */
13
    private $usuario;
14
15
    /**
16
     * @var string Senha da API da Braspress.
17
     */
18
    private $senha;
19
20
    /**
21
     * @var string URL base da API da Braspress, dependendo do ambiente (produção ou homologação).
22
     */
23
    private $baseUrl;
24
25
    /**
26
     * @var string Cabeçalho de autorização para a API da Braspress, baseado em Basic Auth.
27
     */
28
    private $authorizationHeader;
29
30
    /**
31
     * @var array Lista de volumes a serem cotados.
32
     */
33
    private $volumes = [];
34
35
    /**
36
     * @var int Quantidade total de volumes inseridos.
37
     */
38
    private $quantidadeVolumes = 0;
39
40
    /**
41
     * Construtor da classe. Define usuário, senha e URL base dependendo do ambiente.
42
     *
43
     * @param string $usuario Usuário da API.
44
     * @param string $senha Senha da API.
45
     * @param bool $producao Se true, usa a URL de produção; caso contrário, usa a URL de homologação.
46
     */
47
    public function __construct($usuario, $senha, $producao = true)
48
    {
49
        $this->usuario = $this->validarUsuario($usuario);
50
        $this->senha = $this->validarSenha($senha);
51
        $this->baseUrl = $producao ? "https://api.braspress.com" : "https://api-homologacao.braspress.com";
52
        $this->authorizationHeader = "Authorization: Basic " . base64_encode("{$this->usuario}:{$this->senha}");
53
    }
54
55
    /**
56
     * Valida o usuário da API.
57
     *
58
     * @param string $usuario
59
     * @return string
60
     * @throws BraspressClienteException Se o usuário for inválido.
61
     */
62
    private function validarUsuario($usuario)
63
    {
64
        if (empty($usuario) || !is_string($usuario)) {
65
            throw new BraspressClienteException("Usuário inválido.");
66
        }
67
        return $usuario;
68
    }
69
70
    /**
71
     * Valida a senha da API.
72
     *
73
     * @param string $senha
74
     * @return string
75
     * @throws BraspressClienteException Se a senha for inválida.
76
     */
77
    private function validarSenha($senha)
78
    {
79
        if (empty($senha) || !is_string($senha)) {
80
            throw new BraspressClienteException("Senha inválida.");
81
        }
82
        return $senha;
83
    }
84
85
    /**
86
     * Insere um produto na lista de volumes a serem cotados.
87
     *
88
     * @param float $peso Peso do volume.
89
     * @param array $dimensoes Dimensões do volume (comprimento, largura, altura).
90
     * @throws BraspressClienteException Se o peso ou as dimensões forem inválidos.
91
     */
92
    public function inserirProduto($peso, array $dimensoes)
93
    {
94
        $this->validarPeso($peso);
95
        $this->validarDimensoes($dimensoes);
96
97
        $this->volumes[] = [
98
            "comprimento" => $dimensoes['comprimento'],
99
            "largura" => $dimensoes['largura'],
100
            "altura" => $dimensoes['altura'],
101
            "peso" => $peso
102
        ];
103
        $this->quantidadeVolumes++;
104
    }
105
106
    /**
107
     * Valida o peso do volume.
108
     *
109
     * @param float $peso
110
     * @throws BraspressClienteException Se o peso for inválido.
111
     */
112
    private function validarPeso($peso)
113
    {
114
        if ($peso <= 0) {
115
            throw new BraspressClienteException("Peso inválido.");
116
        }
117
    }
118
119
    /**
120
     * Valida as dimensões do volume.
121
     *
122
     * @param array $dimensoes
123
     * @throws BraspressClienteException Se qualquer dimensão for inválida.
124
     */
125
    private function validarDimensoes(array $dimensoes)
126
    {
127
        if (empty($dimensoes['comprimento']) || empty($dimensoes['largura']) || empty($dimensoes['altura'])) {
128
            throw new BraspressClienteException("Dimensões inválidas.");
129
        }
130
131
        foreach (['comprimento', 'largura', 'altura'] as $dimensao) {
132
            if (!is_numeric($dimensoes[$dimensao]) || $dimensoes[$dimensao] <= 0) {
133
                throw new BraspressClienteException("Dimensão $dimensao inválida.");
134
            }
135
        }
136
    }
137
138
    /**
139
     * Calcula o peso total de todos os volumes inseridos.
140
     *
141
     * @return float Peso total.
142
     */
143
    private function calcularPesoTotal()
144
    {
145
        return array_reduce($this->volumes, function($total, $volume) {
146
            return $total + $volume['peso'];
147
        }, 0);
148
    }
149
150
    /**
151
     * Realiza a cotação com a API da Braspress.
152
     *
153
     * @param array $dadosCotacao Dados necessários para a cotação.
154
     * @param string $returnType Tipo de retorno esperado (json ou xml).
155
     * @param string|array $modal Modalidade de transporte ('R' para rodoviário, 'A' para aéreo, ou ambos).
156
     * @return array Resultado da cotação para cada modal.
157
     * @throws BraspressClienteException Se ocorrer um erro na cotação ou na API.
158
     */
159
    public function realizarCotacao(array $dadosCotacao, $returnType = 'json', $modal = 'R')
160
    {
161
        $resultados = [];
162
        $modalidades = is_array($modal) ? $modal : [$modal];
163
164
        foreach ($modalidades as $modalidade) {
165
            $dadosCotacao['modal'] = $this->validarModal($modalidade);
166
            $dadosCotacao['peso'] = $this->calcularPesoTotal();
167
            $dadosCotacao['volumes'] = $this->quantidadeVolumes;
168
            $dadosCotacao['cubagem'] = array_map(function($volume) {
169
                return [
170
                    "comprimento" => $volume['comprimento'],
171
                    "largura" => $volume['largura'],
172
                    "altura" => $volume['altura'],
173
                    "volumes" => 1
174
                ];
175
            }, $this->volumes);
176
177
            $ch = curl_init();
178
            curl_setopt($ch, CURLOPT_URL, "{$this->baseUrl}/v1/cotacao/calcular/{$returnType}");
179
            curl_setopt($ch, CURLOPT_POST, 1);
180
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($dadosCotacao));
181
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
182
                "Content-Type: application/json",
183
                $this->authorizationHeader
184
            ]);
185
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
186
            $response = curl_exec($ch);
187
188
            if (curl_errno($ch)) {
189
                throw new BraspressClienteException('Erro ao realizar cotação: ' . curl_error($ch));
190
            }
191
192
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
193
            curl_close($ch);
194
195
            if ($httpCode != 200) {
196
                throw new BraspressClienteException("Erro ao realizar cotação. HTTP Code: $httpCode. Response: $response", $httpCode, $response);
197
            }
198
199
            if (is_string($response)) {
200
				$resultado = json_decode($response, true);
201
				$resultados[$modalidade === 'R' ? 'Rodoviario' : 'Aereo'] = $resultado;
202
			} else {
203
				throw new BraspressClienteException('Erro ao consultar prazo: resposta inválida recebida.');
204
			}
205
        }
206
207
        return $resultados;
208
    }
209
210
    /**
211
     * Valida a modalidade de transporte.
212
     *
213
     * @param string $modal
214
     * @return string Modalidade validada.
215
     * @throws BraspressClienteException Se a modalidade for inválida.
216
     */
217
    private function validarModal($modal)
218
    {
219
        $modalidadesValidas = ['R', 'A'];
220
        if (!in_array($modal, $modalidadesValidas)) {
221
            throw new BraspressClienteException("Modalidade inválida: $modal.");
222
        }
223
        return $modal;
224
    }
225
}
226