# Como consumir API de CPF em PrestaShop com módulos customizados

> Guia completo para consumir a API de CPF da CPFHub em PrestaShop criando módulos customizados com validação no checkout.

**Publicado:** 31/07/2026
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-consumir-api-de-cpf-em-prestashop-com-modulos-customizados

---


Para consumir a API de CPF da CPFHub em PrestaShop, crie um módulo customizado que registra hooks no checkout, faz chamadas cURL para `https://api.cpfhub.io/cpf/{CPF}` com o header `x-api-key` e retorna o resultado via AJAX para o JavaScript do storefront. O PrestaShop não oferece validação de CPF nativamente, então essa abordagem por módulo é a maneira mais organizada de adicionar essa funcionalidade sem modificar o core da plataforma. A latência média da API é de ~900ms — exibir um estado de carregamento durante a chamada melhora a experiência do usuário. Consulte a [documentação oficial de módulos do PrestaShop](https://devdocs.prestashop-project.org/8/modules/) para entender o ciclo de vida de hooks e controllers antes de começar.

---

## Estrutura do módulo PrestaShop

Um módulo PrestaShop segue uma estrutura de diretórios bem definida. Crie a seguinte estrutura:

```
modules/
 cpfhubvalidator/
 cpfhubvalidator.php
 controllers/
 front/
 validation.php
 views/
 templates/
 hook/
 cpf_field.tpl
 js/
 cpfhub-validator.js
 css/
 cpfhub-validator.css
```

---

## Arquivo principal do módulo

O arquivo principal registra hooks, instala configurações e define o comportamento do módulo:

```php
<?php
// modules/cpfhubvalidator/cpfhubvalidator.php

if (!defined('_PS_VERSION_')) {
 exit;
}

class CpfHubValidator extends Module
{
 public function __construct()
 {
 $this->name = 'cpfhubvalidator';
 $this->tab = 'front_office_features';
 $this->version = '1.0.0';
 $this->author = 'Sua Empresa';
 $this->need_instance = 0;

 parent::__construct();

 $this->displayName = $this->l('CPFHub Validator');
 $this->description = $this->l('Validação de CPF em tempo real via API CPFHub.io');
 }

 public function install()
 {
 return parent::install()
 && $this->registerHook('displayCustomerAccountForm')
 && $this->registerHook('displayHeader')
 && $this->registerHook('actionValidateCustomerAddressForm')
 && Configuration::updateValue('CPFHUB_API_KEY', '')
 && Configuration::updateValue('CPFHUB_ENABLED', 1);
 }

 public function uninstall()
 {
 return parent::uninstall()
 && Configuration::deleteByName('CPFHUB_API_KEY')
 && Configuration::deleteByName('CPFHUB_ENABLED');
 }

 public function getContent()
 {
 $output = '';

 if (Tools::isSubmit('submitCpfHubSettings')) {
 $apiKey = Tools::getValue('CPFHUB_API_KEY');
 $enabled = (int) Tools::getValue('CPFHUB_ENABLED');

 Configuration::updateValue('CPFHUB_API_KEY', $apiKey);
 Configuration::updateValue('CPFHUB_ENABLED', $enabled);

 $output .= $this->displayConfirmation($this->l('Configurações salvas.'));
 }

 return $output . $this->renderForm();
 }

 private function renderForm()
 {
 $fields = [
 'form' => [
 'legend' => [
 'title' => $this->l('Configurações CPFHub'),
 ],
 'input' => [
 [
 'type' => 'text',
 'label' => $this->l('Chave de API'),
 'name' => 'CPFHUB_API_KEY',
 'required' => true,
 'desc' => $this->l('Obtenha em cpfhub.io'),
 ],
 [
 'type' => 'switch',
 'label' => $this->l('Ativar validação'),
 'name' => 'CPFHUB_ENABLED',
 'values' => [
 ['id' => 'active_on', 'value' => 1, 'label' => $this->l('Sim')],
 ['id' => 'active_off', 'value' => 0, 'label' => $this->l('Não')],
 ],
 ],
 ],
 'submit' => [
 'title' => $this->l('Salvar'),
 ],
 ],
 ];

 $helper = new HelperForm();
 $helper->submit_action = 'submitCpfHubSettings';
 $helper->fields_value = [
 'CPFHUB_API_KEY' => Configuration::get('CPFHUB_API_KEY'),
 'CPFHUB_ENABLED' => Configuration::get('CPFHUB_ENABLED'),
 ];

 return $helper->generateForm([$fields]);
 }

 public function hookDisplayHeader()
 {
 if (!Configuration::get('CPFHUB_ENABLED')) {
 return;
 }

 Media::addJsDef([
 'cpfhubValidationUrl' => $this->context->link->getModuleLink(
 'cpfhubvalidator',
 'validation'
 ),
 ]);

 $this->context->controller->addJS(
 $this->_path . 'views/js/cpfhub-validator.js'
 );
 $this->context->controller->addCSS(
 $this->_path . 'views/css/cpfhub-validator.css'
 );
 }

 public function hookDisplayCustomerAccountForm($params)
 {
 if (!Configuration::get('CPFHUB_ENABLED')) {
 return '';
 }

 return $this->display(__FILE__, 'views/templates/hook/cpf_field.tpl');
 }

 public function hookActionValidateCustomerAddressForm($params)
 {
 if (!Configuration::get('CPFHUB_ENABLED')) {
 return;
 }

 $cpf = preg_replace('/\D/', '', Tools::getValue('cpf'));

 if (empty($cpf) || strlen($cpf) !== 11) {
 $params['form']->getField('cpf')->addError(
 $this->l('Por favor, informe um CPF válido.')
 );
 }
 }
}
```

---

## Controller de validação AJAX

Crie o front controller que recebe as requisições AJAX:

```php
<?php
// modules/cpfhubvalidator/controllers/front/validation.php

class CpfHubValidatorValidationModuleFrontController extends ModuleFrontController
{
 public function initContent()
 {
 parent::initContent();

 if (!$this->isTokenValid()) {
 $this->ajaxResponse(false, 'Token inválido.');
 return;
 }

 $cpf = preg_replace('/\D/', '', Tools::getValue('cpf'));

 if (strlen($cpf) !== 11) {
 $this->ajaxResponse(false, 'CPF deve conter 11 dígitos.');
 return;
 }

 $result = $this->validateCpf($cpf);
 $this->ajaxResponse($result['success'], $result['message'], $result['data'] ?? []);
 }

 private function validateCpf($cpf)
 {
 $apiKey = Configuration::get('CPFHUB_API_KEY');
 $url = "https://api.cpfhub.io/cpf/{$cpf}";

 $ch = curl_init();
 curl_setopt_array($ch, [
 CURLOPT_URL => $url,
 CURLOPT_RETURNTRANSFER => true,
 CURLOPT_HTTPHEADER => [
 "x-api-key: {$apiKey}",
 "Accept: application/json",
 ],
 CURLOPT_TIMEOUT => 10,
 CURLOPT_CONNECTTIMEOUT => 5,
 ]);

 $response = curl_exec($ch);
 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
 $error = curl_error($ch);
 curl_close($ch);

 if ($error) {
 return [
 'success' => false,
 'message' => 'Erro na comunicação com a API.',
 ];
 }

 $data = json_decode($response, true);

 if ($httpCode === 200 && !empty($data['success'])) {
 return [
 'success' => true,
 'message' => 'CPF válido.',
 'data' => $data['data'],
 ];
 }

 return [
 'success' => false,
 'message' => 'CPF não encontrado na base de dados.',
 ];
 }

 private function ajaxResponse($success, $message, $data = [])
 {
 header('Content-Type: application/json');
 die(json_encode([
 'success' => $success,
 'message' => $message,
 'data' => $data,
 ]));
 }
}
```

---

## Template Smarty para o campo de CPF

```smarty
{* modules/cpfhubvalidator/views/templates/hook/cpf_field.tpl *}
<div class="form-group cpfhub-field-wrapper">
 <label for="cpf" class="col-md-3 form-control-label required">
 CPF
 </label>
 <div class="col-md-6">
 <input
 type="text"
 id="cpf"
 name="cpf"
 class="form-control"
 placeholder="000.000.000-00"
 inputmode="numeric"
 maxlength="14"
 required
 />
 <div id="cpfhub-feedback" class="cpfhub-feedback"></div>
 </div>
</div>
```

---

## JavaScript para validação frontend

```javascript
// modules/cpfhubvalidator/views/js/cpfhub-validator.js
(function () {
 "use strict";

 var debounceTimer = null;

 document.addEventListener("DOMContentLoaded", function () {
 var cpfField = document.getElementById("cpf");
 if (!cpfField) return;

 var feedback = document.getElementById("cpfhub-feedback");

 cpfField.addEventListener("input", function () {
 formatCpf(cpfField);

 if (debounceTimer) clearTimeout(debounceTimer);
 debounceTimer = setTimeout(function () {
 var cpf = cpfField.value.replace(/\D/g, "");
 if (cpf.length === 11) {
 validateCpf(cpf, feedback);
 } else {
 feedback.textContent = "";
 feedback.className = "cpfhub-feedback";
 }
 }, 600);
 });
 });

 function formatCpf(field) {
 var value = field.value.replace(/\D/g, "").slice(0, 11);
 if (value.length > 9) {
 value = value.replace(/(\d{3})(\d{3})(\d{3})(\d{1,2})/, "$1.$2.$3-$4");
 } else if (value.length > 6) {
 value = value.replace(/(\d{3})(\d{3})(\d{1,3})/, "$1.$2.$3");
 } else if (value.length > 3) {
 value = value.replace(/(\d{3})(\d{1,3})/, "$1.$2");
 }
 field.value = value;
 }

 function validateCpf(cpf, feedback) {
 feedback.textContent = "Validando...";
 feedback.className = "cpfhub-feedback cpfhub-loading";

 var controller = new AbortController();
 var timeoutId = setTimeout(function () {
 controller.abort();
 }, 12000);

 var formData = new FormData();
 formData.append("cpf", cpf);
 formData.append("ajax", "1");
 formData.append("token", prestashop.static_token);

 fetch(cpfhubValidationUrl, {
 method: "POST",
 body: formData,
 signal: controller.signal,
 })
 .then(function (response) {
 clearTimeout(timeoutId);
 return response.json();
 })
 .then(function (result) {
 if (result.success) {
 feedback.textContent = "CPF válido - " + result.data.name;
 feedback.className = "cpfhub-feedback cpfhub-success";
 } else {
 feedback.textContent = result.message;
 feedback.className = "cpfhub-feedback cpfhub-error";
 }
 })
 .catch(function (err) {
 clearTimeout(timeoutId);
 feedback.textContent =
 err.name === "AbortError"
 ? "Tempo excedido. Tente novamente."
 : "Erro na validação.";
 feedback.className = "cpfhub-feedback cpfhub-error";
 });
 }
})();
```

---

## Estilos CSS do módulo

```css
/* modules/cpfhubvalidator/views/css/cpfhub-validator.css */
.cpfhub-field-wrapper {
 margin-bottom: 1rem;
}

.cpfhub-feedback {
 font-size: 0.85rem;
 margin-top: 4px;
 min-height: 1.2em;
 transition: color 0.2s ease;
}

.cpfhub-loading {
 color: #6b7280;
}

.cpfhub-success {
 color: #059669;
 font-weight: 500;
}

.cpfhub-error {
 color: #dc2626;
}
```

---

## Testando o módulo

Após instalar o módulo pelo backoffice do PrestaShop em **Modules > Module Manager**, configure a chave de API e acesse a página de cadastro de clientes. O campo de CPF deve aparecer com validação automática ao digitar.

Para testar via linha de comando, use:

```bash
# Verificar se o módulo está instalado
php bin/console prestashop:module list | grep cpfhub

# Limpar cache após alterações
php bin/console cache:clear
```

---

## Perguntas frequentes

### Por que criar um módulo customizado em vez de editar o tema diretamente?

Modificar o tema do PrestaShop diretamente torna o código frágil: qualquer atualização de tema apaga as alterações. Um módulo customizado encapsula toda a lógica de validação, registra os hooks apropriados e pode ser instalado, desinstalado e atualizado de forma independente. Essa separação segue as [boas práticas da documentação oficial do PrestaShop](https://devdocs.prestashop-project.org/8/modules/creation/) para desenvolvimento sustentável.

### A API CPFHub.io retorna erro 429 quando o limite de consultas é atingido?

Não. Quando o plano atinge o limite mensal, a API continua respondendo normalmente e cobra R$0,15 por consulta adicional — sem bloquear o serviço nem retornar código de erro 429. O plano gratuito inclui 50 consultas por mês; o plano Pro oferece 1.000 consultas mensais por R$149 com o mesmo modelo de excedente.

### Como proteger a chave de API no módulo PrestaShop?

Armazene a chave usando `Configuration::updateValue('CPFHUB_API_KEY', $apiKey)` e recupere com `Configuration::get('CPFHUB_API_KEY')` — isso usa a tabela de configuração do banco de dados, nunca exposta ao frontend. A chave é usada apenas no controller PHP server-side; o JavaScript do storefront recebe apenas a URL do endpoint interno do módulo, sem acesso direto à API externa. A [ANPD](https://www.gov.br/anpd) orienta que credenciais de acesso a dados pessoais devem ser tratadas com controles de acesso adequados.

### Qual o tempo de resposta esperado e como ajustar os timeouts do cURL?

A latência média da API CPFHub.io é de aproximadamente 900ms. O controller deste módulo define `CURLOPT_TIMEOUT => 10` e `CURLOPT_CONNECTTIMEOUT => 5`, valores adequados para absorver variações de rede sem bloquear o processo PHP por tempo excessivo. No JavaScript, o `AbortController` com 12 segundos de timeout garante que o usuário receba uma mensagem de erro clara caso a conexão falhe.

### Leia também

- [Como validar CPF no frontend com React e API REST](https://cpfhub.io/blog/como-validar-cpf-no-frontend-com-react-e-api-rest)
- [Boas práticas para consumir APIs de CPF de forma segura](https://cpfhub.io/blog/boas-praticas-consumir-apis-cpf-segura)
- [Como consumir API de CPF em Tray Commerce via API de integração](https://cpfhub.io/blog/como-consumir-api-de-cpf-em-tray-commerce-via-api-de-integracao)
- [Autenticação em APIs REST: como garantir segurança na consulta de CPF](https://cpfhub.io/blog/autenticacao-apis-rest-seguranca-consulta-cpf)

---

## Conclusão

Criar um módulo PrestaShop para validação de CPF com a API do [**CPFHub.io**](https://www.cpfhub.io/)

A API da CPFHub oferece tempo de resposta de aproximadamente 900ms, uptime de 99,9% e conformidade com a LGPD -- características essenciais para operações de e-commerce no Brasil.

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/)

