Timbrar Sector Primario
Esta sección detalla la operación del servicio de timbrado especializado para el Sector Primario.
Descripción de la Operación
Esta operación permite timbrar un Comprobante Fiscal Digital por Internet (CFDI) que incluye el Complemento para el Sector Primario. Está diseñada para contribuyentes que realizan actividades agrícolas, silvícolas, ganaderas o pesqueras.
El servicio procesa un CFDI (versión 4.0), lo valida, y lo timbra ante el SAT, devolviendo el XML completo con el Timbre Fiscal Digital (TFD) incorporado.
Parámetros de Entrada (Input)
| Parámetro | Tipo de Dato | Descripción |
|---|---|---|
apikey |
string |
Credencial de acceso al servicio (Solicita aquí). |
xmlCFDI |
string |
Contenido del documento XML del CFDI v4.0 que debe incluir el Complemento para el Sector Primario. |
Parámetros de Salida (Output) - RespuestaTimbrado
La respuesta de esta operación es idéntica a la de la operación timbrar.
| Atributo | Tipo de Dato | Descripción |
|---|---|---|
code |
string |
Código de respuesta de la operación. |
message |
string |
Mensaje detallado de la respuesta. |
data |
string |
XML del CFDI timbrado en caso de éxito. |
Ejemplo de Código
A continuación se presenta un ejemplo de cómo construir la solicitud y procesar la respuesta.
Solicitud (Request)
Herramienta svcutil
Descarga e instala la herramienta svcutil
Ejecuta el comando siguiente (DESARROLLO)
svcutil.exe https://dev.facturaloplus.com/ws/servicio.do?wsdl /out:ServicioTimbradoClient.cs /config:app.configEsto genera dos archivos: ServicioTimbradoClient.cs y la configuración en app.config
Implementación
private static string GetXmlCfdiSectorPrimario() => """
<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante
xmlns:cfdi="http://www.sat.gob.mx/cfd/4"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sp="http://www.sat.gob.mx/sectorprimario"
xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd http://www.sat.gob.mx/sectorprimario http://www.sat.gob.mx/sitio_internet/cfd/sectorprimario/sectorprimario.xsd"
Version="4.0" Serie="SP" Folio="100" Fecha="2025-07-05T12:00:00"
SubTotal="5000.00" Moneda="MXN" Total="5000.00" TipoDeComprobante="I"
Exportacion="01" MetodoPago="PUE" FormaPago="01"
NoCertificado="30001000000300023708" Certificado="MIIC..." Sello="..."
LugarExpedicion="60123">
<cfdi:Emisor Rfc="ABC010101XYZ" Nombre="Productor Agrícola Ejemplo" RegimenFiscal="621"/>
<cfdi:Receptor Rfc="XAXX010101000" Nombre="Comprador General" DomicilioFiscalReceptor="64000" RegimenFiscalReceptor="616" UsoCFDI="G01"/>
<cfdi:Conceptos>
<cfdi:Concepto ObjetoImp="01" ClaveProdServ="01010101" ClaveUnidad="KGM" Cantidad="100" Descripcion="Maíz Blanco" ValorUnitario="50.00" Importe="5000.00"/>
</cfdi:Conceptos>
<cfdi:Complemento>
<sp:SectorPrimario Version="1.0" TipoOperacion="Venta"/>
</cfdi:Complemento>
</cfdi:Comprobante>
""";
public async Task<RespuestaTimbrado> TimbrarSPAsync(string apiKey, string xmlCfdi)
{
using var client = new ServicioTimbradoWSPortTypeClient("ServicioTimbradoWSPort");
try
{
var response = await client.timbrarSPAsync(apiKey, xmlCfdi);
return new RespuestaTimbrado
{
Code = response.code,
Message = response.message,
Data = response.data
};
}
catch (Exception ex)
{
Console.WriteLine($"Error al timbrar Sector Primario: {ex.Message}");
throw;
}
}
public class RespuestaTimbrado
{
public string? Code { get; set; }
public string? Message { get; set; }
public string? Data { get; set; }
}
// Ejemplo de uso
public async Task EjemploUsoTimbrarSPAsync()
{
string apiKey = "TU_API_KEY_AQUI";
string xmlCfdi = GetXmlCfdiSectorPrimario();
var resultado = await TimbrarSPAsync(apiKey, xmlCfdi);
if (resultado?.Code == "200")
{
Console.WriteLine("¡Timbrado Sector Primario Exitoso!");
Console.WriteLine(resultado.Data);
}
else
{
Console.WriteLine($"Error: {resultado?.Code} - {resultado?.Message}");
}
}Herramienta wsimport
Java incluye la herramienta wsimport en el JDK para generar las clases cliente a partir de un WSDL.
Ejecuta el siguiente comando en tu terminal para el ambiente de DESARROLLO:
wsimport -keep -p com.facturaloplus.cliente https://dev.facturaloplus.com/ws/servicio.do?wsdl-keep: Conserva los archivos fuente .java generados.
-p: Especifica el paquete (package) donde se guardarán las clases.
Implementación
import java.util.concurrent.CompletableFuture;
public class TimbradoSPService {
// ... (Definición de ExecutorService, Logger, etc.)
public String generarXmlCfdiSectorPrimario() {
return """
<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante
xmlns:cfdi="http://www.sat.gob.mx/cfd/4"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sp="http://www.sat.gob.mx/sectorprimario"
xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd http://www.sat.gob.mx/sectorprimario http://www.sat.gob.mx/sitio_internet/cfd/sectorprimario/sectorprimario.xsd"
Version="4.0" Serie="SP" Folio="100" Fecha="2025-07-05T12:00:00"
SubTotal="5000.00" Moneda="MXN" Total="5000.00" TipoDeComprobante="I"
Exportacion="01" MetodoPago="PUE" FormaPago="01"
NoCertificado="30001000000300023708" Certificado="MIIC..." Sello="..."
LugarExpedicion="60123">
<cfdi:Emisor Rfc="ABC010101XYZ" Nombre="Productor Agrícola Ejemplo" RegimenFiscal="621"/>
<cfdi:Receptor Rfc="XAXX010101000" Nombre="Comprador General" DomicilioFiscalReceptor="64000" RegimenFiscalReceptor="616" UsoCFDI="G01"/>
<cfdi:Conceptos>
<cfdi:Concepto ObjetoImp="01" ClaveProdServ="01010101" ClaveUnidad="KGM" Cantidad="100" Descripcion="Maíz Blanco" ValorUnitario="50.00" Importe="5000.00"/>
</cfdi:Conceptos>
<cfdi:Complemento>
<sp:SectorPrimario Version="1.0" TipoOperacion="Venta"/>
</cfdi:Complemento>
</cfdi:Comprobante>
""";
}
public CompletableFuture<RespuestaTimbrado> timbrarSPAsync(String apiKey, String xmlCfdi) {
return CompletableFuture.supplyAsync(() -> {
try {
ServicioTimbradoWS service = new ServicioTimbradoWS();
ServicioTimbradoWSPortType port = service.getServicioTimbradoWSPort();
Respuesta response = port.timbrarSP(apiKey, xmlCfdi);
RespuestaTimbrado resultado = new RespuestaTimbrado();
resultado.setCode(response.getCode());
resultado.setMessage(response.getMessage());
resultado.setData(response.getData());
return resultado;
} catch (Exception ex) {
throw new RuntimeException("Error al timbrar Sector Primario", ex);
}
}, executor);
}
// Ejemplo de uso
public static void main(String[] args) {
TimbradoSPService service = new TimbradoSPService();
String apiKey = "TU_API_KEY_AQUI";
String xmlCfdi = service.generarXmlCfdiSectorPrimario();
service.timbrarSPAsync(apiKey, xmlCfdi).whenComplete((resultado, ex) -> {
if (ex != null) {
System.err.println("Error: " + ex.getMessage());
} else if ("200".equals(resultado.getCode())) {
System.out.println("¡Timbrado Sector Primario Exitoso!");
System.out.println(resultado.getData());
} else {
System.err.println("Error: " + resultado.getCode() + " - " + resultado.getMessage());
}
service.shutdown();
}).join();
}
}Herramienta Zeep
Para interactuar con servicios SOAP en Python, la librería zeep es una excelente opción. Proporciona una interfaz limpia y moderna.
Instala la librería usando pip:
pip install zeepImplementación
El siguiente código muestra una implementación robusta utilizando zeep y asyncio para realizar llamadas asíncronas al servicio web.
import asyncio
from zeep.asyncio import AsyncClient
def generar_xml_cfdi_sector_primario() -> str:
return """\
<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante
xmlns:cfdi="http://www.sat.gob.mx/cfd/4"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sp="http://www.sat.gob.mx/sectorprimario"
xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd http://www.sat.gob.mx/sectorprimario http://www.sat.gob.mx/sitio_internet/cfd/sectorprimario/sectorprimario.xsd"
Version="4.0" Serie="SP" Folio="100" Fecha="2025-07-05T12:00:00"
SubTotal="5000.00" Moneda="MXN" Total="5000.00" TipoDeComprobante="I"
Exportacion="01" MetodoPago="PUE" FormaPago="01"
NoCertificado="30001000000300023708" Certificado="MIIC..." Sello="..."
LugarExpedicion="60123">
<cfdi:Emisor Rfc="ABC010101XYZ" Nombre="Productor Agrícola Ejemplo" RegimenFiscal="621"/>
<cfdi:Receptor Rfc="XAXX010101000" Nombre="Comprador General" DomicilioFiscalReceptor="64000" RegimenFiscal="616" UsoCFDI="G01"/>
<cfdi:Conceptos>
<cfdi:Concepto ObjetoImp="01" ClaveProdServ="01010101" ClaveUnidad="KGM" Cantidad="100" Descripcion="Maíz Blanco" ValorUnitario="50.00" Importe="5000.00"/>
</cfdi:Conceptos>
<cfdi:Complemento>
<sp:SectorPrimario Version="1.0" TipoOperacion="Venta"/>
</cfdi:Complemento>
"""
class TimbradoService:
def __init__(self, wsdl_url: str):
self.wsdl_url = wsdl_url
self.async_client = AsyncClient(self.wsdl_url)
async def timbrar_sp_async(self, api_key: str, xml_cfdi: str) -> RespuestaTimbrado:
response = await self.async_client.service.timbrarSP(
apikey=api_key,
xmlCFDI=xml_cfdi
)
return RespuestaTimbrado(
code=response.code,
message=response.message,
data=response.data
)
async def main():
service = TimbradoService("https://dev.facturaloplus.com/ws/servicio.do?wsdl")
api_key = "TU_API_KEY_AQUI";
xml_cfdi = generar_xml_cfdi_sector_primario();
resultado = await service.timbrar_sp_async(api_key, xml_cfdi);
if resultado.code == "200":
print("¡Timbrado Sector Primario Exitoso!");
print(resultado.data);
else:
print(f"Error: {resultado.code} - {resultado.message}");
if __name__ == "__main__":
asyncio.run(main());Herramienta SoapClient
PHP tiene soporte nativo para SOAP a través de la extensión SOAP. Asegúrate de que la extensión php-soap esté habilitada en tu archivo php.ini.
Implementación
El siguiente código muestra una implementación orientada a objetos para consumir el servicio de timbrado.
<?php
function generarXmlCfdiSectorPrimario(): string {
return <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante
xmlns:cfdi="http://www.sat.gob.mx/cfd/4"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sp="http://www.sat.gob.mx/sectorprimario"
xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd http://www.sat.gob.mx/sectorprimario http://www.sat.gob.mx/sitio_internet/cfd/sectorprimario/sectorprimario.xsd"
Version="4.0" Serie="SP" Folio="100" Fecha="2025-07-05T12:00:00"
SubTotal="5000.00" Moneda="MXN" Total="5000.00" TipoDeComprobante="I"
Exportacion="01" MetodoPago="PUE" FormaPago="01"
NoCertificado="30001000000300023708" Certificado="MIIC..." Sello="..."
LugarExpedicion="60123">
<cfdi:Emisor Rfc="ABC010101XYZ" Nombre="Productor Agrícola Ejemplo" RegimenFiscal="621"/>
<cfdi:Receptor Rfc="XAXX010101000" Nombre="Comprador General" DomicilioFiscalReceptor="64000" RegimenFiscalReceptor="616" UsoCFDI="G01"/>
<cfdi:Conceptos>
<cfdi:Concepto ObjetoImp="01" ClaveProdServ="01010101" ClaveUnidad="KGM" Cantidad="100" Descripcion="Maíz Blanco" ValorUnitario="50.00" Importe="5000.00"/>
</cfdi:Conceptos>
<cfdi:Complemento>
<sp:SectorPrimario Version="1.0" TipoOperacion="Venta"/>
</cfdi:Complemento>
</cfdi:Comprobante>
XML;
}
class TimbradoService {
private string $wsdlUrl;
public function __construct(string $wsdlUrl) {
$this->wsdlUrl = $wsdlUrl;
}
public function timbrarSP(string $apiKey, string $xmlCfdi): RespuestaTimbrado {
$respuesta = new RespuestaTimbrado();
try {
$soapClient = new SoapClient($this->wsdlUrl, ['trace' => 1, 'exceptions' => true]);
$params = [
'apikey' => $apiKey,
'xmlCFDI' => $xmlCfdi
];
$response = $soapClient->timbrarSP($params);
$respuesta->code = $response->return->code ?? null;
$respuesta->message = $response->return->message ?? null;
$respuesta->data = $response->return->data ?? null;
} catch (Exception $e) {
$respuesta->code = "CLIENT_ERROR";
$respuesta->message = $e->getMessage();
}
return $respuesta;
}
}
// Ejemplo de uso
$service = new TimbradoService("https://dev.facturaloplus.com/ws/servicio.do?wsdl");
$apiKey = "TU_API_KEY_AQUI";
$xmlCfdi = generarXmlCfdiSectorPrimario();
$resultado = $service->timbrarSP($apiKey, $xmlCfdi);
header('Content-Type: text/plain');
if ($resultado->code === '200') {
echo "¡Timbrado Sector Primario Exitoso!\n";
echo $resultado.data;
} else {
echo "Error: {$resultado.code} - {$resultado.message}\n";
}
?>
Respuesta (Response)
La estructura de la respuesta SOAP es la misma que la de la operación timbrar.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope ...>
<SOAP-ENV:Body>
<ns1:timbrarSPResponse xmlns:ns1="urn:ws_api">
<return xsi:type="tns:RespuestaTimbrado">
<code xsi:type="xsd:string">CÓDIGO</code>
<message xsi:type="xsd:string">MENSAJE</message>
<data xsi:type="xsd:string"><![CDATA[CFDI TIMBRADO]]></data>
</return>
</ns1:timbrarSPResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>Códigos de respuesta
Los códigos de respuesta para el timbrado de CFDI son importantes para entender el resultado de la solicitud. A continuación se detallan los códigos más comunes que puedes recibir al realizar una solicitud de timbrado a través de la API.
| Código | Descripción |
|---|---|
| 200 | Solicitud procesada con éxito |
| 300 | API KEY Inválida o inexistente |
| 301 | XML mal formado |
| 302 | El sello del emisor no es válido |
| 303 | El RFC del CSD del emisor no corresponde al RFC del Emisor |
| 304 | CSD del Emisor ha sido revobado |
| 305 | La fecha de emisión no está dentro de la vigencia del CSD del Emisor |
| 306 | La llave utilizada para sellar debe ser un CSD |
| 307 | El CFDI contiene un timbre previo |
| 308 | El CSD del emisor no ha sido firmado por uno de los Certificados de autoridad del SAT |
| 401 | El rango de la fecha de generación no debe de ser mayor a 72 horas para la emisión del timbre |
| 402 | RFC del emisor no se encuentra en el régimen de contribuyentes (Lista de validación de régimen) LCO |