brazilianfriendsofsymfony/frete-braspress-bundle
Installation Add the bundle to your Symfony project via Composer:
composer require brazilianfriendsofsymfony/frete-braspress-bundle
Enable the bundle in config/bundles.php:
return [
// ...
BrazilianFriendsOfSymfony\FreteBraspressBundle\BFOSFreteBraspressBundle::class => ['all' => true],
];
Configuration
Add the required parameters to config/packages/b_f_o_s_frete_braspress.yaml:
b_f_o_s_frete_braspress:
api_key: '%env(BRASPRESS_API_KEY)%' # Your Braspress API key
base_url: 'https://api.braspress.com.br' # Default Braspress API URL
First Use Case
Inject the FreteBraspressService into a controller or service and calculate shipping costs:
use BrazilianFriendsOfSymfony\FreteBraspressBundle\Service\FreteBraspressService;
class ShippingController extends AbstractController
{
public function __construct(
private FreteBraspressService $freteService
) {}
public function calculateFrete(Request $request)
{
$frete = $this->freteService->calculateFrete(
$request->get('cep'), // Origin CEP
$request->get('cep_destino'), // Destination CEP
$request->get('peso'), // Package weight (in kg)
$request->get('dimensoes') // Array of dimensions [length, width, height] (in cm)
);
return $this->json($frete);
}
}
Frontend Integration Use the service in a Symfony form or API endpoint to validate shipping costs before checkout:
// Example: Validate shipping cost in a form submission
public function validateShipping(ShippingForm $form)
{
$data = $form->getData();
$frete = $this->freteService->calculateFrete(
$data->getOriginCep(),
$data->getDestinationCep(),
$data->getWeight(),
$data->getDimensions()
);
if ($frete['error']) {
$form->addError(new FormError($frete['message']));
}
return $frete;
}
Caching Frete Results Cache API responses to reduce calls to Braspress (e.g., using Symfony Cache component):
use Symfony\Contracts\Cache\CacheInterface;
class FreteBraspressService
{
public function __construct(
private ClientInterface $httpClient,
private CacheInterface $cache,
private string $apiKey,
private string $baseUrl
) {}
public function calculateFrete(string $cepOrigin, string $cepDest, float $weight, array $dimensions): array
{
$cacheKey = "frete_{$cepOrigin}_{$cepDest}_{$weight}_" . implode('_', $dimensions);
$frete = $this->cache->get($cacheKey, function() use ($cepOrigin, $cepDest, $weight, $dimensions) {
// Call Braspress API
return $this->callBraspressApi($cepOrigin, $cepDest, $weight, $dimensions);
});
return $frete;
}
}
Batch Processing For e-commerce platforms, pre-calculate frete for multiple orders:
public function calculateFreteBatch(array $ordersData): array
{
$results = [];
foreach ($ordersData as $order) {
$results[] = $this->freteService->calculateFrete(
$order['cep_origem'],
$order['cep_destino'],
$order['peso'],
$order['dimensoes']
);
}
return $results;
}
Event-Driven Updates Trigger frete recalculation when order details change (e.g., address update):
// In an event subscriber
public function onOrderAddressUpdated(OrderAddressUpdatedEvent $event)
{
$order = $event->getOrder();
$frete = $this->freteService->calculateFrete(
$order->getOriginCep(),
$order->getDestinationCep(),
$order->getWeight(),
$order->getDimensions()
);
$order->setFrete($frete);
$this->orderRepository->save($order);
}
API Key Security
BRASPRESS_API_KEY in your code. Always use environment variables (%env(BRASPRESS_API_KEY)%)..env file in production (e.g., via .gitignore and server permissions).Rate Limiting
try {
$frete = $this->freteService->calculateFrete(...);
} catch (RateLimitExceededException $e) {
sleep(2); // Wait before retrying
$frete = $this->freteService->calculateFrete(...);
}
CEP Validation
private function isValidCep(string $cep): bool
{
return preg_match('/^\d{5}-\d{3}$|^\d{8}$/', $cep);
}
Dimension Units
[length, width, height] in cm). Convert if needed:
$dimensions = [
$order->getLength() / 10, // Convert meters to cm
$order->getWidth() / 10,
$order->getHeight() / 10
];
Weight Units
$weight = $order->getWeightGrams() / 1000;
Enable API Debugging Add a debug flag to log API requests/responses:
# config/packages/dev/b_f_o_s_frete_braspress.yaml
b_f_o_s_frete_braspress:
debug: true # Logs requests/responses to Symfony profiler
Mock Braspress API in Tests Use a mock HTTP client for unit tests:
use Symfony\Contracts\HttpClient\MockHttpClient;
public function testCalculateFrete()
{
$mock = new MockHttpClient();
$mock->add([
'response' => [
'json' => [
'frete' => 15.99,
'prazo_entrega' => '3 dias'
]
]
]);
$service = new FreteBraspressService($mock, $this->cache, $this->apiKey, $this->baseUrl);
$result = $service->calculateFrete('12345678', '87654321', 1.5, [30, 20, 10]);
$this->assertEquals(15.99, $result['frete']);
}
Handle API Errors Gracefully Braspress may return errors like invalid CEPs or unsupported services. Normalize responses:
public function calculateFrete(string $cepOrigin, string $cepDest, float $weight, array $dimensions): array
{
try {
$response = $this->httpClient->request('POST', $this->baseUrl . '/frete', [
'headers' => ['Authorization' => 'Bearer ' . $this->apiKey],
'json' => [
'cep_origem' => $cepOrigin,
'cep_destino' => $cepDest,
'peso' => $weight,
'dimensoes' => $dimensions
]
]);
$data = $response->toArray();
if (isset($data['error'])) {
return ['error' => true, 'message' => $data['error']];
}
return $data;
} catch (Exception $e) {
return ['error' => true, 'message' => 'Failed to calculate frete: ' . $e->getMessage()];
}
}
class CustomFreteService extends FreteBraspressService
{
public function calculateCustomFrete(array $orderData): array
{
$baseFrete = parent::calculateFrete(
$orderData['cep_orig
How can I help you explore Laravel packages today?