| 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 WC_Order; |
| 9 |
|
| 10 |
if (!defined('ABSPATH')) |
| 11 |
exit; // Segurança |
| 12 |
|
| 13 |
class SuperFrete_Order |
| 14 |
{ |
| 15 |
|
| 16 |
public function __construct() |
| 17 |
{ |
| 18 |
add_action('woocommerce_thankyou', [$this, 'send_order_to_superfrete'], 100, 1); |
| 19 |
} |
| 20 |
|
| 21 |
/** |
| 22 |
* Envia os dados do pedido para a API SuperFrete. |
| 23 |
*/ |
| 24 |
public function send_order_to_superfrete($order_id) |
| 25 |
{ |
| 26 |
|
| 27 |
if (!$order_id) |
| 28 |
return; |
| 29 |
|
| 30 |
|
| 31 |
$order = wc_get_order($order_id); |
| 32 |
if (!$order) |
| 33 |
return; |
| 34 |
|
| 35 |
$superfrete_status = get_post_meta($order_id, '_superfrete_status', true); |
| 36 |
if ($superfrete_status == 'enviado') |
| 37 |
return; |
| 38 |
|
| 39 |
|
| 40 |
|
| 41 |
Logger::log('SuperFrete', 'Pedido #' . $order_id . ' capturado para envio à API.'); |
| 42 |
|
| 43 |
// Obtém os dados do remetente (endereço da loja) |
| 44 |
$cep_origem = get_option('woocommerce_store_postcode'); |
| 45 |
$store_raw_country = get_option('woocommerce_default_country'); |
| 46 |
|
| 47 |
// Split the country/state |
| 48 |
$split_country = explode(":", $store_raw_country); |
| 49 |
$store_country = $split_country[0]; |
| 50 |
$store_state = $split_country[1]; |
| 51 |
$cep_limpo = preg_replace('/[^0-9]/', '', $cep_origem); |
| 52 |
$remetente = [ |
| 53 |
'name' => get_option('woocommerce_store_name', 'Minha Loja'), |
| 54 |
'address' => get_option('woocommerce_store_address'), |
| 55 |
'complement' => get_option('woocommerce_store_address_2', ''), |
| 56 |
'number' => get_option('woocommerce_store_number', ''), |
| 57 |
'district' => get_option('woocommerce_store_neighborhood'), |
| 58 |
'city' => get_option('woocommerce_store_city'), |
| 59 |
'state_abbr' => $store_state, |
| 60 |
'postal_code' => $cep_limpo |
| 61 |
]; |
| 62 |
|
| 63 |
// Obtém os dados do destinatário (cliente) |
| 64 |
$shipping = $order->get_address('shipping'); |
| 65 |
|
| 66 |
// Se estiver vazio, usa o billing como fallback |
| 67 |
if (empty($shipping) || empty($shipping['first_name'])) { |
| 68 |
$shipping = $order->get_address('billing'); |
| 69 |
} |
| 70 |
|
| 71 |
// Verifica e adiciona os campos personalizados |
| 72 |
if (empty($shipping['number'])) { |
| 73 |
$shipping['number'] = $order->get_meta('_shipping_number'); |
| 74 |
} |
| 75 |
if (empty($shipping['neighborhood'])) { |
| 76 |
$shipping['neighborhood'] = $order->get_meta('_shipping_neighborhood'); |
| 77 |
} |
| 78 |
$destinatario = [ |
| 79 |
'name' => $shipping['first_name'] . ' ' . $shipping['last_name'], |
| 80 |
'address' => $shipping['address_1'], |
| 81 |
'complement' => $shipping['address_2'], |
| 82 |
'number' => $shipping['number'], |
| 83 |
'district' => $shipping['neighborhood'], |
| 84 |
'city' => $shipping['city'], |
| 85 |
'state_abbr' => $shipping['state'], |
| 86 |
'postal_code' => preg_replace('/[^\p{L}\p{N}\s]/', '', $shipping['postcode']) |
| 87 |
]; |
| 88 |
|
| 89 |
// Obtém o método de envio escolhido |
| 90 |
$chosen_methods = $order->get_shipping_methods(); |
| 91 |
$service = ""; |
| 92 |
|
| 93 |
foreach ($chosen_methods as $method) { |
| 94 |
|
| 95 |
|
| 96 |
if (strpos(strtolower($method->get_name()), 'pac') !== false) { |
| 97 |
$service = "1"; |
| 98 |
} elseif (strpos(strtolower($method->get_name()), 'sedex') !== false) { |
| 99 |
$service = "2"; |
| 100 |
} elseif (strpos(strtolower($method->get_name()), 'mini envios') !== false) { |
| 101 |
$service = "17"; |
| 102 |
} |
| 103 |
} |
| 104 |
$request = new Request(); |
| 105 |
|
| 106 |
$produtos = []; |
| 107 |
|
| 108 |
$insurance_value = 0; |
| 109 |
|
| 110 |
foreach ($order->get_items() as $item_id => $item) { |
| 111 |
$product = $item->get_product(); |
| 112 |
|
| 113 |
if ($product && !$product->is_virtual()) { |
| 114 |
$qty = $item->get_quantity(); |
| 115 |
$total = $order->get_item_total($item, false); // valor unitário sem frete |
| 116 |
$insurance_value += $total * $qty; |
| 117 |
|
| 118 |
$weight_unit = get_option('woocommerce_weight_unit'); |
| 119 |
$dimension_unit = get_option('woocommerce_dimension_unit'); |
| 120 |
|
| 121 |
$produtos[] = [ |
| 122 |
'quantity' => $item['quantity'], |
| 123 |
'weight' => ($weight_unit === 'g') ? floatval($product->get_weight()) / 1000 : floatval($product->get_weight()), |
| 124 |
'height' => ($dimension_unit === 'm') ? floatval($product->get_height()) * 100 : floatval($product->get_height()), |
| 125 |
'width' => ($dimension_unit === 'm') ? floatval($product->get_width()) * 100 : floatval($product->get_width()), |
| 126 |
'length' => ($dimension_unit === 'm') ? floatval($product->get_length()) * 100 : floatval($product->get_length()), |
| 127 |
|
| 128 |
]; |
| 129 |
} |
| 130 |
|
| 131 |
} |
| 132 |
if (empty($produtos)) { |
| 133 |
Logger::log('SuperFrete', 'Pedido #' . $order_id . ' não enviado para a SuperFrete, pois contém apenas produtos virtuais.'); |
| 134 |
return; |
| 135 |
} |
| 136 |
|
| 137 |
$payload_products = [ |
| 138 |
'from' => $remetente, |
| 139 |
'to' => $destinatario, |
| 140 |
'services' => $service, // deve ser string, ex: "1,2,17" |
| 141 |
'options' => [ |
| 142 |
'insurance_value' => round($insurance_value, 2), |
| 143 |
'receipt' => false, |
| 144 |
'own_hand' => false, |
| 145 |
], |
| 146 |
'products' => $produtos |
| 147 |
]; |
| 148 |
|
| 149 |
$response_package = $request->call_superfrete_api('/api/v0/calculator', 'POST', $payload_products, false); |
| 150 |
|
| 151 |
$volume_data = [ |
| 152 |
'height' => 0.3, |
| 153 |
'width' => 0.3, |
| 154 |
'length' => 0.3, |
| 155 |
'weight' => 0.2 |
| 156 |
]; |
| 157 |
|
| 158 |
if (!empty($response_package) && isset($response_package[0]['packages'][0])) { |
| 159 |
$package = $response_package[0]['packages'][0]; |
| 160 |
|
| 161 |
$volume_data = [ |
| 162 |
'height' => (float) $package['dimensions']['height'], |
| 163 |
'width' => (float) $package['dimensions']['width'], |
| 164 |
'length' => (float) $package['dimensions']['length'], |
| 165 |
'weight' => (float) $package['weight'] |
| 166 |
]; |
| 167 |
} |
| 168 |
// Obtém os produtos do pedido |
| 169 |
$produtos = []; |
| 170 |
|
| 171 |
foreach ($order->get_items() as $item_id => $item) { |
| 172 |
|
| 173 |
$product = $item->get_product(); |
| 174 |
|
| 175 |
if ($product && !$product->is_virtual()) { |
| 176 |
$produtos[] = [ |
| 177 |
'name' => $product->get_name(), |
| 178 |
'quantity' => strval($item->get_quantity()), |
| 179 |
'unitary_value' => strval($order->get_item_total($item, false)) |
| 180 |
]; |
| 181 |
} |
| 182 |
} |
| 183 |
// Monta o payload final |
| 184 |
$payload = [ |
| 185 |
'from' => $remetente, |
| 186 |
'to' => $destinatario, |
| 187 |
'email' => $order->get_billing_email(), |
| 188 |
'service' => $service, |
| 189 |
'products' => $produtos, |
| 190 |
'volumes' => $volume_data, |
| 191 |
'options' => [ |
| 192 |
'insurance_value' => round($insurance_value, 2), |
| 193 |
'receipt' => false, |
| 194 |
'own_hand' => false, |
| 195 |
'non_commercial' => false, |
| 196 |
'tags' => [ |
| 197 |
[ |
| 198 |
'tag' => strval($order->get_id()), |
| 199 |
'url' => get_admin_url(null, 'post.php?post=' . $order_id . '&action=edit') |
| 200 |
] |
| 201 |
], |
| 202 |
], |
| 203 |
'platform' => 'WooCommerce' |
| 204 |
]; |
| 205 |
|
| 206 |
Logger::log('SuperFrete', 'Enviando pedido #' . $order_id . ' para API: ' . wp_json_encode($payload)); |
| 207 |
|
| 208 |
// Faz a requisição à API SuperFrete |
| 209 |
|
| 210 |
$response = $request->call_superfrete_api('/api/v0/cart', 'POST', $payload, true); |
| 211 |
|
| 212 |
if (!$response) { |
| 213 |
|
| 214 |
$missing_fields = []; |
| 215 |
|
| 216 |
if (empty($destinatario['name'])) { |
| 217 |
$missing_fields['name'] = 'Nome do destinatário'; |
| 218 |
} |
| 219 |
if (empty($destinatario['address'])) { |
| 220 |
$missing_fields['address'] = 'Endereço'; |
| 221 |
} |
| 222 |
if (empty($destinatario['number'])) { |
| 223 |
$missing_fields['number'] = 'Número'; |
| 224 |
} |
| 225 |
if (empty($destinatario['district'])) { |
| 226 |
$missing_fields['district'] = 'Bairro'; |
| 227 |
} |
| 228 |
if (empty($destinatario['city'])) { |
| 229 |
$missing_fields['city'] = 'Cidade'; |
| 230 |
} |
| 231 |
if (empty($destinatario['state_abbr'])) { |
| 232 |
$missing_fields['state_abbr'] = 'Estado'; |
| 233 |
} |
| 234 |
if (empty($destinatario['postal_code'])) { |
| 235 |
$missing_fields['postal_code'] = 'CEP'; |
| 236 |
} |
| 237 |
|
| 238 |
if (!empty($missing_fields)) { |
| 239 |
SuperFrete_Notice::add_error($order_id, 'Alguns dados estão ausentes para o cálculo do frete.', $missing_fields); |
| 240 |
return; |
| 241 |
} |
| 242 |
if (session_id() && isset($_SESSION['superfrete_correction'][$order_id])) { |
| 243 |
foreach ($_SESSION['superfrete_correction'][$order_id] as $key => $value) { |
| 244 |
if (isset($destinatario[$key]) && empty($destinatario[$key])) { |
| 245 |
$destinatario[$key] = $value; |
| 246 |
} |
| 247 |
} |
| 248 |
unset($_SESSION['superfrete_correction'][$order_id]); // Remove após uso |
| 249 |
} |
| 250 |
} |
| 251 |
|
| 252 |
Logger::log('SuperFrete', 'Resposta da API para o pedido #' . $order_id . ': ' . wp_json_encode($response)); |
| 253 |
if ($response) { |
| 254 |
update_post_meta($order_id, '_superfrete_id', $response['id']); |
| 255 |
update_post_meta($order_id, '_superfrete_protocol', $response['protocol']); |
| 256 |
update_post_meta($order_id, '_superfrete_price', $response['price']); |
| 257 |
update_post_meta($order_id, '_superfrete_status', 'enviado'); |
| 258 |
} |
| 259 |
return $response; |
| 260 |
} |
| 261 |
} |
| 262 |
|