PluginProbe
SuperFrete / 3.3.2
SuperFrete v3.3.2
trunk 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4
superfrete / app / Controllers / SuperFrete_Order.php

SuperFrete_Order.php in SuperFrete 3.3.2, at app/Controllers/SuperFrete_Order.php

408 lines 16.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SuperFrete_API\Controllers;
4
5 use SuperFrete_API\Http\Request;
6 use SuperFrete_API\Helpers\Logger;
7 use SuperFrete_API\Helpers\SuperFrete_Notice;
8 use SuperFrete_API\Helpers\AddressHelper;
9 use WC_Order;
10
11 if (!defined('ABSPATH'))
12 exit; // Segurança
13
14 class SuperFrete_Order
15 {
16
17 public function __construct()
18 {
19 add_action('woocommerce_thankyou', [$this, 'send_order_to_superfrete'], 100, 1);
20 }
21
22 /**
23 * Envia os dados do pedido para a API SuperFrete.
24 */
25 public function send_order_to_superfrete($order_id)
26 {
27
28 if (!$order_id)
29 return;
30
31
32 $order = wc_get_order($order_id);
33 if (!$order)
34 return;
35
36 $order = wc_get_order($order_id);
37 $superfrete_status = $order ? $order->get_meta('_superfrete_status') : '';
38 if ($superfrete_status == 'enviado')
39 return;
40
41
42
43 Logger::log('SuperFrete', 'Pedido #' . $order_id . ' capturado para envio à API.');
44
45 // Obtém os dados do remetente (endereço da loja)
46 $cep_origem = get_option('woocommerce_store_postcode');
47 $store_raw_country = get_option('woocommerce_default_country');
48
49 // Split the country/state
50 $split_country = explode(":", $store_raw_country);
51 $store_country = $split_country[0];
52 $store_state = $split_country[1];
53 $cep_limpo = preg_replace('/[^0-9]/', '', $cep_origem);
54 $remetente = [
55 'name' => get_option('woocommerce_store_name', 'Minha Loja'),
56 'address' => get_option('woocommerce_store_address'),
57 'complement' => get_option('woocommerce_store_address_2', ''),
58 'number' => get_option('woocommerce_store_number', ''),
59 'district' => get_option('woocommerce_store_neighborhood'),
60 'city' => get_option('woocommerce_store_city'),
61 'state_abbr' => $store_state,
62 'postal_code' => $cep_limpo
63 ];
64
65 // Obtém os dados do destinatário (cliente)
66 $shipping = $order->get_address('shipping');
67
68 // Se estiver vazio, usa o billing como fallback
69 if (empty($shipping) || empty($shipping['first_name'])) {
70 $shipping = $order->get_address('billing');
71 }
72
73 // Verifica e adiciona os campos personalizados
74 if (empty($shipping['number'])) {
75 // Try multiple possible field names for number
76 $possible_number_fields = [
77 '_shipping_number',
78 '_billing_number',
79 '_WC_OTHER/SHIPPING/NUMBER',
80 'shipping/number',
81 'billing_number'
82 ];
83
84 foreach ($possible_number_fields as $field) {
85 $value = $order->get_meta($field);
86 Logger::log('SuperFrete', 'Checking number field ' . $field . ' for order #' . $order_id . ': "' . $value . '"');
87 if (!empty($value)) {
88 $shipping['number'] = $value;
89 Logger::log('SuperFrete', 'Using number from field ' . $field . ' for order #' . $order_id . ': ' . $value);
90 break;
91 }
92 }
93
94 // If still empty, search directly in meta data
95 if (empty($shipping['number'])) {
96 $all_meta = $order->get_meta_data();
97 foreach ($all_meta as $meta) {
98 if (strpos(strtolower($meta->key), 'number') !== false && !empty($meta->value)) {
99 $shipping['number'] = $meta->value;
100 Logger::log('SuperFrete', 'Found number via meta search for order #' . $order_id . ' (key: ' . $meta->key . '): ' . $meta->value);
101 break;
102 }
103 }
104 }
105 }
106
107 if (empty($shipping['neighborhood'])) {
108 // Try multiple possible field names for neighborhood
109 $possible_neighborhood_fields = [
110 '_shipping_neighborhood',
111 '_billing_neighborhood',
112 '_WC_OTHER/SHIPPING/NEIGHBORHOOD',
113 'shipping/neighborhood',
114 'billing_neighborhood'
115 ];
116
117 foreach ($possible_neighborhood_fields as $field) {
118 $value = $order->get_meta($field);
119 Logger::log('SuperFrete', 'Checking neighborhood field ' . $field . ' for order #' . $order_id . ': "' . $value . '"');
120 if (!empty($value)) {
121 $shipping['neighborhood'] = $value;
122 Logger::log('SuperFrete', 'Using neighborhood from field ' . $field . ' for order #' . $order_id . ': ' . $value);
123 break;
124 }
125 }
126
127 // If still empty, search directly in meta data
128 if (empty($shipping['neighborhood'])) {
129 $all_meta = $order->get_meta_data();
130 foreach ($all_meta as $meta) {
131 if (strpos(strtolower($meta->key), 'neighborhood') !== false && !empty($meta->value)) {
132 $shipping['neighborhood'] = $meta->value;
133 Logger::log('SuperFrete', 'Found neighborhood via meta search for order #' . $order_id . ' (key: ' . $meta->key . '): ' . $meta->value);
134 break;
135 }
136 }
137 }
138 }
139
140 // If district is still missing, try to get it from ViaCEP
141 if (empty($shipping['neighborhood']) && !empty($shipping['postcode'])) {
142 Logger::log('SuperFrete', 'District missing for order #' . $order_id . ', trying ViaCEP for CEP: ' . $shipping['postcode']);
143 $district_from_viacep = AddressHelper::get_district_from_postal_code($shipping['postcode']);
144 if ($district_from_viacep) {
145 $shipping['neighborhood'] = $district_from_viacep;
146 Logger::log('SuperFrete', 'Got district from ViaCEP for order #' . $order_id . ': ' . $district_from_viacep);
147 } else {
148 Logger::log('SuperFrete', 'Could not get district from ViaCEP for order #' . $order_id . ' with CEP: ' . $shipping['postcode']);
149 }
150 }
151
152 // Get customer document (CPF/CNPJ)
153 $document = '';
154
155 // Search through all meta data for document field
156 $all_meta = $order->get_meta_data();
157 foreach ($all_meta as $meta) {
158 // Check if this could be our document field
159 if (strpos($meta->key, 'DOCUMENT') !== false || strpos($meta->key, 'document') !== false) {
160 $clean_value = preg_replace('/[^0-9]/', '', $meta->value);
161
162 if (strlen($clean_value) == 11 || strlen($clean_value) == 14) {
163 $document = $clean_value;
164 Logger::log('SuperFrete', 'Document found for order #' . $order_id . ': ' . substr($document, 0, 3) . '***');
165 break;
166 }
167 }
168 }
169
170 // If no document found, log warning
171 if (empty($document)) {
172 Logger::log('SuperFrete', 'Warning: No CPF/CNPJ found for order #' . $order_id);
173 }
174
175 $destinatario = [
176 'name' => $shipping['first_name'] . ' ' . $shipping['last_name'],
177 'address' => $shipping['address_1'],
178 'complement' => $shipping['address_2'],
179 'number' => $shipping['number'],
180 'district' => $shipping['neighborhood'],
181 'city' => $shipping['city'],
182 'state_abbr' => $shipping['state'],
183 'postal_code' => preg_replace('/[^\p{L}\p{N}\s]/', '', $shipping['postcode'])
184 ];
185
186 // Add document if available
187 if (!empty($document)) {
188 $destinatario['document'] = $document;
189 Logger::log('SuperFrete', 'Document added to destinatario for order #' . $order_id . ': ' . substr($document, 0, 3) . '***');
190 } else {
191 Logger::log('SuperFrete', 'WARNING: No document found to add to destinatario for order #' . $order_id);
192 }
193
194 // Obtém o método de envio escolhido
195 $chosen_methods = $order->get_shipping_methods();
196 $service = "";
197
198 foreach ($chosen_methods as $method) {
199 // First try to get service ID from method metadata
200 $method_data = $method->get_data();
201 if (isset($method_data['meta_data']) && is_array($method_data['meta_data'])) {
202 foreach ($method_data['meta_data'] as $meta) {
203 if ($meta->key === 'service_id') {
204 $service = strval($meta->value);
205 Logger::log('SuperFrete', 'Got service ID from metadata for order #' . $order_id . ': ' . $service);
206 break 2; // Exit both loops
207 }
208 }
209 }
210
211 // Fallback to name-based detection if no metadata
212 if (empty($service)) {
213 $method_id = $method->get_method_id();
214 $method_name = strtolower($method->get_name());
215
216 // Check method ID first (more reliable)
217 if (strpos($method_id, 'superfrete_pac') !== false) {
218 $service = "1";
219 } elseif (strpos($method_id, 'superfrete_sedex') !== false) {
220 $service = "2";
221 } elseif (strpos($method_id, 'superfrete_jadlog') !== false) {
222 $service = "3";
223 } elseif (strpos($method_id, 'superfrete_mini_envio') !== false) {
224 $service = "17";
225 } elseif (strpos($method_id, 'superfrete_loggi') !== false) {
226 $service = "31";
227 }
228 // Fallback to name checking
229 elseif (strpos($method_name, 'pac') !== false) {
230 $service = "1";
231 } elseif (strpos($method_name, 'sedex') !== false) {
232 $service = "2";
233 } elseif (strpos($method_name, 'jadlog') !== false) {
234 $service = "3";
235 } elseif (strpos($method_name, 'mini envio') !== false) {
236 $service = "17";
237 } elseif (strpos($method_name, 'loggi') !== false) {
238 $service = "31";
239 }
240
241 Logger::log('SuperFrete', 'Service ID for order #' . $order_id . ' determined from method ID/name: ' . $service . ' (method_id: ' . $method_id . ', name: ' . $method_name . ')');
242 }
243 }
244 $request = new Request();
245
246 $produtos = [];
247
248 $insurance_value = 0;
249
250 foreach ($order->get_items() as $item_id => $item) {
251 $product = $item->get_product();
252
253 if ($product && !$product->is_virtual()) {
254 $qty = $item->get_quantity();
255 $total = $order->get_item_total($item, false); // valor unitário sem frete
256 $insurance_value += $total * $qty;
257
258 $weight_unit = get_option('woocommerce_weight_unit');
259 $dimension_unit = get_option('woocommerce_dimension_unit');
260
261 $produtos[] = [
262 'quantity' => $item['quantity'],
263 'weight' => ($weight_unit === 'g') ? floatval($product->get_weight()) / 1000 : floatval($product->get_weight()),
264 'height' => ($dimension_unit === 'm') ? floatval($product->get_height()) * 100 : floatval($product->get_height()),
265 'width' => ($dimension_unit === 'm') ? floatval($product->get_width()) * 100 : floatval($product->get_width()),
266 'length' => ($dimension_unit === 'm') ? floatval($product->get_length()) * 100 : floatval($product->get_length()),
267
268 ];
269 }
270
271 }
272 if (empty($produtos)) {
273 Logger::log('SuperFrete', 'Pedido #' . $order_id . ' não enviado para a SuperFrete, pois contém apenas produtos virtuais.');
274 return;
275 }
276
277 $payload_products = [
278 'from' => $remetente,
279 'to' => $destinatario,
280 'services' => $service, // deve ser string, ex: "1,2,17"
281 'options' => [
282 'insurance_value' => round($insurance_value, 2),
283 'receipt' => false,
284 'own_hand' => false,
285 ],
286 'products' => $produtos
287 ];
288
289 $response_package = $request->call_superfrete_api('/api/v0/calculator', 'POST', $payload_products, false);
290
291 $volume_data = [
292 'height' => 0.3,
293 'width' => 0.3,
294 'length' => 0.3,
295 'weight' => 0.2
296 ];
297
298 if (!empty($response_package) && isset($response_package[0]['packages'][0])) {
299 $package = $response_package[0]['packages'][0];
300
301 $volume_data = [
302 'height' => (float) $package['dimensions']['height'],
303 'width' => (float) $package['dimensions']['width'],
304 'length' => (float) $package['dimensions']['length'],
305 'weight' => (float) $package['weight']
306 ];
307 }
308 // Obtém os produtos do pedido
309 $produtos = [];
310
311 foreach ($order->get_items() as $item_id => $item) {
312
313 $product = $item->get_product();
314
315 if ($product && !$product->is_virtual()) {
316 $produtos[] = [
317 'name' => $product->get_name(),
318 'quantity' => strval($item->get_quantity()),
319 'unitary_value' => strval($order->get_item_total($item, false))
320 ];
321 }
322 }
323 // Monta o payload final
324 $payload = [
325 'from' => $remetente,
326 'to' => $destinatario,
327 'email' => $order->get_billing_email(),
328 'service' => intval($service),
329 'products' => $produtos,
330 'volumes' => $volume_data,
331 'options' => [
332 'insurance_value' => round($insurance_value, 2),
333 'receipt' => false,
334 'own_hand' => false,
335 'non_commercial' => false,
336 'tags' => [
337 [
338 'tag' => strval($order->get_id()),
339 'url' => get_admin_url(null, 'post.php?post=' . $order_id . '&action=edit')
340 ]
341 ],
342 ],
343 'platform' => 'WooCommerce'
344 ];
345
346 Logger::log('SuperFrete', 'Enviando pedido #' . $order_id . ' para API: ' . wp_json_encode($payload));
347
348 // Faz a requisição à API SuperFrete
349
350 $response = $request->call_superfrete_api('/api/v0/cart', 'POST', $payload, true);
351
352 if (!$response) {
353
354 $missing_fields = [];
355
356 if (empty($destinatario['name'])) {
357 $missing_fields['name'] = 'Nome do destinatário';
358 }
359 if (empty($destinatario['address'])) {
360 $missing_fields['address'] = 'Endereço';
361 }
362 if (empty($destinatario['number'])) {
363 $missing_fields['number'] = 'Número';
364 }
365 if (empty($destinatario['district'])) {
366 $missing_fields['district'] = 'Bairro';
367 }
368 if (empty($destinatario['city'])) {
369 $missing_fields['city'] = 'Cidade';
370 }
371 if (empty($destinatario['state_abbr'])) {
372 $missing_fields['state_abbr'] = 'Estado';
373 }
374 if (empty($destinatario['postal_code'])) {
375 $missing_fields['postal_code'] = 'CEP';
376 }
377
378 if (!empty($missing_fields)) {
379 SuperFrete_Notice::add_error($order_id, 'Alguns dados estão ausentes para o cálculo do frete.', $missing_fields);
380 return;
381 }
382 if (session_id() && isset($_SESSION['superfrete_correction'][$order_id])) {
383 foreach ($_SESSION['superfrete_correction'][$order_id] as $key => $value) {
384 if (isset($destinatario[$key]) && empty($destinatario[$key])) {
385 $destinatario[$key] = $value;
386 }
387 }
388 unset($_SESSION['superfrete_correction'][$order_id]); // Remove após uso
389 }
390 }
391
392 Logger::log('SuperFrete', 'Resposta da API para o pedido #' . $order_id . ': ' . wp_json_encode($response));
393
394 if ($response) {
395 $order = wc_get_order($order_id);
396 if ($order) {
397 $order->update_meta_data('_superfrete_id', $response['id']);
398 $order->update_meta_data('_superfrete_protocol', $response['protocol']);
399 $order->update_meta_data('_superfrete_price', $response['price']);
400 $order->update_meta_data('_superfrete_status', 'enviado');
401 $order->save();
402 }
403 }
404
405 return $response;
406 }
407 }
408