Passed
Push — master ( 8254e1...8a2170 )
by Thalles
01:55 queued 13s
created

Frete::generatePayload()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 18
c 2
b 0
f 0
dl 0
loc 22
rs 9.6666
cc 1
nc 1
nop 0
1
<?php
2
3
namespace ThallesDKoester\Entregas;
4
5
use Exception;
6
7
/**
8
 * Thalles D. Koester | Class Frete
9
 *
10
 * @author  Thalles D. koester <[email protected]>
11
 * @package ThallesDKoester\Entregas
12
 */
13
class Frete
14
{
15
    use Curl;
16
    use Xml;
17
18
    const URL_CORREIOS = 'http://ws.correios.com.br/calculador/CalcPrecoPrazo.asmx/CalcPrecoPrazo';
19
20
    /** @var array */
21
    private $zipcode;
22
23
    /** @var string */
24
    private $types;
25
26
    /** @var array */
27
    private $item;
28
29
    /** @var string */
30
    private $error;
31
32
    /** @var array */
33
    private $options = [];
34
35
    /** @var array */
36
    private $methods = [
37
        'sedex' => '04014',
38
        'sedex_a_cobrar' => '04065',
39
        'sedex_10' => '40215',
40
        'sedex_hoje' => '40290',
41
        'pac' => '04510',
42
        'pac_a_cobrar' => '04707',
43
        'pac_contrato' => '04669',
44
        'sedex_contrato' => '04162',
45
        'esedex' => '81019',
46
    ];
47
48
    /**
49
     * Frete constructor.
50
     * @param array      $zipcode
51
     * @param array      $types
52
     * @param array      $item
53
     * @param array|null $options
54
     * @throws Exception
55
     */
56
    public function __construct(array $zipcode, array $types, array $item, ?array $options = null)
57
    {
58
        $this->setZipcode($zipcode);
59
        $this->setTypes($types);
60
        $this->setItem($item);
61
62
        if ($options) {
63
            $this->setOptions($options);
64
        }
65
    }
66
67
    /**
68
     * @return string
69
     */
70
    public function getError(): string
71
    {
72
        return $this->error;
73
    }
74
75
    /**
76
     * @param string|null $type
77
     * @return array|string
78
     */
79
    public function getTypesAvailable(?string $type = null)
80
    {
81
        if ($type) {
82
            return $this->methods[$type];
83
        }
84
        return $this->methods;
85
    }
86
87
    /**
88
     * @param string $value
89
     * @return string
90
     */
91
    public function getTypesIndex(string $value): ?string
92
    {
93
        $data = array_search($value, $this->methods);
94
        return ($data ? $data : null);
95
    }
96
97
    /**
98
     * @return array|null
99
     */
100
    public function getFrete(): ?array
101
    {
102
        $url = self::URL_CORREIOS . '?' . $this->generatePayload();
103
        try {
104
            $data = $this->request($url, 'GET');
105
        } catch (Exception $e) {
106
            $this->error = $e;
107
            return null;
108
        }
109
110
        $fretes = $this->xml2array($data)['Servicos'][0]['cServico'];
111
112
        $return = [];
113
        foreach ($fretes as $frete) {
114
            $return[] = [
115
                'codigo' => (int)$frete['Codigo'][0],
116
                'valor' => $frete['Valor'][0],
117
                'prazo' => $frete['PrazoEntrega'][0],
118
                'mao_propria' => $frete['ValorMaoPropria'][0],
119
                'aviso_recebimento' => $frete['ValorAvisoRecebimento'][0],
120
                'valor_declarado' => $frete['ValorValorDeclarado'][0],
121
                'entrega_domiciliar' => ($frete['EntregaDomiciliar'][0] === 'S' ? true : false),
122
                'entrega_sabado' => ($frete['EntregaSabado'][0] === 'S' ? true : false),
123
                'error' => ['codigo' => (int)$frete['Erro'][0], 'mensagem' => $frete['MsgErro'][0]],
124
            ];
125
        }
126
        return $return;
127
    }
128
129
    /**
130
     * @param array $zipcode
131
     */
132
    private function setZipcode(array $zipcode): void
133
    {
134
        $this->zipcode = array_map(function ($zip) {
135
            return preg_replace("/[^0-9]/", "", $zip);
136
        }, $zipcode);
137
    }
138
139
    /**
140
     * @param array $types
141
     * @throws Exception
142
     */
143
    private function setTypes(array $types): void
144
    {
145
        $newTypes = [];
146
        foreach ($types as $key => $value) {
147
            if (empty($this->methods[$value])) {
148
                throw new Exception("Tipo de frete {$value} não está disponível para uso.");
149
            }
150
            $newTypes[] = $this->methods[$value];
151
        }
152
        $this->types = implode(",", $newTypes);
153
    }
154
155
    /**
156
     * @param array $item
157
     */
158
    private function setItem(array $item): void
159
    {
160
        $this->item['peso'] = floatval($item['peso'] / 1000);
161
        $this->item['altura'] = ($item['altura'] > 2 ? $item['altura'] : 2);
162
        $this->item['comprimento'] = ($item['comprimento'] > 11 ? $item['comprimento'] : 11);
163
        $this->item['largura'] = ($item['largura'] > 16 ? $item['largura'] : 16);
164
        $this->item['diametro'] = ($item['diametro'] ?? 0);
165
    }
166
167
    /**
168
     * @param array $options
169
     */
170
    private function setOptions(array $options): void
171
    {
172
        foreach ($options as $key => $value) {
173
            $this->options[$key] = $value;
174
        }
175
176
        $this->options['valor_declarado'] = (!empty($this->options['valor_declarado'])
177
            ? number_format($this->options['valor_declarado'], '2', ',', '') : 0);
178
        $this->options['mao_propria'] = (isset($this->options['mao_propria']) && $this->options['mao_propria']
179
            ? 'S' : 'N');
180
        $this->options['aviso_recebimento'] = (isset($this->options['aviso_recebimento']) && $this->options['aviso_recebimento']
181
            ? 'S' : 'N');
182
    }
183
184
    /**
185
     * @return string
186
     */
187
    private function generatePayload(): string
188
    {
189
        $payload = [
190
            'nCdServico' => $this->types,
191
            'nCdEmpresa' => ($this->options['empresa'] ?? ''),
192
            'sDsSenha' => ($this->options['senha'] ?? ''),
193
            'sCepOrigem' => $this->zipcode['origem'],
194
            'sCepDestino' => $this->zipcode['destino'],
195
            'nVlPeso' => $this->item['peso'],
196
            'nCdFormato' => $this->item['formato'],
197
            'nVlComprimento' => $this->item['comprimento'],
198
            'nVlAltura' => $this->item['altura'],
199
            'nVlLargura' => $this->item['largura'],
200
            'nVlDiametro' => $this->item['diametro'],
201
            'sCdMaoPropria' => $this->options['mao_propria'],
202
            'nVlValorDeclarado' => $this->options['valor_declarado'],
203
            'sCdAvisoRecebimento' => $this->options['aviso_recebimento'],
204
            'sDtCalculo' => date('d/m/Y'),
205
            'StrRetorno' => 'xml'
206
        ];
207
208
        return http_build_query($payload);
209
    }
210
}